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

Last change on this file since 22012 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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