- fixed the index of the item chosen in the filter combo box
[wine] / dlls / commdlg / filedlg95.c
1 /*
2  * COMMDLG - File Open Dialogs Win95 look and feel
3  *
4  */
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "winbase.h"
9 #include "ldt.h"
10 #include "heap.h"
11 #include "commdlg.h"
12 #include "dlgs.h"
13 #include "cdlg.h"
14 #include "debugtools.h"
15 #include "cderr.h"
16 #include "tweak.h"
17 #include "winnls.h"
18 #include "shellapi.h"
19 #include "tchar.h"
20 #include "filedlgbrowser.h"
21 #include "wine/obj_contextmenu.h"
22
23 DEFAULT_DEBUG_CHANNEL(commdlg)
24
25 /***********************************************************************
26  * Data structure and global variables
27  */
28 typedef struct SFolder
29 {
30   int m_iImageIndex;    /* Index of picture in image list */
31   HIMAGELIST hImgList;
32   int m_iIndent;      /* Indentation index */
33   LPITEMIDLIST pidlItem;  /* absolute pidl of the item */ 
34
35 } SFOLDER,*LPSFOLDER;
36
37 typedef struct tagLookInInfo
38 {
39   int iMaxIndentation;
40   UINT uSelectedItem;
41 } LookInInfos;
42
43
44 /***********************************************************************
45  * Defines and global variables
46  */
47
48 /* Draw item constant */
49 #define ICONWIDTH 18
50 #define YTEXTOFFSET 2
51 #define XTEXTOFFSET 3
52
53 /* AddItem flags*/
54 #define LISTEND -1
55
56 /* SearchItem methods */
57 #define SEARCH_PIDL 1
58 #define SEARCH_EXP  2
59 #define ITEM_NOTFOUND -1
60
61 /* Undefined windows message sent by CreateViewObject*/
62 #define WM_GETISHELLBROWSER  WM_USER+7
63
64 /* NOTE
65  * Those macros exist in windowsx.h. However, you can't really use them since
66  * they rely on the UNICODE defines and can't be use inside Wine itself.
67  */
68
69 /* Combo box macros */
70 #define CBAddString(hwnd,str) \
71   SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
72
73 #define CBInsertString(hwnd,str,pos) \
74   SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
75
76 #define CBDeleteString(hwnd,pos) \
77   SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
78
79 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
80   SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
81
82 #define CBGetItemDataPtr(hwnd,iItemId) \
83   SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
84
85 #define CBGetLBText(hwnd,iItemId,str) \
86   SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
87
88 #define CBGetCurSel(hwnd) \
89   SendMessageA(hwnd,CB_GETCURSEL,0,0);
90
91 #define CBSetCurSel(hwnd,pos) \
92   SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
93
94 #define CBGetCount(hwnd) \
95     SendMessageA(hwnd,CB_GETCOUNT,0,0);
96 #define CBShowDropDown(hwnd,show) \
97   SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
98 #define CBSetItemHeight(hwnd,index,height) \
99   SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
100
101
102 const char *FileOpenDlgInfosStr = "FileOpenDlgInfos"; /* windows property description string */
103 const char *LookInInfosStr = "LookInInfos"; /* LOOKIN combo box property */
104
105 static const char defaultFilter[] = "*.*";
106
107 /***********************************************************************
108  * Prototypes
109  */
110
111 /* Internal functions used by the dialog */
112 static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam);
113 static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
114 static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
115        BOOL    FILEDLG95_OnOpen(HWND hwnd);
116 static LRESULT FILEDLG95_InitUI(HWND hwnd);
117 static void    FILEDLG95_Clean(HWND hwnd);
118
119 /* Functions used by the shell object */
120 static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
121 static BOOL    FILEDLG95_SHELL_UpFolder(HWND hwnd);
122 static BOOL    FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
123 static BOOL    FILEDLG95_SHELL_NewFolder(HWND hwnd);
124 static void    FILEDLG95_SHELL_Clean(HWND hwnd);
125
126 /* Functions used by the filetype combo box */
127 static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd);
128 static BOOL    FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode);
129 static int     FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt);
130 static void    FILEDLG95_FILETYPE_Clean(HWND hwnd);
131
132 /* Functions used by the Look In combo box */
133 static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo);
134 static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct);
135 static BOOL    FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode);
136 static int     FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId);
137 static int     FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod);
138 static int     FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl);
139 static int     FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd);
140        int     FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
141 static void    FILEDLG95_LOOKIN_Clean(HWND hwnd);
142
143 /* Miscellaneous tool functions */
144 HRESULT       GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
145 HRESULT       GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
146 IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
147 LPITEMIDLIST  GetParentPidl(LPITEMIDLIST pidl);
148 LPITEMIDLIST  GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);
149
150 /* Shell memory allocation */
151 void *MemAlloc(UINT size);
152 void MemFree(void *mem);
153
154 BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos);
155 HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
156 HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode);
157 HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
158
159 /***********************************************************************
160  *      GetFileName95
161  *
162  * Creates an Open common dialog box that lets the user select 
163  * the drive, directory, and the name of a file or set of files to open.
164  *
165  * IN  : The FileOpenDlgInfos structure associated with the dialog
166  * OUT : TRUE on success
167  *       FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
168  */
169 BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos)
170 {
171
172     LRESULT lRes;
173     LPCVOID template;
174     HRSRC hRes;
175     HANDLE hDlgTmpl = 0;
176
177     /* Create the dialog from a template */
178
179     if(!(hRes = FindResourceA(COMMDLG_hInstance32,MAKEINTRESOURCEA(NEWFILEOPENORD),RT_DIALOGA)))
180     {
181         COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
182         return FALSE;
183     }
184     if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hRes )) ||
185         !(template = LockResource( hDlgTmpl )))
186     {
187         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
188         return FALSE;
189     }
190     lRes = DialogBoxIndirectParamA(COMMDLG_hInstance32,
191                                   (LPDLGTEMPLATEA) template,
192                                   fodInfos->ofnInfos.hwndOwner,
193                                   (DLGPROC) FileOpenDlgProc95,
194                                   (LPARAM) fodInfos);
195
196     /* Unable to create the dialog*/
197     if( lRes == -1)
198         return FALSE;
199     
200     return lRes;
201 }
202
203 /***********************************************************************
204  *      GetFileDialog95A
205  *
206  * Copy the OPENFILENAMEA structure in a FileOpenDlgInfos structure.
207  * Call GetFileName95 with this structure and clean the memory.
208  *
209  * IN  : The OPENFILENAMEA initialisation structure passed to
210  *       GetOpenFileNameA win api function (see filedlg.c)
211  */
212 BOOL  WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
213 {
214
215   BOOL ret;
216   FileOpenDlgInfos *fodInfos;
217   
218   /* Initialise FileOpenDlgInfos structure*/  
219   fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
220   memset(&fodInfos->ofnInfos,'\0',sizeof(*ofn)); fodInfos->ofnInfos.lStructSize = sizeof(*ofn);
221   fodInfos->ofnInfos.hwndOwner = ofn->hwndOwner;
222   fodInfos->ofnInfos.hInstance = MapHModuleLS(ofn->hInstance);
223   if (ofn->lpstrFilter)
224   {
225     LPSTR s,x;
226
227     /* filter is a list...  title\0ext\0......\0\0 */
228     s = (LPSTR)ofn->lpstrFilter;
229     while (*s)
230       s = s+strlen(s)+1;
231     s++;
232     x = (LPSTR)MemAlloc(s-ofn->lpstrFilter);
233     memcpy(x,ofn->lpstrFilter,s-ofn->lpstrFilter);
234     fodInfos->ofnInfos.lpstrFilter = (LPSTR)x;
235   }
236   if (ofn->lpstrCustomFilter)
237   {
238     LPSTR s,x;
239
240     /* filter is a list...  title\0ext\0......\0\0 */
241     s = (LPSTR)ofn->lpstrCustomFilter;
242     while (*s)
243       s = s+strlen(s)+1;
244     s++;
245     x = MemAlloc(s-ofn->lpstrCustomFilter);
246     memcpy(x,ofn->lpstrCustomFilter,s-ofn->lpstrCustomFilter);
247     fodInfos->ofnInfos.lpstrCustomFilter = (LPSTR)x;
248   }
249   fodInfos->ofnInfos.nMaxCustFilter = ofn->nMaxCustFilter;
250   if(ofn->nFilterIndex)
251     fodInfos->ofnInfos.nFilterIndex = --ofn->nFilterIndex;
252   if (ofn->nMaxFile)
253   {
254       fodInfos->ofnInfos.lpstrFile = (LPSTR)MemAlloc(ofn->nMaxFile);
255       strcpy((LPSTR)fodInfos->ofnInfos.lpstrFile,ofn->lpstrFile);
256   }
257   fodInfos->ofnInfos.nMaxFile = ofn->nMaxFile;
258   fodInfos->ofnInfos.nMaxFileTitle = ofn->nMaxFileTitle;
259     if (fodInfos->ofnInfos.nMaxFileTitle)
260       fodInfos->ofnInfos.lpstrFileTitle = (LPSTR)MemAlloc(ofn->nMaxFileTitle);
261   if (ofn->lpstrInitialDir)
262   {
263       fodInfos->ofnInfos.lpstrInitialDir = (LPSTR)MemAlloc(strlen(ofn->lpstrInitialDir)+1);
264       strcpy((LPSTR)fodInfos->ofnInfos.lpstrInitialDir,ofn->lpstrInitialDir);
265   }
266
267   if (ofn->lpstrTitle)
268   {
269       fodInfos->ofnInfos.lpstrTitle = (LPSTR)MemAlloc(strlen(ofn->lpstrTitle)+1);
270       strcpy((LPSTR)fodInfos->ofnInfos.lpstrTitle,ofn->lpstrTitle);
271   }
272
273   fodInfos->ofnInfos.Flags = ofn->Flags|OFN_WINE;
274   fodInfos->ofnInfos.nFileOffset = ofn->nFileOffset;
275   fodInfos->ofnInfos.nFileExtension = ofn->nFileExtension;
276   if (ofn->lpstrDefExt)
277   {
278       fodInfos->ofnInfos.lpstrDefExt = MemAlloc(strlen(ofn->lpstrDefExt)+1);
279       strcpy((LPSTR)fodInfos->ofnInfos.lpstrDefExt,ofn->lpstrDefExt);
280   }
281   fodInfos->ofnInfos.lCustData = ofn->lCustData;
282   fodInfos->ofnInfos.lpfnHook = (LPOFNHOOKPROC)ofn->lpfnHook;
283
284   if (ofn->lpTemplateName)
285   {
286       fodInfos->ofnInfos.lpTemplateName = ofn->lpTemplateName;
287   }
288
289   /* Replace the NULL lpstrInitialDir by the current folder */
290   if(!ofn->lpstrInitialDir)
291   {
292     fodInfos->ofnInfos.lpstrInitialDir = MemAlloc(MAX_PATH);
293     GetCurrentDirectoryA(MAX_PATH,(LPSTR)fodInfos->ofnInfos.lpstrInitialDir);
294   }
295
296   /* Initialise the dialog property */
297   fodInfos->DlgInfos.dwDlgProp = 0;
298   fodInfos->DlgInfos.hwndCustomDlg = (HWND)NULL;
299   
300   switch(iDlgType)
301   {
302   case OPEN_DIALOG :
303       ret = GetFileName95(fodInfos);
304       break;
305   case SAVE_DIALOG :
306       fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
307       ret = GetFileName95(fodInfos);
308       break;
309   default :
310       ret = 0;
311   }
312
313   ofn->nFileOffset = fodInfos->ofnInfos.nFileOffset;
314   ofn->nFileExtension = fodInfos->ofnInfos.nFileExtension;
315
316   /*
317      Transfer the combo index in the OPENFILENAME structure;
318      No support for custom filters, so nFilterIndex must be one-based.
319   */
320   ofn->nFilterIndex = fodInfos->ofnInfos.nFilterIndex + 1;
321
322   if (fodInfos->ofnInfos.lpstrFilter)
323       MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFilter));
324   if (fodInfos->ofnInfos.lpTemplateName)
325       MemFree((LPVOID)(fodInfos->ofnInfos.lpTemplateName));
326   if (fodInfos->ofnInfos.lpstrDefExt)
327       MemFree((LPVOID)(fodInfos->ofnInfos.lpstrDefExt));
328   if (fodInfos->ofnInfos.lpstrTitle)
329       MemFree((LPVOID)(fodInfos->ofnInfos.lpstrTitle));
330   if (fodInfos->ofnInfos.lpstrInitialDir)
331       MemFree((LPVOID)(fodInfos->ofnInfos.lpstrInitialDir));
332   if (fodInfos->ofnInfos.lpstrCustomFilter)
333       MemFree((LPVOID)(fodInfos->ofnInfos.lpstrCustomFilter));
334
335   if (fodInfos->ofnInfos.lpstrFile) 
336     {
337       strcpy(ofn->lpstrFile,fodInfos->ofnInfos.lpstrFile);
338       MemFree((LPVOID)fodInfos->ofnInfos.lpstrFile);
339     }
340   if (fodInfos->ofnInfos.lpstrFileTitle) 
341     {
342       if (ofn->lpstrFileTitle)
343           strcpy(ofn->lpstrFileTitle,
344                  fodInfos->ofnInfos.lpstrFileTitle);
345       MemFree((LPVOID)fodInfos->ofnInfos.lpstrFileTitle);
346       }
347
348   MemFree((LPVOID)(fodInfos));
349   return ret;
350 }
351
352 /***********************************************************************
353  *      GetFileDialog95W
354  *
355  * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
356  * Call GetFileName95 with this structure and clean the memory.
357  *
358  * IN  : The OPENFILENAMEW initialisation structure passed to
359  *       GetOpenFileNameW win api function (see filedlg.c)
360  */
361 BOOL  WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType)
362 {
363   BOOL ret;
364   FileOpenDlgInfos *fodInfos;
365
366   /* Initialise FileOpenDlgInfos structure*/
367   fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
368   memset(&fodInfos->ofnInfos,'\0',sizeof(*ofn));
369   fodInfos->ofnInfos.lStructSize = sizeof(*ofn);
370   fodInfos->ofnInfos.hwndOwner = ofn->hwndOwner;
371   fodInfos->ofnInfos.hInstance = MapHModuleLS(ofn->hInstance);
372   if (ofn->lpstrFilter)
373   {
374     LPWSTR  s;
375     LPSTR x,y;
376     int n;
377
378     /* filter is a list...  title\0ext\0......\0\0 */
379     s = (LPWSTR)ofn->lpstrFilter;
380     
381     while (*s)
382       s = s+lstrlenW(s)+1;
383     s++;
384     n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
385     x = y = (LPSTR)MemAlloc(n);
386     s = (LPWSTR)ofn->lpstrFilter;
387     while (*s) {
388       lstrcpyWtoA(x,s);
389       x+=lstrlenA(x)+1;
390       s+=lstrlenW(s)+1;
391     }
392     *x=0;
393     fodInfos->ofnInfos.lpstrFilter = (LPSTR)y;
394   }
395   if (ofn->lpstrCustomFilter) {
396     LPWSTR  s;
397     LPSTR x,y;
398     int n;
399
400     /* filter is a list...  title\0ext\0......\0\0 */
401     s = (LPWSTR)ofn->lpstrCustomFilter;
402     while (*s)
403       s = s+lstrlenW(s)+1;
404     s++;
405     n = s - ofn->lpstrCustomFilter;
406     x = y = (LPSTR)MemAlloc(n);
407     s = (LPWSTR)ofn->lpstrCustomFilter;
408     while (*s) {
409       lstrcpyWtoA(x,s);
410       x+=lstrlenA(x)+1;
411       s+=lstrlenW(s)+1;
412     }
413     *x=0;
414     fodInfos->ofnInfos.lpstrCustomFilter = (LPSTR)y;
415   }
416   fodInfos->ofnInfos.nMaxCustFilter = ofn->nMaxCustFilter;
417   fodInfos->ofnInfos.nFilterIndex = ofn->nFilterIndex;
418   if (ofn->nMaxFile)
419      fodInfos->ofnInfos.lpstrFile = (LPSTR)MemAlloc(ofn->nMaxFile);
420   fodInfos->ofnInfos.nMaxFile = ofn->nMaxFile;
421   fodInfos->ofnInfos.nMaxFileTitle = ofn->nMaxFileTitle;
422   if (ofn->nMaxFileTitle)
423     fodInfos->ofnInfos.lpstrFileTitle = (LPSTR)MemAlloc(ofn->nMaxFileTitle);
424   if (ofn->lpstrInitialDir)
425   {
426     fodInfos->ofnInfos.lpstrInitialDir = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrInitialDir)+1);
427     lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrInitialDir,ofn->lpstrInitialDir);
428   }
429   if (ofn->lpstrTitle)
430   {
431     fodInfos->ofnInfos.lpstrTitle = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrTitle)+1);
432     lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrTitle,ofn->lpstrTitle);
433   }
434   fodInfos->ofnInfos.Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
435   fodInfos->ofnInfos.nFileOffset = ofn->nFileOffset;
436   fodInfos->ofnInfos.nFileExtension = ofn->nFileExtension;
437   if (ofn->lpstrDefExt)
438   {
439     fodInfos->ofnInfos.lpstrDefExt = (LPSTR)MemAlloc(lstrlenW(ofn->lpstrDefExt)+1);
440     lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpstrDefExt,ofn->lpstrDefExt);
441   }
442   fodInfos->ofnInfos.lCustData = ofn->lCustData;
443   fodInfos->ofnInfos.lpfnHook = (LPOFNHOOKPROC)ofn->lpfnHook;
444   if (ofn->lpTemplateName) 
445   { 
446     fodInfos->ofnInfos.lpTemplateName = (LPSTR)MemAlloc(lstrlenW(ofn->lpTemplateName)+1);
447     lstrcpyWtoA((LPSTR)fodInfos->ofnInfos.lpTemplateName,ofn->lpTemplateName);
448   }
449   /* Initialise the dialog property */
450   fodInfos->DlgInfos.dwDlgProp = 0;
451   
452   switch(iDlgType)
453   {
454   case OPEN_DIALOG :
455       ret = GetFileName95(fodInfos);
456       break;
457   case SAVE_DIALOG :
458       fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
459       ret = GetFileName95(fodInfos);
460       break;
461   default :
462       ret = 0;
463   }
464       
465   /* Cleaning */
466   ofn->nFileOffset = fodInfos->ofnInfos.nFileOffset;
467   ofn->nFileExtension = fodInfos->ofnInfos.nFileExtension;
468
469   /*
470      Transfer the combo index in the OPENFILENAME structure;
471      No support for custom filters, so nFilterIndex must be one-based.
472   */
473   ofn->nFilterIndex = fodInfos->ofnInfos.nFilterIndex + 1;
474
475   if (fodInfos->ofnInfos.lpstrFilter)
476     MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFilter));
477   if (fodInfos->ofnInfos.lpTemplateName)
478     MemFree((LPVOID)(fodInfos->ofnInfos.lpTemplateName));
479   if (fodInfos->ofnInfos.lpstrDefExt)
480     MemFree((LPVOID)(fodInfos->ofnInfos.lpstrDefExt));
481   if (fodInfos->ofnInfos.lpstrTitle)
482     MemFree((LPVOID)(fodInfos->ofnInfos.lpstrTitle));
483   if (fodInfos->ofnInfos.lpstrInitialDir)
484     MemFree((LPVOID)(fodInfos->ofnInfos.lpstrInitialDir));
485   if (fodInfos->ofnInfos.lpstrCustomFilter)
486     MemFree((LPVOID)(fodInfos->ofnInfos.lpstrCustomFilter));
487
488   if (fodInfos->ofnInfos.lpstrFile) {
489   lstrcpyAtoW(ofn->lpstrFile,(fodInfos->ofnInfos.lpstrFile));
490   MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFile));
491   }
492
493   if (fodInfos->ofnInfos.lpstrFileTitle) {
494       if (ofn->lpstrFileTitle)
495                 lstrcpyAtoW(ofn->lpstrFileTitle,
496       (fodInfos->ofnInfos.lpstrFileTitle));
497       MemFree((LPVOID)(fodInfos->ofnInfos.lpstrFileTitle));
498   }
499   MemFree((LPVOID)(fodInfos));
500   return ret;
501
502 }
503
504 void ArrangeCtrlPositions( HWND hwndChildDlg, HWND hwndParentDlg)
505 {
506
507         HWND hwndChild,hwndStc32;
508         RECT rectParent, rectChild, rectCtrl, rectStc32, rectTemp;
509         POINT ptMoveCtl;
510         HDWP handle;
511         POINT ptParentClient;
512
513         ptMoveCtl.x = ptMoveCtl.y = 0;
514         hwndStc32=GetDlgItem(hwndChildDlg,stc32);
515         GetClientRect(hwndParentDlg,&rectParent);
516         GetClientRect(hwndChildDlg,&rectChild);
517         if(hwndStc32)
518         {
519                 GetWindowRect(hwndStc32,&rectStc32);
520                 MapWindowPoints(0, hwndChildDlg,(LPPOINT)&rectStc32,2);
521                 CopyRect(&rectTemp,&rectStc32);
522
523                 SetRect(&rectStc32,rectStc32.left,rectStc32.top,rectStc32.left + (rectParent.right-rectParent.left),rectStc32.top+(rectParent.bottom-rectParent.top));
524                 SetWindowPos(hwndStc32,0,rectStc32.left,rectStc32.top,rectStc32.right-rectStc32.left,rectStc32.bottom-rectStc32.top,SWP_NOMOVE|SWP_NOZORDER | SWP_NOACTIVATE);
525
526                 if(rectStc32.right < rectTemp.right)
527                 {
528                         ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
529                         ptMoveCtl.x = 0;
530                 }
531                 else
532                 {
533                         ptMoveCtl.x = (rectStc32.right - rectTemp.right);
534                         ptParentClient.x = max((rectParent.right-rectParent.left),((rectChild.right-rectChild.left)+rectStc32.right-rectTemp.right));
535                 }
536                 if(rectStc32.bottom < rectTemp.bottom)
537                 {
538                         ptParentClient.y = max((rectParent.bottom-rectParent.top),(rectChild.bottom-rectChild.top));
539                         ptMoveCtl.y = 0;
540                 }
541                 else
542                 {
543                         ptMoveCtl.y = (rectStc32.bottom - rectTemp.bottom);
544                         ptParentClient.y = max((rectParent.bottom-rectParent.top),((rectChild.bottom-rectChild.top)+rectStc32.bottom-rectTemp.bottom));
545                 }
546         }
547         else
548         {
549                 if( (GetWindow(hwndChildDlg,GW_CHILD)) == (HWND) NULL)
550                    return;
551                 ptParentClient.x = rectParent.right-rectParent.left;
552                 ptParentClient.y = (rectParent.bottom-rectParent.top) + (rectChild.bottom-rectChild.top);
553                 ptMoveCtl.y = rectParent.bottom-rectParent.top;
554                 ptMoveCtl.x=0;
555         }
556         SetRect(&rectParent,rectParent.left,rectParent.top,rectParent.left+ptParentClient.x,rectParent.top+ptParentClient.y);
557         AdjustWindowRectEx( &rectParent,GetWindowLongA(hwndParentDlg,GWL_STYLE),FALSE,GetWindowLongA(hwndParentDlg,GWL_EXSTYLE));
558
559         SetWindowPos(hwndChildDlg, 0, 0,0, ptParentClient.x,ptParentClient.y,
560                  SWP_NOZORDER );
561         SetWindowPos(hwndParentDlg, 0, rectParent.left,rectParent.top, (rectParent.right- rectParent.left),
562                 (rectParent.bottom-rectParent.top),SWP_NOMOVE | SWP_NOZORDER);
563         
564         hwndChild = GetWindow(hwndChildDlg,GW_CHILD);
565         handle = BeginDeferWindowPos( 1 );
566         if(hwndStc32)
567         {
568                 GetWindowRect(hwndStc32,&rectStc32);
569                 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
570         }
571         else
572                 SetRect(&rectStc32,0,0,0,0);
573
574         if (hwndChild && handle)
575         {
576                 do
577                 {
578                         if(hwndChild != hwndStc32)
579                         {
580                         if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
581                                 continue;
582                         GetWindowRect(hwndChild,&rectCtrl);
583                         MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
584                                   
585                                 /*
586                                    Check the initial position of the controls relative to the initial
587                                    position and size of stc32 (before it is expanded).
588                                 */
589                 if (rectCtrl.left > rectTemp.right && rectCtrl.top > rectTemp.bottom)
590                                 {
591                                         rectCtrl.left += ptMoveCtl.x;
592                                 rectCtrl.top  += ptMoveCtl.y;
593                                 }
594                                 else if (rectCtrl.left > rectTemp.right)
595                                         rectCtrl.left += ptMoveCtl.x;
596                                 else if (rectCtrl.top > rectTemp.bottom)
597                                         rectCtrl.top  += ptMoveCtl.y;
598                                         
599                                 handle = DeferWindowPos(handle, hwndChild, 0, rectCtrl.left, rectCtrl.top, 
600                                 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
601                                 SWP_NOSIZE | SWP_NOZORDER );
602                                 }
603                         }
604                 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL && handle);
605         }               
606         if(handle)
607                 EndDeferWindowPos( handle );
608         handle = BeginDeferWindowPos( 1 );
609         hwndChild = GetWindow(hwndParentDlg,GW_CHILD);
610         
611         if(hwndStc32)
612         {
613                 GetWindowRect(hwndStc32,&rectStc32);
614                 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
615                 ptMoveCtl.x = rectStc32.left - 0;
616                 ptMoveCtl.y = rectStc32.top - 0;
617                 if (hwndChild && handle)
618                 {
619                         do
620                         {
621                                 if(hwndChild != hwndChildDlg)
622                                 {
623
624                                         if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
625                                                 continue;
626                                         GetWindowRect(hwndChild,&rectCtrl);
627                                         MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
628
629                                         rectCtrl.left += ptMoveCtl.x;
630                                         rectCtrl.top += ptMoveCtl.y;
631
632                                         handle = DeferWindowPos(        handle, hwndChild, 0, rectCtrl.left, rectCtrl.top, 
633                                         rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
634                                         SWP_NOSIZE |SWP_NOZORDER );
635                                 }
636                         }
637                         while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
638                 }               
639                 if(handle)
640                 EndDeferWindowPos( handle );
641         }
642
643 }
644
645
646 HRESULT WINAPI FileOpenDlgProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
647 {
648   static WNDPROC procUserHook=NULL;
649   switch(uMsg)
650   {
651         case WM_INITDIALOG:
652         {         
653                 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *)lParam;
654                 procUserHook=NULL;
655                 lParam = (LPARAM) &fodInfos->ofnInfos;
656                 ArrangeCtrlPositions(hwnd,GetParent(hwnd));
657                 if(fodInfos->ofnInfos.Flags & OFN_ENABLEHOOK)
658                         procUserHook = (WNDPROC) fodInfos->ofnInfos.lpfnHook;
659                 if(procUserHook)
660                          return CallWindowProcA(procUserHook,hwnd,uMsg,wParam,lParam);
661                 return 0;       
662         } }
663  if(procUserHook)
664       return CallWindowProcA(procUserHook,hwnd,uMsg,wParam,lParam); 
665   return DefWindowProcA(hwnd,uMsg,wParam,lParam); 
666 }
667
668 HWND CreateTemplateDialog(FileOpenDlgInfos *fodInfos,HWND hwnd)
669 {
670     LPCVOID template;
671     HRSRC hRes;
672     HANDLE hDlgTmpl = 0;
673     HWND hChildDlg = 0;
674    if (fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATE || fodInfos->ofnInfos.Flags & OFN_ENABLETEMPLATEHANDLE)
675    {
676         if (fodInfos->ofnInfos.Flags  & OFN_ENABLETEMPLATEHANDLE)
677         {
678            if( !(template = LockResource( fodInfos->ofnInfos.hInstance)))
679                 {
680                 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
681                 return (HWND)NULL;
682                 }
683                 
684         }
685         else
686         {
687          if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos.hInstance),
688             (fodInfos->ofnInfos.lpTemplateName), RT_DIALOGA)))
689         {
690                 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
691                  return (HWND)NULL;
692         }
693         if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos.hInstance),
694              hRes )) ||
695                  !(template = LockResource( hDlgTmpl )))
696         {
697                 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
698                 return (HWND)NULL;
699         }
700         }
701
702         hChildDlg= CreateDialogIndirectParamA(fodInfos->ofnInfos.hInstance,template,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
703         if(hChildDlg)
704         {
705                 ShowWindow(hChildDlg,SW_SHOW); 
706                 return hChildDlg;
707         }
708  }
709  else if(fodInfos->ofnInfos.Flags & OFN_ENABLEHOOK && fodInfos->ofnInfos.lpfnHook)
710  {
711         RECT rectHwnd;
712         DLGTEMPLATE tmplate;
713         GetClientRect(hwnd,&rectHwnd);
714         tmplate.style = WS_CHILD | WS_CLIPSIBLINGS;
715         tmplate.dwExtendedStyle = 0;
716         tmplate.cdit = 0;
717         tmplate.x = 0;
718         tmplate.y = 0;
719         tmplate.cx = rectHwnd.right-rectHwnd.left;
720         tmplate.cy = rectHwnd.bottom-rectHwnd.top;
721        
722         return CreateDialogIndirectParamA(fodInfos->ofnInfos.hInstance,&tmplate,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
723  }
724 return (HWND)NULL;
725 }
726
727 /***********************************************************************
728 *          SendCustomDlgNotificationMessage
729 *
730 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
731 */
732
733 HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode)
734 {
735     FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwndParentDlg,FileOpenDlgInfosStr);
736     if(!fodInfos)
737         return 0;
738     if(fodInfos->DlgInfos.hwndCustomDlg)
739     {
740         OFNOTIFYA ofnNotify;
741         ofnNotify.hdr.hwndFrom=hwndParentDlg;
742         ofnNotify.hdr.idFrom=0;
743         ofnNotify.hdr.code = uCode;
744         ofnNotify.lpOFN = &fodInfos->ofnInfos;
745         return SendMessageA(fodInfos->DlgInfos.hwndCustomDlg,WM_NOTIFY,0,(LPARAM)&ofnNotify);
746     }
747     return TRUE;
748 }
749
750 /***********************************************************************
751 *         FILEDLG95_HandleCustomDialogMessages
752 *
753 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
754 */
755 HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
756 {
757     LPSTR lpstrFileSpec;
758     char lpstrCurrentDir[MAX_PATH]="";
759     FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
760     if(!fodInfos)
761         return TRUE;
762     switch(uMsg)
763     {
764         case CDM_GETFILEPATH:
765         { 
766             char lpstrPathSpec[MAX_PATH]="";
767             GetDlgItemTextA(hwnd,IDC_FILENAME,(LPSTR)lParam, (int)wParam);
768             lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA((LPSTR)lParam);
769             strcpy(lpstrPathSpec,(LPSTR)lParam);
770             COMDLG32_PathRemoveFileSpecA(lpstrPathSpec);
771             if(!lpstrPathSpec[0])
772                 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
773                 lpstrPathSpec);
774             strcat(lpstrPathSpec,"\\");
775             strcat(lpstrPathSpec,(LPSTR)lParam);
776             strcpy((LPSTR)lParam,(LPSTR)lpstrPathSpec);
777         }
778             return TRUE;
779         case CDM_GETFOLDERPATH:
780             if(lParam)
781             {
782                 if(fodInfos)
783                 {
784                     COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
785                     lpstrCurrentDir);
786                     strncpy((LPSTR)lParam,lpstrCurrentDir,(int)wParam);
787                 }
788                 else
789                 *((LPSTR)lParam)=0;
790             }
791             return TRUE;
792     case CDM_GETSPEC:
793             if(lParam)
794             {
795                 GetDlgItemTextA(hwnd,IDC_FILENAME,(LPSTR)lParam, (int)wParam);
796                 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA((LPSTR)lParam);
797                 if(lpstrFileSpec)
798                    strcpy((LPSTR)lParam, lpstrFileSpec);
799                 else
800                     *((LPSTR)lParam)=0;
801             }
802             return TRUE;
803         case CDM_HIDECONTROL:
804         case CDM_SETCONTROLTEXT:
805         case CDM_SETDEFEXT:
806         FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
807         return TRUE;
808     }
809     return TRUE;
810 }
811  
812 /***********************************************************************
813  *          FileOpenDlgProc95
814  *
815  * File open dialog procedure
816  */
817 HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
818 {
819
820   switch(uMsg)
821   {
822     case WM_INITDIALOG :
823          ((FileOpenDlgInfos *)lParam)->DlgInfos.hwndCustomDlg = 
824         CreateTemplateDialog((FileOpenDlgInfos *)lParam,hwnd);
825          FILEDLG95_OnWMInitDialog(hwnd, wParam, lParam);
826          SendCustomDlgNotificationMessage(hwnd,CDN_INITDONE);
827          return 0;
828     case WM_COMMAND:
829       return FILEDLG95_OnWMCommand(hwnd, wParam, lParam);
830     case WM_DRAWITEM:
831       {
832         switch(((LPDRAWITEMSTRUCT)lParam)->CtlID)
833         {
834         case IDC_LOOKIN:
835           FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT) lParam);
836           return TRUE;
837         }
838       }
839       return FALSE;
840           
841     case WM_GETISHELLBROWSER:
842       return FILEDLG95_OnWMGetIShellBrowser(hwnd);
843
844   case WM_DESTROY:
845       RemovePropA(hwnd, FileOpenDlgInfosStr);
846
847     default :
848       if(uMsg >= CDM_FIRST && uMsg <= CDM_LAST)
849         return FILEDLG95_HandleCustomDialogMessages(hwnd, uMsg, wParam, lParam);
850       return FALSE;
851   }
852 }
853
854 /***********************************************************************
855  *      FILEDLG95_OnWMInitDialog
856  *
857  * WM_INITDIALOG message handler
858  */
859 static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam)
860 {
861   LPITEMIDLIST pidlItemId;
862   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) lParam;
863
864   TRACE("\n");
865
866   /* Adds the FileOpenDlgInfos in the property list of the dialog 
867      so it will be easily accessible through a GetPropA(...) */
868   SetPropA(hwnd, FileOpenDlgInfosStr, (HANDLE) fodInfos);
869
870   /* Make sure the common control DLL is loaded */      
871   InitCommonControls();
872
873   /* Initialise shell objects */
874   FILEDLG95_SHELL_Init(hwnd);
875
876   /* Initialise dialog UI */
877   FILEDLG95_InitUI(hwnd);
878
879   /* Initialize the Look In combo box*/
880   FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
881
882   /* Initialize the filter combo box */
883   FILEDLG95_FILETYPE_Init(hwnd);
884
885   /* Get the initial directory pidl */
886
887   if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos.lpstrInitialDir)))
888   {
889     char path[MAX_PATH];
890
891     GetCurrentDirectoryA(MAX_PATH,path);
892     pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
893                      path);
894
895   }
896
897   /* Browse to the initial directory */
898   IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId,SBSP_RELATIVE);
899
900   /* Free pidlItem memory */
901   COMDLG32_SHFree(pidlItemId);
902
903   return TRUE;
904 }
905 /***********************************************************************
906  *      FILEDLG95_Clean
907  *
908  * Regroups all the cleaning functions of the filedlg
909  */
910 void FILEDLG95_Clean(HWND hwnd)
911 {
912       FILEDLG95_FILETYPE_Clean(hwnd);
913       FILEDLG95_LOOKIN_Clean(hwnd);
914       FILEDLG95_SHELL_Clean(hwnd);
915 }
916 /***********************************************************************
917  *      FILEDLG95_OnWMCommand
918  *
919  * WM_COMMAND message handler
920  */
921 static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
922 {
923   WORD wNotifyCode = HIWORD(wParam); /* notification code */
924   WORD wID = LOWORD(wParam);         /* item, control, or accelerator identifier */
925   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
926
927   switch(wID)
928   {
929     /* OK button */
930   case IDOK:
931       if(FILEDLG95_OnOpen(hwnd))
932         SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
933     break;
934     /* Cancel button */
935   case IDCANCEL:
936       FILEDLG95_Clean(hwnd);
937       EndDialog(hwnd, FALSE);
938     break;
939     /* Filetype combo box */
940   case IDC_FILETYPE:
941     FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
942     SendCustomDlgNotificationMessage(hwnd,CDN_TYPECHANGE);
943     break;
944     /* LookIn combo box */
945   case IDC_LOOKIN:
946     FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
947     break;
948
949   /* --- toolbar --- */
950     /* Up folder button */
951   case FCIDM_TB_UPFOLDER:
952     FILEDLG95_SHELL_UpFolder(hwnd);
953     break;
954     /* New folder button */
955   case FCIDM_TB_NEWFOLDER:
956     FILEDLG95_SHELL_NewFolder(hwnd);
957     break;
958     /* List option button */
959   case FCIDM_TB_SMALLICON:
960     FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
961     break;
962     /* Details option button */
963   case FCIDM_TB_REPORTVIEW:
964     FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
965     break;
966
967   case IDC_FILENAME:
968     break;
969
970   }
971   /* Do not use the listview selection anymore */
972   fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
973   return 0; 
974 }
975
976 /***********************************************************************
977  *      FILEDLG95_OnWMGetIShellBrowser
978  *
979  * WM_GETISHELLBROWSER message handler
980  */
981 static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
982 {
983
984   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
985
986   TRACE("\n");
987
988   SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
989
990   return TRUE; 
991 }
992
993
994 /***********************************************************************
995  *      FILEDLG95_InitUI
996  *
997  */
998 static LRESULT FILEDLG95_InitUI(HWND hwnd)
999 {
1000   TBBUTTON tbb[] =
1001   {{VIEW_PARENTFOLDER, FCIDM_TB_UPFOLDER,   TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1002    {0,                 0,                   TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
1003    {VIEW_NEWFOLDER,    FCIDM_TB_NEWFOLDER,  TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1004    {0,                 0,                   TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
1005    {VIEW_LIST,         FCIDM_TB_SMALLICON,  TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1006    {VIEW_DETAILS,      FCIDM_TB_REPORTVIEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
1007   };
1008   RECT rectTB;
1009   
1010   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1011
1012   TRACE("%p\n", fodInfos);
1013
1014   /* Get the hwnd of the controls */
1015   fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
1016   fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
1017   fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
1018
1019   /* construct the toolbar */
1020   GetWindowRect(GetDlgItem(hwnd,IDC_TOOLBARSTATIC),&rectTB);
1021   MapWindowPoints( 0, hwnd,(LPPOINT)&rectTB,2);
1022
1023   fodInfos->DlgInfos.hwndTB = CreateWindowExA(0, TOOLBARCLASSNAMEA, (LPSTR) NULL, 
1024         WS_CHILD | WS_GROUP | TBSTYLE_TOOLTIPS | CCS_NODIVIDER | CCS_NORESIZE,
1025         0, 0, 150, 26,
1026         hwnd, (HMENU) IDC_TOOLBAR, COMMDLG_hInstance32, NULL); 
1027  
1028   SetWindowPos(fodInfos->DlgInfos.hwndTB, 0, 
1029         rectTB.left,rectTB.top, rectTB.right-rectTB.left, rectTB.bottom-rectTB.top,
1030         SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
1031
1032   SendMessageA(fodInfos->DlgInfos.hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
1033   SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);
1034   SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBUTTONSA, (WPARAM) 6,(LPARAM) &tbb);
1035   SendMessageA(fodInfos->DlgInfos.hwndTB, TB_AUTOSIZE, 0, 0); 
1036
1037   /* Set the window text with the text specified in the OPENFILENAME structure */
1038   if(fodInfos->ofnInfos.lpstrTitle)
1039   {
1040       SetWindowTextA(hwnd,fodInfos->ofnInfos.lpstrTitle);
1041   }
1042   else if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1043   {
1044       SetWindowTextA(hwnd,"Save");
1045   }
1046
1047   /* Initialise the file name edit control */
1048   if(strlen(fodInfos->ofnInfos.lpstrFile))
1049   {
1050       SetDlgItemTextA(hwnd,IDC_FILENAME,fodInfos->ofnInfos.lpstrFile);
1051   }
1052   /* Must the open as read only check box be checked ?*/
1053   if(fodInfos->ofnInfos.Flags & OFN_READONLY)
1054   {
1055     SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
1056   }
1057   /* Must the open as read only check box be hid ?*/
1058   if(fodInfos->ofnInfos.Flags & OFN_HIDEREADONLY)
1059   {
1060     ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
1061   }
1062   /* change Open to Save */
1063   if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1064   {
1065       SetDlgItemTextA(hwnd,IDOK,"Save");
1066   }
1067   return 0;
1068 }
1069
1070 /***********************************************************************
1071  *      FILEDLG95_OnOpen
1072  *
1073  * Ok button WM_COMMAND message handler
1074  * 
1075  * If the function succeeds, the return value is nonzero.
1076  */
1077 BOOL FILEDLG95_OnOpen(HWND hwnd)
1078 {
1079   char lpstrSpecifiedByUser[MAX_PATH] = "";
1080   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1081   LPITEMIDLIST pidlSelection;
1082
1083   TRACE("\n");
1084
1085   /* Check if there is a selected item in the listview */
1086   if(fodInfos->DlgInfos.dwDlgProp & FODPROP_USEVIEW)
1087   {
1088       pidlSelection = GetSelectedPidl(fodInfos->Shell.FOIShellView);
1089       GetName(fodInfos->Shell.FOIShellFolder,pidlSelection,SHGDN_NORMAL,lpstrSpecifiedByUser);
1090       COMDLG32_SHFree((LPVOID)pidlSelection);
1091   }
1092   else
1093       /* Get the text from the filename edit */
1094       GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrSpecifiedByUser,MAX_PATH);
1095
1096   if(strlen(lpstrSpecifiedByUser))
1097   {
1098       LPSHELLFOLDER psfDesktop;
1099       LPITEMIDLIST browsePidl;
1100       LPSTR lpstrFileSpec;
1101       LPSTR lpstrTemp;
1102       char lpstrPathSpec[MAX_PATH] = "";
1103       char lpstrCurrentDir[MAX_PATH] = "";
1104       char lpstrPathAndFile[MAX_PATH] = "";
1105
1106       /* Separate the file spec from the path spec 
1107          e.g.: 
1108               lpstrSpecifiedByUser  lpstrPathSpec  lpstrFileSpec
1109               C:\TEXT1\TEXT2        C:\TEXT1          TEXT2
1110       */      
1111       lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrSpecifiedByUser);
1112       strcpy(lpstrPathSpec,lpstrSpecifiedByUser);
1113       COMDLG32_PathRemoveFileSpecA(lpstrPathSpec);
1114       
1115       /* Get the index of the selected item in the filetype combo box */
1116       fodInfos->ofnInfos.nFilterIndex = (DWORD) CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1117
1118       /* Get the current directory name */
1119       COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
1120                                     lpstrCurrentDir);
1121
1122       /* Create an absolute path name */ 
1123       if(lpstrSpecifiedByUser[1] != ':')
1124       {
1125           switch(lpstrSpecifiedByUser[0])
1126           {
1127           /* Add drive spec  \TEXT => C:\TEXT */
1128           case '\\':
1129               {
1130                   INT iCopy = 2;
1131                   char lpstrTmp[MAX_PATH] = "";
1132                   if(!strlen(lpstrPathSpec))
1133                       iCopy = 3;
1134                   strncpy(lpstrTmp,lpstrCurrentDir,iCopy);
1135                   strcat(lpstrTmp,lpstrPathSpec);
1136                   strcpy(lpstrPathSpec,lpstrTmp);
1137               }
1138               break;           
1139           /* Go to parent ..\TEXT */ 
1140           case '.':
1141               {
1142                   INT iSize;
1143                   char lpstrTmp2[MAX_PATH] = "";
1144                   LPSTR lpstrTmp = strrchr(lpstrCurrentDir,'\\');
1145                   iSize = lpstrTmp - lpstrCurrentDir;
1146                   strncpy(lpstrTmp2,lpstrCurrentDir,iSize + 1);
1147                   if(strlen(lpstrSpecifiedByUser) <= 3)
1148                       strcpy(lpstrFileSpec,"");
1149                   if(strcmp(lpstrPathSpec,".."))
1150                       strcat(lpstrTmp2,&lpstrPathSpec[3]);
1151                   strcpy(lpstrPathSpec,lpstrTmp2);
1152               }
1153               break;
1154           default:
1155   {
1156                   char lpstrTmp[MAX_PATH] = "";
1157                   if(strcmp(&lpstrCurrentDir[strlen(lpstrCurrentDir)-1],"\\"))
1158                       strcat(lpstrCurrentDir,"\\");
1159                   strcpy(lpstrTmp,lpstrCurrentDir);
1160                   strcat(lpstrTmp,lpstrPathSpec);
1161                   strcpy(lpstrPathSpec,lpstrTmp);
1162               }
1163                  
1164           } /* end switch */
1165       }
1166
1167       if(strlen(lpstrPathSpec))
1168       {
1169           /* Browse to the right directory */
1170           COMDLG32_SHGetDesktopFolder(&psfDesktop); 
1171           if((browsePidl = GetPidlFromName(psfDesktop,lpstrPathSpec)))
1172           {
1173               /* Browse to directory */
1174               IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1175                                          browsePidl,
1176                                          SBSP_ABSOLUTE);
1177               COMDLG32_SHFree(browsePidl);
1178           }
1179           else
1180           {
1181               /* Path does not exist */
1182               if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1183               {
1184                   MessageBoxA(hwnd,
1185                               "Path does not exist",
1186                               fodInfos->ofnInfos.lpstrTitle,
1187                               MB_OK | MB_ICONEXCLAMATION);
1188                   return FALSE;
1189               }
1190           }
1191           
1192           strcat(lpstrPathAndFile,lpstrPathSpec);
1193           IShellFolder_Release(psfDesktop);
1194       }
1195       else
1196       {
1197           strcat(lpstrPathAndFile,lpstrCurrentDir);
1198       }
1199
1200       /* Create the path and file string */
1201       COMDLG32_PathAddBackslashA(lpstrPathAndFile);
1202       strcat(lpstrPathAndFile,lpstrFileSpec);
1203       
1204       /* Update the edit field */
1205       SetDlgItemTextA(hwnd,IDC_FILENAME,lpstrFileSpec);
1206       SendDlgItemMessageA(hwnd,IDC_FILENAME,EM_SETSEL,0,-1);
1207       
1208       /* Don't go further if we dont have a file spec */
1209       if(!strlen(lpstrFileSpec) || !strcmp(lpstrFileSpec,lpstrPathSpec))
1210           return FALSE;
1211
1212       /* Time to check lpstrFileSpec         */ 
1213       /* search => contains * or ?           */
1214       /* browse => contains a directory name */
1215       /* file   => contains a file name      */
1216
1217     /* Check if this is a search */
1218       if(strchr(lpstrFileSpec,'*') || strchr(lpstrFileSpec,'?'))
1219     {
1220       int iPos;
1221
1222        /* Set the current filter with the current selection */
1223       if(fodInfos->ShellInfos.lpstrCurrentFilter)
1224          MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1225
1226           fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFileSpec)+1)*2);
1227           lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,
1228                       (LPSTR)strlwr((LPSTR)lpstrFileSpec));
1229       
1230       IShellView_Refresh(fodInfos->Shell.FOIShellView);
1231
1232           if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB,
1233                                                        lpstrFileSpec)))
1234         CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1235
1236       return FALSE;
1237     }
1238
1239       /* browse if the user specified a directory */
1240       if((browsePidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
1241                                        lpstrFileSpec)))
1242     {
1243           ULONG  ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
1244           int    nMsgBoxRet;
1245           char   lpstrFileExist[MAX_PATH + 50];
1246
1247           IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 
1248                                        1, 
1249                                        &browsePidl, 
1250                                        &ulAttr);
1251
1252           /* The file does exist, so ask the user if we should overwrite it */
1253           if(fodInfos->ofnInfos.Flags & OFN_OVERWRITEPROMPT)
1254           {
1255                 strcpy(lpstrFileExist, lpstrFileSpec);
1256                 strcat(lpstrFileExist, " already exists.\nDo you want to replace it?");
1257
1258                 nMsgBoxRet = MessageBoxA(hwnd,
1259                                         lpstrFileExist,
1260                                         fodInfos->ofnInfos.lpstrTitle,
1261                                         MB_YESNO | MB_ICONEXCLAMATION);
1262                 if(nMsgBoxRet == IDNO) return FALSE;
1263           }
1264         
1265           /* Browse to directory */
1266           if(ulAttr)
1267         {
1268               if(FAILED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1269                                                    browsePidl,
1270                                                    SBSP_RELATIVE)))
1271         {
1272                   if(fodInfos->ofnInfos.Flags & OFN_PATHMUSTEXIST)
1273         {
1274                       MessageBoxA(hwnd,
1275                                   "Path does not exist",
1276                                   fodInfos->ofnInfos.lpstrTitle,
1277                                   MB_OK | MB_ICONEXCLAMATION);
1278                       COMDLG32_SHFree(browsePidl);
1279                       return FALSE;
1280         }
1281     }
1282               COMDLG32_SHFree(browsePidl);
1283               return FALSE;
1284     }
1285           COMDLG32_SHFree(browsePidl);
1286       }
1287       else
1288     {
1289           /* File does not exist in current directory */
1290
1291           /* The selected file does not exist */
1292       /* Tell the user the selected does not exist */
1293       if(fodInfos->ofnInfos.Flags & OFN_FILEMUSTEXIST)
1294       {
1295         char lpstrNotFound[100];
1296         char lpstrMsg[100];
1297         char tmp[400];
1298
1299               LoadStringA(COMMDLG_hInstance32,
1300                           IDS_FILENOTFOUND,
1301                           lpstrNotFound,
1302                           100);
1303               LoadStringA(COMMDLG_hInstance32,
1304                           IDS_VERIFYFILE,
1305                           lpstrMsg,
1306                           100);
1307
1308         strcpy(tmp,fodInfos->ofnInfos.lpstrFile);
1309         strcat(tmp,"\n");
1310         strcat(tmp,lpstrNotFound);
1311         strcat(tmp,"\n");
1312         strcat(tmp,lpstrMsg);
1313
1314               MessageBoxA(hwnd,
1315                           tmp,
1316                           fodInfos->ofnInfos.lpstrTitle,
1317                           MB_OK | MB_ICONEXCLAMATION);
1318         return FALSE;
1319       }
1320       /* Ask the user if he wants to create the file*/
1321       if(fodInfos->ofnInfos.Flags & OFN_CREATEPROMPT)
1322       {
1323         char tmp[100];
1324
1325         LoadStringA(COMMDLG_hInstance32,IDS_CREATEFILE,tmp,100);
1326
1327               if(IDYES == MessageBoxA(hwnd,tmp,fodInfos->ofnInfos.lpstrTitle,
1328                                       MB_YESNO | MB_ICONQUESTION))
1329         {
1330             /* Create the file, clean and exit */
1331             FILEDLG95_Clean(hwnd);
1332             return EndDialog(hwnd,TRUE);
1333         }
1334         return FALSE;        
1335       }
1336     }
1337
1338       /* Open the selected file */
1339
1340       /* Check file extension */
1341       if(!strrchr(lpstrPathAndFile,'.'))
1342       {
1343           /* if the file has no extension, append the selected
1344              extension of the filetype combo box */
1345           int iExt; 
1346           LPSTR lpstrExt;
1347           iExt = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1348           lpstrTemp = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iExt);
1349
1350           if((lpstrExt = strchr(lpstrTemp,';')))
1351           {
1352               int i = lpstrExt - lpstrTemp;
1353               lpstrExt = MemAlloc(i);
1354               strncpy(lpstrExt,&lpstrTemp[1],i-1);
1355           }
1356           else
1357           {
1358               lpstrExt = MemAlloc(strlen(lpstrTemp));
1359               strcpy(lpstrExt,&lpstrTemp[1]);
1360           }
1361                   
1362           if(!strcmp(&lpstrExt[1],"*") && fodInfos->ofnInfos.lpstrDefExt)
1363           {
1364               lpstrExt = MemAlloc(strlen(fodInfos->ofnInfos.lpstrDefExt)+2);
1365               strcat(lpstrExt,".");
1366               strcat(lpstrExt,(LPSTR) fodInfos->ofnInfos.lpstrDefExt);
1367           }
1368           strcat(lpstrPathAndFile,lpstrExt);
1369       }
1370       /* Check that size size of the file does not exceed buffer size */
1371       if(strlen(lpstrPathAndFile) > fodInfos->ofnInfos.nMaxFile)
1372       {
1373           /* set error FNERR_BUFFERTOSMALL */
1374           FILEDLG95_Clean(hwnd);
1375           return EndDialog(hwnd,FALSE);
1376       }
1377       strcpy(fodInfos->ofnInfos.lpstrFile,lpstrPathAndFile);
1378
1379       /* Set the lpstrFileTitle of the OPENFILENAME structure */
1380       if(fodInfos->ofnInfos.lpstrFileTitle)
1381           strncpy(fodInfos->ofnInfos.lpstrFileTitle,
1382                   lpstrFileSpec,
1383                   fodInfos->ofnInfos.nMaxFileTitle);
1384
1385       /* Check if the file is to be opened as read only */            
1386       if(BST_CHECKED == SendDlgItemMessageA(hwnd,
1387                                             IDC_OPENREADONLY,
1388                                             BM_GETSTATE,0,0))
1389           SetFileAttributesA(fodInfos->ofnInfos.lpstrFile,
1390                              FILE_ATTRIBUTE_READONLY);
1391
1392       /*  nFileExtension and nFileOffset of OPENFILENAME structure */
1393       lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'\\');
1394       fodInfos->ofnInfos.nFileOffset = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1395       lpstrTemp = strrchr(fodInfos->ofnInfos.lpstrFile,'.');
1396       fodInfos->ofnInfos.nFileExtension = lpstrTemp - fodInfos->ofnInfos.lpstrFile + 1;
1397
1398     
1399     /* clean and exit */
1400     FILEDLG95_Clean(hwnd);
1401     return EndDialog(hwnd,TRUE);
1402   }
1403
1404   return FALSE;
1405 }
1406
1407 /***********************************************************************
1408  *      FILEDLG95_SHELL_Init
1409  *
1410  * Initialisation of the shell objects
1411  */
1412 static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1413 {
1414   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1415
1416   TRACE("\n");
1417
1418   /*
1419    * Initialisation of the FileOpenDialogInfos structure 
1420    */
1421
1422   /* Shell */
1423
1424   fodInfos->Shell.FOIShellView = NULL;
1425   if(FAILED(COMDLG32_SHGetDesktopFolder(&fodInfos->Shell.FOIShellFolder)))
1426     return E_FAIL;
1427
1428   /*ShellInfos */
1429   fodInfos->ShellInfos.hwndOwner = hwnd;
1430
1431   fodInfos->ShellInfos.folderSettings.fFlags = FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1432   fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1433
1434   GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1435   ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1436   ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1437
1438   /* Construct the IShellBrowser interface */
1439   fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);  
1440     
1441   return NOERROR;
1442 }
1443
1444 /***********************************************************************
1445  *      FILEDLG95_SHELL_ExecuteCommand
1446  *
1447  * Change the folder option and refresh the view
1448  * If the function succeeds, the return value is nonzero.
1449  */
1450 static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1451 {
1452   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1453
1454   IContextMenu * pcm;
1455   CMINVOKECOMMANDINFO ci;
1456   TRACE("\n");
1457
1458   if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1459                                         SVGIO_BACKGROUND,
1460                                         &IID_IContextMenu,
1461                                         (LPVOID*)&pcm)))
1462   {
1463     ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1464     ci.lpVerb = lpVerb;
1465     ci.hwnd = hwnd;
1466
1467     IContextMenu_InvokeCommand(pcm, &ci);
1468     IContextMenu_Release(pcm);
1469   }
1470
1471   return FALSE;
1472 }
1473
1474 /***********************************************************************
1475  *      FILEDLG95_SHELL_UpFolder
1476  *
1477  * Browse to the specified object
1478  * If the function succeeds, the return value is nonzero.
1479  */
1480 static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1481 {
1482   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1483
1484   TRACE("\n");
1485
1486   if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1487                                           NULL,
1488                                           SBSP_PARENT)))
1489   {
1490     return TRUE;
1491   }
1492   return FALSE;
1493 }
1494
1495 /***********************************************************************
1496  *      FILEDLG95_SHELL_NewFolder
1497  *
1498  * Creates a new directory with New folder as name 
1499  * If the function succeeds, the return value is nonzero.
1500  * FIXME: let the contextmenu (CMDSTR_NEWFOLDER) do this thing
1501  */
1502 static BOOL FILEDLG95_SHELL_NewFolder(HWND hwnd)
1503 {
1504   char lpstrDirName[MAX_PATH] = "New folder";
1505   BOOL bRes;
1506   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1507
1508   TRACE("\n");
1509
1510   if((bRes = CreateDirectoryA(lpstrDirName,NULL)))
1511   {
1512     LPITEMIDLIST pidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,lpstrDirName);
1513     IShellView_Refresh(fodInfos->Shell.FOIShellView);
1514     IShellView_SelectItem(fodInfos->Shell.FOIShellView,
1515                 pidl,
1516                         (SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
1517                 |SVSI_FOCUSED|SVSI_SELECT));
1518   }
1519
1520
1521
1522   return bRes;
1523 }
1524
1525 /***********************************************************************
1526  *      FILEDLG95_SHELL_Clean
1527  *
1528  * Cleans the memory used by shell objects
1529  */
1530 static void FILEDLG95_SHELL_Clean(HWND hwnd)
1531 {
1532     FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1533
1534     TRACE("\n");
1535
1536     /* clean Shell interfaces */
1537     IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1538     IShellView_Release(fodInfos->Shell.FOIShellView);
1539     IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1540     IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1541 }
1542
1543 /***********************************************************************
1544  *      FILEDLG95_FILETYPE_Init
1545  *
1546  * Initialisation of the file type combo box 
1547  */
1548 static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1549 {
1550   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1551
1552   TRACE("\n");
1553
1554   if(fodInfos->ofnInfos.lpstrFilter)
1555   {
1556     int iStrIndex = 0;
1557     int iPos = 0;
1558     LPSTR lpstrFilter;
1559     LPSTR lpstrTmp;
1560
1561     for(;;)
1562     {
1563       /* filter is a list...  title\0ext\0......\0\0 */
1564       /* Set the combo item text to the title and the item data
1565          to the ext */
1566       char *lpstrExt = NULL;
1567       LPSTR lpstrExtTmp = NULL;
1568       /* Get the title */
1569       lpstrTmp = (&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1570       if(!strlen(lpstrTmp))
1571         break;
1572       iStrIndex += strlen(lpstrTmp) +1;
1573       /* Get the extension */
1574       lpstrExtTmp = (&((LPBYTE)fodInfos->ofnInfos.lpstrFilter)[iStrIndex]);
1575       if(!lpstrExtTmp)
1576           break;
1577
1578       lpstrExt = (LPSTR) MemAlloc(strlen(lpstrExtTmp)+1);
1579       if(!lpstrExt)
1580           break;
1581       
1582       strcpy(lpstrExt,lpstrExtTmp);
1583
1584       iStrIndex += strlen(lpstrExt) +1;
1585             
1586       /* Add the item at the end of the combo */
1587       CBAddString(fodInfos->DlgInfos.hwndFileTypeCB,lpstrTmp);
1588       CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos++,lpstrExt);
1589     }
1590     /* Set the current filter to the one specified
1591        in the initialisation structure */
1592     CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,
1593                 fodInfos->ofnInfos.nFilterIndex);
1594
1595     lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1596                                            fodInfos->ofnInfos.nFilterIndex);
1597     if(lpstrFilter)
1598     {
1599         fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1600         lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,strlwr(lpstrFilter));
1601     }
1602   }
1603   return NOERROR;
1604 }
1605
1606 /***********************************************************************
1607  *      FILEDLG95_FILETYPE_OnCommand
1608  *
1609  * WM_COMMAND of the file type combo box
1610  * If the function succeeds, the return value is nonzero.
1611  */
1612 static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1613 {
1614   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1615
1616   switch(wNotifyCode)
1617   {
1618     case CBN_CLOSEUP:
1619     {
1620       LPSTR lpstrFilter;
1621
1622       /* Get the current item of the filetype combo box */
1623       int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1624
1625       /* Set the current filter with the current selection */
1626       if(fodInfos->ShellInfos.lpstrCurrentFilter)
1627          MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1628
1629       lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1630                                              iItem);
1631       if(lpstrFilter)
1632       {
1633         fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1634         lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,(LPSTR)strlwr((LPSTR)lpstrFilter));
1635       }
1636
1637       /* Refresh the actual view to display the included items*/
1638       IShellView_Refresh(fodInfos->Shell.FOIShellView);
1639
1640     }
1641   }
1642   return FALSE;
1643 }
1644 /***********************************************************************
1645  *      FILEDLG95_FILETYPE_SearchExt
1646  *
1647  * Search for pidl in the lookin combo box
1648  * returns the index of the found item
1649  */
1650 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt)
1651 {
1652   int i = 0;
1653   int iCount = CBGetCount(hwnd);
1654
1655   TRACE("\n");
1656
1657   for(;i<iCount;i++)
1658   {
1659     LPSTR ext = (LPSTR) CBGetItemDataPtr(hwnd,i);
1660
1661     if(!_stricmp(lpstrExt,ext))
1662       return i;
1663
1664   }
1665
1666   return -1;
1667 }
1668
1669 /***********************************************************************
1670  *      FILEDLG95_FILETYPE_Clean
1671  *
1672  * Clean the memory used by the filetype combo box
1673  */
1674 static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
1675 {
1676   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1677   int iPos;
1678   int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
1679
1680   TRACE("\n");
1681
1682   /* Delete each string of the combo and their associated data */
1683   for(iPos = iCount-1;iPos>=0;iPos--)
1684   {
1685     MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos)));
1686     CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1687   }
1688   /* Current filter */
1689   if(fodInfos->ShellInfos.lpstrCurrentFilter)
1690      MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1691
1692 }
1693     
1694 /***********************************************************************
1695  *      FILEDLG95_LOOKIN_Init
1696  *
1697  * Initialisation of the look in combo box 
1698  */
1699 static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
1700 {
1701   IShellFolder  *psfRoot, *psfDrives;
1702   IEnumIDList   *lpeRoot, *lpeDrives;
1703   LPITEMIDLIST  pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
1704
1705   LookInInfos *liInfos = MemAlloc(sizeof(LookInInfos));
1706
1707   TRACE("\n");
1708
1709   liInfos->iMaxIndentation = 0;
1710
1711   SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
1712   CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
1713
1714   /* Initialise data of Desktop folder */
1715   COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
1716   FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1717   COMDLG32_SHFree(pidlTmp);
1718
1719   COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
1720
1721   COMDLG32_SHGetDesktopFolder(&psfRoot);
1722
1723   if (psfRoot)
1724   {
1725     /* enumerate the contents of the desktop */
1726     if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
1727     {
1728       while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
1729       {
1730         FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1731
1732         /* special handling for CSIDL_DRIVES */
1733         if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
1734         {
1735           if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
1736           {
1737             /* enumerate the drives */
1738             if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
1739             {
1740               while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
1741               {
1742                 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
1743                 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
1744                 COMDLG32_SHFree(pidlAbsTmp);
1745                 COMDLG32_SHFree(pidlTmp1);
1746               }
1747               IEnumIDList_Release(lpeDrives);
1748             }
1749             IShellFolder_Release(psfDrives);
1750           }
1751         }
1752         COMDLG32_SHFree(pidlTmp);
1753       }
1754       IEnumIDList_Release(lpeRoot);
1755     }
1756   }
1757
1758   IShellFolder_Release(psfRoot);
1759   COMDLG32_SHFree(pidlDrives);
1760
1761   return NOERROR;
1762 }
1763
1764 /***********************************************************************
1765  *      FILEDLG95_LOOKIN_DrawItem
1766  *
1767  * WM_DRAWITEM message handler
1768  */
1769 static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
1770 {
1771   COLORREF crWin = GetSysColor(COLOR_WINDOW);
1772   COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
1773   COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
1774   RECT rectText;
1775   RECT rectIcon;
1776   SHFILEINFOA sfi;
1777   HIMAGELIST ilItemImage;
1778   int iIndentation;
1779   LPSFOLDER tmpFolder;
1780
1781
1782   LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
1783
1784   TRACE("\n");
1785
1786   if(pDIStruct->itemID == -1)
1787     return 0;
1788
1789   if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
1790                             pDIStruct->itemID)))
1791     return 0;
1792
1793
1794   if(pDIStruct->itemID == liInfos->uSelectedItem)
1795   {
1796     ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1797                                                0,    
1798                                                &sfi,    
1799                                                sizeof (SHFILEINFOA),   
1800                                                SHGFI_PIDL | SHGFI_SMALLICON |    
1801                                                SHGFI_OPENICON | SHGFI_SYSICONINDEX    | 
1802                                                SHGFI_DISPLAYNAME );   
1803   }
1804   else
1805   {
1806     ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1807                                                   0, 
1808                                                   &sfi, 
1809                                                   sizeof (SHFILEINFOA),
1810                                                   SHGFI_PIDL | SHGFI_SMALLICON | 
1811                                                   SHGFI_SYSICONINDEX | 
1812                                                   SHGFI_DISPLAYNAME);
1813   }
1814
1815   /* Is this item selected ?*/
1816   if(pDIStruct->itemState & ODS_SELECTED)
1817   {
1818     SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
1819     SetBkColor(pDIStruct->hDC,crHighLight);
1820     FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
1821   }
1822   else
1823   {
1824     SetTextColor(pDIStruct->hDC,crText);
1825     SetBkColor(pDIStruct->hDC,crWin);
1826     FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
1827   }
1828
1829   /* Do not indent item  if drawing in the edit of the combo*/
1830   if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
1831   {
1832     iIndentation = 0;
1833     ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1834                                                 0, 
1835                                                 &sfi, 
1836                                                 sizeof (SHFILEINFOA), 
1837                                                 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON 
1838                                                 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME  );
1839
1840   }
1841   else
1842   {
1843     iIndentation = tmpFolder->m_iIndent;
1844   }
1845   /* Draw text and icon */
1846
1847   /* Initialise the icon display area */
1848   rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
1849   rectIcon.top = pDIStruct->rcItem.top;
1850   rectIcon.right = rectIcon.left + ICONWIDTH;
1851   rectIcon.bottom = pDIStruct->rcItem.bottom;
1852
1853   /* Initialise the text display area */
1854   rectText.left = rectIcon.right;
1855   rectText.top = pDIStruct->rcItem.top + YTEXTOFFSET;
1856   rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
1857   rectText.bottom = pDIStruct->rcItem.bottom;
1858
1859  
1860   /* Draw the icon from the image list */
1861   COMDLG32_ImageList_Draw(ilItemImage,
1862                  sfi.iIcon,
1863                  pDIStruct->hDC,  
1864                  rectIcon.left,  
1865                  rectIcon.top,  
1866                  ILD_TRANSPARENT );  
1867
1868   /* Draw the associated text */
1869   if(sfi.szDisplayName)
1870     TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
1871
1872
1873   return NOERROR;
1874 }
1875
1876 /***********************************************************************
1877  *      FILEDLG95_LOOKIN_OnCommand
1878  *
1879  * LookIn combo box WM_COMMAND message handler
1880  * If the function succeeds, the return value is nonzero.
1881  */
1882 static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
1883 {
1884   FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1885
1886   TRACE("\n");
1887
1888   switch(wNotifyCode)
1889   {
1890   case CBN_CLOSEUP:
1891     {
1892       LPSFOLDER tmpFolder;
1893       int iItem; 
1894
1895       iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
1896
1897       if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
1898                                                iItem)))
1899         return FALSE;
1900
1901
1902       if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1903                                               tmpFolder->pidlItem,
1904                                               SBSP_ABSOLUTE)))
1905       {
1906         return TRUE;
1907       }
1908       break;
1909     }
1910       
1911   }
1912   return FALSE;
1913 }
1914
1915 /***********************************************************************
1916  *      FILEDLG95_LOOKIN_AddItem
1917  *
1918  * Adds an absolute pidl item to the lookin combo box
1919  * returns the index of the inserted item
1920  */
1921 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
1922 {
1923   LPITEMIDLIST pidlNext;
1924   SHFILEINFOA sfi;
1925   SFOLDER *tmpFolder = MemAlloc(sizeof(SFOLDER));
1926   LookInInfos *liInfos;
1927
1928   TRACE("\n");
1929
1930   if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
1931     return -1;
1932     
1933   tmpFolder->m_iIndent = 0;
1934
1935   if(!pidl)
1936     return -1;
1937
1938   /* Calculate the indentation of the item in the lookin*/
1939   pidlNext = pidl;
1940   while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
1941   {
1942     tmpFolder->m_iIndent++;
1943   }
1944
1945   tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl);
1946
1947   if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
1948     liInfos->iMaxIndentation = tmpFolder->m_iIndent;
1949   
1950   COMDLG32_SHGetFileInfoA((LPSTR)pidl,
1951                   0,
1952                   &sfi,
1953                   sizeof(sfi),
1954                   SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX 
1955                   | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES);
1956
1957
1958   if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
1959     {
1960         int iItemID;
1961     /* Add the item at the end of the list */
1962     if(iInsertId < 0)
1963     {
1964       iItemID = CBAddString(hwnd,sfi.szDisplayName);
1965     }
1966     /* Insert the item at the iInsertId position*/
1967     else
1968     {
1969       iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
1970     }
1971
1972         CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
1973         return iItemID;
1974   }
1975
1976   return -1;
1977
1978 }
1979
1980 /***********************************************************************
1981  *      FILEDLG95_LOOKIN_InsertItemAfterParent
1982  *
1983  * Insert an item below its parent 
1984  */
1985 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
1986 {
1987   
1988   LPITEMIDLIST pidlParent = GetParentPidl(pidl);
1989   int iParentPos;
1990
1991   TRACE("\n");
1992
1993   iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
1994
1995   if(iParentPos < 0)
1996   {
1997     iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
1998   }
1999
2000   /* Free pidlParent memory */
2001   COMDLG32_SHFree((LPVOID)pidlParent);
2002
2003   return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
2004 }
2005
2006 /***********************************************************************
2007  *      FILEDLG95_LOOKIN_SelectItem
2008  *
2009  * Adds an absolute pidl item to the lookin combo box
2010  * returns the index of the inserted item
2011  */
2012 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
2013 {
2014   int iItemPos;
2015   LookInInfos *liInfos;
2016
2017   TRACE("\n");
2018
2019   iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
2020
2021   liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2022
2023   if(iItemPos < 0)
2024   {
2025     while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
2026     iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
2027   }
2028
2029   else
2030   {
2031     SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2032     while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
2033     {
2034       int iRemovedItem;
2035
2036       if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
2037         break;
2038       if(iRemovedItem < iItemPos)
2039         iItemPos--;
2040     }
2041   }
2042   
2043   CBSetCurSel(hwnd,iItemPos);
2044   liInfos->uSelectedItem = iItemPos;
2045
2046   return 0;
2047
2048 }
2049
2050 /***********************************************************************
2051  *      FILEDLG95_LOOKIN_RemoveMostExpandedItem
2052  *
2053  * Remove the item with an expansion level over iExpansionLevel
2054  */
2055 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
2056 {
2057   int iItemPos;
2058
2059   LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2060
2061   TRACE("\n");
2062
2063   if(liInfos->iMaxIndentation <= 2)
2064     return -1;
2065
2066   if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
2067   {
2068     SFOLDER *tmpFolder;
2069     tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2070     CBDeleteString(hwnd,iItemPos);
2071     liInfos->iMaxIndentation--;
2072
2073     return iItemPos;
2074   }
2075
2076   return -1;
2077 }
2078
2079 /***********************************************************************
2080  *      FILEDLG95_LOOKIN_SearchItem
2081  *
2082  * Search for pidl in the lookin combo box
2083  * returns the index of the found item
2084  */
2085 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2086 {
2087   int i = 0;
2088   int iCount = CBGetCount(hwnd);
2089
2090   TRACE("\n");
2091
2092   for(;i<iCount;i++)
2093   {
2094     LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2095
2096     if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2097       return i;
2098     if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2099       return i;
2100
2101   }
2102
2103   return -1;
2104 }
2105
2106 /***********************************************************************
2107  *      FILEDLG95_LOOKIN_Clean
2108  *
2109  * Clean the memory used by the lookin combo box
2110  */
2111 static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2112 {
2113     FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2114     int iPos;
2115     int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2116
2117     TRACE("\n");
2118
2119     /* Delete each string of the combo and their associated data */
2120     for(iPos = iCount-1;iPos>=0;iPos--)
2121     {
2122         MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos)));
2123         CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2124     }
2125     /* LookInInfos structure */
2126     RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2127
2128 }
2129 /*
2130  * TOOLS
2131  */
2132
2133 /***********************************************************************
2134  *      GetName
2135  *
2136  * Get the pidl's display name (relative to folder) and 
2137  * put it in lpstrFileName.
2138  * 
2139  * Return NOERROR on success,
2140  * E_FAIL otherwise
2141  */
2142
2143 HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2144 {
2145   STRRET str;
2146   HRESULT hRes;
2147
2148   TRACE("%p %p\n", lpsf, pidl);
2149
2150   if(!lpsf)
2151   {
2152     HRESULT hRes;
2153     COMDLG32_SHGetDesktopFolder(&lpsf);
2154     hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2155     IShellFolder_Release(lpsf);
2156     return hRes;
2157   }
2158
2159   /* Get the display name of the pidl relative to the folder */
2160   if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf,
2161                                                      pidl, 
2162                                                      dwFlags, 
2163                                                      &str)))
2164   {
2165       return StrRetToBufA(&str, pidl,lpstrFileName, MAX_PATH);
2166   }
2167   return E_FAIL;
2168 }
2169
2170 /***********************************************************************
2171  *      GetShellFolderFromPidl
2172  *
2173  * pidlRel is the item pidl relative 
2174  * Return the IShellFolder of the absolute pidl
2175  */
2176 IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2177 {
2178   IShellFolder *psf = NULL,*psfParent;
2179
2180   TRACE("%p\n", pidlAbs);
2181
2182   if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent)))
2183   {
2184     psf = psfParent;
2185     if(pidlAbs && pidlAbs->mkid.cb)
2186     {
2187       if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2188       {
2189         IShellFolder_Release(psfParent);
2190         return psf;
2191       }
2192     }
2193     /* return the desktop */
2194     return psfParent;
2195   }
2196   return NULL;
2197 }
2198
2199 /***********************************************************************
2200  *      GetParentPidl
2201  *
2202  * Return the LPITEMIDLIST to the parent of the pidl in the list
2203  */
2204 LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2205 {
2206   LPITEMIDLIST pidlParent;
2207
2208   TRACE("%p\n", pidl);
2209
2210   pidlParent = COMDLG32_PIDL_ILClone(pidl);
2211   COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2212      
2213   return pidlParent;
2214 }
2215
2216 /***********************************************************************
2217  *      GetPidlFromName
2218  *
2219  * returns the pidl of the file name relative to folder 
2220  * NULL if an error occured
2221  */
2222 LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName)
2223 {
2224   LPITEMIDLIST pidl;
2225   ULONG ulEaten;
2226   wchar_t lpwstrDirName[MAX_PATH];
2227
2228
2229   TRACE("sf=%p file=%s\n", psf, lpcstrFileName);
2230
2231   if(!lpcstrFileName)
2232     return NULL;
2233     
2234   MultiByteToWideChar(CP_ACP,
2235                       MB_PRECOMPOSED,   
2236                       lpcstrFileName,  
2237                       -1,  
2238                       (LPWSTR)lpwstrDirName,  
2239                       MAX_PATH);  
2240
2241   IShellFolder_ParseDisplayName(psf,                                0,
2242                                              NULL,
2243                                              (LPWSTR)lpwstrDirName,
2244                                              &ulEaten,
2245                                              &pidl,
2246                                 NULL);   
2247
2248     return pidl;
2249 }
2250
2251 /***********************************************************************
2252  *      GetFileExtension
2253  *
2254  */
2255 BOOL GetFileExtension(IShellFolder *psf,LPITEMIDLIST pidl,LPSTR lpstrFileExtension)
2256 {
2257   char FileName[MAX_PATH];
2258   int result;
2259   char *pdest;
2260   int ch = '.';
2261
2262   if(SUCCEEDED(GetName(psf,pidl,SHGDN_NORMAL,FileName)))
2263   {
2264     if(!(pdest = strrchr( FileName, ch )))
2265       return FALSE;
2266
2267     result = pdest - FileName + 1;
2268     strcpy(lpstrFileExtension,&FileName[result]);
2269     return TRUE;
2270   }
2271   return FALSE;
2272 }
2273
2274 /*
2275  * Memory allocation methods */
2276 void *MemAlloc(UINT size)
2277 {
2278     return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2279 }
2280
2281 void MemFree(void *mem)
2282 {
2283     if(mem)
2284     {
2285         HeapFree(GetProcessHeap(),0,mem);
2286     }
2287 }