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

Last change on this file since 10012 was 9306, checked in by sandervl, 23 years ago

PF: if lpstrInitialDir is not a dir but a filename

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