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

Last change on this file since 8596 was 8279, checked in by sandervl, 24 years ago

PF: If application specifies full path in file dialog structure (and initial dir string is NULL), then change to the directory.

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