source: trunk/src/comdlg32/filedlg95.c@ 10367

Last change on this file since 10367 was 10111, checked in by sandervl, 22 years ago

PF: Patrick's 2001 fixes broke too much. Stay with ReWind for now

File size: 86.1 KB
Line 
1/*
2 * COMMDLG - File Open Dialogs Win95 look and feel
3 *
4 * FIXME: The whole concept of handling unicode is badly broken.
5 * many hook-messages expecting a pointer to a
6 * OPENFILENAMEA or W structure. With the current architecture
7 * we would have to convert the beast at every call to a hook.
8 * we have to find a better solution but if would likely cause
9 * a complete rewrite with after we shouldhandle the
10 * OPENFILENAME structure without any converting (jsch).
11 *
12 * FIXME: any hook gets a OPENFILENAMEA structure
13 *
14 * FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
15 *
16 * FIXME: old style hook messages are not implemented (except FILEOKSTRING)
17 *
18 * FIXME: lpstrCustomFilter not handled
19 *
20 * FIXME: if the size of lpstrFile (nMaxFile) is too small the first
21 * two bytes of lpstrFile should contain the needed size
22 *
23 * FIXME: algorithm for selecting the initial directory is too simple
24 *
25 * FIXME: add to recent docs
26 *
27 * FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
28 * OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING, OFN_EXTENSIONDIFFERENT,
29 * OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
30 * OFN_NOTESTFILECREATE, OFN_OVERWRITEPROMPT, OFN_USEMONIKERS
31 *
32 * FIXME: lCustData for lpfnHook (WM_INITDIALOG)
33 *
34 *
35 */
36#ifdef __WIN32OS2__
37#include <windef.h>
38#include <winbase.h>
39#include <wingdi.h>
40#include <winuser.h>
41#include <heapstring.h>
42#include <misc.h>
43#include <win\shlwapi.h>
44
45#define MapHModuleSL(a) a
46#define MapHModuleLS(a) a
47#define snprintf wsnprintfA
48#endif
49
50#include <ctype.h>
51#include <stdlib.h>
52#include <stdio.h>
53#include <string.h>
54
55#include "winbase.h"
56#include "ntddk.h"
57#include "winnls.h"
58#include "heap.h"
59#include "commdlg.h"
60#include "dlgs.h"
61#include "cdlg.h"
62#include "debugtools.h"
63#include "cderr.h"
64#include "shellapi.h"
65#include "shlguid.h"
66#include "filedlgbrowser.h"
67#include "shlwapi.h"
68#include "wine/obj_contextmenu.h"
69
70DEFAULT_DEBUG_CHANNEL(commdlg);
71
72#define UNIMPLEMENTED_FLAGS \
73(OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
74OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING | OFN_EXTENSIONDIFFERENT |\
75OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
76OFN_NOTESTFILECREATE | OFN_OVERWRITEPROMPT /*| OFN_USEMONIKERS*/)
77
78#define IsHooked(fodInfos) \
79 ((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
80/***********************************************************************
81 * Data structure and global variables
82 */
83typedef struct SFolder
84{
85 int m_iImageIndex; /* Index of picture in image list */
86 HIMAGELIST hImgList;
87 int m_iIndent; /* Indentation index */
88 LPITEMIDLIST pidlItem; /* absolute pidl of the item */
89
90} SFOLDER,*LPSFOLDER;
91
92typedef struct tagLookInInfo
93{
94 int iMaxIndentation;
95 UINT uSelectedItem;
96} LookInInfos;
97
98
99/***********************************************************************
100 * Defines and global variables
101 */
102
103/* Draw item constant */
104#define ICONWIDTH 18
105#define XTEXTOFFSET 3
106
107/* AddItem flags*/
108#define LISTEND -1
109
110/* SearchItem methods */
111#define SEARCH_PIDL 1
112#define SEARCH_EXP 2
113#define ITEM_NOTFOUND -1
114
115/* Undefined windows message sent by CreateViewObject*/
116#define WM_GETISHELLBROWSER WM_USER+7
117
118/* NOTE
119 * Those macros exist in windowsx.h. However, you can't really use them since
120 * they rely on the UNICODE defines and can't be used inside Wine itself.
121 */
122
123/* Combo box macros */
124#define CBAddString(hwnd,str) \
125 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
126
127#define CBInsertString(hwnd,str,pos) \
128 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
129
130#define CBDeleteString(hwnd,pos) \
131 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
132
133#define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
134 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
135
136#define CBGetItemDataPtr(hwnd,iItemId) \
137 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
138
139#define CBGetLBText(hwnd,iItemId,str) \
140 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
141
142#define CBGetCurSel(hwnd) \
143 SendMessageA(hwnd,CB_GETCURSEL,0,0);
144
145#define CBSetCurSel(hwnd,pos) \
146 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
147
148#define CBGetCount(hwnd) \
149 SendMessageA(hwnd,CB_GETCOUNT,0,0);
150#define CBShowDropDown(hwnd,show) \
151 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
152#define CBSetItemHeight(hwnd,index,height) \
153 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
154
155
156const char *FileOpenDlgInfosStr = "FileOpenDlgInfos"; /* windows property description string */
157const char *LookInInfosStr = "LookInInfos"; /* LOOKIN combo box property */
158
159static const char defaultFilter[] = "*.*";
160
161/***********************************************************************
162 * Prototypes
163 */
164
165/* Internal functions used by the dialog */
166static LRESULT FILEDLG95_FillControls(HWND hwnd, WPARAM wParam, LPARAM lParam);
167static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
168static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
169 BOOL FILEDLG95_OnOpen(HWND hwnd);
170static LRESULT FILEDLG95_InitControls(HWND hwnd);
171static void FILEDLG95_Clean(HWND hwnd);
172
173/* Functions used by the shell navigation */
174static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
175static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd);
176static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
177static void FILEDLG95_SHELL_Clean(HWND hwnd);
178static BOOL FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd);
179
180/* Functions used by the filetype combo box */
181static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd);
182static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode);
183static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPCSTR lpstrExt);
184static void FILEDLG95_FILETYPE_Clean(HWND hwnd);
185
186/* Functions used by the Look In combo box */
187static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo);
188static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct);
189static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode);
190static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId);
191static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod);
192static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl);
193static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd);
194 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
195static void FILEDLG95_LOOKIN_Clean(HWND hwnd);
196
197/* Miscellaneous tool functions */
198HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
199HRESULT GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
200IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
201LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl);
202LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);
203
204/* Shell memory allocation */
205static void *MemAlloc(UINT size);
206static void MemFree(void *mem);
207
208BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos);
209HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
210HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode);
211HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
212BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed);
213static BOOL BrowseSelectedFolder(HWND hwnd);
214
215/***********************************************************************
216 * GetFileName95
217 *
218 * Creates an Open common dialog box that lets the user select
219 * the drive, directory, and the name of a file or set of files to open.
220 *
221 * IN : The FileOpenDlgInfos structure associated with the dialog
222 * OUT : TRUE on success
223 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
224 */
225BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos)
226{
227
228 LRESULT lRes;
229 LPCVOID template;
230 HRSRC hRes;
231 HANDLE hDlgTmpl = 0;
232
233 /* test for missing functionality */
234 if (fodInfos->ofnInfos->Flags & UNIMPLEMENTED_FLAGS)
235 {
236 FIXME("Flags 0x%08lx not yet implemented\n",
237 fodInfos->ofnInfos->Flags & UNIMPLEMENTED_FLAGS);
238 }
239
240 /* Create the dialog from a template */
241
242 if(!(hRes = FindResourceA(COMMDLG_hInstance32,MAKEINTRESOURCEA(NEWFILEOPENORD),RT_DIALOGA)))
243 {
244 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
245 return FALSE;
246 }
247 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hRes )) ||
248 !(template = LockResource( hDlgTmpl )))
249 {
250 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
251 return FALSE;
252 }
253
254 /* old style hook messages */
255 if (IsHooked(fodInfos))
256 {
257 fodInfos->HookMsg.fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
258 fodInfos->HookMsg.lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
259 fodInfos->HookMsg.helpmsgstring = RegisterWindowMessageA(HELPMSGSTRINGA);
260 fodInfos->HookMsg.sharevistring = RegisterWindowMessageA(SHAREVISTRINGA);
261 }
262
263 lRes = DialogBoxIndirectParamA(COMMDLG_hInstance32,
264 (LPDLGTEMPLATEA) template,
265 fodInfos->ofnInfos->hwndOwner,
266 (DLGPROC) FileOpenDlgProc95,
267 (LPARAM) fodInfos);
268
269 /* Unable to create the dialog */
270 if( lRes == -1)
271 return FALSE;
272
273 return lRes;
274}
275
276/***********************************************************************
277 * GetFileDialog95A
278 *
279 * Call GetFileName95 with this structure and clean the memory.
280 *
281 * IN : The OPENFILENAMEA initialisation structure passed to
282 * GetOpenFileNameA win api function (see filedlg.c)
283 */
284BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
285{
286
287 BOOL ret;
288 FileOpenDlgInfos *fodInfos;
289 HINSTANCE hInstance;
290 LPCSTR lpstrInitialDir = (LPCSTR)-1;
291 LPSTR lpstrSavDir = NULL;
292 DWORD dwFlags = 0;
293
294 /* Initialise FileOpenDlgInfos structure*/
295 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
296 ZeroMemory(fodInfos, sizeof(FileOpenDlgInfos));
297
298 /* Pass in the original ofn */
299 fodInfos->ofnInfos = ofn;
300
301 /* Save original hInstance value */
302 hInstance = ofn->hInstance;
303 fodInfos->ofnInfos->hInstance = MapHModuleLS(ofn->hInstance);
304
305 /* save current directory */
306 if (ofn->Flags & OFN_NOCHANGEDIR)
307 {
308 lpstrSavDir = MemAlloc(MAX_PATH);
309 GetCurrentDirectoryA(MAX_PATH, lpstrSavDir);
310 }
311
312 dwFlags = ofn->Flags;
313 ofn->Flags = ofn->Flags|OFN_WINE;
314
315 /* Initialise the dialog property */
316 fodInfos->DlgInfos.dwDlgProp = 0;
317 fodInfos->DlgInfos.hwndCustomDlg = (HWND)NULL;
318
319 switch(iDlgType)
320 {
321 case OPEN_DIALOG :
322 ret = GetFileName95(fodInfos);
323 break;
324 case SAVE_DIALOG :
325 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
326#ifdef __WIN32OS2__
327 //NT4 seems to ignore this flag (fixes ElstarFormular save dialog)
328 ofn->Flags &= ~OFN_FILEMUSTEXIST;
329#endif
330 ret = GetFileName95(fodInfos);
331 break;
332 default :
333 ret = 0;
334 }
335
336 if (lpstrSavDir)
337 {
338 SetCurrentDirectoryA(lpstrSavDir);
339 MemFree(lpstrSavDir);
340 }
341
342 if (lpstrInitialDir != (LPCSTR)-1)
343 {
344 MemFree((LPVOID)(ofn->lpstrInitialDir));
345 ofn->lpstrInitialDir = lpstrInitialDir;
346 }
347
348 ofn->Flags = dwFlags;
349 ofn->hInstance = hInstance;
350 MemFree((LPVOID)(fodInfos));
351 return ret;
352}
353
354/***********************************************************************
355 * GetFileDialog95W
356 *
357 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
358 * Call GetFileName95 with this structure and clean the memory.
359 *
360 * FIXME: lpstrCustomFilter has to converted back
361 *
362 */
363
364/* converting IN arguments */
365#define AllocInArgWtoA(arg, save) \
366 if(arg) \
367 { \
368 DWORD _len = WideCharToMultiByte( CP_ACP, 0, arg, -1, NULL, 0, NULL, NULL ); \
369 save = arg; \
370 arg = MemAlloc(_len); \
371 WideCharToMultiByte( CP_ACP, 0, save, -1, (LPSTR)arg, _len, NULL, NULL ); \
372 }
373
374#define FreeInArg(arg, save) \
375 if(arg) \
376 { \
377 MemFree((LPSTR)arg); \
378 arg = save; \
379 }
380
381/* converting OUT arguments */
382#define AllocOutArgWtoA(arg, save, len) \
383 if(arg) \
384 { \
385 save = arg; \
386 arg = MemAlloc(len); \
387 }
388
389#define FreeOutArg(arg, save, len) \
390 if(arg) \
391 { \
392 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)(arg), -1, (save), (len) ); \
393 MemFree(arg); \
394 arg = save; \
395 }
396
397BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType)
398{
399 BOOL ret;
400 FileOpenDlgInfos *fodInfos;
401 HINSTANCE hInstance;
402
403 /* out arguments */
404 LPWSTR lpstrFile = NULL;
405 LPWSTR lpstrFileTitle = NULL;
406#ifdef __WIN32OS2__
407 LPSTR lpstrSavDir = NULL;
408#endif
409
410 /* in/out arguments */
411 LPWSTR lpstrCustomFilter = NULL;
412
413 /* input arguments */
414 LPCWSTR lpstrFilter = NULL;
415 LPCWSTR lpstrInitialDir = NULL;
416 LPCWSTR lpstrTitle = NULL;
417 LPCWSTR lpstrDefExt = NULL;
418 LPCWSTR lpTemplateName = NULL;
419 DWORD dwFlags;
420
421 /* Initialise FileOpenDlgInfos structure*/
422 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
423 ZeroMemory(fodInfos, sizeof(FileOpenDlgInfos));
424
425 /* Pass in the original ofn */
426 fodInfos->ofnInfos = (LPOPENFILENAMEA) ofn;
427
428 /* convert lpstrFilter */
429 if (ofn->lpstrFilter)
430 {
431 LPCWSTR s;
432 LPSTR y;
433 int n, len;
434
435 lpstrFilter = ofn->lpstrFilter;
436
437 /* filter is a list... title\0ext\0......\0\0 */
438 s = ofn->lpstrFilter;
439
440 while (*s) s = s+strlenW(s)+1;
441 s++;
442 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
443 len = WideCharToMultiByte( CP_ACP, 0, ofn->lpstrFilter, n, NULL, 0, NULL, NULL );
444 y = (LPSTR)MemAlloc(len);
445 WideCharToMultiByte( CP_ACP, 0, ofn->lpstrFilter, n, y, len, NULL, NULL );
446#ifdef __WIN32OS2__
447 ofn->lpstrFilter = (LPWSTR)y;
448#else
449 (LPSTR)ofn->lpstrFilter = y;
450#endif
451 }
452
453 /* convert lpstrCustomFilter */
454 if (ofn->lpstrCustomFilter)
455 {
456 LPWSTR s;
457 LPSTR y;
458 int n, len;
459
460 lpstrCustomFilter = ofn->lpstrCustomFilter;
461 /* filter is a list... title\0ext\0......\0\0 */
462 s = ofn->lpstrCustomFilter;
463 while (*s) s = s+strlenW(s)+1;
464 s++;
465 n = s - ofn->lpstrCustomFilter;
466 len = WideCharToMultiByte( CP_ACP, 0, ofn->lpstrCustomFilter, n, NULL, 0, NULL, NULL );
467 y = (LPSTR)MemAlloc(len);
468 WideCharToMultiByte( CP_ACP, 0, ofn->lpstrCustomFilter, n, y, len, NULL, NULL );
469#ifdef __WIN32OS2__
470 ofn->lpstrCustomFilter = (LPWSTR)y;
471#else
472 (LPSTR)ofn->lpstrCustomFilter = y;
473#endif
474 }
475
476 /* convert string arguments, save others */
477 AllocOutArgWtoA(ofn->lpstrFile, lpstrFile, ofn->nMaxFile);
478 AllocOutArgWtoA(ofn->lpstrFileTitle, lpstrFileTitle, ofn->nMaxFileTitle);
479 AllocInArgWtoA(ofn->lpstrInitialDir, lpstrInitialDir);
480 AllocInArgWtoA(ofn->lpstrTitle, lpstrTitle);
481 AllocInArgWtoA(ofn->lpstrDefExt, lpstrDefExt);
482#ifdef __WIN32OS2__
483 if(HIWORD(ofn->lpTemplateName)) {
484#endif
485 AllocInArgWtoA(ofn->lpTemplateName, lpTemplateName);
486#ifdef __WIN32OS2__
487 }
488 else lpTemplateName = ofn->lpTemplateName;
489#endif
490
491 dwFlags = ofn->Flags;
492 hInstance = ofn->hInstance;
493
494#ifdef __WIN32OS2__
495 /* save current directory */
496 if (ofn->Flags & OFN_NOCHANGEDIR)
497 {
498 lpstrSavDir = MemAlloc(MAX_PATH);
499 GetCurrentDirectoryA(MAX_PATH, lpstrSavDir);
500 }
501#endif
502
503 ofn->Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
504 ofn->hInstance = MapHModuleLS(ofn->hInstance);
505
506 switch(iDlgType)
507 {
508 case OPEN_DIALOG :
509 ret = GetFileName95(fodInfos);
510 break;
511 case SAVE_DIALOG :
512 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
513#ifdef __WIN32OS2__
514 //NT4 seems to ignore this flag (fixes ElstarFormular save dialog)
515 ofn->Flags &= ~OFN_FILEMUSTEXIST;
516#endif
517 ret = GetFileName95(fodInfos);
518 break;
519 default :
520 ret = 0;
521 }
522
523#ifdef __WIN32OS2__
524 if (lpstrSavDir)
525 {
526 SetCurrentDirectoryA(lpstrSavDir);
527 MemFree(lpstrSavDir);
528 }
529#endif
530
531 /* restore saved IN arguments and convert OUT arguments back */
532 ofn->Flags = dwFlags;
533 ofn->hInstance = hInstance;
534 FreeInArg(ofn->lpstrFilter, lpstrFilter);
535 FreeInArg(ofn->lpstrCustomFilter, lpstrCustomFilter);
536 FreeOutArg(ofn->lpstrFile, lpstrFile, ofn->nMaxFile);
537 FreeOutArg(ofn->lpstrFileTitle, lpstrFileTitle, ofn->nMaxFileTitle);
538 FreeInArg(ofn->lpstrInitialDir, lpstrInitialDir);
539 FreeInArg(ofn->lpstrTitle, lpstrTitle);
540 FreeInArg(ofn->lpstrDefExt, lpstrDefExt);
541#ifdef __WIN32OS2__
542 if(HIWORD(lpTemplateName)) {
543 FreeInArg(ofn->lpTemplateName, lpTemplateName);
544 }
545 else ofn->lpTemplateName = lpTemplateName;
546#else
547 FreeInArg(ofn->lpTemplateName, lpTemplateName);
548#endif
549
550 MemFree((LPVOID)(fodInfos));
551 return ret;
552}
553
554void ArrangeCtrlPositions( HWND hwndChildDlg, HWND hwndParentDlg)
555{
556 HWND hwndChild,hwndStc32;
557 RECT rectParent, rectChild, rectCtrl, rectStc32, rectTemp;
558 POINT ptMoveCtl;
559 POINT ptParentClient;
560
561 TRACE("\n");
562
563 ptMoveCtl.x = ptMoveCtl.y = 0;
564 hwndStc32=GetDlgItem(hwndChildDlg,stc32);
565 GetClientRect(hwndParentDlg,&rectParent);
566 GetClientRect(hwndChildDlg,&rectChild);
567
568 if(hwndStc32)
569 {
570 GetWindowRect(hwndStc32,&rectStc32);
571 MapWindowPoints(0, hwndChildDlg,(LPPOINT)&rectStc32,2);
572 CopyRect(&rectTemp,&rectStc32);
573
574 SetRect(&rectStc32,rectStc32.left,rectStc32.top,rectStc32.left + (rectParent.right-rectParent.left),rectStc32.top+(rectParent.bottom-rectParent.top));
575 SetWindowPos(hwndStc32,0,rectStc32.left,rectStc32.top,rectStc32.right-rectStc32.left,rectStc32.bottom-rectStc32.top,SWP_NOMOVE|SWP_NOZORDER | SWP_NOACTIVATE);
576
577 if(rectStc32.right < rectTemp.right)
578 {
579 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
580 ptMoveCtl.x = 0;
581 }
582 else
583 {
584 ptMoveCtl.x = (rectStc32.right - rectTemp.right);
585 ptParentClient.x = max((rectParent.right-rectParent.left),((rectChild.right-rectChild.left)+rectStc32.right-rectTemp.right));
586 }
587
588 if(rectStc32.bottom < rectTemp.bottom)
589 {
590 ptParentClient.y = max((rectParent.bottom-rectParent.top),(rectChild.bottom-rectChild.top));
591 ptMoveCtl.y = 0;
592 }
593 else
594 {
595 ptMoveCtl.y = (rectStc32.bottom - rectTemp.bottom);
596 ptParentClient.y = max((rectParent.bottom-rectParent.top),((rectChild.bottom-rectChild.top)+rectStc32.bottom-rectTemp.bottom));
597 }
598 }
599 else
600 {
601 if( (GetWindow(hwndChildDlg,GW_CHILD)) == (HWND) NULL) return;
602
603 SetRectEmpty(&rectTemp);
604 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
605 ptParentClient.y = (rectParent.bottom-rectParent.top) + (rectChild.bottom-rectChild.top);
606 ptMoveCtl.y = rectParent.bottom-rectParent.top;
607 ptMoveCtl.x=0;
608 }
609 SetRect(&rectParent,rectParent.left,rectParent.top,rectParent.left+ptParentClient.x,rectParent.top+ptParentClient.y);
610 AdjustWindowRectEx( &rectParent,GetWindowLongA(hwndParentDlg,GWL_STYLE),FALSE,GetWindowLongA(hwndParentDlg,GWL_EXSTYLE));
611
612 SetWindowPos(hwndChildDlg, 0, 0,0, ptParentClient.x,ptParentClient.y, SWP_NOZORDER );
613 SetWindowPos(hwndParentDlg, 0, rectParent.left,rectParent.top, (rectParent.right- rectParent.left),
614 (rectParent.bottom-rectParent.top),SWP_NOMOVE | SWP_NOZORDER);
615
616 hwndChild = GetWindow(hwndChildDlg,GW_CHILD);
617 if(hwndStc32)
618 {
619 GetWindowRect(hwndStc32,&rectStc32);
620 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
621 }
622 else
623 SetRect(&rectStc32,0,0,0,0);
624
625 if (hwndChild )
626 {
627 do
628 {
629 if(hwndChild != hwndStc32)
630 {
631 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
632 continue;
633 GetWindowRect(hwndChild,&rectCtrl);
634 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
635
636 /*
637 Check the initial position of the controls relative to the initial
638 position and size of stc32 (before it is expanded).
639 */
640 if (rectCtrl.left >= rectTemp.right && rectCtrl.top >= rectTemp.bottom)
641 {
642 rectCtrl.left += ptMoveCtl.x;
643 rectCtrl.top += ptMoveCtl.y;
644 }
645 else if (rectCtrl.left >= rectTemp.right)
646 {
647 rectCtrl.left += ptMoveCtl.x;
648 }
649 else if (rectCtrl.top >= rectTemp.bottom)
650 {
651 rectCtrl.top += ptMoveCtl.y;
652 }
653
654 SetWindowPos( hwndChild, 0, rectCtrl.left, rectCtrl.top,
655 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
656 SWP_NOSIZE | SWP_NOZORDER );
657 }
658 } while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
659 }
660 hwndChild = GetWindow(hwndParentDlg,GW_CHILD);
661
662 if(hwndStc32)
663 {
664 GetWindowRect(hwndStc32,&rectStc32);
665 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
666 ptMoveCtl.x = rectStc32.left - 0;
667 ptMoveCtl.y = rectStc32.top - 0;
668 if (hwndChild )
669 {
670 do
671 {
672 if(hwndChild != hwndChildDlg)
673 {
674 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
675 continue;
676 GetWindowRect(hwndChild,&rectCtrl);
677 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
678
679 rectCtrl.left += ptMoveCtl.x;
680 rectCtrl.top += ptMoveCtl.y;
681
682 SetWindowPos( hwndChild, 0, rectCtrl.left, rectCtrl.top,
683 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
684 SWP_NOSIZE |SWP_NOZORDER );
685 }
686 } while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
687 }
688 }
689}
690
691
692HRESULT WINAPI FileOpenDlgProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
693{
694 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(GetParent(hwnd),FileOpenDlgInfosStr);
695
696#if 0
697 TRACE("0x%04x\n", uMsg);
698#endif
699
700 switch(uMsg)
701 {
702 case WM_INITDIALOG:
703 {
704 fodInfos = (FileOpenDlgInfos *)lParam;
705 lParam = (LPARAM) fodInfos->ofnInfos;
706 ArrangeCtrlPositions(hwnd,GetParent(hwnd));
707
708 if(fodInfos && IsHooked(fodInfos))
709 return CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,hwnd,uMsg,wParam,lParam);
710 return 0;
711 }
712 }
713
714 if(fodInfos && IsHooked(fodInfos))
715 return CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,hwnd,uMsg,wParam,lParam);
716
717 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
718}
719
720HWND CreateTemplateDialog(FileOpenDlgInfos *fodInfos, HWND hwnd)
721{
722 LPCVOID template;
723 HRSRC hRes;
724 HANDLE hDlgTmpl = 0;
725 HWND hChildDlg = 0;
726
727 TRACE("\n");
728
729 if (fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATE ||
730 fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATEHANDLE)
731 {
732 if (fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATEHANDLE)
733 {
734 if( !(template = LockResource( fodInfos->ofnInfos->hInstance)))
735 {
736 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
737 return (HWND)NULL;
738 }
739 }
740 else
741 {
742 if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos->hInstance),
743 (fodInfos->ofnInfos->lpTemplateName), RT_DIALOGA)))
744 {
745 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
746 return (HWND)NULL;
747 }
748 if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos->hInstance),
749 hRes )) || !(template = LockResource( hDlgTmpl )))
750 {
751 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
752 return (HWND)NULL;
753 }
754 }
755
756 hChildDlg= CreateDialogIndirectParamA(fodInfos->ofnInfos->hInstance,template,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
757 if(hChildDlg)
758 {
759 ShowWindow(hChildDlg,SW_SHOW);
760 return hChildDlg;
761 }
762 }
763 else if( IsHooked(fodInfos))
764 {
765 RECT rectHwnd;
766 DLGTEMPLATE tmplate;
767 GetClientRect(hwnd,&rectHwnd);
768 tmplate.style = WS_CHILD | WS_CLIPSIBLINGS;
769 tmplate.dwExtendedStyle = 0;
770 tmplate.cdit = 0;
771 tmplate.x = 0;
772 tmplate.y = 0;
773 tmplate.cx = rectHwnd.right-rectHwnd.left;
774 tmplate.cy = rectHwnd.bottom-rectHwnd.top;
775
776 return CreateDialogIndirectParamA(fodInfos->ofnInfos->hInstance,&tmplate,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
777 }
778 return (HWND)NULL;
779}
780
781/***********************************************************************
782* SendCustomDlgNotificationMessage
783*
784* Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
785*/
786
787HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode)
788{
789 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwndParentDlg,FileOpenDlgInfosStr);
790
791 TRACE("0x%04x 0x%04x\n",hwndParentDlg, uCode);
792
793 if(!fodInfos) return 0;
794
795 if(fodInfos->ofnInfos->Flags & OFN_UNICODE)
796 FIXME("sending OPENFILENAMEA structure. Hook is expecting OPENFILENAMEW!\n");
797
798 if(fodInfos->DlgInfos.hwndCustomDlg)
799 {
800 OFNOTIFYA ofnNotify;
801 HRESULT ret;
802 ofnNotify.hdr.hwndFrom=hwndParentDlg;
803 ofnNotify.hdr.idFrom=0;
804 ofnNotify.hdr.code = uCode;
805 ofnNotify.lpOFN = fodInfos->ofnInfos;
806 TRACE("CALL NOTIFY for %x\n", uCode);
807 ret = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg,WM_NOTIFY,0,(LPARAM)&ofnNotify);
808 TRACE("RET NOTIFY\n");
809 return ret;
810 }
811 return TRUE;
812}
813
814/***********************************************************************
815* FILEDLG95_HandleCustomDialogMessages
816*
817* Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
818*/
819HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
820{
821 LPSTR lpstrFileSpec;
822 int reqSize;
823 char lpstrPath[MAX_PATH];
824 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
825 if(!fodInfos) return -1;
826
827 switch(uMsg)
828 {
829 case CDM_GETFILEPATH:
830 GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrPath, sizeof(lpstrPath));
831 lpstrFileSpec = (LPSTR)PathFindFileNameA(lpstrPath);
832 if (lpstrFileSpec==lpstrPath)
833 {
834 char lpstrCurrentDir[MAX_PATH];
835 /* Prepend the current path */
836 SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrCurrentDir);
837 if ((LPSTR)lParam!=NULL)
838 snprintf((LPSTR)lParam,(int)wParam,"%s\\%s",lpstrCurrentDir,lpstrPath);
839 reqSize=strlen(lpstrCurrentDir)+1+strlen(lpstrPath)+1;
840 }
841 else
842 {
843 lstrcpynA((LPSTR)lParam,(LPSTR)lpstrPath,(int)wParam);
844 reqSize=strlen(lpstrPath);
845 }
846 /* return the required buffer size */
847 return reqSize;
848
849 case CDM_GETFOLDERPATH:
850 SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrPath);
851 if ((LPSTR)lParam!=NULL)
852 lstrcpynA((LPSTR)lParam,lpstrPath,(int)wParam);
853 return strlen(lpstrPath);
854
855 case CDM_GETSPEC:
856 reqSize=GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrPath, sizeof(lpstrPath));
857 lpstrFileSpec = (LPSTR)PathFindFileNameA(lpstrPath);
858 if ((LPSTR)lParam!=NULL)
859 lstrcpynA((LPSTR)lParam, lpstrFileSpec, (int)wParam);
860 return strlen(lpstrFileSpec);
861
862 case CDM_SETCONTROLTEXT:
863 if ( 0 != lParam )
864 SetDlgItemTextA( hwnd, (UINT) wParam, (LPSTR) lParam );
865 return TRUE;
866
867 case CDM_HIDECONTROL:
868 case CDM_SETDEFEXT:
869 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
870 return -1;
871 }
872 return TRUE;
873}
874
875/***********************************************************************
876 * FileOpenDlgProc95
877 *
878 * File open dialog procedure
879 */
880HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
881{
882#if 0
883 TRACE("0x%04x 0x%04x\n", hwnd, uMsg);
884#endif
885
886 switch(uMsg)
887 {
888 case WM_INITDIALOG:
889 {
890 FileOpenDlgInfos * fodInfos = (FileOpenDlgInfos *)lParam;
891
892 /* Adds the FileOpenDlgInfos in the property list of the dialog
893 so it will be easily accessible through a GetPropA(...) */
894 SetPropA(hwnd, FileOpenDlgInfosStr, (HANDLE) fodInfos);
895
896 fodInfos->DlgInfos.hwndCustomDlg =
897 CreateTemplateDialog((FileOpenDlgInfos *)lParam, hwnd);
898
899 FILEDLG95_InitControls(hwnd);
900 SendCustomDlgNotificationMessage(hwnd,CDN_INITDONE);
901 FILEDLG95_FillControls(hwnd, wParam, lParam);
902 SendCustomDlgNotificationMessage(hwnd,CDN_SELCHANGE);
903 SetWindowPos(fodInfos->DlgInfos.hwndCustomDlg, HWND_BOTTOM,
904 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
905 return 0;
906 }
907 case WM_COMMAND:
908 return FILEDLG95_OnWMCommand(hwnd, wParam, lParam);
909 case WM_DRAWITEM:
910 {
911 switch(((LPDRAWITEMSTRUCT)lParam)->CtlID)
912 {
913 case IDC_LOOKIN:
914 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT) lParam);
915 return TRUE;
916 }
917 }
918 return FALSE;
919
920 case WM_GETISHELLBROWSER:
921 return FILEDLG95_OnWMGetIShellBrowser(hwnd);
922
923 case WM_DESTROY:
924 RemovePropA(hwnd, FileOpenDlgInfosStr);
925 return FALSE;
926
927 case WM_NOTIFY:
928 {
929 LPNMHDR lpnmh = (LPNMHDR)lParam;
930 UINT stringId = -1;
931
932 /* set up the button tooltips strings */
933 if(TTN_GETDISPINFOA == lpnmh->code )
934 {
935 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
936 switch(lpnmh->idFrom )
937 {
938 /* Up folder button */
939 case FCIDM_TB_UPFOLDER:
940 stringId = IDS_UPFOLDER;
941 break;
942 /* New folder button */
943 case FCIDM_TB_NEWFOLDER:
944 stringId = IDS_NEWFOLDER;
945 break;
946 /* List option button */
947 case FCIDM_TB_SMALLICON:
948 stringId = IDS_LISTVIEW;
949 break;
950 /* Details option button */
951 case FCIDM_TB_REPORTVIEW:
952 stringId = IDS_REPORTVIEW;
953 break;
954 /* Desktop button */
955 case FCIDM_TB_DESKTOP:
956 stringId = IDS_TODESKTOP;
957 break;
958 default:
959 stringId = 0;
960 }
961 lpdi->hinst = COMMDLG_hInstance32;
962 lpdi->lpszText = (LPSTR) stringId;
963 }
964 return FALSE;
965 }
966 default :
967 if(uMsg >= CDM_FIRST && uMsg <= CDM_LAST)
968 return FILEDLG95_HandleCustomDialogMessages(hwnd, uMsg, wParam, lParam);
969 return FALSE;
970 }
971}
972
973/***********************************************************************
974 * FILEDLG95_InitControls
975 *
976 * WM_INITDIALOG message handler (before hook notification)
977 */
978static LRESULT FILEDLG95_InitControls(HWND hwnd)
979{
980 TBBUTTON tbb[] =
981 {
982 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
983 {VIEW_PARENTFOLDER, FCIDM_TB_UPFOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
984 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
985 {VIEW_NEWFOLDER+1, FCIDM_TB_DESKTOP, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
986 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
987 {VIEW_NEWFOLDER, FCIDM_TB_NEWFOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
988 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
989 {VIEW_LIST, FCIDM_TB_SMALLICON, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
990 {VIEW_DETAILS, FCIDM_TB_REPORTVIEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
991 };
992 TBADDBITMAP tba[] =
993 {
994 { HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR },
995 { COMDLG32_hInstance, 800 } // desktop icon
996 };
997
998 RECT rectTB;
999
1000 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1001
1002 TRACE("%p\n", fodInfos);
1003
1004 /* Get the hwnd of the controls */
1005 fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
1006 fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
1007 fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
1008
1009 /* construct the toolbar */
1010 GetWindowRect(GetDlgItem(hwnd,IDC_TOOLBARSTATIC),&rectTB);
1011 MapWindowPoints( 0, hwnd,(LPPOINT)&rectTB,2);
1012
1013 fodInfos->DlgInfos.hwndTB = CreateWindowExA(0, TOOLBARCLASSNAMEA, (LPSTR) NULL,
1014 WS_CHILD | WS_GROUP | TBSTYLE_TOOLTIPS | CCS_NODIVIDER | CCS_NORESIZE,
1015 0, 0, 150, 26, hwnd, (HMENU) IDC_TOOLBAR, COMMDLG_hInstance32, NULL);
1016
1017 SetWindowPos(fodInfos->DlgInfos.hwndTB, 0,
1018 rectTB.left,rectTB.top, rectTB.right-rectTB.left, rectTB.bottom-rectTB.top,
1019 SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
1020
1021 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
1022
1023/* fixme: use TB_LOADIMAGES when implemented */
1024/* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1025 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBITMAP, (WPARAM) 12, (LPARAM) &tba[0]);
1026 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBITMAP, (WPARAM) 1, (LPARAM) &tba[1]);
1027
1028 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBUTTONSA, (WPARAM) 9,(LPARAM) &tbb);
1029 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_AUTOSIZE, 0, 0);
1030
1031 /* Set the window text with the text specified in the OPENFILENAME structure */
1032 if(fodInfos->ofnInfos->lpstrTitle)
1033 {
1034 SetWindowTextA(hwnd,fodInfos->ofnInfos->lpstrTitle);
1035 }
1036 else if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1037 {
1038 SetWindowTextA(hwnd,"Save");
1039 }
1040
1041 /* Initialise the file name edit control */
1042 if(fodInfos->ofnInfos->lpstrFile)
1043 {
1044 LPSTR lpstrFile = PathFindFileNameA(fodInfos->ofnInfos->lpstrFile);
1045 SetDlgItemTextA(hwnd, IDC_FILENAME, lpstrFile);
1046 }
1047
1048 /* Must the open as read only check box be checked ?*/
1049 if(fodInfos->ofnInfos->Flags & OFN_READONLY)
1050 {
1051 SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
1052 }
1053
1054 /* Must the open as read only check box be hid ?*/
1055 if(fodInfos->ofnInfos->Flags & OFN_HIDEREADONLY)
1056 {
1057 ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
1058 }
1059
1060 /* Must the help button be hid ?*/
1061 if (!(fodInfos->ofnInfos->Flags & OFN_SHOWHELP))
1062 {
1063 ShowWindow(GetDlgItem(hwnd, pshHelp), SW_HIDE);
1064 }
1065
1066 /* Resize the height, if open as read only checkbox ad help button
1067 are hidden and we are not using a custom template */
1068 if ( (fodInfos->ofnInfos->Flags & OFN_HIDEREADONLY) &&
1069 (!(fodInfos->ofnInfos->Flags &
1070 (OFN_SHOWHELP|OFN_ENABLETEMPLATE|OFN_ENABLETEMPLATEHANDLE))))
1071 {
1072 RECT rectDlg, rectHelp, rectCancel;
1073 GetWindowRect(hwnd, &rectDlg);
1074 GetWindowRect(GetDlgItem(hwnd, pshHelp), &rectHelp);
1075 GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rectCancel);
1076 /* subtract the height of the help button plus the space between
1077 the help button and the cancel button to the height of the dialog */
1078 SetWindowPos(hwnd, 0, 0, 0, rectDlg.right-rectDlg.left,
1079 (rectDlg.bottom-rectDlg.top) - (rectHelp.bottom - rectCancel.bottom),
1080 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
1081 }
1082
1083 /* change Open to Save FIXME: use resources */
1084 if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1085 {
1086 SetDlgItemTextA(hwnd,IDOK,"&Save");
1087 SetDlgItemTextA(hwnd,IDC_LOOKINSTATIC,"Save &in");
1088 }
1089 return 0;
1090}
1091
1092/***********************************************************************
1093 * FILEDLG95_FillControls
1094 *
1095 * WM_INITDIALOG message handler (after hook notification)
1096 */
1097static LRESULT FILEDLG95_FillControls(HWND hwnd, WPARAM wParam, LPARAM lParam)
1098{
1099 LPITEMIDLIST pidlItemId = NULL;
1100 CHAR *dopstr = NULL;
1101
1102 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) lParam;
1103
1104 TRACE("dir=%s file=%s\n",
1105 fodInfos->ofnInfos->lpstrInitialDir, fodInfos->ofnInfos->lpstrFile);
1106
1107#ifdef __WIN32OS2__
1108 /*@PF
1109 How can Wine miss this?? Very common situation for Windows apps!
1110 If InitialDir is NULL and we have full blown path in lpstrFile we set
1111 directory to it.
1112
1113 Q: What about Unicode?
1114
1115 */
1116
1117 if (fodInfos->ofnInfos->lpstrInitialDir == NULL && fodInfos->ofnInfos->lpstrFile &&
1118 !PathIsRelativeA(fodInfos->ofnInfos->lpstrFile) &&
1119 PathGetDriveNumberA(fodInfos->ofnInfos->lpstrFile) != -1)
1120 {
1121 dopstr = HEAP_strdupA(GetProcessHeap(), 0,fodInfos->ofnInfos->lpstrFile);
1122 *strrchr(dopstr,'\\') = '\0';
1123 fodInfos->ofnInfos->lpstrInitialDir = dopstr;
1124 }
1125#endif
1126
1127 /* Get the initial directory pidl */
1128 if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos->lpstrInitialDir)))
1129 {
1130 char path[MAX_PATH];
1131
1132 GetCurrentDirectoryA(MAX_PATH,path);
1133 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder, path);
1134 }
1135#ifdef __WIN32OS2__
1136 /* @PF Another WINE hole. If lpstrInitialDir is not a dir but a filename
1137 skip it and use current directory. */
1138
1139 else
1140 {
1141 DWORD dwAttr = GetFileAttributesA(fodInfos->ofnInfos->lpstrInitialDir);
1142 if(dwAttr != -1 )
1143 {
1144 if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
1145 {
1146 char path[MAX_PATH];
1147
1148 GetCurrentDirectoryA(MAX_PATH,path);
1149 COMDLG32_SHFree(pidlItemId);
1150 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder, path);
1151 }
1152 }
1153 }
1154#endif
1155 /* Initialise shell objects */
1156 FILEDLG95_SHELL_Init(hwnd);
1157
1158 /* Initialize the Look In combo box */
1159 FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
1160
1161 /* Initialize the filter combo box */
1162 FILEDLG95_FILETYPE_Init(hwnd);
1163
1164 /* Browse to the initial directory */
1165 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId, SBSP_ABSOLUTE);
1166
1167 /* Free pidlItem memory */
1168 COMDLG32_SHFree(pidlItemId);
1169
1170#ifdef __WIN32OS2__
1171 /* Free dopstr */
1172 if (dopstr)
1173 {
1174 fodInfos->ofnInfos->lpstrInitialDir = NULL;
1175 HEAP_free(dopstr);
1176 }
1177#endif
1178 return TRUE;
1179}
1180/***********************************************************************
1181 * FILEDLG95_Clean
1182 *
1183 * Regroups all the cleaning functions of the filedlg
1184 */
1185void FILEDLG95_Clean(HWND hwnd)
1186{
1187 FILEDLG95_FILETYPE_Clean(hwnd);
1188 FILEDLG95_LOOKIN_Clean(hwnd);
1189 FILEDLG95_SHELL_Clean(hwnd);
1190}
1191/***********************************************************************
1192 * FILEDLG95_OnWMCommand
1193 *
1194 * WM_COMMAND message handler
1195 */
1196static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
1197{
1198 WORD wNotifyCode = HIWORD(wParam); /* notification code */
1199 WORD wID = LOWORD(wParam); /* item, control, or accelerator identifier */
1200 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1201
1202 switch(wID)
1203 {
1204 /* OK button */
1205 case IDOK:
1206#ifndef __WIN32OS2__
1207 if(FILEDLG95_OnOpen(hwnd))
1208 SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
1209 break;
1210#else
1211 {
1212 // 20011017 PH
1213 // some apps require the resources to be still there
1214 // for the CDN_ processing.
1215 BOOL fResult = FILEDLG95_OnOpen(hwnd);
1216 if(fResult)
1217 SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
1218 break;
1219 }
1220#endif
1221 /* Cancel button */
1222 case IDCANCEL:
1223 FILEDLG95_Clean(hwnd);
1224 EndDialog(hwnd, FALSE);
1225 break;
1226 /* Filetype combo box */
1227 case IDC_FILETYPE:
1228 FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
1229 break;
1230 /* LookIn combo box */
1231 case IDC_LOOKIN:
1232 FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
1233 break;
1234
1235 /* --- toolbar --- */
1236 /* Up folder button */
1237 case FCIDM_TB_UPFOLDER:
1238 FILEDLG95_SHELL_UpFolder(hwnd);
1239 break;
1240 /* New folder button */
1241 case FCIDM_TB_NEWFOLDER:
1242 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_NEWFOLDER);
1243 break;
1244 /* List option button */
1245 case FCIDM_TB_SMALLICON:
1246 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
1247 break;
1248 /* Details option button */
1249 case FCIDM_TB_REPORTVIEW:
1250 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
1251 break;
1252 /* Details option button */
1253 case FCIDM_TB_DESKTOP:
1254 FILEDLG95_SHELL_BrowseToDesktop(hwnd);
1255 break;
1256
1257 case IDC_FILENAME:
1258 break;
1259
1260 }
1261 /* Do not use the listview selection anymore */
1262 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
1263 return 0;
1264}
1265
1266/***********************************************************************
1267 * FILEDLG95_OnWMGetIShellBrowser
1268 *
1269 * WM_GETISHELLBROWSER message handler
1270 */
1271static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
1272{
1273
1274 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1275
1276 TRACE("\n");
1277
1278 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
1279
1280 return TRUE;
1281}
1282
1283
1284/***********************************************************************
1285 * FILEDLG95_OnOpenMultipleFiles
1286 *
1287 * Handles the opening of multiple files.
1288 *
1289 * FIXME
1290 * check destination buffer size
1291 */
1292BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed)
1293{
1294 CHAR lpstrPathSpec[MAX_PATH] = "";
1295 LPSTR lpstrFile;
1296 UINT nCount, nSizePath;
1297 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1298
1299 TRACE("\n");
1300
1301 lpstrFile = fodInfos->ofnInfos->lpstrFile;
1302 lpstrFile[0] = '\0';
1303
1304 SHGetPathFromIDListA( fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathSpec );
1305
1306 if ( !(fodInfos->ofnInfos->Flags & OFN_NOVALIDATE) &&
1307 ( fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST))
1308 {
1309 LPSTR lpstrTemp = lpstrFileList;
1310
1311 for ( nCount = 0; nCount < nFileCount; nCount++ )
1312 {
1313 LPITEMIDLIST pidl;
1314
1315 pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder, lpstrTemp);
1316 if (!pidl)
1317 {
1318 CHAR lpstrNotFound[100];
1319 CHAR lpstrMsg[100];
1320 CHAR tmp[400];
1321
1322 LoadStringA(COMMDLG_hInstance32, IDS_FILENOTFOUND, lpstrNotFound, 100);
1323 LoadStringA(COMMDLG_hInstance32, IDS_VERIFYFILE, lpstrMsg, 100);
1324
1325 strcpy(tmp, lpstrTemp);
1326 strcat(tmp, "\n");
1327 strcat(tmp, lpstrNotFound);
1328 strcat(tmp, "\n");
1329 strcat(tmp, lpstrMsg);
1330
1331 MessageBoxA(hwnd, tmp, fodInfos->ofnInfos->lpstrTitle, MB_OK | MB_ICONEXCLAMATION);
1332 return FALSE;
1333 }
1334
1335 /* move to the next file in the list of files */
1336 lpstrTemp += strlen(lpstrTemp) + 1;
1337 COMDLG32_SHFree(pidl);
1338 }
1339 }
1340
1341 nSizePath = strlen(lpstrPathSpec);
1342 strcpy( lpstrFile, lpstrPathSpec);
1343 memcpy( lpstrFile + nSizePath + 1, lpstrFileList, sizeUsed );
1344
1345 fodInfos->ofnInfos->nFileOffset = nSizePath + 1;
1346 fodInfos->ofnInfos->nFileExtension = 0;
1347
1348 /* clean and exit */
1349 FILEDLG95_Clean(hwnd);
1350 return EndDialog(hwnd,TRUE);
1351}
1352
1353/***********************************************************************
1354 * FILEDLG95_OnOpen
1355 *
1356 * Ok button WM_COMMAND message handler
1357 *
1358 * If the function succeeds, the return value is nonzero.
1359 */
1360#define ONOPEN_BROWSE 1
1361#define ONOPEN_OPEN 2
1362#define ONOPEN_SEARCH 3
1363static void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
1364{
1365 char strMsgTitle[MAX_PATH];
1366 char strMsgText [MAX_PATH];
1367 if (idCaption)
1368 LoadStringA(COMDLG32_hInstance, idCaption, strMsgTitle, sizeof(strMsgTitle));
1369 else
1370 strMsgTitle[0] = '\0';
1371 LoadStringA(COMDLG32_hInstance, idText, strMsgText, sizeof(strMsgText));
1372 MessageBoxA(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND);
1373}
1374
1375BOOL FILEDLG95_OnOpen(HWND hwnd)
1376{
1377 char * lpstrFileList;
1378 UINT nFileCount = 0;
1379 UINT sizeUsed = 0;
1380 BOOL ret = TRUE;
1381 char lpstrPathAndFile[MAX_PATH];
1382 char lpstrTemp[MAX_PATH];
1383 LPSHELLFOLDER lpsf = NULL;
1384 int nOpenAction;
1385 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1386
1387 TRACE("hwnd=0x%04x\n", hwnd);
1388
1389 /* get the files from the edit control */
1390 nFileCount = FILEDLG95_FILENAME_GetFileNames(hwnd, &lpstrFileList, &sizeUsed);
1391
1392 /* try if the user selected a folder in the shellview */
1393 if(nFileCount == 0)
1394 {
1395 BrowseSelectedFolder(hwnd);
1396 return FALSE;
1397 }
1398
1399 if(nFileCount > 1)
1400 {
1401 ret = FILEDLG95_OnOpenMultipleFiles(hwnd, lpstrFileList, nFileCount, sizeUsed);
1402 goto ret;
1403 }
1404
1405 TRACE("count=%u len=%u file=%s\n", nFileCount, sizeUsed, lpstrFileList);
1406
1407/*
1408 Step 1: Build a complete path name from the current folder and
1409 the filename or path in the edit box.
1410 Special cases:
1411 - the path in the edit box is a root path
1412 (with or without drive letter)
1413 - the edit box contains ".." (or a path with ".." in it)
1414*/
1415
1416 /* Get the current directory name */
1417 if (!SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathAndFile))
1418 {
1419 /* we are in a special folder, default to desktop */
1420 if(FAILED(COMDLG32_SHGetFolderPathA(hwnd, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, 0, 0, lpstrPathAndFile)))
1421 {
1422 /* last fallback */
1423 GetCurrentDirectoryA(MAX_PATH, lpstrPathAndFile);
1424 }
1425 }
1426 PathAddBackslashA(lpstrPathAndFile);
1427
1428 TRACE("current directory=%s\n", lpstrPathAndFile);
1429
1430 /* if the user specifyed a fully qualified path use it */
1431 if(PathIsRelativeA(lpstrFileList))
1432 {
1433 strcat(lpstrPathAndFile, lpstrFileList);
1434 }
1435 else
1436 {
1437 /* does the path have a drive letter? */
1438 if (PathGetDriveNumberA(lpstrFileList) == -1)
1439 strcpy(lpstrPathAndFile+2, lpstrFileList);
1440 else
1441 strcpy(lpstrPathAndFile, lpstrFileList);
1442 }
1443
1444 /* resolve "." and ".." */
1445 PathCanonicalizeA(lpstrTemp, lpstrPathAndFile );
1446 strcpy(lpstrPathAndFile, lpstrTemp);
1447 TRACE("canon=%s\n", lpstrPathAndFile);
1448
1449 MemFree(lpstrFileList);
1450
1451/*
1452 Step 2: here we have a cleaned up path
1453
1454 We have to parse the path step by step to see if we have to browse
1455 to a folder if the path points to a directory or the last
1456 valid element is a directory.
1457
1458 valid variables:
1459 lpstrPathAndFile: cleaned up path
1460 */
1461
1462 nOpenAction = ONOPEN_BROWSE;
1463
1464#ifdef __WIN32OS2__
1465 /* @@@AH 2001-06-02 moved out of !OFN_NONVALIDATE block - needs to be set */
1466 if (FAILED (SHGetDesktopFolder(&lpsf))) return FALSE;
1467#endif
1468
1469 /* dont apply any checks with OFN_NOVALIDATE */
1470 if(!(fodInfos->ofnInfos->Flags & OFN_NOVALIDATE))
1471 {
1472 LPSTR lpszTemp, lpszTemp1;
1473 LPITEMIDLIST pidl = NULL;
1474
1475 /* check for invalid chars */
1476 if(strpbrk(lpstrPathAndFile+3, "/:<>|") != NULL)
1477 {
1478 FILEDLG95_OnOpenMessage(hwnd, IDS_INVALID_FILENAME_TITLE, IDS_INVALID_FILENAME);
1479 ret = FALSE;
1480 goto ret;
1481 }
1482#ifndef __WIN32OS2__
1483 if (FAILED (SHGetDesktopFolder(&lpsf))) return FALSE;
1484#endif
1485 lpszTemp1 = lpszTemp = lpstrPathAndFile;
1486 while (lpszTemp1)
1487 {
1488 LPSHELLFOLDER lpsfChild;
1489 WCHAR lpwstrTemp[MAX_PATH];
1490 DWORD dwEaten, dwAttributes;
1491
1492 lpszTemp = PathFindNextComponentA(lpszTemp);
1493
1494 if (!lpszTemp) break; /* end of path */
1495
1496 if(*lpszTemp)
1497 {
1498 DWORD len = MultiByteToWideChar( CP_ACP, 0, lpszTemp1, lpszTemp - lpszTemp1,
1499 lpwstrTemp, MAX_PATH );
1500 lpwstrTemp[len] = 0;
1501 }
1502 else
1503 {
1504 MultiByteToWideChar( CP_ACP, 0, lpszTemp1, -1,
1505 lpwstrTemp, sizeof(lpwstrTemp)/sizeof(WCHAR) );
1506
1507 /* if the last element is a wildcard do a search */
1508 if(strpbrk(lpszTemp1, "*?") != NULL)
1509 {
1510 nOpenAction = ONOPEN_SEARCH;
1511 break;
1512 }
1513 }
1514 lpszTemp1 = lpszTemp;
1515
1516 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp), debugstr_a(lpszTemp), lpsf);
1517
1518 if(lstrlenW(lpwstrTemp)==2) PathAddBackslashW(lpwstrTemp);
1519
1520 dwAttributes = SFGAO_FOLDER;
1521 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf, hwnd, NULL, lpwstrTemp, &dwEaten, &pidl, &dwAttributes)))
1522 {
1523 /* the path component is valid, we have a pidl of the next path component */
1524 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes, pidl);
1525 if(dwAttributes & SFGAO_FOLDER)
1526 {
1527 if(FAILED(IShellFolder_BindToObject(lpsf, pidl, 0, &IID_IShellFolder, (LPVOID*)&lpsfChild)))
1528 {
1529 ERR("bind to failed\n"); /* should not fail */
1530 break;
1531 }
1532 IShellFolder_Release(lpsf);
1533 lpsf = lpsfChild;
1534 lpsfChild = NULL;
1535 }
1536 else
1537 {
1538 TRACE("value\n");
1539
1540 /* end dialog, return value */
1541 nOpenAction = ONOPEN_OPEN;
1542 break;
1543 }
1544 COMDLG32_SHFree(pidl);
1545 pidl = NULL;
1546 }
1547 else
1548 {
1549 if(*lpszTemp) /* points to trailing null for last path element */
1550 {
1551 if(fodInfos->ofnInfos->Flags & OFN_PATHMUSTEXIST)
1552 {
1553 FILEDLG95_OnOpenMessage(hwnd, 0, IDS_PATHNOTEXISTING);
1554 break;
1555 }
1556 }
1557 else
1558 {
1559 if(fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST)
1560 {
1561 FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
1562 break;
1563 }
1564 }
1565 /* change to the current folder */
1566 nOpenAction = ONOPEN_OPEN;
1567 break;
1568 }
1569 }
1570 if(pidl) COMDLG32_SHFree(pidl);
1571 }
1572#ifdef __WIN32OS2__
1573 else
1574 {
1575 // @@@AH 2001-06-02 when we are in OFN_NOVALIDATE mode, the action
1576 // must be to open the specified file when pressing open button
1577 TRACE("OFN_NOVALIDATE mode, set open action to ONOPEN_OPEN\n");
1578 nOpenAction = ONOPEN_OPEN;
1579 }
1580#endif
1581
1582/*
1583 Step 3: here we have a cleaned up and validated path
1584
1585 valid variables:
1586 lpsf: ShellFolder bound to the rightmost valid path component
1587 lpstrPathAndFile: cleaned up path
1588 nOpenAction: action to do
1589*/
1590 TRACE("end validate sf=%p\n", lpsf);
1591
1592 switch(nOpenAction)
1593 {
1594 case ONOPEN_SEARCH: /* set the current filter to the file mask and refresh */
1595 TRACE("ONOPEN_SEARCH %s\n", lpstrPathAndFile);
1596 {
1597 int iPos;
1598 LPSTR lpszTemp = PathFindFileNameA(lpstrPathAndFile);
1599 DWORD len;
1600
1601 /* replace the current filter */
1602 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1603 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1604 len = MultiByteToWideChar( CP_ACP, 0, lpszTemp, -1, NULL, 0 );
1605 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc(len * sizeof(WCHAR));
1606 MultiByteToWideChar( CP_ACP, 0, lpszTemp, -1,
1607 fodInfos->ShellInfos.lpstrCurrentFilter, len );
1608
1609 /* set the filter cb to the extension when possible */
1610 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB, lpszTemp)))
1611 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB, iPos);
1612 }
1613 /* fall through */
1614 case ONOPEN_BROWSE: /* browse to the highest folder we could bind to */
1615 TRACE("ONOPEN_BROWSE\n");
1616 {
1617 IPersistFolder2 * ppf2;
1618 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf, &IID_IPersistFolder2, (LPVOID*)&ppf2)))
1619 {
1620 LPITEMIDLIST pidlCurrent;
1621 IPersistFolder2_GetCurFolder(ppf2, &pidlCurrent);
1622 IPersistFolder2_Release(ppf2);
1623 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent, fodInfos->ShellInfos.pidlAbsCurrent))
1624 {
1625 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser, pidlCurrent, SBSP_ABSOLUTE);
1626 }
1627 else if( nOpenAction == ONOPEN_SEARCH )
1628 {
1629 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1630 }
1631 COMDLG32_SHFree(pidlCurrent);
1632 }
1633 }
1634 ret = FALSE;
1635 break;
1636 case ONOPEN_OPEN: /* fill in the return struct and close the dialog */
1637 TRACE("ONOPEN_OPEN %s\n", lpstrPathAndFile);
1638 {
1639 /* add default extension */
1640 if (fodInfos->ofnInfos->lpstrDefExt)
1641 {
1642 if (! *PathFindExtensionA(lpstrPathAndFile))
1643 {
1644 /* only add "." in case a default extension does exist */
1645 if (*fodInfos->ofnInfos->lpstrDefExt != '\0')
1646 {
1647 strcat(lpstrPathAndFile, ".");
1648 strcat(lpstrPathAndFile, fodInfos->ofnInfos->lpstrDefExt);
1649 }
1650 }
1651 }
1652
1653 /* Check that the size of the file does not exceed buffer size.
1654 (Allow for extra \0 if OFN_MULTISELECT is set.) */
1655 if(strlen(lpstrPathAndFile) < fodInfos->ofnInfos->nMaxFile -
1656 ((fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT) ? 1 : 0))
1657 {
1658 LPSTR lpszTemp;
1659
1660 /* fill destination buffer */
1661 strcpy(fodInfos->ofnInfos->lpstrFile, lpstrPathAndFile);
1662 if (fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT)
1663 fodInfos->ofnInfos->lpstrFile[strlen(fodInfos->ofnInfos->lpstrFile)
1664 + 1] = '\0';
1665
1666 /* set filename offset */
1667 lpszTemp = PathFindFileNameA(lpstrPathAndFile);
1668 fodInfos->ofnInfos->nFileOffset = lpszTemp - lpstrPathAndFile;
1669
1670 /* set extension offset */
1671 lpszTemp = PathFindExtensionA(lpstrPathAndFile);
1672 fodInfos->ofnInfos->nFileExtension = (*lpszTemp) ? lpszTemp - lpstrPathAndFile + 1 : 0;
1673
1674 /* set the lpstrFileTitle */
1675 if(fodInfos->ofnInfos->lpstrFileTitle)
1676 {
1677 LPSTR lpstrFileTitle = PathFindFileNameA(lpstrPathAndFile);
1678 strncpy(fodInfos->ofnInfos->lpstrFileTitle, lpstrFileTitle, fodInfos->ofnInfos->nMaxFileTitle);
1679 }
1680
1681 /* ask the hook if we can close */
1682 if(IsHooked(fodInfos))
1683 {
1684 /* FIXME we are sending ASCII-structures. Does not work with NT */
1685 /* first old style */
1686 TRACE("---\n");
1687 CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,
1688 fodInfos->DlgInfos.hwndCustomDlg,
1689 fodInfos->HookMsg.fileokstring, 0, (LPARAM)fodInfos->ofnInfos);
1690 if (GetWindowLongA(hwnd, DWL_MSGRESULT))
1691 {
1692 TRACE("cancled\n");
1693 ret = FALSE;
1694 goto ret;
1695 }
1696 }
1697
1698 TRACE("close\n");
1699 FILEDLG95_Clean(hwnd);
1700 ret = EndDialog(hwnd, TRUE);
1701 }
1702 else
1703 {
1704 /* FIXME set error FNERR_BUFFERTOSMALL */
1705 FILEDLG95_Clean(hwnd);
1706 ret = EndDialog(hwnd, FALSE);
1707 }
1708 goto ret;
1709 }
1710 break;
1711 }
1712
1713ret:
1714 if(lpsf) IShellFolder_Release(lpsf);
1715 return ret;
1716}
1717
1718/***********************************************************************
1719 * FILEDLG95_SHELL_Init
1720 *
1721 * Initialisation of the shell objects
1722 */
1723static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1724{
1725 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1726
1727 TRACE("\n");
1728
1729 /*
1730 * Initialisation of the FileOpenDialogInfos structure
1731 */
1732
1733 /* Shell */
1734
1735 /*ShellInfos */
1736 fodInfos->ShellInfos.hwndOwner = hwnd;
1737
1738 /* Disable multi-select if flag not set */
1739 if (!(fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT))
1740 {
1741 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_SINGLESEL;
1742 }
1743 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1744 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1745
1746 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1747 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1748 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1749
1750 /* Construct the IShellBrowser interface */
1751 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1752
1753 return NOERROR;
1754}
1755
1756/***********************************************************************
1757 * FILEDLG95_SHELL_ExecuteCommand
1758 *
1759 * Change the folder option and refresh the view
1760 * If the function succeeds, the return value is nonzero.
1761 */
1762static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1763{
1764 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1765
1766 IContextMenu * pcm;
1767 TRACE("(0x%08x,%p)\n", hwnd, lpVerb);
1768
1769 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1770 SVGIO_BACKGROUND,
1771 &IID_IContextMenu,
1772 (LPVOID*)&pcm)))
1773 {
1774 CMINVOKECOMMANDINFO ci;
1775 ZeroMemory(&ci, sizeof(CMINVOKECOMMANDINFO));
1776 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1777 ci.lpVerb = lpVerb;
1778 ci.hwnd = hwnd;
1779
1780 IContextMenu_InvokeCommand(pcm, &ci);
1781 IContextMenu_Release(pcm);
1782 }
1783
1784 return FALSE;
1785}
1786
1787/***********************************************************************
1788 * FILEDLG95_SHELL_UpFolder
1789 *
1790 * Browse to the specified object
1791 * If the function succeeds, the return value is nonzero.
1792 */
1793static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1794{
1795 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1796
1797 TRACE("\n");
1798
1799 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1800 NULL,
1801 SBSP_PARENT)))
1802 {
1803 return TRUE;
1804 }
1805 return FALSE;
1806}
1807
1808/***********************************************************************
1809 * FILEDLG95_SHELL_BrowseToDesktop
1810 *
1811 * Browse to the Desktop
1812 * If the function succeeds, the return value is nonzero.
1813 */
1814static BOOL FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd)
1815{
1816 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1817 LPITEMIDLIST pidl;
1818 HRESULT hres;
1819
1820 TRACE("\n");
1821
1822 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidl);
1823 hres = IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser, pidl, SBSP_ABSOLUTE);
1824 COMDLG32_SHFree(pidl);
1825 return SUCCEEDED(hres);
1826}
1827/***********************************************************************
1828 * FILEDLG95_SHELL_Clean
1829 *
1830 * Cleans the memory used by shell objects
1831 */
1832static void FILEDLG95_SHELL_Clean(HWND hwnd)
1833{
1834 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1835
1836 TRACE("\n");
1837
1838 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
1839
1840 /* clean Shell interfaces */
1841 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1842 IShellView_Release(fodInfos->Shell.FOIShellView);
1843 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1844 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1845 if (fodInfos->Shell.FOIDataObject)
1846 IDataObject_Release(fodInfos->Shell.FOIDataObject);
1847}
1848
1849/***********************************************************************
1850 * FILEDLG95_FILETYPE_Init
1851 *
1852 * Initialisation of the file type combo box
1853 */
1854static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1855{
1856 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1857
1858 TRACE("\n");
1859
1860 if(fodInfos->ofnInfos->lpstrFilter)
1861 {
1862 int nFilters = 0; /* number of filters */
1863 LPSTR lpstrFilter;
1864 LPCSTR lpstrPos = fodInfos->ofnInfos->lpstrFilter;
1865
1866 for(;;)
1867 {
1868 /* filter is a list... title\0ext\0......\0\0
1869 * Set the combo item text to the title and the item data
1870 * to the ext
1871 */
1872 LPCSTR lpstrDisplay;
1873 LPSTR lpstrExt;
1874
1875 /* Get the title */
1876 if(! *lpstrPos) break; /* end */
1877 lpstrDisplay = lpstrPos;
1878 lpstrPos += strlen(lpstrPos) + 1;
1879
1880 /* Copy the extensions */
1881 if (! *lpstrPos) return E_FAIL; /* malformed filter */
1882 if (!(lpstrExt = (LPSTR) MemAlloc(strlen(lpstrPos)+1))) return E_FAIL;
1883 strcpy(lpstrExt,lpstrPos);
1884 lpstrPos += strlen(lpstrPos) + 1;
1885
1886 /* Add the item at the end of the combo */
1887 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB, lpstrDisplay);
1888 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB, nFilters, lpstrExt);
1889 nFilters++;
1890 }
1891 /*
1892 * Set the current filter to the one specified
1893 * in the initialisation structure
1894 * FIXME: lpstrCustomFilter not handled at all
1895 */
1896
1897 /* set default filter index */
1898 if(fodInfos->ofnInfos->nFilterIndex == 0 && fodInfos->ofnInfos->lpstrCustomFilter == NULL)
1899 fodInfos->ofnInfos->nFilterIndex = 1;
1900
1901 /* First, check to make sure our index isn't out of bounds. */
1902 if ( fodInfos->ofnInfos->nFilterIndex > nFilters )
1903 fodInfos->ofnInfos->nFilterIndex = nFilters;
1904
1905 /* Set the current index selection. */
1906 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB, fodInfos->ofnInfos->nFilterIndex-1);
1907
1908 /* Get the corresponding text string from the combo box. */
1909 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1910 fodInfos->ofnInfos->nFilterIndex-1);
1911
1912 if ((INT)lpstrFilter == CB_ERR) /* control is empty */
1913 lpstrFilter = NULL;
1914
1915 if(lpstrFilter)
1916 {
1917 DWORD len;
1918 _strlwr(lpstrFilter); /* lowercase */
1919 len = MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1, NULL, 0 );
1920 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc( len * sizeof(WCHAR) );
1921 MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1,
1922 fodInfos->ShellInfos.lpstrCurrentFilter, len );
1923 }
1924 }
1925 return NOERROR;
1926}
1927
1928/***********************************************************************
1929 * FILEDLG95_FILETYPE_OnCommand
1930 *
1931 * WM_COMMAND of the file type combo box
1932 * If the function succeeds, the return value is nonzero.
1933 */
1934static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1935{
1936 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1937
1938 switch(wNotifyCode)
1939 {
1940 case CBN_SELENDOK:
1941 {
1942 LPSTR lpstrFilter;
1943
1944 /* Get the current item of the filetype combo box */
1945 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1946
1947 /* set the current filter index - indexed from 1 */
1948 fodInfos->ofnInfos->nFilterIndex = iItem + 1;
1949
1950 /* Set the current filter with the current selection */
1951 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1952 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1953
1954 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1955 iItem);
1956 if((int)lpstrFilter != CB_ERR)
1957 {
1958 DWORD len;
1959 _strlwr(lpstrFilter); /* lowercase */
1960 len = MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1, NULL, 0 );
1961 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc( len * sizeof(WCHAR) );
1962 MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1,
1963 fodInfos->ShellInfos.lpstrCurrentFilter, len );
1964 SendCustomDlgNotificationMessage(hwnd,CDN_TYPECHANGE);
1965 }
1966
1967 /* Refresh the actual view to display the included items*/
1968 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1969 }
1970 }
1971 return FALSE;
1972}
1973/***********************************************************************
1974 * FILEDLG95_FILETYPE_SearchExt
1975 *
1976 * searches for a extension in the filetype box
1977 */
1978static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPCSTR lpstrExt)
1979{
1980 int i, iCount = CBGetCount(hwnd);
1981
1982 TRACE("%s\n", lpstrExt);
1983
1984 if(iCount != CB_ERR)
1985 {
1986 for(i=0;i<iCount;i++)
1987 {
1988 if(!strcasecmp(lpstrExt,(LPSTR)CBGetItemDataPtr(hwnd,i)))
1989 return i;
1990 }
1991 }
1992 return -1;
1993}
1994
1995/***********************************************************************
1996 * FILEDLG95_FILETYPE_Clean
1997 *
1998 * Clean the memory used by the filetype combo box
1999 */
2000static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
2001{
2002 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2003 int iPos;
2004 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
2005
2006 TRACE("\n");
2007
2008 /* Delete each string of the combo and their associated data */
2009 if(iCount != CB_ERR)
2010 {
2011 for(iPos = iCount-1;iPos>=0;iPos--)
2012 {
2013 MemFree((LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos));
2014 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
2015 }
2016 }
2017 /* Current filter */
2018 if(fodInfos->ShellInfos.lpstrCurrentFilter)
2019 MemFree(fodInfos->ShellInfos.lpstrCurrentFilter);
2020
2021}
2022
2023/***********************************************************************
2024 * FILEDLG95_LOOKIN_Init
2025 *
2026 * Initialisation of the look in combo box
2027 */
2028static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
2029{
2030 IShellFolder *psfRoot, *psfDrives;
2031 IEnumIDList *lpeRoot, *lpeDrives;
2032 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
2033
2034 LookInInfos *liInfos = MemAlloc(sizeof(LookInInfos));
2035
2036 TRACE("\n");
2037
2038 liInfos->iMaxIndentation = 0;
2039
2040 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
2041
2042 /* set item height for both text field and listbox */
2043 CBSetItemHeight(hwndCombo,-1,GetSystemMetrics(SM_CYSMICON));
2044 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
2045
2046 /* Initialise data of Desktop folder */
2047 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
2048 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
2049 COMDLG32_SHFree(pidlTmp);
2050
2051 SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
2052
2053 SHGetDesktopFolder(&psfRoot);
2054
2055 if (psfRoot)
2056 {
2057 /* enumerate the contents of the desktop */
2058 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
2059 {
2060 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
2061 {
2062 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
2063
2064 /* special handling for CSIDL_DRIVES */
2065 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
2066 {
2067 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
2068 {
2069 /* enumerate the drives */
2070 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
2071 {
2072 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
2073 {
2074 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
2075 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
2076 COMDLG32_SHFree(pidlAbsTmp);
2077 COMDLG32_SHFree(pidlTmp1);
2078 }
2079 IEnumIDList_Release(lpeDrives);
2080 }
2081 IShellFolder_Release(psfDrives);
2082 }
2083 }
2084 COMDLG32_SHFree(pidlTmp);
2085 }
2086 IEnumIDList_Release(lpeRoot);
2087 }
2088 }
2089
2090 IShellFolder_Release(psfRoot);
2091 COMDLG32_SHFree(pidlDrives);
2092 return NOERROR;
2093}
2094
2095/***********************************************************************
2096 * FILEDLG95_LOOKIN_DrawItem
2097 *
2098 * WM_DRAWITEM message handler
2099 */
2100static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
2101{
2102 COLORREF crWin = GetSysColor(COLOR_WINDOW);
2103 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
2104 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
2105 RECT rectText;
2106 RECT rectIcon;
2107 SHFILEINFOA sfi;
2108 HIMAGELIST ilItemImage;
2109 int iIndentation;
2110 TEXTMETRICA tm;
2111 LPSFOLDER tmpFolder;
2112
2113
2114 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
2115
2116 TRACE("\n");
2117
2118 if(pDIStruct->itemID == -1)
2119 return 0;
2120
2121 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
2122 pDIStruct->itemID)))
2123 return 0;
2124
2125
2126 if(pDIStruct->itemID == liInfos->uSelectedItem)
2127 {
2128 ilItemImage = (HIMAGELIST) SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2129 0,
2130 &sfi,
2131 sizeof (SHFILEINFOA),
2132 SHGFI_PIDL | SHGFI_SMALLICON |
2133 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
2134 SHGFI_DISPLAYNAME );
2135 }
2136 else
2137 {
2138 ilItemImage = (HIMAGELIST) SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2139 0,
2140 &sfi,
2141 sizeof (SHFILEINFOA),
2142 SHGFI_PIDL | SHGFI_SMALLICON |
2143 SHGFI_SYSICONINDEX |
2144 SHGFI_DISPLAYNAME);
2145 }
2146
2147 /* Is this item selected ? */
2148 if(pDIStruct->itemState & ODS_SELECTED)
2149 {
2150 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
2151 SetBkColor(pDIStruct->hDC,crHighLight);
2152 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
2153 }
2154 else
2155 {
2156 SetTextColor(pDIStruct->hDC,crText);
2157 SetBkColor(pDIStruct->hDC,crWin);
2158 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
2159 }
2160
2161 /* Do not indent item if drawing in the edit of the combo */
2162 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
2163 {
2164 iIndentation = 0;
2165 ilItemImage = (HIMAGELIST) SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2166 0,
2167 &sfi,
2168 sizeof (SHFILEINFOA),
2169 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
2170 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
2171
2172 }
2173 else
2174 {
2175 iIndentation = tmpFolder->m_iIndent;
2176 }
2177 /* Draw text and icon */
2178
2179 /* Initialise the icon display area */
2180 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
2181 rectIcon.top = pDIStruct->rcItem.top;
2182 rectIcon.right = rectIcon.left + ICONWIDTH;
2183 rectIcon.bottom = pDIStruct->rcItem.bottom;
2184
2185 /* Initialise the text display area */
2186 GetTextMetricsA(pDIStruct->hDC, &tm);
2187 rectText.left = rectIcon.right;
2188 rectText.top =
2189 (pDIStruct->rcItem.top + pDIStruct->rcItem.bottom - tm.tmHeight) / 2;
2190 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
2191 rectText.bottom =
2192 (pDIStruct->rcItem.top + pDIStruct->rcItem.bottom + tm.tmHeight) / 2;
2193
2194 /* Draw the icon from the image list */
2195 ImageList_Draw(ilItemImage,
2196 sfi.iIcon,
2197 pDIStruct->hDC,
2198 rectIcon.left,
2199 rectIcon.top,
2200 ILD_TRANSPARENT );
2201
2202 /* Draw the associated text */
2203 if(sfi.szDisplayName)
2204 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
2205
2206
2207 return NOERROR;
2208}
2209
2210/***********************************************************************
2211 * FILEDLG95_LOOKIN_OnCommand
2212 *
2213 * LookIn combo box WM_COMMAND message handler
2214 * If the function succeeds, the return value is nonzero.
2215 */
2216static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
2217{
2218 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2219
2220 TRACE("%p\n", fodInfos);
2221
2222 switch(wNotifyCode)
2223 {
2224 case CBN_SELENDOK:
2225 {
2226 LPSFOLDER tmpFolder;
2227 int iItem;
2228
2229 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
2230
2231 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
2232 iItem)))
2233 return FALSE;
2234
2235
2236 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
2237 tmpFolder->pidlItem,
2238 SBSP_ABSOLUTE)))
2239 {
2240 return TRUE;
2241 }
2242 break;
2243 }
2244
2245 }
2246 return FALSE;
2247}
2248
2249/***********************************************************************
2250 * FILEDLG95_LOOKIN_AddItem
2251 *
2252 * Adds an absolute pidl item to the lookin combo box
2253 * returns the index of the inserted item
2254 */
2255static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
2256{
2257 LPITEMIDLIST pidlNext;
2258 SHFILEINFOA sfi;
2259 SFOLDER *tmpFolder;
2260 LookInInfos *liInfos;
2261
2262 TRACE("%08x\n", iInsertId);
2263
2264 if(!pidl)
2265 return -1;
2266
2267 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
2268 return -1;
2269
2270 tmpFolder = MemAlloc(sizeof(SFOLDER));
2271 tmpFolder->m_iIndent = 0;
2272
2273 /* Calculate the indentation of the item in the lookin*/
2274 pidlNext = pidl;
2275 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
2276 {
2277 tmpFolder->m_iIndent++;
2278 }
2279
2280 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl); /* FIXME: memory leak*/
2281
2282 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
2283 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
2284
2285 sfi.dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
2286 SHGetFileInfoA((LPSTR)pidl,
2287 0,
2288 &sfi,
2289 sizeof(sfi),
2290 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
2291 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES | SHGFI_ATTR_SPECIFIED);
2292
2293 TRACE("-- Add %s attr=%08lx\n", sfi.szDisplayName, sfi.dwAttributes);
2294
2295 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
2296 {
2297 int iItemID;
2298
2299 TRACE("-- Add %s at %u\n", sfi.szDisplayName, tmpFolder->m_iIndent);
2300
2301 /* Add the item at the end of the list */
2302 if(iInsertId < 0)
2303 {
2304 iItemID = CBAddString(hwnd,sfi.szDisplayName);
2305 }
2306 /* Insert the item at the iInsertId position*/
2307 else
2308 {
2309 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
2310 }
2311
2312 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
2313 return iItemID;
2314 }
2315
2316 MemFree( tmpFolder );
2317 return -1;
2318
2319}
2320
2321/***********************************************************************
2322 * FILEDLG95_LOOKIN_InsertItemAfterParent
2323 *
2324 * Insert an item below its parent
2325 */
2326static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
2327{
2328
2329 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
2330 int iParentPos;
2331
2332 TRACE("\n");
2333
2334 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
2335
2336 if(iParentPos < 0)
2337 {
2338 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
2339 }
2340
2341 /* Free pidlParent memory */
2342 COMDLG32_SHFree((LPVOID)pidlParent);
2343
2344 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
2345}
2346
2347/***********************************************************************
2348 * FILEDLG95_LOOKIN_SelectItem
2349 *
2350 * Adds an absolute pidl item to the lookin combo box
2351 * returns the index of the inserted item
2352 */
2353int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
2354{
2355 int iItemPos;
2356 LookInInfos *liInfos;
2357
2358 TRACE("\n");
2359
2360 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
2361
2362 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2363
2364 if(iItemPos < 0)
2365 {
2366 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
2367 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
2368 }
2369
2370 else
2371 {
2372 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2373 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
2374 {
2375 int iRemovedItem;
2376
2377 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
2378 break;
2379 if(iRemovedItem < iItemPos)
2380 iItemPos--;
2381 }
2382 }
2383
2384 CBSetCurSel(hwnd,iItemPos);
2385 liInfos->uSelectedItem = iItemPos;
2386
2387 return 0;
2388
2389}
2390
2391/***********************************************************************
2392 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2393 *
2394 * Remove the item with an expansion level over iExpansionLevel
2395 */
2396static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
2397{
2398 int iItemPos;
2399
2400 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2401
2402 TRACE("\n");
2403
2404 if(liInfos->iMaxIndentation <= 2)
2405 return -1;
2406
2407 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
2408 {
2409 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2410 COMDLG32_SHFree(tmpFolder->pidlItem);
2411 MemFree(tmpFolder);
2412 CBDeleteString(hwnd,iItemPos);
2413 liInfos->iMaxIndentation--;
2414
2415 return iItemPos;
2416 }
2417
2418 return -1;
2419}
2420
2421/***********************************************************************
2422 * FILEDLG95_LOOKIN_SearchItem
2423 *
2424 * Search for pidl in the lookin combo box
2425 * returns the index of the found item
2426 */
2427static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2428{
2429 int i = 0;
2430 int iCount = CBGetCount(hwnd);
2431
2432 TRACE("0x%08x 0x%x\n",searchArg, iSearchMethod);
2433
2434 if (iCount != CB_ERR)
2435 {
2436 for(;i<iCount;i++)
2437 {
2438 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2439
2440 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2441 return i;
2442 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2443 return i;
2444 }
2445 }
2446
2447 return -1;
2448}
2449
2450/***********************************************************************
2451 * FILEDLG95_LOOKIN_Clean
2452 *
2453 * Clean the memory used by the lookin combo box
2454 */
2455static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2456{
2457 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2458 int iPos;
2459 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2460
2461 TRACE("\n");
2462
2463 /* Delete each string of the combo and their associated data */
2464 if (iCount != CB_ERR)
2465 {
2466 for(iPos = iCount-1;iPos>=0;iPos--)
2467 {
2468 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos);
2469 COMDLG32_SHFree(tmpFolder->pidlItem);
2470 MemFree(tmpFolder);
2471 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2472 }
2473 }
2474
2475 /* LookInInfos structure */
2476 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2477
2478}
2479/***********************************************************************
2480 * FILEDLG95_FILENAME_FillFromSelection
2481 *
2482 * fills the edit box from the cached DataObject
2483 */
2484void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd)
2485{
2486 FileOpenDlgInfos *fodInfos;
2487 LPITEMIDLIST pidl;
2488 UINT nFiles = 0, nFileToOpen, nFileSelected, nLength = 0;
2489 char lpstrTemp[MAX_PATH];
2490 LPSTR lpstrAllFile = NULL, lpstrCurrFile = NULL;
2491
2492 TRACE("\n");
2493 fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2494
2495 /* Count how many files we have */
2496 nFileSelected = GetNumSelected( fodInfos->Shell.FOIDataObject );
2497
2498 /* calculate the string length, count files */
2499 if (nFileSelected >= 1)
2500 {
2501 nLength += 3; /* first and last quotes, trailing \0 */
2502 for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
2503 {
2504 pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
2505
2506 if (pidl)
2507 {
2508 /* get the total length of the selected file names*/
2509 lpstrTemp[0] = '\0';
2510 GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER, lpstrTemp );
2511
2512 if ( ! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl) ) /* Ignore folders */
2513 {
2514 nLength += strlen( lpstrTemp ) + 3;
2515 nFiles++;
2516 }
2517 COMDLG32_SHFree( pidl );
2518 }
2519 }
2520 }
2521
2522 /* allocate the buffer */
2523 if (nFiles <= 1) nLength = MAX_PATH;
2524 lpstrAllFile = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength);
2525 lpstrAllFile[0] = '\0';
2526
2527 /* Generate the string for the edit control */
2528 if(nFiles >= 1)
2529 {
2530 lpstrCurrFile = lpstrAllFile;
2531 for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
2532 {
2533 pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
2534
2535 if (pidl)
2536 {
2537 /* get the file name */
2538 lpstrTemp[0] = '\0';
2539 GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER, lpstrTemp );
2540
2541 if (! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl)) /* Ignore folders */
2542 {
2543 if ( nFiles > 1)
2544 {
2545 *lpstrCurrFile++ = '\"';
2546 strcpy( lpstrCurrFile, lpstrTemp );
2547 lpstrCurrFile += strlen( lpstrTemp );
2548 strcpy( lpstrCurrFile, "\" " );
2549 lpstrCurrFile += 2;
2550 }
2551 else
2552 {
2553 strcpy( lpstrAllFile, lpstrTemp );
2554 }
2555 }
2556 COMDLG32_SHFree( (LPVOID) pidl );
2557 }
2558 }
2559 }
2560#ifdef __WIN32OS2__
2561 //Selecting a directory previously erased the last selected file
2562 if(nFiles) {
2563 SetWindowTextA( fodInfos->DlgInfos.hwndFileName, lpstrAllFile );
2564 }
2565#else
2566 SetWindowTextA( fodInfos->DlgInfos.hwndFileName, lpstrAllFile );
2567#endif
2568 HeapFree(GetProcessHeap(),0, lpstrAllFile );
2569}
2570
2571
2572/* copied from shell32 to avoid linking to it */
2573static HRESULT COMDLG32_StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
2574{
2575 switch (src->uType)
2576 {
2577 case STRRET_WSTR:
2578 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
2579 COMDLG32_SHFree(src->u.pOleStr);
2580 break;
2581
2582 case STRRET_CSTRA:
2583 lstrcpynA((LPSTR)dest, src->u.cStr, len);
2584 break;
2585
2586 case STRRET_OFFSETA:
2587 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
2588 break;
2589
2590 default:
2591 FIXME("unknown type!\n");
2592 if (len)
2593 {
2594 *(LPSTR)dest = '\0';
2595 }
2596 return(FALSE);
2597 }
2598 return S_OK;
2599}
2600
2601/***********************************************************************
2602 * FILEDLG95_FILENAME_GetFileNames
2603 *
2604 * copies the filenames to a 0-delimited string list (A\0B\0C\0\0)
2605 */
2606int FILEDLG95_FILENAME_GetFileNames (HWND hwnd, LPSTR * lpstrFileList, UINT * sizeUsed)
2607{
2608 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2609 UINT nStrCharCount = 0; /* index in src buffer */
2610 UINT nFileIndex = 0; /* index in dest buffer */
2611 UINT nFileCount = 0; /* number of files */
2612 UINT nStrLen = 0; /* length of string in edit control */
2613 LPSTR lpstrEdit; /* buffer for string from edit control */
2614
2615 TRACE("\n");
2616
2617 /* get the filenames from the edit control */
2618 nStrLen = SendMessageA(fodInfos->DlgInfos.hwndFileName, WM_GETTEXTLENGTH, 0, 0);
2619 lpstrEdit = MemAlloc(nStrLen+1);
2620 GetDlgItemTextA(hwnd, IDC_FILENAME, lpstrEdit, nStrLen+1);
2621
2622 TRACE("nStrLen=%u str=%s\n", nStrLen, lpstrEdit);
2623
2624 /* we might get single filename without any '"',
2625 * so we need nStrLen + terminating \0 + end-of-list \0 */
2626 *lpstrFileList = MemAlloc(nStrLen+2);
2627 *sizeUsed = 0;
2628
2629 /* build 0-delimited file list from filenames */
2630 while ( nStrCharCount <= nStrLen )
2631 {
2632 if ( lpstrEdit[nStrCharCount]=='"' )
2633 {
2634 nStrCharCount++;
2635 while ((lpstrEdit[nStrCharCount]!='"') && (nStrCharCount <= nStrLen))
2636 {
2637 (*lpstrFileList)[nFileIndex++] = lpstrEdit[nStrCharCount];
2638 (*sizeUsed)++;
2639 nStrCharCount++;
2640 }
2641 (*lpstrFileList)[nFileIndex++] = '\0';
2642 (*sizeUsed)++;
2643 nFileCount++;
2644 }
2645 nStrCharCount++;
2646 }
2647
2648 /* single, unquoted string */
2649 if ((nStrLen > 0) && (*sizeUsed == 0) )
2650 {
2651 strcpy(*lpstrFileList, lpstrEdit);
2652 nFileIndex = strlen(lpstrEdit) + 1;
2653 (*sizeUsed) = nFileIndex;
2654 nFileCount = 1;
2655 }
2656
2657 /* trailing \0 */
2658 (*lpstrFileList)[nFileIndex] = '\0';
2659 (*sizeUsed)++;
2660
2661 MemFree(lpstrEdit);
2662 return nFileCount;
2663}
2664
2665#define SETDefFormatEtc(fe,cf,med) \
2666{ \
2667 (fe).cfFormat = cf;\
2668 (fe).dwAspect = DVASPECT_CONTENT; \
2669 (fe).ptd =NULL;\
2670 (fe).tymed = med;\
2671 (fe).lindex = -1;\
2672};
2673
2674/*
2675 * DATAOBJECT Helper functions
2676 */
2677
2678/***********************************************************************
2679 * COMCTL32_ReleaseStgMedium
2680 *
2681 * like ReleaseStgMedium from ole32
2682 */
2683static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium)
2684{
2685 if(medium.pUnkForRelease)
2686 {
2687 IUnknown_Release(medium.pUnkForRelease);
2688 }
2689 else
2690 {
2691 GlobalUnlock(medium.u.hGlobal);
2692 GlobalFree(medium.u.hGlobal);
2693 }
2694}
2695
2696/***********************************************************************
2697 * GetPidlFromDataObject
2698 *
2699 * Return pidl(s) by number from the cached DataObject
2700 *
2701 * nPidlIndex=0 gets the fully qualified root path
2702 */
2703LPITEMIDLIST GetPidlFromDataObject ( IDataObject *doSelected, UINT nPidlIndex)
2704{
2705
2706 STGMEDIUM medium;
2707 FORMATETC formatetc;
2708 LPITEMIDLIST pidl = NULL;
2709
2710 TRACE("sv=%p index=%u\n", doSelected, nPidlIndex);
2711
2712 /* Set the FORMATETC structure*/
2713 SETDefFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
2714
2715 /* Get the pidls from IDataObject */
2716 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
2717 {
2718 LPIDA cida = GlobalLock(medium.u.hGlobal);
2719 if(nPidlIndex <= cida->cidl)
2720 {
2721 pidl = COMDLG32_PIDL_ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[nPidlIndex]]));
2722 }
2723 COMCTL32_ReleaseStgMedium(medium);
2724 }
2725 return pidl;
2726}
2727
2728/***********************************************************************
2729 * GetNumSelected
2730 *
2731 * Return the number of selected items in the DataObject.
2732 *
2733*/
2734UINT GetNumSelected( IDataObject *doSelected )
2735{
2736 UINT retVal = 0;
2737 STGMEDIUM medium;
2738 FORMATETC formatetc;
2739
2740 TRACE("sv=%p\n", doSelected);
2741
2742 if (!doSelected) return 0;
2743
2744 /* Set the FORMATETC structure*/
2745 SETDefFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
2746
2747 /* Get the pidls from IDataObject */
2748 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
2749 {
2750 LPIDA cida = GlobalLock(medium.u.hGlobal);
2751 retVal = cida->cidl;
2752 COMCTL32_ReleaseStgMedium(medium);
2753 return retVal;
2754 }
2755 return 0;
2756}
2757
2758/*
2759 * TOOLS
2760 */
2761
2762/***********************************************************************
2763 * GetName
2764 *
2765 * Get the pidl's display name (relative to folder) and
2766 * put it in lpstrFileName.
2767 *
2768 * Return NOERROR on success,
2769 * E_FAIL otherwise
2770 */
2771
2772HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2773{
2774 STRRET str;
2775 HRESULT hRes;
2776
2777 TRACE("sf=%p pidl=%p\n", lpsf, pidl);
2778
2779 if(!lpsf)
2780 {
2781 HRESULT hRes;
2782 SHGetDesktopFolder(&lpsf);
2783 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2784 IShellFolder_Release(lpsf);
2785 return hRes;
2786 }
2787
2788 /* Get the display name of the pidl relative to the folder */
2789 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf, pidl, dwFlags, &str)))
2790 {
2791 return COMDLG32_StrRetToStrNA(lpstrFileName, MAX_PATH, &str, pidl);
2792 }
2793 return E_FAIL;
2794}
2795
2796/***********************************************************************
2797 * GetShellFolderFromPidl
2798 *
2799 * pidlRel is the item pidl relative
2800 * Return the IShellFolder of the absolute pidl
2801 */
2802IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2803{
2804 IShellFolder *psf = NULL,*psfParent;
2805
2806 TRACE("%p\n", pidlAbs);
2807
2808 if(SUCCEEDED(SHGetDesktopFolder(&psfParent)))
2809 {
2810 psf = psfParent;
2811 if(pidlAbs && pidlAbs->mkid.cb)
2812 {
2813 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2814 {
2815 IShellFolder_Release(psfParent);
2816 return psf;
2817 }
2818 }
2819 /* return the desktop */
2820 return psfParent;
2821 }
2822 return NULL;
2823}
2824
2825/***********************************************************************
2826 * GetParentPidl
2827 *
2828 * Return the LPITEMIDLIST to the parent of the pidl in the list
2829 */
2830LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2831{
2832 LPITEMIDLIST pidlParent;
2833
2834 TRACE("%p\n", pidl);
2835
2836 pidlParent = COMDLG32_PIDL_ILClone(pidl);
2837 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2838
2839 return pidlParent;
2840}
2841
2842/***********************************************************************
2843 * GetPidlFromName
2844 *
2845 * returns the pidl of the file name relative to folder
2846 * NULL if an error occurred
2847 */
2848LPITEMIDLIST GetPidlFromName(IShellFolder *lpsf,LPCSTR lpcstrFileName)
2849{
2850 LPITEMIDLIST pidl;
2851 ULONG ulEaten;
2852 WCHAR lpwstrDirName[MAX_PATH];
2853
2854 TRACE("sf=%p file=%s\n", lpsf, lpcstrFileName);
2855
2856 if(!lpcstrFileName) return NULL;
2857 if(!*lpcstrFileName) return NULL;
2858
2859 MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpcstrFileName,-1,(LPWSTR)lpwstrDirName,MAX_PATH);
2860
2861 if(!lpsf)
2862 {
2863 SHGetDesktopFolder(&lpsf);
2864 pidl = GetPidlFromName(lpsf, lpcstrFileName);
2865 IShellFolder_Release(lpsf);
2866 }
2867 else
2868 {
2869 IShellFolder_ParseDisplayName(lpsf, 0, NULL, (LPWSTR)lpwstrDirName, &ulEaten, &pidl, NULL);
2870 }
2871 return pidl;
2872}
2873
2874/*
2875*/
2876BOOL IsPidlFolder (LPSHELLFOLDER psf, LPITEMIDLIST pidl)
2877{
2878 ULONG uAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
2879 HRESULT ret;
2880
2881 TRACE("%p, %p\n", psf, pidl);
2882
2883 ret = IShellFolder_GetAttributesOf( psf, 1, &pidl, &uAttr );
2884
2885 TRACE("-- 0x%08lx 0x%08lx\n", uAttr, ret);
2886 /* see documentation shell 4.1*/
2887 return uAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
2888}
2889
2890/***********************************************************************
2891 * BrowseSelectedFolder
2892 */
2893static BOOL BrowseSelectedFolder(HWND hwnd)
2894{
2895 BOOL bBrowseSelFolder = FALSE;
2896 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2897
2898 TRACE("\n");
2899
2900 if (GetNumSelected(fodInfos->Shell.FOIDataObject) == 1)
2901 {
2902 LPITEMIDLIST pidlSelection;
2903
2904 /* get the file selected */
2905 pidlSelection = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, 1);
2906 if (IsPidlFolder (fodInfos->Shell.FOIShellFolder, pidlSelection))
2907 {
2908 if ( FAILED( IShellBrowser_BrowseObject( fodInfos->Shell.FOIShellBrowser,
2909 pidlSelection, SBSP_RELATIVE ) ) )
2910 {
2911 MessageBoxA( hwnd, "Path does not exist", fodInfos->ofnInfos->lpstrTitle,
2912 MB_OK | MB_ICONEXCLAMATION );
2913 }
2914
2915 bBrowseSelFolder = TRUE;
2916 }
2917 COMDLG32_SHFree( pidlSelection );
2918 }
2919
2920 return bBrowseSelFolder;
2921}
2922
2923/*
2924 * Memory allocation methods */
2925static void *MemAlloc(UINT size)
2926{
2927 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2928}
2929
2930static void MemFree(void *mem)
2931{
2932 if(mem)
2933 {
2934 HeapFree(GetProcessHeap(),0,mem);
2935 }
2936}
2937
Note: See TracBrowser for help on using the repository browser.