Make sure all Wine processes share the same X display.
[wine.git] / dlls / commdlg / filedlg95.c
blobe6247a222fc014410c1aba2d525f2f296a878930
1 /*
2 * COMMDLG - File Open Dialogs Win95 look and feel
4 */
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include "winbase.h"
10 #include "ldt.h"
11 #include "heap.h"
12 #include "commdlg.h"
13 #include "dlgs.h"
14 #include "cdlg.h"
15 #include "debugtools.h"
16 #include "cderr.h"
17 #include "tweak.h"
18 #include "winnls.h"
19 #include "shellapi.h"
20 #include "tchar.h"
21 #include "filedlgbrowser.h"
22 #include "wine/obj_contextmenu.h"
24 DEFAULT_DEBUG_CHANNEL(commdlg);
26 /***********************************************************************
27 * Data structure and global variables
29 typedef struct SFolder
31 int m_iImageIndex; /* Index of picture in image list */
32 HIMAGELIST hImgList;
33 int m_iIndent; /* Indentation index */
34 LPITEMIDLIST pidlItem; /* absolute pidl of the item */
36 } SFOLDER,*LPSFOLDER;
38 typedef struct tagLookInInfo
40 int iMaxIndentation;
41 UINT uSelectedItem;
42 } LookInInfos;
45 /***********************************************************************
46 * Defines and global variables
49 /* Draw item constant */
50 #define ICONWIDTH 18
51 #define YTEXTOFFSET 2
52 #define XTEXTOFFSET 3
54 /* AddItem flags*/
55 #define LISTEND -1
57 /* SearchItem methods */
58 #define SEARCH_PIDL 1
59 #define SEARCH_EXP 2
60 #define ITEM_NOTFOUND -1
62 /* Undefined windows message sent by CreateViewObject*/
63 #define WM_GETISHELLBROWSER WM_USER+7
65 /* NOTE
66 * Those macros exist in windowsx.h. However, you can't really use them since
67 * they rely on the UNICODE defines and can't be use inside Wine itself.
70 /* Combo box macros */
71 #define CBAddString(hwnd,str) \
72 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
74 #define CBInsertString(hwnd,str,pos) \
75 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
77 #define CBDeleteString(hwnd,pos) \
78 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
80 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
81 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
83 #define CBGetItemDataPtr(hwnd,iItemId) \
84 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
86 #define CBGetLBText(hwnd,iItemId,str) \
87 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
89 #define CBGetCurSel(hwnd) \
90 SendMessageA(hwnd,CB_GETCURSEL,0,0);
92 #define CBSetCurSel(hwnd,pos) \
93 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
95 #define CBGetCount(hwnd) \
96 SendMessageA(hwnd,CB_GETCOUNT,0,0);
97 #define CBShowDropDown(hwnd,show) \
98 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
99 #define CBSetItemHeight(hwnd,index,height) \
100 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
103 const char *FileOpenDlgInfosStr = "FileOpenDlgInfos"; /* windows property description string */
104 const char *LookInInfosStr = "LookInInfos"; /* LOOKIN combo box property */
106 static const char defaultFilter[] = "*.*";
108 /***********************************************************************
109 * Prototypes
112 /* Internal functions used by the dialog */
113 static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam);
114 static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam);
115 static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd);
116 BOOL FILEDLG95_OnOpen(HWND hwnd);
117 static LRESULT FILEDLG95_InitUI(HWND hwnd);
118 static void FILEDLG95_Clean(HWND hwnd);
120 /* Functions used by the shell object */
121 static LRESULT FILEDLG95_SHELL_Init(HWND hwnd);
122 static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd);
123 static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb);
124 static void FILEDLG95_SHELL_Clean(HWND hwnd);
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);
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);
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);
150 /* Shell memory allocation */
151 static void *MemAlloc(UINT size);
152 static void MemFree(void *mem);
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 BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed);
160 /***********************************************************************
161 * GetFileName95
163 * Creates an Open common dialog box that lets the user select
164 * the drive, directory, and the name of a file or set of files to open.
166 * IN : The FileOpenDlgInfos structure associated with the dialog
167 * OUT : TRUE on success
168 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
170 BOOL WINAPI GetFileName95(FileOpenDlgInfos *fodInfos)
173 LRESULT lRes;
174 LPCVOID template;
175 HRSRC hRes;
176 HANDLE hDlgTmpl = 0;
178 /* Create the dialog from a template */
180 if(!(hRes = FindResourceA(COMMDLG_hInstance32,MAKEINTRESOURCEA(NEWFILEOPENORD),RT_DIALOGA)))
182 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
183 return FALSE;
185 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hRes )) ||
186 !(template = LockResource( hDlgTmpl )))
188 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
189 return FALSE;
191 lRes = DialogBoxIndirectParamA(COMMDLG_hInstance32,
192 (LPDLGTEMPLATEA) template,
193 fodInfos->ofnInfos->hwndOwner,
194 (DLGPROC) FileOpenDlgProc95,
195 (LPARAM) fodInfos);
197 /* Unable to create the dialog*/
198 if( lRes == -1)
199 return FALSE;
201 return lRes;
204 /***********************************************************************
205 * GetFileDialog95A
207 * Copy the OPENFILENAMEA structure in a FileOpenDlgInfos structure.
208 * Call GetFileName95 with this structure and clean the memory.
210 * IN : The OPENFILENAMEA initialisation structure passed to
211 * GetOpenFileNameA win api function (see filedlg.c)
213 BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType)
216 BOOL ret;
217 FileOpenDlgInfos *fodInfos;
218 HINSTANCE hInstance;
219 LPCSTR lpstrFilter = NULL;
220 LPSTR lpstrCustomFilter = NULL;
221 LPCSTR lpstrInitialDir = NULL;
222 DWORD dwFlags = 0;
224 /* Initialise FileOpenDlgInfos structure*/
225 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
227 /* Pass in the original ofn */
228 fodInfos->ofnInfos = ofn;
230 /* Save original hInstance value */
231 hInstance = ofn->hInstance;
232 fodInfos->ofnInfos->hInstance = MapHModuleLS(ofn->hInstance);
234 if (ofn->lpstrFilter)
236 LPSTR s,x;
237 lpstrFilter = ofn->lpstrFilter;
239 /* filter is a list... title\0ext\0......\0\0 */
240 s = (LPSTR)ofn->lpstrFilter;
241 while (*s)
242 s = s+strlen(s)+1;
243 s++;
244 x = (LPSTR)MemAlloc(s-ofn->lpstrFilter);
245 memcpy(x,ofn->lpstrFilter,s-ofn->lpstrFilter);
246 fodInfos->ofnInfos->lpstrFilter = (LPSTR)x;
248 if (ofn->lpstrCustomFilter)
250 LPSTR s,x;
251 lpstrCustomFilter = ofn->lpstrCustomFilter;
253 /* filter is a list... title\0ext\0......\0\0 */
254 s = (LPSTR)ofn->lpstrCustomFilter;
255 while (*s)
256 s = s+strlen(s)+1;
257 s++;
258 x = MemAlloc(s-ofn->lpstrCustomFilter);
259 memcpy(x,ofn->lpstrCustomFilter,s-ofn->lpstrCustomFilter);
260 fodInfos->ofnInfos->lpstrCustomFilter = (LPSTR)x;
263 dwFlags = ofn->Flags;
264 fodInfos->ofnInfos->Flags = ofn->Flags|OFN_WINE;
266 /* Replace the NULL lpstrInitialDir by the current folder */
267 lpstrInitialDir = ofn->lpstrInitialDir;
268 if(!lpstrInitialDir)
270 fodInfos->ofnInfos->lpstrInitialDir = MemAlloc(MAX_PATH);
271 GetCurrentDirectoryA(MAX_PATH,(LPSTR)fodInfos->ofnInfos->lpstrInitialDir);
274 /* Initialise the dialog property */
275 fodInfos->DlgInfos.dwDlgProp = 0;
276 fodInfos->DlgInfos.hwndCustomDlg = (HWND)NULL;
278 switch(iDlgType)
280 case OPEN_DIALOG :
281 ret = GetFileName95(fodInfos);
282 break;
283 case SAVE_DIALOG :
284 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
285 ret = GetFileName95(fodInfos);
286 break;
287 default :
288 ret = 0;
291 if (lpstrInitialDir)
293 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrInitialDir));
294 fodInfos->ofnInfos->lpstrInitialDir = lpstrInitialDir;
296 if (lpstrFilter)
298 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrFilter));
299 fodInfos->ofnInfos->lpstrFilter = lpstrFilter;
301 if (lpstrCustomFilter)
303 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrCustomFilter));
304 fodInfos->ofnInfos->lpstrCustomFilter = lpstrCustomFilter;
307 ofn->Flags = dwFlags;
308 ofn->hInstance = hInstance;
309 MemFree((LPVOID)(fodInfos));
310 return ret;
313 /***********************************************************************
314 * GetFileDialog95W
316 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
317 * Call GetFileName95 with this structure and clean the memory.
319 * IN : The OPENFILENAMEW initialisation structure passed to
320 * GetOpenFileNameW win api function (see filedlg.c)
322 * FIXME:
323 * some more strings are needing to be convertet AtoW
325 BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType)
327 BOOL ret;
328 FileOpenDlgInfos *fodInfos;
329 HINSTANCE hInstance;
330 LPCSTR lpstrFilter = NULL;
331 LPSTR lpstrCustomFilter = NULL;
332 LPWSTR lpstrFile = NULL;
333 DWORD dwFlags;
335 /* Initialise FileOpenDlgInfos structure*/
336 fodInfos = (FileOpenDlgInfos*)MemAlloc(sizeof(FileOpenDlgInfos));
338 /* Pass in the original ofn */
339 fodInfos->ofnInfos = (LPOPENFILENAMEA) ofn;
341 /* Save hInstance */
342 hInstance = fodInfos->ofnInfos->hInstance;
343 fodInfos->ofnInfos->hInstance = MapHModuleLS(ofn->hInstance);
345 /* Save lpstrFilter */
346 if (ofn->lpstrFilter)
348 LPWSTR s;
349 LPSTR x,y;
350 int n;
352 lpstrFilter = fodInfos->ofnInfos->lpstrFilter;
354 /* filter is a list... title\0ext\0......\0\0 */
355 s = (LPWSTR)ofn->lpstrFilter;
357 while (*s)
358 s = s+lstrlenW(s)+1;
359 s++;
360 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
361 x = y = (LPSTR)MemAlloc(n);
362 s = (LPWSTR)ofn->lpstrFilter;
363 while (*s) {
364 lstrcpyWtoA(x,s);
365 x+=lstrlenA(x)+1;
366 s+=lstrlenW(s)+1;
368 *x=0;
369 fodInfos->ofnInfos->lpstrFilter = (LPSTR)y;
371 /* Save lpstrCustomFilter */
372 if (ofn->lpstrCustomFilter)
374 LPWSTR s;
375 LPSTR x,y;
376 int n;
378 lpstrCustomFilter = fodInfos->ofnInfos->lpstrCustomFilter;
379 /* filter is a list... title\0ext\0......\0\0 */
380 s = (LPWSTR)ofn->lpstrCustomFilter;
381 while (*s)
382 s = s+lstrlenW(s)+1;
383 s++;
384 n = s - ofn->lpstrCustomFilter;
385 x = y = (LPSTR)MemAlloc(n);
386 s = (LPWSTR)ofn->lpstrCustomFilter;
387 while (*s) {
388 lstrcpyWtoA(x,s);
389 x+=lstrlenA(x)+1;
390 s+=lstrlenW(s)+1;
392 *x=0;
393 fodInfos->ofnInfos->lpstrCustomFilter = (LPSTR)y;
396 /* Save Flags */
397 dwFlags = fodInfos->ofnInfos->Flags;
398 fodInfos->ofnInfos->Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
400 /* Initialise the dialog property */
401 fodInfos->DlgInfos.dwDlgProp = 0;
403 /* allocate ansi filename buffer */
404 lpstrFile = ofn->lpstrFile;
405 ofn->lpstrFile = MemAlloc(ofn->nMaxFile);
407 switch(iDlgType)
409 case OPEN_DIALOG :
410 ret = GetFileName95(fodInfos);
411 break;
412 case SAVE_DIALOG :
413 fodInfos->DlgInfos.dwDlgProp |= FODPROP_SAVEDLG;
414 ret = GetFileName95(fodInfos);
415 break;
416 default :
417 ret = 0;
420 /* Cleaning */
421 /* Restore Flags */
422 fodInfos->ofnInfos->Flags = dwFlags;
424 /* Restore lpstrFilter */
425 if (fodInfos->ofnInfos->lpstrFilter)
427 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrFilter));
428 fodInfos->ofnInfos->lpstrFilter = lpstrFilter;
430 if (fodInfos->ofnInfos->lpstrCustomFilter)
432 MemFree((LPVOID)(fodInfos->ofnInfos->lpstrCustomFilter));
433 fodInfos->ofnInfos->lpstrCustomFilter = lpstrCustomFilter;
436 /* Restore hInstance */
437 fodInfos->ofnInfos->hInstance = hInstance;
438 MemFree((LPVOID)(fodInfos));
440 /* filename */
441 lstrcpynAtoW(lpstrFile, (LPCSTR)ofn->lpstrFile, ofn->nMaxFile);
442 MemFree(ofn->lpstrFile);
443 ofn->lpstrFile = lpstrFile;
445 return ret;
448 void ArrangeCtrlPositions( HWND hwndChildDlg, HWND hwndParentDlg)
451 HWND hwndChild,hwndStc32;
452 RECT rectParent, rectChild, rectCtrl, rectStc32, rectTemp;
453 POINT ptMoveCtl;
454 POINT ptParentClient;
456 ptMoveCtl.x = ptMoveCtl.y = 0;
457 hwndStc32=GetDlgItem(hwndChildDlg,stc32);
458 GetClientRect(hwndParentDlg,&rectParent);
459 GetClientRect(hwndChildDlg,&rectChild);
460 if(hwndStc32)
462 GetWindowRect(hwndStc32,&rectStc32);
463 MapWindowPoints(0, hwndChildDlg,(LPPOINT)&rectStc32,2);
464 CopyRect(&rectTemp,&rectStc32);
466 SetRect(&rectStc32,rectStc32.left,rectStc32.top,rectStc32.left + (rectParent.right-rectParent.left),rectStc32.top+(rectParent.bottom-rectParent.top));
467 SetWindowPos(hwndStc32,0,rectStc32.left,rectStc32.top,rectStc32.right-rectStc32.left,rectStc32.bottom-rectStc32.top,SWP_NOMOVE|SWP_NOZORDER | SWP_NOACTIVATE);
469 if(rectStc32.right < rectTemp.right)
471 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
472 ptMoveCtl.x = 0;
474 else
476 ptMoveCtl.x = (rectStc32.right - rectTemp.right);
477 ptParentClient.x = max((rectParent.right-rectParent.left),((rectChild.right-rectChild.left)+rectStc32.right-rectTemp.right));
479 if(rectStc32.bottom < rectTemp.bottom)
481 ptParentClient.y = max((rectParent.bottom-rectParent.top),(rectChild.bottom-rectChild.top));
482 ptMoveCtl.y = 0;
484 else
486 ptMoveCtl.y = (rectStc32.bottom - rectTemp.bottom);
487 ptParentClient.y = max((rectParent.bottom-rectParent.top),((rectChild.bottom-rectChild.top)+rectStc32.bottom-rectTemp.bottom));
490 else
492 if( (GetWindow(hwndChildDlg,GW_CHILD)) == (HWND) NULL)
493 return;
494 SetRectEmpty(&rectTemp);
495 ptParentClient.x = max((rectParent.right-rectParent.left),(rectChild.right-rectChild.left));
496 ptParentClient.y = (rectParent.bottom-rectParent.top) + (rectChild.bottom-rectChild.top);
497 ptMoveCtl.y = rectParent.bottom-rectParent.top;
498 ptMoveCtl.x=0;
500 SetRect(&rectParent,rectParent.left,rectParent.top,rectParent.left+ptParentClient.x,rectParent.top+ptParentClient.y);
501 AdjustWindowRectEx( &rectParent,GetWindowLongA(hwndParentDlg,GWL_STYLE),FALSE,GetWindowLongA(hwndParentDlg,GWL_EXSTYLE));
503 SetWindowPos(hwndChildDlg, 0, 0,0, ptParentClient.x,ptParentClient.y,
504 SWP_NOZORDER );
505 SetWindowPos(hwndParentDlg, 0, rectParent.left,rectParent.top, (rectParent.right- rectParent.left),
506 (rectParent.bottom-rectParent.top),SWP_NOMOVE | SWP_NOZORDER);
508 hwndChild = GetWindow(hwndChildDlg,GW_CHILD);
509 if(hwndStc32)
511 GetWindowRect(hwndStc32,&rectStc32);
512 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
514 else
515 SetRect(&rectStc32,0,0,0,0);
517 if (hwndChild )
521 if(hwndChild != hwndStc32)
523 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
524 continue;
525 GetWindowRect(hwndChild,&rectCtrl);
526 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
529 Check the initial position of the controls relative to the initial
530 position and size of stc32 (before it is expanded).
532 if (rectCtrl.left >= rectTemp.right && rectCtrl.top >= rectTemp.bottom)
534 rectCtrl.left += ptMoveCtl.x;
535 rectCtrl.top += ptMoveCtl.y;
537 else if (rectCtrl.left >= rectTemp.right)
538 rectCtrl.left += ptMoveCtl.x;
539 else if (rectCtrl.top >= rectTemp.bottom)
540 rectCtrl.top += ptMoveCtl.y;
542 SetWindowPos( hwndChild, 0, rectCtrl.left, rectCtrl.top,
543 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
544 SWP_NOSIZE | SWP_NOZORDER );
547 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
549 hwndChild = GetWindow(hwndParentDlg,GW_CHILD);
551 if(hwndStc32)
553 GetWindowRect(hwndStc32,&rectStc32);
554 MapWindowPoints( 0, hwndChildDlg,(LPPOINT)&rectStc32,2);
555 ptMoveCtl.x = rectStc32.left - 0;
556 ptMoveCtl.y = rectStc32.top - 0;
557 if (hwndChild )
561 if(hwndChild != hwndChildDlg)
564 if (GetWindowLongA( hwndChild, GWL_STYLE ) & WS_MAXIMIZE)
565 continue;
566 GetWindowRect(hwndChild,&rectCtrl);
567 MapWindowPoints( 0, hwndParentDlg,(LPPOINT)&rectCtrl,2);
569 rectCtrl.left += ptMoveCtl.x;
570 rectCtrl.top += ptMoveCtl.y;
572 SetWindowPos( hwndChild, 0, rectCtrl.left, rectCtrl.top,
573 rectCtrl.right-rectCtrl.left,rectCtrl.bottom-rectCtrl.top,
574 SWP_NOSIZE |SWP_NOZORDER );
577 while ((hwndChild=GetWindow( hwndChild, GW_HWNDNEXT )) != (HWND)NULL);
584 HRESULT WINAPI FileOpenDlgProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
586 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(GetParent(hwnd),FileOpenDlgInfosStr);
587 switch(uMsg)
589 case WM_INITDIALOG:
591 fodInfos = (FileOpenDlgInfos *)lParam;
592 lParam = (LPARAM) fodInfos->ofnInfos;
593 ArrangeCtrlPositions(hwnd,GetParent(hwnd));
594 if(fodInfos && (fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
595 return CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,hwnd,uMsg,wParam,lParam);
596 return 0;
599 if(fodInfos && (fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook )
600 return CallWindowProcA((WNDPROC)fodInfos->ofnInfos->lpfnHook,hwnd,uMsg,wParam,lParam);
601 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
604 HWND CreateTemplateDialog(FileOpenDlgInfos *fodInfos,HWND hwnd)
606 LPCVOID template;
607 HRSRC hRes;
608 HANDLE hDlgTmpl = 0;
609 HWND hChildDlg = 0;
610 if (fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATE || fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATEHANDLE)
612 if (fodInfos->ofnInfos->Flags & OFN_ENABLETEMPLATEHANDLE)
614 if( !(template = LockResource( fodInfos->ofnInfos->hInstance)))
616 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
617 return (HWND)NULL;
621 else
623 if (!(hRes = FindResourceA(MapHModuleSL(fodInfos->ofnInfos->hInstance),
624 (fodInfos->ofnInfos->lpTemplateName), RT_DIALOGA)))
626 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
627 return (HWND)NULL;
629 if (!(hDlgTmpl = LoadResource( MapHModuleSL(fodInfos->ofnInfos->hInstance),
630 hRes )) ||
631 !(template = LockResource( hDlgTmpl )))
633 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
634 return (HWND)NULL;
638 hChildDlg= CreateDialogIndirectParamA(fodInfos->ofnInfos->hInstance,template,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
639 if(hChildDlg)
641 ShowWindow(hChildDlg,SW_SHOW);
642 return hChildDlg;
645 else if(fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK && fodInfos->ofnInfos->lpfnHook)
647 RECT rectHwnd;
648 DLGTEMPLATE tmplate;
649 GetClientRect(hwnd,&rectHwnd);
650 tmplate.style = WS_CHILD | WS_CLIPSIBLINGS;
651 tmplate.dwExtendedStyle = 0;
652 tmplate.cdit = 0;
653 tmplate.x = 0;
654 tmplate.y = 0;
655 tmplate.cx = rectHwnd.right-rectHwnd.left;
656 tmplate.cy = rectHwnd.bottom-rectHwnd.top;
658 return CreateDialogIndirectParamA(fodInfos->ofnInfos->hInstance,&tmplate,hwnd,(DLGPROC)FileOpenDlgProcUserTemplate,(LPARAM)fodInfos);
660 return (HWND)NULL;
663 /***********************************************************************
664 * SendCustomDlgNotificationMessage
666 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
669 HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode)
671 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwndParentDlg,FileOpenDlgInfosStr);
672 if(!fodInfos)
673 return 0;
674 if(fodInfos->DlgInfos.hwndCustomDlg)
676 OFNOTIFYA ofnNotify;
677 ofnNotify.hdr.hwndFrom=hwndParentDlg;
678 ofnNotify.hdr.idFrom=0;
679 ofnNotify.hdr.code = uCode;
680 ofnNotify.lpOFN = fodInfos->ofnInfos;
681 return SendMessageA(fodInfos->DlgInfos.hwndCustomDlg,WM_NOTIFY,0,(LPARAM)&ofnNotify);
683 return TRUE;
686 /***********************************************************************
687 * FILEDLG95_HandleCustomDialogMessages
689 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
691 HRESULT FILEDLG95_HandleCustomDialogMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
693 LPSTR lpstrFileSpec;
694 int reqSize;
695 char lpstrPath[MAX_PATH];
696 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
697 if(!fodInfos) return -1;
699 switch(uMsg)
701 case CDM_GETFILEPATH:
702 GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrPath, sizeof(lpstrPath));
703 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrPath);
704 if (lpstrFileSpec==lpstrPath)
706 char lpstrCurrentDir[MAX_PATH];
707 /* Prepend the current path */
708 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrCurrentDir);
709 if ((LPSTR)lParam!=NULL)
710 wsnprintfA((LPSTR)lParam,(int)wParam,"%s\\%s",lpstrCurrentDir,lpstrPath);
711 reqSize=strlen(lpstrCurrentDir)+1+strlen(lpstrPath)+1;
713 else
715 lstrcpynA((LPSTR)lParam,(LPSTR)lpstrPath,(int)wParam);
716 reqSize=strlen(lpstrPath);
718 /* return the required buffer size */
719 return reqSize;
721 case CDM_GETFOLDERPATH:
722 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrPath);
723 if ((LPSTR)lParam!=NULL)
724 lstrcpynA((LPSTR)lParam,lpstrPath,(int)wParam);
725 return strlen(lpstrPath);
727 case CDM_GETSPEC:
728 reqSize=GetDlgItemTextA(hwnd,IDC_FILENAME,lpstrPath, sizeof(lpstrPath));
729 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrPath);
730 if ((LPSTR)lParam!=NULL)
731 lstrcpynA((LPSTR)lParam, lpstrFileSpec, (int)wParam);
732 return strlen(lpstrFileSpec);
734 case CDM_SETCONTROLTEXT:
735 if ( 0 != lParam )
736 SetDlgItemTextA( hwnd, (UINT) wParam, (LPSTR) lParam );
737 return TRUE;
739 case CDM_HIDECONTROL:
740 case CDM_SETDEFEXT:
741 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
742 return -1;
744 return TRUE;
747 /***********************************************************************
748 * FileOpenDlgProc95
750 * File open dialog procedure
752 HRESULT WINAPI FileOpenDlgProc95(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
754 switch(uMsg)
756 case WM_INITDIALOG :
757 /* Adds the FileOpenDlgInfos in the property list of the dialog
758 so it will be easily accessible through a GetPropA(...) */
759 SetPropA(hwnd, FileOpenDlgInfosStr, (HANDLE) lParam);
761 FILEDLG95_OnWMInitDialog(hwnd, wParam, lParam);
762 ((FileOpenDlgInfos *)lParam)->DlgInfos.hwndCustomDlg =
763 CreateTemplateDialog((FileOpenDlgInfos *)lParam,hwnd);
764 SendCustomDlgNotificationMessage(hwnd,CDN_INITDONE);
765 return 0;
766 case WM_COMMAND:
767 return FILEDLG95_OnWMCommand(hwnd, wParam, lParam);
768 case WM_DRAWITEM:
770 switch(((LPDRAWITEMSTRUCT)lParam)->CtlID)
772 case IDC_LOOKIN:
773 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT) lParam);
774 return TRUE;
777 return FALSE;
779 case WM_GETISHELLBROWSER:
780 return FILEDLG95_OnWMGetIShellBrowser(hwnd);
782 case WM_DESTROY:
783 RemovePropA(hwnd, FileOpenDlgInfosStr);
784 return FALSE;
786 case WM_NOTIFY:
788 LPNMHDR lpnmh = (LPNMHDR)lParam;
789 UINT stringId = -1;
791 /* set up the button tooltips strings */
792 if(TTN_GETDISPINFOA == lpnmh->code )
794 LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
795 switch(lpnmh->idFrom )
797 /* Up folder button */
798 case FCIDM_TB_UPFOLDER:
799 stringId = IDS_UPFOLDER;
800 break;
801 /* New folder button */
802 case FCIDM_TB_NEWFOLDER:
803 stringId = IDS_NEWFOLDER;
804 break;
805 /* List option button */
806 case FCIDM_TB_SMALLICON:
807 stringId = IDS_LISTVIEW;
808 break;
809 /* Details option button */
810 case FCIDM_TB_REPORTVIEW:
811 stringId = IDS_REPORTVIEW;
812 break;
814 lpdi->hinst = COMMDLG_hInstance32;
815 lpdi->lpszText = (LPSTR) stringId;
817 return FALSE;
819 default :
820 if(uMsg >= CDM_FIRST && uMsg <= CDM_LAST)
821 return FILEDLG95_HandleCustomDialogMessages(hwnd, uMsg, wParam, lParam);
822 return FALSE;
826 /***********************************************************************
827 * FILEDLG95_OnWMInitDialog
829 * WM_INITDIALOG message handler
831 static LRESULT FILEDLG95_OnWMInitDialog(HWND hwnd, WPARAM wParam, LPARAM lParam)
833 LPITEMIDLIST pidlItemId;
834 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) lParam;
836 TRACE("\n");
838 /* Initialise shell objects */
839 FILEDLG95_SHELL_Init(hwnd);
841 /* Initialise dialog UI */
842 FILEDLG95_InitUI(hwnd);
844 /* Initialize the Look In combo box*/
845 FILEDLG95_LOOKIN_Init(fodInfos->DlgInfos.hwndLookInCB);
847 /* Initialize the filter combo box */
848 FILEDLG95_FILETYPE_Init(hwnd);
850 /* Get the initial directory pidl */
852 if(!(pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,fodInfos->ofnInfos->lpstrInitialDir)))
854 char path[MAX_PATH];
856 GetCurrentDirectoryA(MAX_PATH,path);
857 pidlItemId = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
858 path);
862 /* Browse to the initial directory */
863 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,pidlItemId,SBSP_RELATIVE);
865 /* Free pidlItem memory */
866 COMDLG32_SHFree(pidlItemId);
868 return TRUE;
870 /***********************************************************************
871 * FILEDLG95_Clean
873 * Regroups all the cleaning functions of the filedlg
875 void FILEDLG95_Clean(HWND hwnd)
877 FILEDLG95_FILETYPE_Clean(hwnd);
878 FILEDLG95_LOOKIN_Clean(hwnd);
879 FILEDLG95_SHELL_Clean(hwnd);
881 /***********************************************************************
882 * FILEDLG95_OnWMCommand
884 * WM_COMMAND message handler
886 static LRESULT FILEDLG95_OnWMCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
888 WORD wNotifyCode = HIWORD(wParam); /* notification code */
889 WORD wID = LOWORD(wParam); /* item, control, or accelerator identifier */
890 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
892 switch(wID)
894 /* OK button */
895 case IDOK:
896 if(FILEDLG95_OnOpen(hwnd))
897 SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
898 break;
899 /* Cancel button */
900 case IDCANCEL:
901 FILEDLG95_Clean(hwnd);
902 EndDialog(hwnd, FALSE);
903 break;
904 /* Filetype combo box */
905 case IDC_FILETYPE:
906 FILEDLG95_FILETYPE_OnCommand(hwnd,wNotifyCode);
907 break;
908 /* LookIn combo box */
909 case IDC_LOOKIN:
910 FILEDLG95_LOOKIN_OnCommand(hwnd,wNotifyCode);
911 break;
913 /* --- toolbar --- */
914 /* Up folder button */
915 case FCIDM_TB_UPFOLDER:
916 FILEDLG95_SHELL_UpFolder(hwnd);
917 break;
918 /* New folder button */
919 case FCIDM_TB_NEWFOLDER:
920 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_NEWFOLDER);
921 break;
922 /* List option button */
923 case FCIDM_TB_SMALLICON:
924 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWLIST);
925 break;
926 /* Details option button */
927 case FCIDM_TB_REPORTVIEW:
928 FILEDLG95_SHELL_ExecuteCommand(hwnd,CMDSTR_VIEWDETAILS);
929 break;
931 case IDC_FILENAME:
932 break;
935 /* Do not use the listview selection anymore */
936 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
937 return 0;
940 /***********************************************************************
941 * FILEDLG95_OnWMGetIShellBrowser
943 * WM_GETISHELLBROWSER message handler
945 static LRESULT FILEDLG95_OnWMGetIShellBrowser(HWND hwnd)
948 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
950 TRACE("\n");
952 SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser);
954 return TRUE;
958 /***********************************************************************
959 * FILEDLG95_InitUI
962 static LRESULT FILEDLG95_InitUI(HWND hwnd)
964 TBBUTTON tbb[] =
965 {{VIEW_PARENTFOLDER, FCIDM_TB_UPFOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
966 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
967 {VIEW_NEWFOLDER, FCIDM_TB_NEWFOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
968 {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0, 0}, 0, 0 },
969 {VIEW_LIST, FCIDM_TB_SMALLICON, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
970 {VIEW_DETAILS, FCIDM_TB_REPORTVIEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, 0 },
972 TBADDBITMAP tba = { HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR };
973 RECT rectTB;
975 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
977 TRACE("%p\n", fodInfos);
979 /* Get the hwnd of the controls */
980 fodInfos->DlgInfos.hwndFileName = GetDlgItem(hwnd,IDC_FILENAME);
981 fodInfos->DlgInfos.hwndFileTypeCB = GetDlgItem(hwnd,IDC_FILETYPE);
982 fodInfos->DlgInfos.hwndLookInCB = GetDlgItem(hwnd,IDC_LOOKIN);
984 /* construct the toolbar */
985 GetWindowRect(GetDlgItem(hwnd,IDC_TOOLBARSTATIC),&rectTB);
986 MapWindowPoints( 0, hwnd,(LPPOINT)&rectTB,2);
988 fodInfos->DlgInfos.hwndTB = CreateWindowExA(0, TOOLBARCLASSNAMEA, (LPSTR) NULL,
989 WS_CHILD | WS_GROUP | TBSTYLE_TOOLTIPS | CCS_NODIVIDER | CCS_NORESIZE,
990 0, 0, 150, 26,
991 hwnd, (HMENU) IDC_TOOLBAR, COMMDLG_hInstance32, NULL);
993 SetWindowPos(fodInfos->DlgInfos.hwndTB, 0,
994 rectTB.left,rectTB.top, rectTB.right-rectTB.left, rectTB.bottom-rectTB.top,
995 SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER );
997 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
999 /* fixme: use TB_LOADIMAGES when implemented */
1000 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1001 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBITMAP, (WPARAM) 12, (LPARAM) &tba);
1003 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_ADDBUTTONSA, (WPARAM) 6,(LPARAM) &tbb);
1004 SendMessageA(fodInfos->DlgInfos.hwndTB, TB_AUTOSIZE, 0, 0);
1006 /* Set the window text with the text specified in the OPENFILENAME structure */
1007 if(fodInfos->ofnInfos->lpstrTitle)
1009 SetWindowTextA(hwnd,fodInfos->ofnInfos->lpstrTitle);
1011 else if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1013 SetWindowTextA(hwnd,"Save");
1016 /* Initialise the file name edit control */
1017 if(fodInfos->ofnInfos->lpstrFile)
1019 SetDlgItemTextA(hwnd,IDC_FILENAME,fodInfos->ofnInfos->lpstrFile);
1021 /* Must the open as read only check box be checked ?*/
1022 if(fodInfos->ofnInfos->Flags & OFN_READONLY)
1024 SendDlgItemMessageA(hwnd,IDC_OPENREADONLY,BM_SETCHECK,(WPARAM)TRUE,0);
1026 /* Must the open as read only check box be hid ?*/
1027 if(fodInfos->ofnInfos->Flags & OFN_HIDEREADONLY)
1029 ShowWindow(GetDlgItem(hwnd,IDC_OPENREADONLY),SW_HIDE);
1031 /* Must the help button be hid ?*/
1032 if (!(fodInfos->ofnInfos->Flags & OFN_SHOWHELP))
1034 ShowWindow(GetDlgItem(hwnd, pshHelp), SW_HIDE);
1036 /* Resize the height, if open as read only checkbox ad help button
1037 are hidden */
1038 if ( (fodInfos->ofnInfos->Flags & OFN_HIDEREADONLY) &&
1039 (!(fodInfos->ofnInfos->Flags & OFN_SHOWHELP)) )
1041 RECT rectDlg, rectHelp, rectCancel;
1042 GetWindowRect(hwnd, &rectDlg);
1043 GetWindowRect(GetDlgItem(hwnd, pshHelp), &rectHelp);
1044 GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rectCancel);
1045 /* subtract the height of the help button plus the space between
1046 the help button and the cancel button to the height of the dialog */
1047 SetWindowPos(hwnd, 0, 0, 0, rectDlg.right-rectDlg.left,
1048 (rectDlg.bottom-rectDlg.top) - (rectHelp.bottom - rectCancel.bottom),
1049 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
1051 /* change Open to Save */
1052 if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
1054 SetDlgItemTextA(hwnd,IDOK,"Save");
1056 return 0;
1059 /***********************************************************************
1060 * FILEDLG95_OnOpenMultipleFiles
1062 * Handles the opening of multiple files.
1065 BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPSTR lpstrFileList, UINT nFileCount, UINT sizeUsed)
1067 CHAR lpstrPathSpec[MAX_PATH] = "";
1068 CHAR lpstrTempFileList[MAX_PATH] = "";
1069 LPSTR lpstrFile;
1070 UINT sizePath;
1071 UINT nCount;
1072 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1074 TRACE("\n");
1076 lpstrFile = fodInfos->ofnInfos->lpstrFile;
1078 COMDLG32_SHGetPathFromIDListA( fodInfos->ShellInfos.pidlAbsCurrent, lpstrPathSpec );
1079 sizePath = lstrlenA( lpstrPathSpec );
1081 memset( lpstrFile, 0x0, fodInfos->ofnInfos->nMaxFile * sizeof(CHAR) );
1083 if ( fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST ||
1084 !(fodInfos->ofnInfos->Flags & OFN_EXPLORER ))
1086 LPSTR lpstrTemp = lpstrFileList;
1088 for ( nCount = 0; nCount < nFileCount; nCount++ )
1090 WIN32_FIND_DATAA findData;
1091 CHAR lpstrFindFile[MAX_PATH];
1093 memset( lpstrFindFile, 0x0, MAX_PATH * sizeof(CHAR) );
1095 lstrcpyA( lpstrFindFile, lpstrPathSpec );
1096 lstrcatA( lpstrFindFile, "\\" );
1097 lstrcatA( lpstrFindFile, lpstrTemp );
1099 if ( FindFirstFileA( lpstrFindFile, &findData ) == INVALID_HANDLE_VALUE )
1101 CHAR lpstrNotFound[100];
1102 CHAR lpstrMsg[100];
1103 CHAR tmp[400];
1105 LoadStringA(COMMDLG_hInstance32, IDS_FILENOTFOUND, lpstrNotFound, 100);
1106 LoadStringA(COMMDLG_hInstance32, IDS_VERIFYFILE, lpstrMsg, 100);
1108 strcpy(tmp, lpstrFindFile);
1109 strcat(tmp, "\n");
1110 strcat(tmp, lpstrNotFound);
1111 strcat(tmp, "\n");
1112 strcat(tmp, lpstrMsg);
1114 MessageBoxA(hwnd,
1115 tmp,
1116 fodInfos->ofnInfos->lpstrTitle,
1117 MB_OK | MB_ICONEXCLAMATION);
1118 return FALSE;
1121 if (!(fodInfos->ofnInfos->Flags & OFN_EXPLORER ))
1123 lstrcatA( lpstrTempFileList, findData.cAlternateFileName);
1124 if ( nCount + 1 < nFileCount)
1125 lstrcatA( lpstrTempFileList, " ");
1127 lpstrTemp += strlen(lpstrFileList) + 1;
1131 if ( fodInfos->ofnInfos->Flags & OFN_EXPLORER )
1133 lstrcpyA( lpstrFile, lpstrPathSpec);
1134 memcpy( lpstrFile + sizePath + 1, lpstrFileList, sizeof(CHAR) * sizeUsed );
1136 else
1138 memcpy( lpstrFile, lpstrTempFileList, sizeof(CHAR) * strlen(lpstrTempFileList));
1141 fodInfos->ofnInfos->nFileOffset = sizePath + 1;
1142 fodInfos->ofnInfos->nFileExtension = 0;
1144 /* clean and exit */
1145 FILEDLG95_Clean(hwnd);
1146 return EndDialog(hwnd,TRUE);
1149 /***********************************************************************
1150 * FILEDLG95_OnOpen
1152 * Ok button WM_COMMAND message handler
1154 * If the function succeeds, the return value is nonzero.
1156 BOOL FILEDLG95_OnOpen(HWND hwnd)
1158 CHAR lpstrSpecifiedByUser[MAX_PATH];
1159 CHAR lpstrFileList[MAX_PATH];
1160 LPSTR lpstrFile;
1161 UINT nStrCharCount = 0;
1162 UINT nFileCount = 0;
1163 UINT nFileIndex = 0;
1164 UINT sizeUsed = 0;
1165 UINT nStrLen = 0;
1166 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1168 lpstrSpecifiedByUser[0]=0;
1170 TRACE("\n");
1173 lpstrFile = fodInfos->ofnInfos->lpstrFile;
1175 GetDlgItemTextA(hwnd, IDC_FILENAME, lpstrSpecifiedByUser, MAX_PATH);
1176 nStrLen = strlen(lpstrSpecifiedByUser);
1178 while ( nStrCharCount <= nStrLen )
1180 if ( lpstrSpecifiedByUser[nStrCharCount]=='"' )
1182 nStrCharCount++;
1183 while ((lpstrSpecifiedByUser[nStrCharCount]!='"') &&
1184 (nStrCharCount <= nStrLen))
1186 lpstrFileList[nFileIndex++] = lpstrSpecifiedByUser[nStrCharCount];
1187 nStrCharCount++;
1188 sizeUsed++;
1190 lpstrFileList[nFileIndex++] = '\0';
1191 sizeUsed++;
1192 nFileCount++;
1194 nStrCharCount++;
1197 if(nFileCount > 0)
1198 return FILEDLG95_OnOpenMultipleFiles(hwnd, lpstrFileList, nFileCount, sizeUsed);
1200 if (nStrLen)
1202 LPSHELLFOLDER psfDesktop;
1203 LPITEMIDLIST browsePidl;
1204 LPSTR lpstrFileSpec;
1205 LPSTR lpstrTemp;
1206 char lpstrPathSpec[MAX_PATH];
1207 char lpstrCurrentDir[MAX_PATH];
1208 char lpstrPathAndFile[MAX_PATH];
1210 lpstrPathSpec[0] = '\0';
1211 lpstrCurrentDir[0] = '\0';
1212 lpstrPathAndFile[0] = '\0';
1214 /* Separate the file spec from the path spec
1215 e.g.:
1216 lpstrSpecifiedByUser lpstrPathSpec lpstrFileSpec
1217 C:\TEXT1\TEXT2 C:\TEXT1 TEXT2
1219 if (nFileCount == 0)
1221 lpstrFileSpec = (LPSTR)COMDLG32_PathFindFilenameA(lpstrSpecifiedByUser);
1222 strcpy(lpstrPathSpec,lpstrSpecifiedByUser);
1223 COMDLG32_PathRemoveFileSpecA(lpstrPathSpec);
1226 /* Get the index of the selected item in the filetype combo box */
1227 fodInfos->ofnInfos->nFilterIndex = (DWORD) CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1228 /* nFilterIndex is 1 based while combo GetCurSel return zero based index */
1229 fodInfos->ofnInfos->nFilterIndex++;
1231 /* Get the current directory name */
1232 COMDLG32_SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,
1233 lpstrCurrentDir);
1235 /* Create an absolute path name */
1236 if(lpstrSpecifiedByUser[1] != ':')
1238 switch(lpstrSpecifiedByUser[0])
1240 /* Add drive spec \TEXT => C:\TEXT */
1241 case '\\':
1243 int lenPathSpec=strlen(lpstrPathSpec);
1244 int iCopy = (lenPathSpec!=0?2:3);
1245 memmove(lpstrPathSpec+iCopy,lpstrPathSpec,lenPathSpec);
1246 strncpy(lpstrPathSpec,lpstrCurrentDir,iCopy);
1248 break;
1249 /* Go to parent ..\TEXT */
1250 case '.':
1252 int iSize;
1253 char lpstrTmp2[MAX_PATH];
1254 LPSTR lpstrTmp = strrchr(lpstrCurrentDir,'\\');
1256 iSize = lpstrTmp - lpstrCurrentDir;
1257 strncpy(lpstrTmp2,lpstrCurrentDir,iSize + 1);
1258 if(strlen(lpstrSpecifiedByUser) <= 3)
1259 *lpstrFileSpec='\0';
1260 if(strcmp(lpstrPathSpec,".."))
1261 strcat(lpstrTmp2,&lpstrPathSpec[3]);
1262 strcpy(lpstrPathSpec,lpstrTmp2);
1264 break;
1265 default:
1267 char lpstrTmp[MAX_PATH];
1269 if(strcmp(&lpstrCurrentDir[strlen(lpstrCurrentDir)-1],"\\"))
1270 strcat(lpstrCurrentDir,"\\");
1271 strcpy(lpstrTmp,lpstrCurrentDir);
1272 strcat(lpstrTmp,lpstrPathSpec);
1273 strcpy(lpstrPathSpec,lpstrTmp);
1275 } /* end switch */
1278 if(strlen(lpstrPathSpec))
1280 /* Browse to the right directory */
1281 COMDLG32_SHGetDesktopFolder(&psfDesktop);
1282 if((browsePidl = GetPidlFromName(psfDesktop,lpstrPathSpec)))
1284 /* Browse to directory */
1285 IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1286 browsePidl,
1287 SBSP_ABSOLUTE);
1288 COMDLG32_SHFree(browsePidl);
1290 else
1292 /* Path does not exist */
1293 if(fodInfos->ofnInfos->Flags & OFN_PATHMUSTEXIST)
1295 MessageBoxA(hwnd,
1296 "Path does not exist",
1297 fodInfos->ofnInfos->lpstrTitle,
1298 MB_OK | MB_ICONEXCLAMATION);
1299 return FALSE;
1303 strcat(lpstrPathAndFile,lpstrPathSpec);
1304 IShellFolder_Release(psfDesktop);
1306 else
1308 strcat(lpstrPathAndFile,lpstrCurrentDir);
1311 /* Create the path and file string */
1312 COMDLG32_PathAddBackslashA(lpstrPathAndFile);
1313 strcat(lpstrPathAndFile,lpstrFileSpec);
1315 /* Update the edit field */
1316 SetDlgItemTextA(hwnd,IDC_FILENAME,lpstrFileSpec);
1317 SendDlgItemMessageA(hwnd,IDC_FILENAME,EM_SETSEL,0,-1);
1319 /* Don't go further if we dont have a file spec */
1320 if(!strlen(lpstrFileSpec) || !strcmp(lpstrFileSpec,lpstrPathSpec))
1321 return FALSE;
1323 /* Time to check lpstrFileSpec */
1324 /* search => contains * or ? */
1325 /* browse => contains a directory name */
1326 /* file => contains a file name */
1328 /* Check if this is a search */
1329 if(strchr(lpstrFileSpec,'*') || strchr(lpstrFileSpec,'?'))
1331 int iPos;
1333 /* Set the current filter with the current selection */
1334 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1335 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1337 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFileSpec)+1)*2);
1338 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,
1339 (LPSTR)strlwr((LPSTR)lpstrFileSpec));
1341 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1343 if(-1 < (iPos = FILEDLG95_FILETYPE_SearchExt(fodInfos->DlgInfos.hwndFileTypeCB,
1344 lpstrFileSpec)))
1345 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1347 return FALSE;
1350 /* browse if the user specified a directory */
1351 browsePidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
1352 lpstrFileSpec);
1353 if (!browsePidl) /* not a directory check the specified file exists */
1355 int iExt;
1356 char lpstrFileSpecTemp[MAX_PATH];
1357 LPSTR lpstrExt;
1358 LPSTR lpOrg;
1359 LPSTR lpBuf;
1360 iExt = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1361 lpOrg = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB, iExt);
1362 if ((int)lpOrg == -1)
1363 lpOrg = NULL; /* we get -1 if the filetype LB is empty */
1365 lpstrExt = lpOrg;
1368 add user specified extentions to the file one by one and
1369 check if the file exists
1371 while(lpOrg)
1373 int i;
1374 if ((lpstrExt = strchr(lpOrg, ';')))
1376 i = lpstrExt - lpOrg;
1378 else
1379 i = strlen(lpOrg);
1380 lpBuf = MemAlloc(i+1);
1381 strncpy(lpBuf, lpOrg, i);
1382 lpBuf[i] = 0;
1383 strcpy(lpstrFileSpecTemp, lpstrFileSpec);
1384 if (lpstrFileSpecTemp[strlen(lpstrFileSpecTemp)-1] == '.')
1386 if (strchr(lpBuf, '.'))
1387 strcat(lpstrFileSpecTemp, (strchr(lpBuf, '.')) + 1);
1389 else
1390 strcat(lpstrFileSpecTemp, strchr(lpBuf, '.'));
1391 browsePidl = GetPidlFromName(fodInfos->Shell.FOIShellFolder,
1392 lpstrFileSpecTemp);
1393 MemFree((void *)lpBuf);
1394 if (browsePidl)
1396 strcpy(lpstrFileSpec,lpstrFileSpecTemp);
1397 break;
1399 if (lpstrExt)
1400 lpOrg = lpstrExt+1;
1401 else
1402 lpOrg = NULL;
1406 if (browsePidl)
1408 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
1409 int nMsgBoxRet;
1410 char lpstrFileExist[MAX_PATH + 50];
1412 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder,
1414 &browsePidl,
1415 &ulAttr);
1417 /* Browse to directory if it is a folder */
1418 if (ulAttr & SFGAO_FOLDER)
1420 if(FAILED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1421 browsePidl,
1422 SBSP_RELATIVE)))
1424 if(fodInfos->ofnInfos->Flags & OFN_PATHMUSTEXIST)
1426 MessageBoxA(hwnd,
1427 "Path does not exist",
1428 fodInfos->ofnInfos->lpstrTitle,
1429 MB_OK | MB_ICONEXCLAMATION);
1430 COMDLG32_SHFree(browsePidl);
1431 return FALSE;
1434 COMDLG32_SHFree(browsePidl);
1435 return FALSE;
1438 /* The file does exist, so ask the user if we should overwrite it */
1439 if((fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) &&
1440 (fodInfos->ofnInfos->Flags & OFN_OVERWRITEPROMPT))
1442 strcpy(lpstrFileExist, lpstrFileSpec);
1443 strcat(lpstrFileExist, " already exists.\nDo you want to replace it?");
1445 nMsgBoxRet = MessageBoxA(hwnd,
1446 lpstrFileExist,
1447 fodInfos->ofnInfos->lpstrTitle,
1448 MB_YESNO | MB_ICONEXCLAMATION);
1449 if (nMsgBoxRet == IDNO)
1451 COMDLG32_SHFree(browsePidl);
1452 return FALSE;
1455 COMDLG32_SHFree(browsePidl);
1457 else
1459 /* File does not exist in current directory */
1461 /* The selected file does not exist */
1462 /* Tell the user the selected does not exist */
1463 if(fodInfos->ofnInfos->Flags & OFN_FILEMUSTEXIST)
1465 char lpstrNotFound[100];
1466 char lpstrMsg[100];
1467 char tmp[400];
1469 LoadStringA(COMMDLG_hInstance32,
1470 IDS_FILENOTFOUND,
1471 lpstrNotFound,
1472 100);
1473 LoadStringA(COMMDLG_hInstance32,
1474 IDS_VERIFYFILE,
1475 lpstrMsg,
1476 100);
1478 strcpy(tmp,fodInfos->ofnInfos->lpstrFile);
1479 strcat(tmp,"\n");
1480 strcat(tmp,lpstrNotFound);
1481 strcat(tmp,"\n");
1482 strcat(tmp,lpstrMsg);
1484 MessageBoxA(hwnd,
1485 tmp,
1486 fodInfos->ofnInfos->lpstrTitle,
1487 MB_OK | MB_ICONEXCLAMATION);
1488 return FALSE;
1490 /* Ask the user if he wants to create the file*/
1491 if(fodInfos->ofnInfos->Flags & OFN_CREATEPROMPT)
1493 char tmp[100];
1495 LoadStringA(COMMDLG_hInstance32,IDS_CREATEFILE,tmp,100);
1497 if(IDYES == MessageBoxA(hwnd,tmp,fodInfos->ofnInfos->lpstrTitle,
1498 MB_YESNO | MB_ICONQUESTION))
1500 /* Create the file, clean and exit */
1501 FILEDLG95_Clean(hwnd);
1502 return EndDialog(hwnd,TRUE);
1504 return FALSE;
1508 /* Open the selected file */
1510 /* Check file extension */
1511 if(!strrchr(lpstrPathAndFile,'.'))
1513 /* if the file has no extension, append the selected
1514 extension of the filetype combo box */
1515 int iExt;
1516 LPSTR lpstrExt;
1517 iExt = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1518 lpstrTemp = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iExt);
1520 if((LPSTR)-1 != lpstrTemp)
1522 if((lpstrExt = strchr(lpstrTemp,';')))
1524 int i = lpstrExt - lpstrTemp;
1525 lpstrExt = MemAlloc(i);
1526 strncpy(lpstrExt,&lpstrTemp[1],i-1);
1528 else
1530 lpstrExt = MemAlloc(strlen(lpstrTemp));
1531 strcpy(lpstrExt,&lpstrTemp[1]);
1534 if(!strcmp(&lpstrExt[1],"*") && fodInfos->ofnInfos->lpstrDefExt)
1536 MemFree(lpstrExt);
1537 lpstrExt = MemAlloc(strlen(fodInfos->ofnInfos->lpstrDefExt)+2);
1538 strcat(lpstrExt,".");
1539 strcat(lpstrExt,(LPSTR) fodInfos->ofnInfos->lpstrDefExt);
1541 strcat(lpstrPathAndFile,lpstrExt);
1542 MemFree( lpstrExt );
1545 /* Check that size size of the file does not exceed buffer size */
1546 if(strlen(lpstrPathAndFile) > fodInfos->ofnInfos->nMaxFile)
1548 /* set error FNERR_BUFFERTOSMALL */
1549 FILEDLG95_Clean(hwnd);
1550 return EndDialog(hwnd,FALSE);
1552 strcpy(fodInfos->ofnInfos->lpstrFile,lpstrPathAndFile);
1554 /* Set the lpstrFileTitle of the OPENFILENAME structure */
1555 if(fodInfos->ofnInfos->lpstrFileTitle)
1556 strncpy(fodInfos->ofnInfos->lpstrFileTitle,
1557 lpstrFileSpec,
1558 fodInfos->ofnInfos->nMaxFileTitle);
1560 /* Check if the file is to be opened as read only */
1561 if(BST_CHECKED == SendDlgItemMessageA(hwnd,
1562 IDC_OPENREADONLY,
1563 BM_GETSTATE,0,0))
1564 SetFileAttributesA(fodInfos->ofnInfos->lpstrFile,
1565 FILE_ATTRIBUTE_READONLY);
1567 /* nFileExtension and nFileOffset of OPENFILENAME structure */
1568 lpstrTemp = strrchr(fodInfos->ofnInfos->lpstrFile,'\\');
1569 fodInfos->ofnInfos->nFileOffset = lpstrTemp - fodInfos->ofnInfos->lpstrFile + 1;
1570 lpstrTemp = strrchr(fodInfos->ofnInfos->lpstrFile,'.');
1571 fodInfos->ofnInfos->nFileExtension = lpstrTemp - fodInfos->ofnInfos->lpstrFile + 1;
1574 /* clean and exit */
1575 FILEDLG95_Clean(hwnd);
1576 return EndDialog(hwnd,TRUE);
1579 return FALSE;
1582 /***********************************************************************
1583 * FILEDLG95_SHELL_Init
1585 * Initialisation of the shell objects
1587 static HRESULT FILEDLG95_SHELL_Init(HWND hwnd)
1589 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1591 TRACE("\n");
1594 * Initialisation of the FileOpenDialogInfos structure
1597 /* Shell */
1599 fodInfos->Shell.FOIShellView = NULL;
1600 if(FAILED(COMDLG32_SHGetDesktopFolder(&fodInfos->Shell.FOIShellFolder)))
1601 return E_FAIL;
1603 /*ShellInfos */
1604 fodInfos->ShellInfos.hwndOwner = hwnd;
1606 fodInfos->ShellInfos.folderSettings.fFlags = 0;
1607 /* Disable multi-select if flag not set */
1608 if (!(fodInfos->ofnInfos->Flags & OFN_ALLOWMULTISELECT))
1610 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_SINGLESEL;
1612 fodInfos->ShellInfos.folderSettings.fFlags |= FWF_AUTOARRANGE | FWF_ALIGNLEFT;
1613 fodInfos->ShellInfos.folderSettings.ViewMode = FVM_LIST;
1615 GetWindowRect(GetDlgItem(hwnd,IDC_SHELLSTATIC),&fodInfos->ShellInfos.rectView);
1616 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.left);
1617 ScreenToClient(hwnd,(LPPOINT)&fodInfos->ShellInfos.rectView.right);
1619 /* Construct the IShellBrowser interface */
1620 fodInfos->Shell.FOIShellBrowser = IShellBrowserImpl_Construct(hwnd);
1622 return NOERROR;
1625 /***********************************************************************
1626 * FILEDLG95_SHELL_ExecuteCommand
1628 * Change the folder option and refresh the view
1629 * If the function succeeds, the return value is nonzero.
1631 static BOOL FILEDLG95_SHELL_ExecuteCommand(HWND hwnd, LPCSTR lpVerb)
1633 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1635 IContextMenu * pcm;
1636 TRACE("(0x%08x,%p)\n", hwnd, lpVerb);
1638 if(SUCCEEDED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView,
1639 SVGIO_BACKGROUND,
1640 &IID_IContextMenu,
1641 (LPVOID*)&pcm)))
1643 CMINVOKECOMMANDINFO ci;
1644 ZeroMemory(&ci, sizeof(CMINVOKECOMMANDINFO));
1645 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
1646 ci.lpVerb = lpVerb;
1647 ci.hwnd = hwnd;
1649 IContextMenu_InvokeCommand(pcm, &ci);
1650 IContextMenu_Release(pcm);
1653 return FALSE;
1656 /***********************************************************************
1657 * FILEDLG95_SHELL_UpFolder
1659 * Browse to the specified object
1660 * If the function succeeds, the return value is nonzero.
1662 static BOOL FILEDLG95_SHELL_UpFolder(HWND hwnd)
1664 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1666 TRACE("\n");
1668 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
1669 NULL,
1670 SBSP_PARENT)))
1672 return TRUE;
1674 return FALSE;
1677 /***********************************************************************
1678 * FILEDLG95_SHELL_Clean
1680 * Cleans the memory used by shell objects
1682 static void FILEDLG95_SHELL_Clean(HWND hwnd)
1684 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1686 TRACE("\n");
1688 /* clean Shell interfaces */
1689 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
1690 IShellView_Release(fodInfos->Shell.FOIShellView);
1691 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
1692 IShellBrowser_Release(fodInfos->Shell.FOIShellBrowser);
1695 /***********************************************************************
1696 * FILEDLG95_FILETYPE_Init
1698 * Initialisation of the file type combo box
1700 static HRESULT FILEDLG95_FILETYPE_Init(HWND hwnd)
1702 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1704 TRACE("\n");
1706 if(fodInfos->ofnInfos->lpstrFilter)
1708 int iStrIndex = 0;
1709 int iPos = 0;
1710 LPSTR lpstrFilter;
1711 LPSTR lpstrTmp;
1713 for(;;)
1715 /* filter is a list... title\0ext\0......\0\0
1716 * Set the combo item text to the title and the item data
1717 * to the ext
1719 char *lpstrExt = NULL;
1720 LPSTR lpstrExtTmp = NULL;
1722 /* Get the title */
1723 lpstrTmp = (&((LPBYTE)fodInfos->ofnInfos->lpstrFilter)[iStrIndex]);
1724 if(!strlen(lpstrTmp))
1725 break;
1726 iStrIndex += strlen(lpstrTmp) +1;
1727 /* Get the extension */
1728 lpstrExtTmp = (&((LPBYTE)fodInfos->ofnInfos->lpstrFilter)[iStrIndex]);
1729 if(!lpstrExtTmp)
1730 break;
1732 lpstrExt = (LPSTR) MemAlloc(strlen(lpstrExtTmp)+1);
1733 if(!lpstrExt)
1734 break;
1736 strcpy(lpstrExt,lpstrExtTmp);
1738 iStrIndex += strlen(lpstrExt) +1;
1740 /* Add the item at the end of the combo */
1741 CBAddString(fodInfos->DlgInfos.hwndFileTypeCB,lpstrTmp);
1742 CBSetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos++,lpstrExt);
1744 /* Set the current filter to the one specified
1745 * in the initialisation structure
1748 /* set default filter index */
1749 if(fodInfos->ofnInfos->nFilterIndex == 0 && fodInfos->ofnInfos->lpstrCustomFilter == NULL)
1750 fodInfos->ofnInfos->nFilterIndex = 1;
1751 /* First, check to make sure our index isn't out of bounds. */
1752 if ( fodInfos->ofnInfos->nFilterIndex > iPos )
1753 fodInfos->ofnInfos->nFilterIndex = iPos;
1756 /* Get the current index selection. */
1757 CBSetCurSel(fodInfos->DlgInfos.hwndFileTypeCB,
1758 fodInfos->ofnInfos->nFilterIndex-1);
1760 /* Get the corresponding text string from the combo box. */
1761 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1762 fodInfos->ofnInfos->nFilterIndex-1);
1764 if(lpstrFilter)
1766 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1767 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,strlwr(lpstrFilter));
1770 return NOERROR;
1773 /***********************************************************************
1774 * FILEDLG95_FILETYPE_OnCommand
1776 * WM_COMMAND of the file type combo box
1777 * If the function succeeds, the return value is nonzero.
1779 static BOOL FILEDLG95_FILETYPE_OnCommand(HWND hwnd, WORD wNotifyCode)
1781 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1783 switch(wNotifyCode)
1785 case CBN_SELENDOK:
1787 LPSTR lpstrFilter;
1789 /* Get the current item of the filetype combo box */
1790 int iItem = CBGetCurSel(fodInfos->DlgInfos.hwndFileTypeCB);
1792 /* set the current filter index - indexed from 1 */
1793 fodInfos->ofnInfos->nFilterIndex = iItem + 1;
1795 /* Set the current filter with the current selection */
1796 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1797 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1799 lpstrFilter = (LPSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
1800 iItem);
1801 if((int)lpstrFilter != CB_ERR)
1803 fodInfos->ShellInfos.lpstrCurrentFilter = MemAlloc((strlen(lpstrFilter)+1)*2);
1804 lstrcpyAtoW(fodInfos->ShellInfos.lpstrCurrentFilter,(LPSTR)strlwr((LPSTR)lpstrFilter));
1805 SendCustomDlgNotificationMessage(hwnd,CDN_TYPECHANGE);
1808 /* Refresh the actual view to display the included items*/
1809 IShellView_Refresh(fodInfos->Shell.FOIShellView);
1813 return FALSE;
1815 /***********************************************************************
1816 * FILEDLG95_FILETYPE_SearchExt
1818 * Search for pidl in the lookin combo box
1819 * returns the index of the found item
1821 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd,LPSTR lpstrExt)
1823 int i = 0;
1824 int iCount = CBGetCount(hwnd);
1826 TRACE("\n");
1828 for(;i<iCount;i++)
1830 LPSTR ext = (LPSTR) CBGetItemDataPtr(hwnd,i);
1831 if(!strcasecmp(lpstrExt,ext))
1832 return i;
1835 return -1;
1838 /***********************************************************************
1839 * FILEDLG95_FILETYPE_Clean
1841 * Clean the memory used by the filetype combo box
1843 static void FILEDLG95_FILETYPE_Clean(HWND hwnd)
1845 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
1846 int iPos;
1847 int iCount = CBGetCount(fodInfos->DlgInfos.hwndFileTypeCB);
1849 TRACE("\n");
1851 /* Delete each string of the combo and their associated data */
1852 for(iPos = iCount-1;iPos>=0;iPos--)
1854 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,iPos)));
1855 CBDeleteString(fodInfos->DlgInfos.hwndFileTypeCB,iPos);
1857 /* Current filter */
1858 if(fodInfos->ShellInfos.lpstrCurrentFilter)
1859 MemFree((LPVOID)fodInfos->ShellInfos.lpstrCurrentFilter);
1863 /***********************************************************************
1864 * FILEDLG95_LOOKIN_Init
1866 * Initialisation of the look in combo box
1868 static HRESULT FILEDLG95_LOOKIN_Init(HWND hwndCombo)
1870 IShellFolder *psfRoot, *psfDrives;
1871 IEnumIDList *lpeRoot, *lpeDrives;
1872 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
1874 LookInInfos *liInfos = MemAlloc(sizeof(LookInInfos));
1876 TRACE("\n");
1878 liInfos->iMaxIndentation = 0;
1880 SetPropA(hwndCombo, LookInInfosStr, (HANDLE) liInfos);
1881 CBSetItemHeight(hwndCombo,0,GetSystemMetrics(SM_CYSMICON));
1883 /* Initialise data of Desktop folder */
1884 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,&pidlTmp);
1885 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1886 COMDLG32_SHFree(pidlTmp);
1888 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES,&pidlDrives);
1890 COMDLG32_SHGetDesktopFolder(&psfRoot);
1892 if (psfRoot)
1894 /* enumerate the contents of the desktop */
1895 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
1897 while (S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp, NULL))
1899 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlTmp,LISTEND);
1901 /* special handling for CSIDL_DRIVES */
1902 if (COMDLG32_PIDL_ILIsEqual(pidlTmp, pidlDrives))
1904 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp, NULL, &IID_IShellFolder, (LPVOID*)&psfDrives)))
1906 /* enumerate the drives */
1907 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
1909 while (S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1, NULL))
1911 pidlAbsTmp = COMDLG32_PIDL_ILCombine(pidlTmp, pidlTmp1);
1912 FILEDLG95_LOOKIN_AddItem(hwndCombo, pidlAbsTmp,LISTEND);
1913 COMDLG32_SHFree(pidlAbsTmp);
1914 COMDLG32_SHFree(pidlTmp1);
1916 IEnumIDList_Release(lpeDrives);
1918 IShellFolder_Release(psfDrives);
1921 COMDLG32_SHFree(pidlTmp);
1923 IEnumIDList_Release(lpeRoot);
1927 IShellFolder_Release(psfRoot);
1928 COMDLG32_SHFree(pidlDrives);
1929 return NOERROR;
1932 /***********************************************************************
1933 * FILEDLG95_LOOKIN_DrawItem
1935 * WM_DRAWITEM message handler
1937 static LRESULT FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct)
1939 COLORREF crWin = GetSysColor(COLOR_WINDOW);
1940 COLORREF crHighLight = GetSysColor(COLOR_HIGHLIGHT);
1941 COLORREF crText = GetSysColor(COLOR_WINDOWTEXT);
1942 RECT rectText;
1943 RECT rectIcon;
1944 SHFILEINFOA sfi;
1945 HIMAGELIST ilItemImage;
1946 int iIndentation;
1947 LPSFOLDER tmpFolder;
1950 LookInInfos *liInfos = (LookInInfos *)GetPropA(pDIStruct->hwndItem,LookInInfosStr);
1952 TRACE("\n");
1954 if(pDIStruct->itemID == -1)
1955 return 0;
1957 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(pDIStruct->hwndItem,
1958 pDIStruct->itemID)))
1959 return 0;
1962 if(pDIStruct->itemID == liInfos->uSelectedItem)
1964 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1966 &sfi,
1967 sizeof (SHFILEINFOA),
1968 SHGFI_PIDL | SHGFI_SMALLICON |
1969 SHGFI_OPENICON | SHGFI_SYSICONINDEX |
1970 SHGFI_DISPLAYNAME );
1972 else
1974 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
1976 &sfi,
1977 sizeof (SHFILEINFOA),
1978 SHGFI_PIDL | SHGFI_SMALLICON |
1979 SHGFI_SYSICONINDEX |
1980 SHGFI_DISPLAYNAME);
1983 /* Is this item selected ?*/
1984 if(pDIStruct->itemState & ODS_SELECTED)
1986 SetTextColor(pDIStruct->hDC,(0x00FFFFFF & ~(crText)));
1987 SetBkColor(pDIStruct->hDC,crHighLight);
1988 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crHighLight);
1990 else
1992 SetTextColor(pDIStruct->hDC,crText);
1993 SetBkColor(pDIStruct->hDC,crWin);
1994 FillRect(pDIStruct->hDC,&pDIStruct->rcItem,(HBRUSH)crWin);
1997 /* Do not indent item if drawing in the edit of the combo*/
1998 if(pDIStruct->itemState & ODS_COMBOBOXEDIT)
2000 iIndentation = 0;
2001 ilItemImage = (HIMAGELIST) COMDLG32_SHGetFileInfoA ((LPCSTR) tmpFolder->pidlItem,
2003 &sfi,
2004 sizeof (SHFILEINFOA),
2005 SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_OPENICON
2006 | SHGFI_SYSICONINDEX | SHGFI_DISPLAYNAME );
2009 else
2011 iIndentation = tmpFolder->m_iIndent;
2013 /* Draw text and icon */
2015 /* Initialise the icon display area */
2016 rectIcon.left = pDIStruct->rcItem.left + ICONWIDTH/2 * iIndentation;
2017 rectIcon.top = pDIStruct->rcItem.top;
2018 rectIcon.right = rectIcon.left + ICONWIDTH;
2019 rectIcon.bottom = pDIStruct->rcItem.bottom;
2021 /* Initialise the text display area */
2022 rectText.left = rectIcon.right;
2023 rectText.top = pDIStruct->rcItem.top + YTEXTOFFSET;
2024 rectText.right = pDIStruct->rcItem.right + XTEXTOFFSET;
2025 rectText.bottom = pDIStruct->rcItem.bottom;
2028 /* Draw the icon from the image list */
2029 COMDLG32_ImageList_Draw(ilItemImage,
2030 sfi.iIcon,
2031 pDIStruct->hDC,
2032 rectIcon.left,
2033 rectIcon.top,
2034 ILD_TRANSPARENT );
2036 /* Draw the associated text */
2037 if(sfi.szDisplayName)
2038 TextOutA(pDIStruct->hDC,rectText.left,rectText.top,sfi.szDisplayName,strlen(sfi.szDisplayName));
2041 return NOERROR;
2044 /***********************************************************************
2045 * FILEDLG95_LOOKIN_OnCommand
2047 * LookIn combo box WM_COMMAND message handler
2048 * If the function succeeds, the return value is nonzero.
2050 static BOOL FILEDLG95_LOOKIN_OnCommand(HWND hwnd, WORD wNotifyCode)
2052 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2054 TRACE("%p\n", fodInfos);
2056 switch(wNotifyCode)
2058 case CBN_SELENDOK:
2060 LPSFOLDER tmpFolder;
2061 int iItem;
2063 iItem = CBGetCurSel(fodInfos->DlgInfos.hwndLookInCB);
2065 if(!(tmpFolder = (LPSFOLDER) CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,
2066 iItem)))
2067 return FALSE;
2070 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->Shell.FOIShellBrowser,
2071 tmpFolder->pidlItem,
2072 SBSP_ABSOLUTE)))
2074 return TRUE;
2076 break;
2080 return FALSE;
2083 /***********************************************************************
2084 * FILEDLG95_LOOKIN_AddItem
2086 * Adds an absolute pidl item to the lookin combo box
2087 * returns the index of the inserted item
2089 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd,LPITEMIDLIST pidl, int iInsertId)
2091 LPITEMIDLIST pidlNext;
2092 SHFILEINFOA sfi;
2093 SFOLDER *tmpFolder;
2094 LookInInfos *liInfos;
2096 TRACE("\n");
2098 if(!pidl)
2099 return -1;
2101 if(!(liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr)))
2102 return -1;
2104 tmpFolder = MemAlloc(sizeof(SFOLDER));
2105 tmpFolder->m_iIndent = 0;
2107 /* Calculate the indentation of the item in the lookin*/
2108 pidlNext = pidl;
2109 while( (pidlNext=COMDLG32_PIDL_ILGetNext(pidlNext)) )
2111 tmpFolder->m_iIndent++;
2114 tmpFolder->pidlItem = COMDLG32_PIDL_ILClone(pidl);
2116 if(tmpFolder->m_iIndent > liInfos->iMaxIndentation)
2117 liInfos->iMaxIndentation = tmpFolder->m_iIndent;
2119 COMDLG32_SHGetFileInfoA((LPSTR)pidl,
2121 &sfi,
2122 sizeof(sfi),
2123 SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX
2124 | SHGFI_PIDL | SHGFI_SMALLICON | SHGFI_ATTRIBUTES);
2127 if((sfi.dwAttributes & SFGAO_FILESYSANCESTOR) || (sfi.dwAttributes & SFGAO_FILESYSTEM))
2129 int iItemID;
2130 /* Add the item at the end of the list */
2131 if(iInsertId < 0)
2133 iItemID = CBAddString(hwnd,sfi.szDisplayName);
2135 /* Insert the item at the iInsertId position*/
2136 else
2138 iItemID = CBInsertString(hwnd,sfi.szDisplayName,iInsertId);
2141 CBSetItemDataPtr(hwnd,iItemID,tmpFolder);
2142 return iItemID;
2145 MemFree( tmpFolder );
2146 return -1;
2150 /***********************************************************************
2151 * FILEDLG95_LOOKIN_InsertItemAfterParent
2153 * Insert an item below its parent
2155 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd,LPITEMIDLIST pidl)
2158 LPITEMIDLIST pidlParent = GetParentPidl(pidl);
2159 int iParentPos;
2161 TRACE("\n");
2163 iParentPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidlParent,SEARCH_PIDL);
2165 if(iParentPos < 0)
2167 iParentPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidlParent);
2170 /* Free pidlParent memory */
2171 COMDLG32_SHFree((LPVOID)pidlParent);
2173 return FILEDLG95_LOOKIN_AddItem(hwnd,pidl,iParentPos + 1);
2176 /***********************************************************************
2177 * FILEDLG95_LOOKIN_SelectItem
2179 * Adds an absolute pidl item to the lookin combo box
2180 * returns the index of the inserted item
2182 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl)
2184 int iItemPos;
2185 LookInInfos *liInfos;
2187 TRACE("\n");
2189 iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)pidl,SEARCH_PIDL);
2191 liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2193 if(iItemPos < 0)
2195 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd) > -1);
2196 iItemPos = FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd,pidl);
2199 else
2201 SFOLDER *tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2202 while(liInfos->iMaxIndentation > tmpFolder->m_iIndent)
2204 int iRemovedItem;
2206 if(-1 == (iRemovedItem = FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd)))
2207 break;
2208 if(iRemovedItem < iItemPos)
2209 iItemPos--;
2213 CBSetCurSel(hwnd,iItemPos);
2214 liInfos->uSelectedItem = iItemPos;
2216 return 0;
2220 /***********************************************************************
2221 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2223 * Remove the item with an expansion level over iExpansionLevel
2225 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd)
2227 int iItemPos;
2229 LookInInfos *liInfos = (LookInInfos *)GetPropA(hwnd,LookInInfosStr);
2231 TRACE("\n");
2233 if(liInfos->iMaxIndentation <= 2)
2234 return -1;
2236 if((iItemPos = FILEDLG95_LOOKIN_SearchItem(hwnd,(WPARAM)liInfos->iMaxIndentation,SEARCH_EXP)) >=0)
2238 SFOLDER *tmpFolder;
2239 tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,iItemPos);
2240 CBDeleteString(hwnd,iItemPos);
2241 liInfos->iMaxIndentation--;
2243 return iItemPos;
2246 return -1;
2249 /***********************************************************************
2250 * FILEDLG95_LOOKIN_SearchItem
2252 * Search for pidl in the lookin combo box
2253 * returns the index of the found item
2255 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd,WPARAM searchArg,int iSearchMethod)
2257 int i = 0;
2258 int iCount = CBGetCount(hwnd);
2260 TRACE("\n");
2262 for(;i<iCount;i++)
2264 LPSFOLDER tmpFolder = (LPSFOLDER) CBGetItemDataPtr(hwnd,i);
2266 if(iSearchMethod == SEARCH_PIDL && COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST)searchArg,tmpFolder->pidlItem))
2267 return i;
2268 if(iSearchMethod == SEARCH_EXP && tmpFolder->m_iIndent == (int)searchArg)
2269 return i;
2273 return -1;
2276 /***********************************************************************
2277 * FILEDLG95_LOOKIN_Clean
2279 * Clean the memory used by the lookin combo box
2281 static void FILEDLG95_LOOKIN_Clean(HWND hwnd)
2283 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwnd,FileOpenDlgInfosStr);
2284 int iPos;
2285 int iCount = CBGetCount(fodInfos->DlgInfos.hwndLookInCB);
2287 TRACE("\n");
2289 /* Delete each string of the combo and their associated data */
2290 for(iPos = iCount-1;iPos>=0;iPos--)
2292 MemFree((LPVOID)(CBGetItemDataPtr(fodInfos->DlgInfos.hwndLookInCB,iPos)));
2293 CBDeleteString(fodInfos->DlgInfos.hwndLookInCB,iPos);
2295 /* LookInInfos structure */
2296 RemovePropA(fodInfos->DlgInfos.hwndLookInCB,LookInInfosStr);
2300 * TOOLS
2303 /* copied from shell32 to avoid linking to it */
2304 static HRESULT COMDLG32_StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
2306 switch (src->uType)
2308 case STRRET_WSTR:
2309 WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
2310 COMDLG32_SHFree(src->u.pOleStr);
2311 break;
2313 case STRRET_CSTRA:
2314 lstrcpynA((LPSTR)dest, src->u.cStr, len);
2315 break;
2317 case STRRET_OFFSETA:
2318 lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
2319 break;
2321 default:
2322 FIXME("unknown type!\n");
2323 if (len)
2325 *(LPSTR)dest = '\0';
2327 return(FALSE);
2329 return S_OK;
2332 /***********************************************************************
2333 * GetName
2335 * Get the pidl's display name (relative to folder) and
2336 * put it in lpstrFileName.
2338 * Return NOERROR on success,
2339 * E_FAIL otherwise
2342 HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName)
2344 STRRET str;
2345 HRESULT hRes;
2347 TRACE("%p %p\n", lpsf, pidl);
2349 if(!lpsf)
2351 HRESULT hRes;
2352 COMDLG32_SHGetDesktopFolder(&lpsf);
2353 hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName);
2354 IShellFolder_Release(lpsf);
2355 return hRes;
2358 /* Get the display name of the pidl relative to the folder */
2359 if (SUCCEEDED(hRes = IShellFolder_GetDisplayNameOf(lpsf,
2360 pidl,
2361 dwFlags,
2362 &str)))
2364 return COMDLG32_StrRetToStrNA(lpstrFileName, MAX_PATH, &str, pidl);
2366 return E_FAIL;
2369 /***********************************************************************
2370 * GetShellFolderFromPidl
2372 * pidlRel is the item pidl relative
2373 * Return the IShellFolder of the absolute pidl
2375 IShellFolder *GetShellFolderFromPidl(LPITEMIDLIST pidlAbs)
2377 IShellFolder *psf = NULL,*psfParent;
2379 TRACE("%p\n", pidlAbs);
2381 if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent)))
2383 psf = psfParent;
2384 if(pidlAbs && pidlAbs->mkid.cb)
2386 if(SUCCEEDED(IShellFolder_BindToObject(psfParent, pidlAbs, NULL, &IID_IShellFolder, (LPVOID*)&psf)))
2388 IShellFolder_Release(psfParent);
2389 return psf;
2392 /* return the desktop */
2393 return psfParent;
2395 return NULL;
2398 /***********************************************************************
2399 * GetParentPidl
2401 * Return the LPITEMIDLIST to the parent of the pidl in the list
2403 LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl)
2405 LPITEMIDLIST pidlParent;
2407 TRACE("%p\n", pidl);
2409 pidlParent = COMDLG32_PIDL_ILClone(pidl);
2410 COMDLG32_PIDL_ILRemoveLastID(pidlParent);
2412 return pidlParent;
2415 /***********************************************************************
2416 * GetPidlFromName
2418 * returns the pidl of the file name relative to folder
2419 * NULL if an error occured
2421 LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName)
2423 LPITEMIDLIST pidl;
2424 ULONG ulEaten;
2425 wchar_t lpwstrDirName[MAX_PATH];
2428 TRACE("sf=%p file=%s\n", psf, lpcstrFileName);
2430 if(!lpcstrFileName)
2431 return NULL;
2433 MultiByteToWideChar(CP_ACP,
2434 MB_PRECOMPOSED,
2435 lpcstrFileName,
2436 -1,
2437 (LPWSTR)lpwstrDirName,
2438 MAX_PATH);
2440 IShellFolder_ParseDisplayName(psf, 0,
2441 NULL,
2442 (LPWSTR)lpwstrDirName,
2443 &ulEaten,
2444 &pidl,
2445 NULL);
2447 return pidl;
2450 /***********************************************************************
2451 * GetFileExtension
2454 BOOL GetFileExtension(IShellFolder *psf,LPITEMIDLIST pidl,LPSTR lpstrFileExtension)
2456 char FileName[MAX_PATH];
2457 int result;
2458 char *pdest;
2459 int ch = '.';
2461 if(SUCCEEDED(GetName(psf,pidl,SHGDN_NORMAL,FileName)))
2463 if(!(pdest = strrchr( FileName, ch )))
2464 return FALSE;
2466 result = pdest - FileName + 1;
2467 strcpy(lpstrFileExtension,&FileName[result]);
2468 return TRUE;
2470 return FALSE;
2474 * Memory allocation methods */
2475 static void *MemAlloc(UINT size)
2477 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
2480 static void MemFree(void *mem)
2482 if(mem)
2484 HeapFree(GetProcessHeap(),0,mem);