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

Last change on this file since 8889 was 8612, checked in by sandervl, 23 years ago

* empty log message *

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 if (fodInfos->ofnInfos->lpstrInitialDir == NULL && fodInfos->ofnInfos->lpstrFile &&
1117 !PathIsRelativeA(fodInfos->ofnInfos->lpstrFile) &&
1118 PathGetDriveNumberA(fodInfos->ofnInfos->lpstrFile) != -1)
1119 {
1120 dopstr = HEAP_strdupA(GetProcessHeap(), 0,fodInfos->ofnInfos->lpstrFile);
1121 *strrchr(dopstr,'\\') = '\0';
1122 fodInfos->ofnInfos->lpstrInitialDir = dopstr;
1123 }
1124#endif
1125
1126 /* Get the initial directory pidl */
1127 if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos->lpstrInitialDir)))
1128 {
1129 char path[MAX_PATH];
1130
1131 GetCurrentDirectoryA(MAX_PATH,path);
1132 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder, path);
1133 }
1134
1135 /* Initialise shell objects */
1136 FILEDLG95_SHELL_Init(hwnd);
1137
1138 /* Initialize the Look In combo box */
1139 FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
1140
1141 /* Initialize the filter combo box */
1142 FILEDLG95_FILETYPE_Init(hwnd);
1143
1144 /* Browse to the initial directory */
1145 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId, SBSP_ABSOLUTE);
1146
1147 /* Free pidlItem memory */
1148 COMDLG32_SHFree(pidlItemId);
1149
1150#ifdef __WIN32OS2__
1151 /* Free dopstr */
1152 if (dopstr)
1153 {
1154 fodInfos->ofnInfos->lpstrInitialDir = NULL;
1155 HEAP_free(dopstr);
1156 }
1157#endif
1158 return TRUE;
1159}
1160/***********************************************************************
1161 * FILEDLG95_Clean
1162 *
1163 * Regroups all the cleaning functions of the filedlg
1164 */
1165void FILEDLG95_Clean(HWND hwnd)
1166{
1167 FILEDLG95_FILETYPE_Clean(hwnd);
1168 FILEDLG95_LOOKIN_Clean(hwnd);
1169 FILEDLG95_SHELL_Clean(hwnd);
1170}
1171/***********************************************************************
1172 * FILEDLG95_OnWMCommand
1173 *
1174 * WM_COMMAND message handler
1175 */
1176static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
1177{
1178 WORD wNotifyCode = HIWORD(wParam); /* notification code */
1179 WORD wID = LOWORD(wParam); /* item, control, or accelerator identifier */
1180 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1181
1182 switch(wID)
1183 {
1184 /* OK button */
1185 case IDOK:
1186#ifndef __WIN32OS2__
1187 if(FILEDLG95_OnOpen(hwnd))
1188 SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
1189 break;
1190#else
1191 {
1192 // 20011017 PH
1193 // some apps require the resources to be still there
1194 // for the CDN_ processing.
1195 BOOL fResult = FILEDLG95_OnOpen(hwnd);
1196 if(fResult)
1197 SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
1198
1199 FILEDLG95_Clean(hwnd);
1200 EndDialog(hwnd, fResult);
1201 break;
1202 }
1203#endif
1204 /* Cancel button */
1205 case IDCANCEL:
1206 FILEDLG95_Clean(hwnd);
1207 EndDialog(hwnd, FALSE);
1208 break;
1209 /* Filetype combo box */
1210 case IDC_FILETYPE:
1211 FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
1212 break;
1213 /* LookIn combo box */
1214 case IDC_LOOKIN:
1215 FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
1216 break;
1217
1218 /* --- toolbar --- */
1219 /* Up folder button */
1220 case FCIDM_TB_UPFOLDER:
1221 FILEDLG95_SHELL_UpFolder(hwnd);
1222 break;
1223 /* New folder button */
1224 case FCIDM_TB_NEWFOLDER:
1225 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_NEWFOLDER);
1226 break;
1227 /* List option button */
1228 case FCIDM_TB_SMALLICON:
1229 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
1230 break;
1231 /* Details option button */
1232 case FCIDM_TB_REPORTVIEW:
1233 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
1234 break;
1235 /* Details option button */
1236 case FCIDM_TB_DESKTOP:
1237 FILEDLG95_SHELL_BrowseToDesktop(hwnd);
1238 break;
1239
1240 case IDC_FILENAME:
1241 break;
1242
1243 }
1244 /* Do not use the listview selection anymore */
1245 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
1246 return 0;
1247}
1248
1249/***********************************************************************
1250 * FILEDLG95_OnWMGetIShellBrowser
1251 *
1252 * WM_GETISHELLBROWSER message handler
1253 */
1254static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
1255{
1256
1257 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1258
1259 TRACE("\n");
1260
1261 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
1262
1263 return TRUE;
1264}
1265
1266
1267/***********************************************************************
1268 * FILEDLG95_OnOpenMultipleFiles
1269 *
1270 * Handles the opening of multiple files.
1271 *
1272 * FIXME
1273 * check destination buffer size
1274 */
1275BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed)
1276{
1277 CHAR lpstrPathSpec[MAX_PATH] = "";
1278 LPSTR lpstrFile;
1279 UINT nCount, nSizePath;
1280 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1281
1282 TRACE("\n");
1283
1284 lpstrFile = fodInfos->ofnInfos->lpstrFile;
1285 lpstrFile[0] = '\0';
1286
1287 SHGetPathFromIDListA( fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathSpec );
1288
1289 if ( !(fodInfos->ofnInfos->Flags & OFN_NOVALIDATE) &&
1290 ( fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST))
1291 {
1292 LPSTR lpstrTemp = lpstrFileList;
1293
1294 for ( nCount = 0; nCount < nFileCount; nCount++ )
1295 {
1296 LPITEMIDLIST pidl;
1297
1298 pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder, lpstrTemp);
1299 if (!pidl)
1300 {
1301 CHAR lpstrNotFound[100];
1302 CHAR lpstrMsg[100];
1303 CHAR tmp[400];
1304
1305 LoadStringA(COMMDLG_hInstance32, IDS_FILENOTFOUND, lpstrNotFound, 100);
1306 LoadStringA(COMMDLG_hInstance32, IDS_VERIFYFILE, lpstrMsg, 100);
1307
1308 strcpy(tmp, lpstrTemp);
1309 strcat(tmp, "\n");
1310 strcat(tmp, lpstrNotFound);
1311 strcat(tmp, "\n");
1312 strcat(tmp, lpstrMsg);
1313
1314 MessageBoxA(hwnd, tmp, fodInfos->ofnInfos->lpstrTitle, MB_OK | MB_ICONEXCLAMATION);
1315 return FALSE;
1316 }
1317
1318 /* move to the next file in the list of files */
1319 lpstrTemp += strlen(lpstrTemp) + 1;
1320 COMDLG32_SHFree(pidl);
1321 }
1322 }
1323
1324 nSizePath = strlen(lpstrPathSpec);
1325 strcpy( lpstrFile, lpstrPathSpec);
1326 memcpy( lpstrFile + nSizePath + 1, lpstrFileList, sizeUsed );
1327
1328 fodInfos->ofnInfos->nFileOffset = nSizePath + 1;
1329 fodInfos->ofnInfos->nFileExtension = 0;
1330
1331 /* clean and exit */
1332#ifndef __WIN32OS2__
1333 // 20011017 PH
1334 // some apps require the resources to be still there
1335 // for the CDN_ processing.
1336 FILEDLG95_Clean(hwnd);
1337 return EndDialog(hwnd,TRUE);
1338#else
1339 return TRUE;
1340#endif
1341}
1342
1343/***********************************************************************
1344 * FILEDLG95_OnOpen
1345 *
1346 * Ok button WM_COMMAND message handler
1347 *
1348 * If the function succeeds, the return value is nonzero.
1349 */
1350#define ONOPEN_BROWSE 1
1351#define ONOPEN_OPEN 2
1352#define ONOPEN_SEARCH 3
1353static void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
1354{
1355 char strMsgTitle[MAX_PATH];
1356 char strMsgText [MAX_PATH];
1357 if (idCaption)
1358 LoadStringA(COMDLG32_hInstance, idCaption, strMsgTitle, sizeof(strMsgTitle));
1359 else
1360 strMsgTitle[0] = '\0';
1361 LoadStringA(COMDLG32_hInstance, idText, strMsgText, sizeof(strMsgText));
1362 MessageBoxA(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND);
1363}
1364
1365BOOL FILEDLG95_OnOpen(HWND hwnd)
1366{
1367 char * lpstrFileList;
1368 UINT nFileCount = 0;
1369 UINT sizeUsed = 0;
1370 BOOL ret = TRUE;
1371 char lpstrPathAndFile[MAX_PATH];
1372 char lpstrTemp[MAX_PATH];
1373 LPSHELLFOLDER lpsf = NULL;
1374 int nOpenAction;
1375 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1376
1377 TRACE("hwnd=0x%04x\n", hwnd);
1378
1379 /* get the files from the edit control */
1380 nFileCount = FILEDLG95_FILENAME_GetFileNames(hwnd, &lpstrFileList, &sizeUsed);
1381
1382 /* try if the user selected a folder in the shellview */
1383 if(nFileCount == 0)
1384 {
1385 BrowseSelectedFolder(hwnd);
1386 return FALSE;
1387 }
1388
1389 if(nFileCount > 1)
1390 {
1391 ret = FILEDLG95_OnOpenMultipleFiles(hwnd, lpstrFileList, nFileCount, sizeUsed);
1392 goto ret;
1393 }
1394
1395 TRACE("count=%u len=%u file=%s\n", nFileCount, sizeUsed, lpstrFileList);
1396
1397/*
1398 Step 1: Build a complete path name from the current folder and
1399 the filename or path in the edit box.
1400 Special cases:
1401 - the path in the edit box is a root path
1402 (with or without drive letter)
1403 - the edit box contains ".." (or a path with ".." in it)
1404*/
1405
1406 /* Get the current directory name */
1407 if (!SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathAndFile))
1408 {
1409 /* we are in a special folder, default to desktop */
1410 if(FAILED(COMDLG32_SHGetFolderPathA(hwnd, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, 0, 0, lpstrPathAndFile)))
1411 {
1412 /* last fallback */
1413 GetCurrentDirectoryA(MAX_PATH, lpstrPathAndFile);
1414 }
1415 }
1416 PathAddBackslashA(lpstrPathAndFile);
1417
1418 TRACE("current directory=%s\n", lpstrPathAndFile);
1419
1420 /* if the user specifyed a fully qualified path use it */
1421 if(PathIsRelativeA(lpstrFileList))
1422 {
1423 strcat(lpstrPathAndFile, lpstrFileList);
1424 }
1425 else
1426 {
1427 /* does the path have a drive letter? */
1428 if (PathGetDriveNumberA(lpstrFileList) == -1)
1429 strcpy(lpstrPathAndFile+2, lpstrFileList);
1430 else
1431 strcpy(lpstrPathAndFile, lpstrFileList);
1432 }
1433
1434 /* resolve "." and ".." */
1435 PathCanonicalizeA(lpstrTemp, lpstrPathAndFile );
1436 strcpy(lpstrPathAndFile, lpstrTemp);
1437 TRACE("canon=%s\n", lpstrPathAndFile);
1438
1439 MemFree(lpstrFileList);
1440
1441/*
1442 Step 2: here we have a cleaned up path
1443
1444 We have to parse the path step by step to see if we have to browse
1445 to a folder if the path points to a directory or the last
1446 valid element is a directory.
1447
1448 valid variables:
1449 lpstrPathAndFile: cleaned up path
1450 */
1451
1452 nOpenAction = ONOPEN_BROWSE;
1453
1454#ifdef __WIN32OS2__
1455 /* @@@AH 2001-06-02 moved out of !OFN_NONVALIDATE block - needs to be set */
1456 if (FAILED (SHGetDesktopFolder(&lpsf))) return FALSE;
1457#endif
1458
1459 /* dont apply any checks with OFN_NOVALIDATE */
1460 if(!(fodInfos->ofnInfos->Flags & OFN_NOVALIDATE))
1461 {
1462 LPSTR lpszTemp, lpszTemp1;
1463 LPITEMIDLIST pidl = NULL;
1464
1465 /* check for invalid chars */
1466 if(strpbrk(lpstrPathAndFile+3, "/:<>|") != NULL)
1467 {
1468 FILEDLG95_OnOpenMessage(hwnd, IDS_INVALID_FILENAME_TITLE, IDS_INVALID_FILENAME);
1469 ret = FALSE;
1470 goto ret;
1471 }
1472#ifndef __WIN32OS2__
1473 if (FAILED (SHGetDesktopFolder(&lpsf))) return FALSE;
1474#endif
1475 lpszTemp1 = lpszTemp = lpstrPathAndFile;
1476 while (lpszTemp1)
1477 {
1478 LPSHELLFOLDER lpsfChild;
1479 WCHAR lpwstrTemp[MAX_PATH];
1480 DWORD dwEaten, dwAttributes;
1481
1482 lpszTemp = PathFindNextComponentA(lpszTemp);
1483
1484 if (!lpszTemp) break; /* end of path */
1485
1486 if(*lpszTemp)
1487 {
1488 DWORD len = MultiByteToWideChar( CP_ACP, 0, lpszTemp1, lpszTemp - lpszTemp1,
1489 lpwstrTemp, MAX_PATH );
1490 lpwstrTemp[len] = 0;
1491 }
1492 else
1493 {
1494 MultiByteToWideChar( CP_ACP, 0, lpszTemp1, -1,
1495 lpwstrTemp, sizeof(lpwstrTemp)/sizeof(WCHAR) );
1496
1497 /* if the last element is a wildcard do a search */
1498 if(strpbrk(lpszTemp1, "*?") != NULL)
1499 {
1500 nOpenAction = ONOPEN_SEARCH;
1501 break;
1502 }
1503 }
1504 lpszTemp1 = lpszTemp;
1505
1506 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp), debugstr_a(lpszTemp), lpsf);
1507
1508 if(lstrlenW(lpwstrTemp)==2) PathAddBackslashW(lpwstrTemp);
1509
1510 dwAttributes = SFGAO_FOLDER;
1511 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf, hwnd, NULL, lpwstrTemp, &dwEaten, &pidl, &dwAttributes)))
1512 {
1513 /* the path component is valid, we have a pidl of the next path component */
1514 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes, pidl);
1515 if(dwAttributes & SFGAO_FOLDER)
1516 {
1517 if(FAILED(IShellFolder_BindToObject(lpsf, pidl, 0, &IID_IShellFolder, (LPVOID*)&lpsfChild)))
1518 {
1519 ERR("bind to failed\n"); /* should not fail */
1520 break;
1521 }
1522 IShellFolder_Release(lpsf);
1523 lpsf = lpsfChild;
1524 lpsfChild = NULL;
1525 }
1526 else
1527 {
1528 TRACE("value\n");
1529
1530 /* end dialog, return value */
1531 nOpenAction = ONOPEN_OPEN;
1532 break;
1533 }
1534 COMDLG32_SHFree(pidl);
1535 pidl = NULL;
1536 }
1537 else
1538 {
1539 if(*lpszTemp) /* points to trailing null for last path element */
1540 {
1541 if(fodInfos->ofnInfos->Flags & OFN_PATHMUSTEXIST)
1542 {
1543 FILEDLG95_OnOpenMessage(hwnd, 0, IDS_PATHNOTEXISTING);
1544 break;
1545 }
1546 }
1547 else
1548 {
1549 if(fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST)
1550 {
1551 FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
1552 break;
1553 }
1554 }
1555 /* change to the current folder */
1556 nOpenAction = ONOPEN_OPEN;
1557 break;
1558 }
1559 }
1560 if(pidl) COMDLG32_SHFree(pidl);
1561 }
1562#ifdef __WIN32OS2__
1563 else
1564 {
1565 // @@@AH 2001-06-02 when we are in OFN_NOVALIDATE mode, the action
1566 // must be to open the specified file when pressing open button
1567 TRACE("OFN_NOVALIDATE mode, set open action to ONOPEN_OPEN\n");
1568 nOpenAction = ONOPEN_OPEN;
1569 }
1570#endif
1571
1572/*
1573 Step 3: here we have a cleaned up and validated path
1574
1575 valid variables:
1576 lpsf: ShellFolder bound to the rightmost valid path component
1577 lpstrPathAndFile: cleaned up path
1578 nOpenAction: action to do
1579*/
1580 TRACE("end validate sf=%p\n", lpsf);
1581
1582 switch(nOpenAction)
1583 {
1584 case ONOPEN_SEARCH: /* set the current filter to the file mask and refresh */
1585 TRACE("ONOPEN_SEARCH %s\n", lpstrPathAndFile);
1586 {
1587 int iPos;
1588 LPSTR lpszTemp = PathFindFileNameA(lpstrPathAndFile);
1589 DWORD len;
1590
1591 /* replace the current filter */
1592 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1593 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1594 len = MultiByteToWideChar( CP_ACP, 0, lpszTemp, -1, NULL, 0 );
1595 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc(len * sizeof(WCHAR));
1596 MultiByteToWideChar( CP_ACP, 0, lpszTemp, -1,
1597 fodInfos->ShellInfos.lpstrCurrentFilter, len );
1598
1599 /* set the filter cb to the extension when possible */
1600 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB, lpszTemp)))
1601 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB, iPos);
1602 }
1603 /* fall through */
1604 case ONOPEN_BROWSE: /* browse to the highest folder we could bind to */
1605 TRACE("ONOPEN_BROWSE\n");
1606 {
1607 IPersistFolder2 * ppf2;
1608 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf, &IID_IPersistFolder2, (LPVOID*)&ppf2)))
1609 {
1610 LPITEMIDLIST pidlCurrent;
1611 IPersistFolder2_GetCurFolder(ppf2, &pidlCurrent);
1612 IPersistFolder2_Release(ppf2);
1613 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent, fodInfos->ShellInfos.pidlAbsCurrent))
1614 {
1615 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser, pidlCurrent, SBSP_ABSOLUTE);
1616 }
1617 else if( nOpenAction == ONOPEN_SEARCH )
1618 {
1619 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1620 }
1621 COMDLG32_SHFree(pidlCurrent);
1622 }
1623 }
1624 ret = FALSE;
1625 break;
1626 case ONOPEN_OPEN: /* fill in the return struct and close the dialog */
1627 TRACE("ONOPEN_OPEN %s\n", lpstrPathAndFile);
1628 {
1629 /* add default extension */
1630 if (fodInfos->ofnInfos->lpstrDefExt)
1631 {
1632 if (! *PathFindExtensionA(lpstrPathAndFile))
1633 {
1634 /* only add "." in case a default extension does exist */
1635 if (*fodInfos->ofnInfos->lpstrDefExt != '\0')
1636 {
1637 strcat(lpstrPathAndFile, ".");
1638 strcat(lpstrPathAndFile, fodInfos->ofnInfos->lpstrDefExt);
1639 }
1640 }
1641 }
1642
1643 /* Check that the size of the file does not exceed buffer size.
1644 (Allow for extra \0 if OFN_MULTISELECT is set.) */
1645 if(strlen(lpstrPathAndFile) < fodInfos->ofnInfos->nMaxFile -
1646 ((fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT) ? 1 : 0))
1647 {
1648 LPSTR lpszTemp;
1649
1650 /* fill destination buffer */
1651 strcpy(fodInfos->ofnInfos->lpstrFile, lpstrPathAndFile);
1652 if (fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT)
1653 fodInfos->ofnInfos->lpstrFile[strlen(fodInfos->ofnInfos->lpstrFile)
1654 + 1] = '\0';
1655
1656 /* set filename offset */
1657 lpszTemp = PathFindFileNameA(lpstrPathAndFile);
1658 fodInfos->ofnInfos->nFileOffset = lpszTemp - lpstrPathAndFile;
1659
1660 /* set extension offset */
1661 lpszTemp = PathFindExtensionA(lpstrPathAndFile);
1662 fodInfos->ofnInfos->nFileExtension = (*lpszTemp) ? lpszTemp - lpstrPathAndFile + 1 : 0;
1663
1664 /* set the lpstrFileTitle */
1665 if(fodInfos->ofnInfos->lpstrFileTitle)
1666 {
1667 LPSTR lpstrFileTitle = PathFindFileNameA(lpstrPathAndFile);
1668 strncpy(fodInfos->ofnInfos->lpstrFileTitle, lpstrFileTitle, fodInfos->ofnInfos->nMaxFileTitle);
1669 }
1670
1671 /* ask the hook if we can close */
1672 if(IsHooked(fodInfos))
1673 {
1674 /* FIXME we are sending ASCII-structures. Does not work with NT */
1675 /* first old style */
1676 TRACE("---\n");
1677 CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,
1678 fodInfos->DlgInfos.hwndCustomDlg,
1679 fodInfos->HookMsg.fileokstring, 0, (LPARAM)fodInfos->ofnInfos);
1680 if (GetWindowLongA(hwnd, DWL_MSGRESULT))
1681 {
1682 TRACE("cancled\n");
1683 ret = FALSE;
1684 goto ret;
1685 }
1686 }
1687
1688#ifndef __WIN32OS2__
1689 // 20011017 PH
1690 // some apps require the resources to be still there
1691 // for the CDN_ processing.
1692
1693 TRACE("close\n");
1694 FILEDLG95_Clean(hwnd);
1695 ret = EndDialog(hwnd, TRUE);
1696#else
1697 ret = TRUE;
1698#endif
1699 }
1700 else
1701 {
1702 /* FIXME set error FNERR_BUFFERTOSMALL */
1703#ifndef __WIN32OS2__
1704 // 20011017 PH
1705 // some apps require the resources to be still there
1706 // for the CDN_ processing.
1707
1708 FILEDLG95_Clean(hwnd);
1709 ret = EndDialog(hwnd, FALSE);
1710#else
1711 ret = FALSE;
1712#endif
1713 }
1714 goto ret;
1715 }
1716 break;
1717 }
1718
1719ret:
1720 if(lpsf) IShellFolder_Release(lpsf);
1721 return ret;
1722}
1723
1724/***********************************************************************
1725 * FILEDLG95_SHELL_Init
1726 *
1727 * Initialisation of the shell objects
1728 */
1729static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1730{
1731 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1732
1733 TRACE("\n");
1734
1735 /*
1736 * Initialisation of the FileOpenDialogInfos structure
1737 */
1738
1739 /* Shell */
1740
1741 /*ShellInfos */
1742 fodInfos->ShellInfos.hwndOwner = hwnd;
1743
1744 /* Disable multi-select if flag not set */
1745 if (!(fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT))
1746 {
1747 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_SINGLESEL;
1748 }
1749 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1750 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1751
1752 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1753 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1754 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1755
1756 /* Construct the IShellBrowser interface */
1757 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1758
1759 return NOERROR;
1760}
1761
1762/***********************************************************************
1763 * FILEDLG95_SHELL_ExecuteCommand
1764 *
1765 * Change the folder option and refresh the view
1766 * If the function succeeds, the return value is nonzero.
1767 */
1768static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1769{
1770 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1771
1772 IContextMenu * pcm;
1773 TRACE("(0x%08x,%p)\n", hwnd, lpVerb);
1774
1775 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1776 SVGIO_BACKGROUND,
1777 &IID_IContextMenu,
1778 (LPVOID*)&pcm)))
1779 {
1780 CMINVOKECOMMANDINFO ci;
1781 ZeroMemory(&ci, sizeof(CMINVOKECOMMANDINFO));
1782 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1783 ci.lpVerb = lpVerb;
1784 ci.hwnd = hwnd;
1785
1786 IContextMenu_InvokeCommand(pcm, &ci);
1787 IContextMenu_Release(pcm);
1788 }
1789
1790 return FALSE;
1791}
1792
1793/***********************************************************************
1794 * FILEDLG95_SHELL_UpFolder
1795 *
1796 * Browse to the specified object
1797 * If the function succeeds, the return value is nonzero.
1798 */
1799static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1800{
1801 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1802
1803 TRACE("\n");
1804
1805 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1806 NULL,
1807 SBSP_PARENT)))
1808 {
1809 return TRUE;
1810 }
1811 return FALSE;
1812}
1813
1814/***********************************************************************
1815 * FILEDLG95_SHELL_BrowseToDesktop
1816 *
1817 * Browse to the Desktop
1818 * If the function succeeds, the return value is nonzero.
1819 */
1820static BOOL FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd)
1821{
1822 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1823 LPITEMIDLIST pidl;
1824 HRESULT hres;
1825
1826 TRACE("\n");
1827
1828 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidl);
1829 hres = IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser, pidl, SBSP_ABSOLUTE);
1830 COMDLG32_SHFree(pidl);
1831 return SUCCEEDED(hres);
1832}
1833/***********************************************************************
1834 * FILEDLG95_SHELL_Clean
1835 *
1836 * Cleans the memory used by shell objects
1837 */
1838static void FILEDLG95_SHELL_Clean(HWND hwnd)
1839{
1840 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1841
1842 TRACE("\n");
1843
1844 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
1845
1846 /* clean Shell interfaces */
1847 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1848 IShellView_Release(fodInfos->Shell.FOIShellView);
1849 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1850 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1851 if (fodInfos->Shell.FOIDataObject)
1852 IDataObject_Release(fodInfos->Shell.FOIDataObject);
1853}
1854
1855/***********************************************************************
1856 * FILEDLG95_FILETYPE_Init
1857 *
1858 * Initialisation of the file type combo box
1859 */
1860static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1861{
1862 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1863
1864 TRACE("\n");
1865
1866 if(fodInfos->ofnInfos->lpstrFilter)
1867 {
1868 int nFilters = 0; /* number of filters */
1869 LPSTR lpstrFilter;
1870 LPCSTR lpstrPos = fodInfos->ofnInfos->lpstrFilter;
1871
1872 for(;;)
1873 {
1874 /* filter is a list... title\0ext\0......\0\0
1875 * Set the combo item text to the title and the item data
1876 * to the ext
1877 */
1878 LPCSTR lpstrDisplay;
1879 LPSTR lpstrExt;
1880
1881 /* Get the title */
1882 if(! *lpstrPos) break; /* end */
1883 lpstrDisplay = lpstrPos;
1884 lpstrPos += strlen(lpstrPos) + 1;
1885
1886 /* Copy the extensions */
1887 if (! *lpstrPos) return E_FAIL; /* malformed filter */
1888 if (!(lpstrExt = (LPSTR) MemAlloc(strlen(lpstrPos)+1))) return E_FAIL;
1889 strcpy(lpstrExt,lpstrPos);
1890 lpstrPos += strlen(lpstrPos) + 1;
1891
1892 /* Add the item at the end of the combo */
1893 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB, lpstrDisplay);
1894 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB, nFilters, lpstrExt);
1895 nFilters++;
1896 }
1897 /*
1898 * Set the current filter to the one specified
1899 * in the initialisation structure
1900 * FIXME: lpstrCustomFilter not handled at all
1901 */
1902
1903 /* set default filter index */
1904 if(fodInfos->ofnInfos->nFilterIndex == 0 && fodInfos->ofnInfos->lpstrCustomFilter == NULL)
1905 fodInfos->ofnInfos->nFilterIndex = 1;
1906
1907 /* First, check to make sure our index isn't out of bounds. */
1908 if ( fodInfos->ofnInfos->nFilterIndex > nFilters )
1909 fodInfos->ofnInfos->nFilterIndex = nFilters;
1910
1911 /* Set the current index selection. */
1912 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB, fodInfos->ofnInfos->nFilterIndex-1);
1913
1914 /* Get the corresponding text string from the combo box. */
1915 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1916 fodInfos->ofnInfos->nFilterIndex-1);
1917
1918 if ((INT)lpstrFilter == CB_ERR) /* control is empty */
1919 lpstrFilter = NULL;
1920
1921 if(lpstrFilter)
1922 {
1923 DWORD len;
1924 _strlwr(lpstrFilter); /* lowercase */
1925 len = MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1, NULL, 0 );
1926 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc( len * sizeof(WCHAR) );
1927 MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1,
1928 fodInfos->ShellInfos.lpstrCurrentFilter, len );
1929 }
1930 }
1931 return NOERROR;
1932}
1933
1934/***********************************************************************
1935 * FILEDLG95_FILETYPE_OnCommand
1936 *
1937 * WM_COMMAND of the file type combo box
1938 * If the function succeeds, the return value is nonzero.
1939 */
1940static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1941{
1942 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1943
1944 switch(wNotifyCode)
1945 {
1946 case CBN_SELENDOK:
1947 {
1948 LPSTR lpstrFilter;
1949
1950 /* Get the current item of the filetype combo box */
1951 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1952
1953 /* set the current filter index - indexed from 1 */
1954 fodInfos->ofnInfos->nFilterIndex = iItem + 1;
1955
1956 /* Set the current filter with the current selection */
1957 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1958 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1959
1960 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1961 iItem);
1962 if((int)lpstrFilter != CB_ERR)
1963 {
1964 DWORD len;
1965 _strlwr(lpstrFilter); /* lowercase */
1966 len = MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1, NULL, 0 );
1967 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc( len * sizeof(WCHAR) );
1968 MultiByteToWideChar( CP_ACP, 0, lpstrFilter, -1,
1969 fodInfos->ShellInfos.lpstrCurrentFilter, len );
1970 SendCustomDlgNotificationMessage(hwnd,CDN_TYPECHANGE);
1971 }
1972
1973 /* Refresh the actual view to display the included items*/
1974 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1975 }
1976 }
1977 return FALSE;
1978}
1979/***********************************************************************
1980 * FILEDLG95_FILETYPE_SearchExt
1981 *
1982 * searches for a extension in the filetype box
1983 */
1984static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPCSTR lpstrExt)
1985{
1986 int i, iCount = CBGetCount(hwnd);
1987
1988 TRACE("%s\n", lpstrExt);
1989
1990 if(iCount != CB_ERR)
1991 {
1992 for(i=0;i<iCount;i++)
1993 {
1994 if(!strcasecmp(lpstrExt,(LPSTR)CBGetItemDataPtr(hwnd,i)))
1995 return i;
1996 }
1997 }
1998 return -1;
1999}
2000
2001/***********************************************************************
2002 * FILEDLG95_FILETYPE_Clean
2003 *
2004 * Clean the memory used by the filetype combo box
2005 */
2006static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
2007{
2008 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2009 int iPos;
2010 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
2011
2012 TRACE("\n");
2013
2014 /* Delete each string of the combo and their associated data */
2015 if(iCount != CB_ERR)
2016 {
2017 for(iPos = iCount-1;iPos>=0;iPos--)
2018 {
2019 MemFree((LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos));
2020 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
2021 }
2022 }
2023 /* Current filter */
2024 if(fodInfos->ShellInfos.lpstrCurrentFilter)
2025 MemFree(fodInfos->ShellInfos.lpstrCurrentFilter);
2026
2027}
2028
2029/***********************************************************************
2030 * FILEDLG95_LOOKIN_Init
2031 *
2032 * Initialisation of the look in combo box
2033 */
2034static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
2035{
2036 IShellFolder *psfRoot, *psfDrives;
2037 IEnumIDList *lpeRoot, *lpeDrives;
2038 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
2039
2040 LookInInfos *liInfos = MemAlloc(sizeof(LookInInfos));
2041
2042 TRACE("\n");
2043
2044 liInfos->iMaxIndentation = 0;
2045
2046 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
2047
2048 /* set item height for both text field and listbox */
2049 CBSetItemHeight(hwndCombo,-1,GetSystemMetrics(SM_CYSMICON));
2050 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
2051
2052 /* Initialise data of Desktop folder */
2053 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
2054 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
2055 COMDLG32_SHFree(pidlTmp);
2056
2057 SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
2058
2059 SHGetDesktopFolder(&psfRoot);
2060
2061 if (psfRoot)
2062 {
2063 /* enumerate the contents of the desktop */
2064 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
2065 {
2066 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
2067 {
2068 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
2069
2070 /* special handling for CSIDL_DRIVES */
2071 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
2072 {
2073 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
2074 {
2075 /* enumerate the drives */
2076 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
2077 {
2078 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
2079 {
2080 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
2081 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
2082 COMDLG32_SHFree(pidlAbsTmp);
2083 COMDLG32_SHFree(pidlTmp1);
2084 }
2085 IEnumIDList_Release(lpeDrives);
2086 }
2087 IShellFolder_Release(psfDrives);
2088 }
2089 }
2090 COMDLG32_SHFree(pidlTmp);
2091 }
2092 IEnumIDList_Release(lpeRoot);
2093 }
2094 }
2095
2096 IShellFolder_Release(psfRoot);
2097 COMDLG32_SHFree(pidlDrives);
2098 return NOERROR;
2099}
2100
2101/***********************************************************************
2102 * FILEDLG95_LOOKIN_DrawItem
2103 *
2104 * WM_DRAWITEM message handler
2105 */
2106static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
2107{
2108 COLORREF crWin = GetSysColor(COLOR_WINDOW);
2109 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
2110 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
2111 RECT rectText;
2112 RECT rectIcon;
2113 SHFILEINFOA sfi;
2114 HIMAGELIST ilItemImage;
2115 int iIndentation;
2116 TEXTMETRICA tm;
2117 LPSFOLDER tmpFolder;
2118
2119
2120 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
2121
2122 TRACE("\n");
2123
2124 if(pDIStruct->itemID == -1)
2125 return 0;
2126
2127 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
2128 pDIStruct->itemID)))
2129 return 0;
2130
2131
2132 if(pDIStruct->itemID == liInfos->uSelectedItem)
2133 {
2134 ilItemImage = (HIMAGELIST) SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2135 0,
2136 &sfi,
2137 sizeof (SHFILEINFOA),
2138 SHGFI_PIDL | SHGFI_SMALLICON |
2139 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
2140 SHGFI_DISPLAYNAME );
2141 }
2142 else
2143 {
2144 ilItemImage = (HIMAGELIST) SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2145 0,
2146 &sfi,
2147 sizeof (SHFILEINFOA),
2148 SHGFI_PIDL | SHGFI_SMALLICON |
2149 SHGFI_SYSICONINDEX |
2150 SHGFI_DISPLAYNAME);
2151 }
2152
2153 /* Is this item selected ? */
2154 if(pDIStruct->itemState & ODS_SELECTED)
2155 {
2156 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
2157 SetBkColor(pDIStruct->hDC,crHighLight);
2158 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
2159 }
2160 else
2161 {
2162 SetTextColor(pDIStruct->hDC,crText);
2163 SetBkColor(pDIStruct->hDC,crWin);
2164 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
2165 }
2166
2167 /* Do not indent item if drawing in the edit of the combo */
2168 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
2169 {
2170 iIndentation = 0;
2171 ilItemImage = (HIMAGELIST) SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2172 0,
2173 &sfi,
2174 sizeof (SHFILEINFOA),
2175 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
2176 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
2177
2178 }
2179 else
2180 {
2181 iIndentation = tmpFolder->m_iIndent;
2182 }
2183 /* Draw text and icon */
2184
2185 /* Initialise the icon display area */
2186 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
2187 rectIcon.top = pDIStruct->rcItem.top;
2188 rectIcon.right = rectIcon.left + ICONWIDTH;
2189 rectIcon.bottom = pDIStruct->rcItem.bottom;
2190
2191 /* Initialise the text display area */
2192 GetTextMetricsA(pDIStruct->hDC, &tm);
2193 rectText.left = rectIcon.right;
2194 rectText.top =
2195 (pDIStruct->rcItem.top + pDIStruct->rcItem.bottom - tm.tmHeight) / 2;
2196 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
2197 rectText.bottom =
2198 (pDIStruct->rcItem.top + pDIStruct->rcItem.bottom + tm.tmHeight) / 2;
2199
2200 /* Draw the icon from the image list */
2201 ImageList_Draw(ilItemImage,
2202 sfi.iIcon,
2203 pDIStruct->hDC,
2204 rectIcon.left,
2205 rectIcon.top,
2206 ILD_TRANSPARENT );
2207
2208 /* Draw the associated text */
2209 if(sfi.szDisplayName)
2210 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
2211
2212
2213 return NOERROR;
2214}
2215
2216/***********************************************************************
2217 * FILEDLG95_LOOKIN_OnCommand
2218 *
2219 * LookIn combo box WM_COMMAND message handler
2220 * If the function succeeds, the return value is nonzero.
2221 */
2222static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
2223{
2224 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2225
2226 TRACE("%p\n", fodInfos);
2227
2228 switch(wNotifyCode)
2229 {
2230 case CBN_SELENDOK:
2231 {
2232 LPSFOLDER tmpFolder;
2233 int iItem;
2234
2235 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
2236
2237 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
2238 iItem)))
2239 return FALSE;
2240
2241
2242 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
2243 tmpFolder->pidlItem,
2244 SBSP_ABSOLUTE)))
2245 {
2246 return TRUE;
2247 }
2248 break;
2249 }
2250
2251 }
2252 return FALSE;
2253}
2254
2255/***********************************************************************
2256 * FILEDLG95_LOOKIN_AddItem
2257 *
2258 * Adds an absolute pidl item to the lookin combo box
2259 * returns the index of the inserted item
2260 */
2261static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
2262{
2263 LPITEMIDLIST pidlNext;
2264 SHFILEINFOA sfi;
2265 SFOLDER *tmpFolder;
2266 LookInInfos *liInfos;
2267
2268 TRACE("%08x\n", iInsertId);
2269
2270 if(!pidl)
2271 return -1;
2272
2273 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
2274 return -1;
2275
2276 tmpFolder = MemAlloc(sizeof(SFOLDER));
2277 tmpFolder->m_iIndent = 0;
2278
2279 /* Calculate the indentation of the item in the lookin*/
2280 pidlNext = pidl;
2281 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
2282 {
2283 tmpFolder->m_iIndent++;
2284 }
2285
2286 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl); /* FIXME: memory leak*/
2287
2288 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
2289 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
2290
2291 sfi.dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
2292 SHGetFileInfoA((LPSTR)pidl,
2293 0,
2294 &sfi,
2295 sizeof(sfi),
2296 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
2297 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES | SHGFI_ATTR_SPECIFIED);
2298
2299 TRACE("-- Add %s attr=%08lx\n", sfi.szDisplayName, sfi.dwAttributes);
2300
2301 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
2302 {
2303 int iItemID;
2304
2305 TRACE("-- Add %s at %u\n", sfi.szDisplayName, tmpFolder->m_iIndent);
2306
2307 /* Add the item at the end of the list */
2308 if(iInsertId < 0)
2309 {
2310 iItemID = CBAddString(hwnd,sfi.szDisplayName);
2311 }
2312 /* Insert the item at the iInsertId position*/
2313 else
2314 {
2315 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
2316 }
2317
2318 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
2319 return iItemID;
2320 }
2321
2322 MemFree( tmpFolder );
2323 return -1;
2324
2325}
2326
2327/***********************************************************************
2328 * FILEDLG95_LOOKIN_InsertItemAfterParent
2329 *
2330 * Insert an item below its parent
2331 */
2332static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
2333{
2334
2335 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
2336 int iParentPos;
2337
2338 TRACE("\n");
2339
2340 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
2341
2342 if(iParentPos < 0)
2343 {
2344 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
2345 }
2346
2347 /* Free pidlParent memory */
2348 COMDLG32_SHFree((LPVOID)pidlParent);
2349
2350 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
2351}
2352
2353/***********************************************************************
2354 * FILEDLG95_LOOKIN_SelectItem
2355 *
2356 * Adds an absolute pidl item to the lookin combo box
2357 * returns the index of the inserted item
2358 */
2359int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
2360{
2361 int iItemPos;
2362 LookInInfos *liInfos;
2363
2364 TRACE("\n");
2365
2366 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
2367
2368 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2369
2370 if(iItemPos < 0)
2371 {
2372 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
2373 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
2374 }
2375
2376 else
2377 {
2378 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2379 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
2380 {
2381 int iRemovedItem;
2382
2383 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
2384 break;
2385 if(iRemovedItem < iItemPos)
2386 iItemPos--;
2387 }
2388 }
2389
2390 CBSetCurSel(hwnd,iItemPos);
2391 liInfos->uSelectedItem = iItemPos;
2392
2393 return 0;
2394
2395}
2396
2397/***********************************************************************
2398 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2399 *
2400 * Remove the item with an expansion level over iExpansionLevel
2401 */
2402static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
2403{
2404 int iItemPos;
2405
2406 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2407
2408 TRACE("\n");
2409
2410 if(liInfos->iMaxIndentation <= 2)
2411 return -1;
2412
2413 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
2414 {
2415 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2416 COMDLG32_SHFree(tmpFolder->pidlItem);
2417 MemFree(tmpFolder);
2418 CBDeleteString(hwnd,iItemPos);
2419 liInfos->iMaxIndentation--;
2420
2421 return iItemPos;
2422 }
2423
2424 return -1;
2425}
2426
2427/***********************************************************************
2428 * FILEDLG95_LOOKIN_SearchItem
2429 *
2430 * Search for pidl in the lookin combo box
2431 * returns the index of the found item
2432 */
2433static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2434{
2435 int i = 0;
2436 int iCount = CBGetCount(hwnd);
2437
2438 TRACE("0x%08x 0x%x\n",searchArg, iSearchMethod);
2439
2440 if (iCount != CB_ERR)
2441 {
2442 for(;i<iCount;i++)
2443 {
2444 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2445
2446 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2447 return i;
2448 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2449 return i;
2450 }
2451 }
2452
2453 return -1;
2454}
2455
2456/***********************************************************************
2457 * FILEDLG95_LOOKIN_Clean
2458 *
2459 * Clean the memory used by the lookin combo box
2460 */
2461static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2462{
2463 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2464 int iPos;
2465 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2466
2467 TRACE("\n");
2468
2469 /* Delete each string of the combo and their associated data */
2470 if (iCount != CB_ERR)
2471 {
2472 for(iPos = iCount-1;iPos>=0;iPos--)
2473 {
2474 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos);
2475 COMDLG32_SHFree(tmpFolder->pidlItem);
2476 MemFree(tmpFolder);
2477 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2478 }
2479 }
2480
2481 /* LookInInfos structure */
2482 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2483
2484}
2485/***********************************************************************
2486 * FILEDLG95_FILENAME_FillFromSelection
2487 *
2488 * fills the edit box from the cached DataObject
2489 */
2490void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd)
2491{
2492 FileOpenDlgInfos *fodInfos;
2493 LPITEMIDLIST pidl;
2494 UINT nFiles = 0, nFileToOpen, nFileSelected, nLength = 0;
2495 char lpstrTemp[MAX_PATH];
2496 LPSTR lpstrAllFile = NULL, lpstrCurrFile = NULL;
2497
2498 TRACE("\n");
2499 fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2500
2501 /* Count how many files we have */
2502 nFileSelected = GetNumSelected( fodInfos->Shell.FOIDataObject );
2503
2504 /* calculate the string length, count files */
2505 if (nFileSelected >= 1)
2506 {
2507 nLength += 3; /* first and last quotes, trailing \0 */
2508 for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
2509 {
2510 pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
2511
2512 if (pidl)
2513 {
2514 /* get the total length of the selected file names*/
2515 lpstrTemp[0] = '\0';
2516 GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER, lpstrTemp );
2517
2518 if ( ! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl) ) /* Ignore folders */
2519 {
2520 nLength += strlen( lpstrTemp ) + 3;
2521 nFiles++;
2522 }
2523 COMDLG32_SHFree( pidl );
2524 }
2525 }
2526 }
2527
2528 /* allocate the buffer */
2529 if (nFiles <= 1) nLength = MAX_PATH;
2530 lpstrAllFile = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength);
2531 lpstrAllFile[0] = '\0';
2532
2533 /* Generate the string for the edit control */
2534 if(nFiles >= 1)
2535 {
2536 lpstrCurrFile = lpstrAllFile;
2537 for ( nFileToOpen = 0; nFileToOpen < nFileSelected; nFileToOpen++ )
2538 {
2539 pidl = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, nFileToOpen+1 );
2540
2541 if (pidl)
2542 {
2543 /* get the file name */
2544 lpstrTemp[0] = '\0';
2545 GetName( fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER, lpstrTemp );
2546
2547 if (! IsPidlFolder(fodInfos->Shell.FOIShellFolder, pidl)) /* Ignore folders */
2548 {
2549 if ( nFiles > 1)
2550 {
2551 *lpstrCurrFile++ = '\"';
2552 strcpy( lpstrCurrFile, lpstrTemp );
2553 lpstrCurrFile += strlen( lpstrTemp );
2554 strcpy( lpstrCurrFile, "\" " );
2555 lpstrCurrFile += 2;
2556 }
2557 else
2558 {
2559 strcpy( lpstrAllFile, lpstrTemp );
2560 }
2561 }
2562 COMDLG32_SHFree( (LPVOID) pidl );
2563 }
2564 }
2565 }
2566#ifdef __WIN32OS2__
2567 //Selecting a directory previously erased the last selected file
2568 if(nFiles) {
2569 SetWindowTextA( fodInfos->DlgInfos.hwndFileName, lpstrAllFile );
2570 }
2571#else
2572 SetWindowTextA( fodInfos->DlgInfos.hwndFileName, lpstrAllFile );
2573#endif
2574 HeapFree(GetProcessHeap(),0, lpstrAllFile );
2575}
2576
2577
2578/* copied from shell32 to avoid linking to it */
2579static HRESULT COMDLG32_StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
2580{
2581 switch (src->uType)
2582 {
2583 case STRRET_WSTR:
2584 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
2585 COMDLG32_SHFree(src->u.pOleStr);
2586 break;
2587
2588 case STRRET_CSTRA:
2589 lstrcpynA((LPSTR)dest, src->u.cStr, len);
2590 break;
2591
2592 case STRRET_OFFSETA:
2593 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
2594 break;
2595
2596 default:
2597 FIXME("unknown type!\n");
2598 if (len)
2599 {
2600 *(LPSTR)dest = '\0';
2601 }
2602 return(FALSE);
2603 }
2604 return S_OK;
2605}
2606
2607/***********************************************************************
2608 * FILEDLG95_FILENAME_GetFileNames
2609 *
2610 * copies the filenames to a 0-delimited string list (A\0B\0C\0\0)
2611 */
2612int FILEDLG95_FILENAME_GetFileNames (HWND hwnd, LPSTR * lpstrFileList, UINT * sizeUsed)
2613{
2614 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2615 UINT nStrCharCount = 0; /* index in src buffer */
2616 UINT nFileIndex = 0; /* index in dest buffer */
2617 UINT nFileCount = 0; /* number of files */
2618 UINT nStrLen = 0; /* length of string in edit control */
2619 LPSTR lpstrEdit; /* buffer for string from edit control */
2620
2621 TRACE("\n");
2622
2623 /* get the filenames from the edit control */
2624 nStrLen = SendMessageA(fodInfos->DlgInfos.hwndFileName, WM_GETTEXTLENGTH, 0, 0);
2625 lpstrEdit = MemAlloc(nStrLen+1);
2626 GetDlgItemTextA(hwnd, IDC_FILENAME, lpstrEdit, nStrLen+1);
2627
2628 TRACE("nStrLen=%u str=%s\n", nStrLen, lpstrEdit);
2629
2630 /* we might get single filename without any '"',
2631 * so we need nStrLen + terminating \0 + end-of-list \0 */
2632 *lpstrFileList = MemAlloc(nStrLen+2);
2633 *sizeUsed = 0;
2634
2635 /* build 0-delimited file list from filenames */
2636 while ( nStrCharCount <= nStrLen )
2637 {
2638 if ( lpstrEdit[nStrCharCount]=='"' )
2639 {
2640 nStrCharCount++;
2641 while ((lpstrEdit[nStrCharCount]!='"') && (nStrCharCount <= nStrLen))
2642 {
2643 (*lpstrFileList)[nFileIndex++] = lpstrEdit[nStrCharCount];
2644 (*sizeUsed)++;
2645 nStrCharCount++;
2646 }
2647 (*lpstrFileList)[nFileIndex++] = '\0';
2648 (*sizeUsed)++;
2649 nFileCount++;
2650 }
2651 nStrCharCount++;
2652 }
2653
2654 /* single, unquoted string */
2655 if ((nStrLen > 0) && (*sizeUsed == 0) )
2656 {
2657 strcpy(*lpstrFileList, lpstrEdit);
2658 nFileIndex = strlen(lpstrEdit) + 1;
2659 (*sizeUsed) = nFileIndex;
2660 nFileCount = 1;
2661 }
2662
2663 /* trailing \0 */
2664 (*lpstrFileList)[nFileIndex] = '\0';
2665 (*sizeUsed)++;
2666
2667 MemFree(lpstrEdit);
2668 return nFileCount;
2669}
2670
2671#define SETDefFormatEtc(fe,cf,med) \
2672{ \
2673 (fe).cfFormat = cf;\
2674 (fe).dwAspect = DVASPECT_CONTENT; \
2675 (fe).ptd =NULL;\
2676 (fe).tymed = med;\
2677 (fe).lindex = -1;\
2678};
2679
2680/*
2681 * DATAOBJECT Helper functions
2682 */
2683
2684/***********************************************************************
2685 * COMCTL32_ReleaseStgMedium
2686 *
2687 * like ReleaseStgMedium from ole32
2688 */
2689static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium)
2690{
2691 if(medium.pUnkForRelease)
2692 {
2693 IUnknown_Release(medium.pUnkForRelease);
2694 }
2695 else
2696 {
2697 GlobalUnlock(medium.u.hGlobal);
2698 GlobalFree(medium.u.hGlobal);
2699 }
2700}
2701
2702/***********************************************************************
2703 * GetPidlFromDataObject
2704 *
2705 * Return pidl(s) by number from the cached DataObject
2706 *
2707 * nPidlIndex=0 gets the fully qualified root path
2708 */
2709LPITEMIDLIST GetPidlFromDataObject ( IDataObject *doSelected, UINT nPidlIndex)
2710{
2711
2712 STGMEDIUM medium;
2713 FORMATETC formatetc;
2714 LPITEMIDLIST pidl = NULL;
2715
2716 TRACE("sv=%p index=%u\n", doSelected, nPidlIndex);
2717
2718 /* Set the FORMATETC structure*/
2719 SETDefFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
2720
2721 /* Get the pidls from IDataObject */
2722 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
2723 {
2724 LPIDA cida = GlobalLock(medium.u.hGlobal);
2725 if(nPidlIndex <= cida->cidl)
2726 {
2727 pidl = COMDLG32_PIDL_ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[nPidlIndex]]));
2728 }
2729 COMCTL32_ReleaseStgMedium(medium);
2730 }
2731 return pidl;
2732}
2733
2734/***********************************************************************
2735 * GetNumSelected
2736 *
2737 * Return the number of selected items in the DataObject.
2738 *
2739*/
2740UINT GetNumSelected( IDataObject *doSelected )
2741{
2742 UINT retVal = 0;
2743 STGMEDIUM medium;
2744 FORMATETC formatetc;
2745
2746 TRACE("sv=%p\n", doSelected);
2747
2748 if (!doSelected) return 0;
2749
2750 /* Set the FORMATETC structure*/
2751 SETDefFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
2752
2753 /* Get the pidls from IDataObject */
2754 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
2755 {
2756 LPIDA cida = GlobalLock(medium.u.hGlobal);
2757 retVal = cida->cidl;
2758 COMCTL32_ReleaseStgMedium(medium);
2759 return retVal;
2760 }
2761 return 0;
2762}
2763
2764/*
2765 * TOOLS
2766 */
2767
2768/***********************************************************************
2769 * GetName
2770 *
2771 * Get the pidl's display name (relative to folder) and
2772 * put it in lpstrFileName.
2773 *
2774 * Return NOERROR on success,
2775 * E_FAIL otherwise
2776 */
2777
2778HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2779{
2780 STRRET str;
2781 HRESULT hRes;
2782
2783 TRACE("sf=%p pidl=%p\n", lpsf, pidl);
2784
2785 if(!lpsf)
2786 {
2787 HRESULT hRes;
2788 SHGetDesktopFolder(&lpsf);
2789 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2790 IShellFolder_Release(lpsf);
2791 return hRes;
2792 }
2793
2794 /* Get the display name of the pidl relative to the folder */
2795 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf, pidl, dwFlags, &str)))
2796 {
2797 return COMDLG32_StrRetToStrNA(lpstrFileName, MAX_PATH, &str, pidl);
2798 }
2799 return E_FAIL;
2800}
2801
2802/***********************************************************************
2803 * GetShellFolderFromPidl
2804 *
2805 * pidlRel is the item pidl relative
2806 * Return the IShellFolder of the absolute pidl
2807 */
2808IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2809{
2810 IShellFolder *psf = NULL,*psfParent;
2811
2812 TRACE("%p\n", pidlAbs);
2813
2814 if(SUCCEEDED(SHGetDesktopFolder(&psfParent)))
2815 {
2816 psf = psfParent;
2817 if(pidlAbs && pidlAbs->mkid.cb)
2818 {
2819 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2820 {
2821 IShellFolder_Release(psfParent);
2822 return psf;
2823 }
2824 }
2825 /* return the desktop */
2826 return psfParent;
2827 }
2828 return NULL;
2829}
2830
2831/***********************************************************************
2832 * GetParentPidl
2833 *
2834 * Return the LPITEMIDLIST to the parent of the pidl in the list
2835 */
2836LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2837{
2838 LPITEMIDLIST pidlParent;
2839
2840 TRACE("%p\n", pidl);
2841
2842 pidlParent = COMDLG32_PIDL_ILClone(pidl);
2843 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2844
2845 return pidlParent;
2846}
2847
2848/***********************************************************************
2849 * GetPidlFromName
2850 *
2851 * returns the pidl of the file name relative to folder
2852 * NULL if an error occurred
2853 */
2854LPITEMIDLIST GetPidlFromName(IShellFolder *lpsf,LPCSTR lpcstrFileName)
2855{
2856 LPITEMIDLIST pidl;
2857 ULONG ulEaten;
2858 WCHAR lpwstrDirName[MAX_PATH];
2859
2860 TRACE("sf=%p file=%s\n", lpsf, lpcstrFileName);
2861
2862 if(!lpcstrFileName) return NULL;
2863 if(!*lpcstrFileName) return NULL;
2864
2865 MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpcstrFileName,-1,(LPWSTR)lpwstrDirName,MAX_PATH);
2866
2867 if(!lpsf)
2868 {
2869 SHGetDesktopFolder(&lpsf);
2870 pidl = GetPidlFromName(lpsf, lpcstrFileName);
2871 IShellFolder_Release(lpsf);
2872 }
2873 else
2874 {
2875 IShellFolder_ParseDisplayName(lpsf, 0, NULL, (LPWSTR)lpwstrDirName, &ulEaten, &pidl, NULL);
2876 }
2877 return pidl;
2878}
2879
2880/*
2881*/
2882BOOL IsPidlFolder (LPSHELLFOLDER psf, LPITEMIDLIST pidl)
2883{
2884 ULONG uAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
2885 HRESULT ret;
2886
2887 TRACE("%p, %p\n", psf, pidl);
2888
2889 ret = IShellFolder_GetAttributesOf( psf, 1, &pidl, &uAttr );
2890
2891 TRACE("-- 0x%08lx 0x%08lx\n", uAttr, ret);
2892 /* see documentation shell 4.1*/
2893 return uAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
2894}
2895
2896/***********************************************************************
2897 * BrowseSelectedFolder
2898 */
2899static BOOL BrowseSelectedFolder(HWND hwnd)
2900{
2901 BOOL bBrowseSelFolder = FALSE;
2902 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2903
2904 TRACE("\n");
2905
2906 if (GetNumSelected(fodInfos->Shell.FOIDataObject) == 1)
2907 {
2908 LPITEMIDLIST pidlSelection;
2909
2910 /* get the file selected */
2911 pidlSelection = GetPidlFromDataObject( fodInfos->Shell.FOIDataObject, 1);
2912 if (IsPidlFolder (fodInfos->Shell.FOIShellFolder, pidlSelection))
2913 {
2914 if ( FAILED( IShellBrowser_BrowseObject( fodInfos->Shell.FOIShellBrowser,
2915 pidlSelection, SBSP_RELATIVE ) ) )
2916 {
2917 MessageBoxA( hwnd, "Path does not exist", fodInfos->ofnInfos->lpstrTitle,
2918 MB_OK | MB_ICONEXCLAMATION );
2919 }
2920
2921 bBrowseSelFolder = TRUE;
2922 }
2923 COMDLG32_SHFree( pidlSelection );
2924 }
2925
2926 return bBrowseSelFolder;
2927}
2928
2929/*
2930 * Memory allocation methods */
2931static void *MemAlloc(UINT size)
2932{
2933 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2934}
2935
2936static void MemFree(void *mem)
2937{
2938 if(mem)
2939 {
2940 HeapFree(GetProcessHeap(),0,mem);
2941 }
2942}
2943
Note: See TracBrowser for help on using the repository browser.