Buffer overflows and strncpy fixes.
[wine] / dlls / commdlg / filedlg.c
1 /*
2  * COMMDLG - File Dialogs
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  */
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "winbase.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "ldt.h"
14 #include "heap.h"
15 #include "commdlg.h"
16 #include "resource.h"
17 #include "dialog.h"
18 #include "dlgs.h"
19 #include "module.h"
20 #include "drive.h"
21 #include "debugtools.h"
22 #include "winproc.h"
23 #include "cderr.h"
24 #include "tweak.h"
25
26 DEFAULT_DEBUG_CHANNEL(commdlg)
27
28 #include "cdlg.h"
29
30 static HICON16 hFolder = 0;
31 static HICON16 hFolder2 = 0;
32 static HICON16 hFloppy = 0;
33 static HICON16 hHDisk = 0;
34 static HICON16 hCDRom = 0;
35 static HICON16 hNet = 0;
36 static int fldrHeight = 0;
37 static int fldrWidth = 0;
38
39 static const char defaultfilter[]=" \0\0";
40 #define OFN_PROP "FILEDLG_OFN_LPARAM"
41
42 /***********************************************************************
43  *
44  * Windows 3.1 OpenFileName/SaveFileName dialog
45  *
46  */
47 /***********************************************************************
48  *                              FileDlg_Init                    [internal]
49  */
50 static BOOL FileDlg_Init(void)
51 {
52     static BOOL initialized = 0;
53     CURSORICONINFO *fldrInfo;
54     
55     if (!initialized) {
56         if (!hFolder) hFolder = LoadIcon16(0, MAKEINTRESOURCE16(OIC_FOLDER));
57         if (!hFolder2) hFolder2 = LoadIcon16(0, MAKEINTRESOURCE16(OIC_FOLDER2));
58         if (!hFloppy) hFloppy = LoadIcon16(0, MAKEINTRESOURCE16(OIC_FLOPPY));
59         if (!hHDisk) hHDisk = LoadIcon16(0, MAKEINTRESOURCE16(OIC_HDISK));
60         if (!hCDRom) hCDRom = LoadIcon16(0, MAKEINTRESOURCE16(OIC_CDROM));
61         if (!hNet) hNet = LoadIcon16(0, MAKEINTRESOURCE16(OIC_NETWORK));
62         if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 
63             hHDisk == 0 || hCDRom == 0 || hNet == 0)
64         {
65             ERR("Error loading icons !\n");
66             return FALSE;
67         }
68         fldrInfo = (CURSORICONINFO *) GlobalLock16( hFolder2 );
69         if (!fldrInfo)
70         {       
71             ERR("Error measuring icons !\n");
72             return FALSE;
73         }
74         fldrHeight = fldrInfo -> nHeight;
75         fldrWidth = fldrInfo -> nWidth;
76         GlobalUnlock16( hFolder2 );
77         initialized = TRUE;
78     }
79     return TRUE;
80 }
81
82 /***********************************************************************
83  *           FileOpenDlgProc [internal]
84  *
85  * FIXME: Convert to real 32-bit message processing
86  */
87 static LRESULT WINAPI FileOpenDlgProc(HWND hDlg, UINT msg,
88                                       WPARAM wParam, LPARAM lParam)
89 {
90     UINT16 msg16;
91     MSGPARAM16 mp16;
92
93     mp16.lParam = lParam;
94     if (WINPROC_MapMsg32ATo16( hDlg, msg, wParam,
95                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
96         return 0;
97     mp16.lResult = FileOpenDlgProc16( (HWND16)hDlg, msg16, 
98                                       mp16.wParam, mp16.lParam );
99     
100     WINPROC_UnmapMsg32ATo16( hDlg, msg, wParam, lParam, &mp16 );
101     return mp16.lResult;
102 }
103
104 /***********************************************************************
105  *           FileSaveDlgProc [internal]
106  *
107  * FIXME: Convert to real 32-bit message processing
108  */
109 static LRESULT WINAPI FileSaveDlgProc(HWND hDlg, UINT msg,
110                                       WPARAM wParam, LPARAM lParam)
111 {
112     UINT16 msg16;
113     MSGPARAM16 mp16;
114
115     mp16.lParam = lParam;
116     if (WINPROC_MapMsg32ATo16( hDlg, msg, wParam,
117                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
118         return 0;
119     mp16.lResult = FileSaveDlgProc16( (HWND16)hDlg, msg16, 
120                                       mp16.wParam, mp16.lParam );
121     
122     WINPROC_UnmapMsg32ATo16( hDlg, msg, wParam, lParam, &mp16 );
123     return mp16.lResult;
124 }
125
126 /***********************************************************************
127  *           GetOpenFileName16   (COMMDLG.1)
128  *
129  * Creates a dialog box for the user to select a file to open.
130  *
131  * RETURNS
132  *    TRUE on success: user selected a valid file
133  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
134  *
135  * BUGS
136  *    unknown, there are some FIXME's left.
137  */
138 BOOL16 WINAPI GetOpenFileName16( 
139                                 SEGPTR ofn /* addess of structure with data*/
140                                 )
141 {
142     HINSTANCE hInst;
143     HANDLE hDlgTmpl = 0, hResInfo;
144     BOOL bRet = FALSE, win32Format = FALSE;
145     HWND hwndDialog;
146     LPOPENFILENAME16 lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(ofn);
147     LPCVOID template;
148     char defaultopen[]="Open File";
149     char *str=0,*str1=0;
150
151     if (!lpofn || !FileDlg_Init()) return FALSE;
152
153     if (lpofn->Flags & OFN_WINE) {
154             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
155             {
156                 if (!(template = LockResource( MapHModuleSL(lpofn->hInstance ))))
157                 {
158                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
159                     return FALSE;
160                 }
161             }
162             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
163             {
164                 if (!(hResInfo = FindResourceA(MapHModuleSL(lpofn->hInstance),
165                                                 PTR_SEG_TO_LIN(lpofn->lpTemplateName), RT_DIALOGA)))
166                 {
167                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
168                     return FALSE;
169                 }
170                 if (!(hDlgTmpl = LoadResource( MapHModuleSL(lpofn->hInstance),
171                                                  hResInfo )) ||
172                     !(template = LockResource( hDlgTmpl )))
173                 {
174                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
175                     return FALSE;
176                 }
177             } else {
178                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "OPEN_FILE", RT_DIALOGA)))
179                 {
180                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
181                     return FALSE;
182                 }
183                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
184                     !(template = LockResource( hDlgTmpl )))
185                 {
186                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
187                     return FALSE;
188                 }
189             }
190             win32Format = TRUE;
191     } else {
192             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
193             {
194                 if (!(template = LockResource16( lpofn->hInstance )))
195                 {
196                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
197                     return FALSE;
198                 }
199             }
200             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
201             {
202                 if (!(hResInfo = FindResource16(lpofn->hInstance,
203                                                 lpofn->lpTemplateName,
204                                                 RT_DIALOG16)))
205                 {
206                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
207                     return FALSE;
208                 }
209                 if (!(hDlgTmpl = LoadResource16( lpofn->hInstance, hResInfo )) ||
210                     !(template = LockResource16( hDlgTmpl )))
211                 {
212                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
213                     return FALSE;
214                 }
215             } else {
216                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "OPEN_FILE", RT_DIALOGA)))
217                 {
218                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
219                     return FALSE;
220                 }
221                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
222                     !(template = LockResource( hDlgTmpl )))
223                 {
224                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
225                     return FALSE;
226                 }
227                 win32Format = TRUE;
228             }
229     }
230
231     hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
232
233     if (!(lpofn->lpstrFilter))
234       {
235        str = SEGPTR_ALLOC(sizeof(defaultfilter));
236        TRACE("Alloc %p default for Filetype in GetOpenFileName\n",str);
237        memcpy(str,defaultfilter,sizeof(defaultfilter));
238        lpofn->lpstrFilter=SEGPTR_GET(str);
239       }
240
241     if (!(lpofn->lpstrTitle))
242       {
243        str1 = SEGPTR_ALLOC(strlen(defaultopen)+1);
244        TRACE("Alloc %p default for Title in GetOpenFileName\n",str1);
245        strcpy(str1,defaultopen);
246        lpofn->lpstrTitle=SEGPTR_GET(str1);
247       }
248
249     /* FIXME: doesn't handle win32 format correctly yet */
250     hwndDialog = DIALOG_CreateIndirect( hInst, template, win32Format,
251                                         lpofn->hwndOwner,
252                                         (DLGPROC16)FileOpenDlgProc,
253                                         ofn, WIN_PROC_32A );
254     if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpofn->hwndOwner );
255
256     if (str1)
257       {
258        TRACE("Freeing %p default for Title in GetOpenFileName\n",str1);
259         SEGPTR_FREE(str1);
260        lpofn->lpstrTitle=0;
261       }
262
263     if (str)
264       {
265        TRACE("Freeing %p default for Filetype in GetOpenFileName\n",str);
266         SEGPTR_FREE(str);
267        lpofn->lpstrFilter=0;
268       }
269
270     if (hDlgTmpl) {
271             if (lpofn->Flags & OFN_WINE)
272                     FreeResource( hDlgTmpl );
273             else
274                     FreeResource16( hDlgTmpl );
275     }
276
277     TRACE("return lpstrFile='%s' !\n", 
278            (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
279     return bRet;
280 }
281
282
283 /***********************************************************************
284  *           GetSaveFileName   (COMMDLG.2)
285  *
286  * Creates a dialog box for the user to select a file to save.
287  *
288  * RETURNS
289  *    TRUE on succes: user enters a valid file
290  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
291  *
292  * BUGS
293  *    unknown. There are some FIXME's left.
294  */
295 BOOL16 WINAPI GetSaveFileName16( 
296                                 SEGPTR ofn /* addess of structure with data*/
297                                 )
298 {
299     HINSTANCE hInst;
300     HANDLE hDlgTmpl = 0;
301     BOOL bRet = FALSE, win32Format = FALSE;
302     LPOPENFILENAME16 lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(ofn);
303     LPCVOID template;
304     HWND hwndDialog;
305     char defaultsave[]="Save as";
306     char *str =0,*str1=0;
307
308     if (!lpofn || !FileDlg_Init()) return FALSE;
309
310     if (lpofn->Flags & OFN_WINE) {
311             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
312             {
313                 if (!(template = LockResource( MapHModuleSL(lpofn->hInstance ))))
314                 {
315                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
316                     return FALSE;
317                 }
318             }
319             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
320             {
321                 HANDLE hResInfo;
322                 if (!(hResInfo = FindResourceA(MapHModuleSL(lpofn->hInstance),
323                                                  PTR_SEG_TO_LIN(lpofn->lpTemplateName),
324                                                  RT_DIALOGA)))
325                 {
326                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
327                     return FALSE;
328                 }
329                 if (!(hDlgTmpl = LoadResource(MapHModuleSL(lpofn->hInstance),
330                                                 hResInfo)) ||
331                     !(template = LockResource(hDlgTmpl)))
332                 {
333                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
334                     return FALSE;
335                 }
336                 win32Format= TRUE;
337             } else {
338                 HANDLE hResInfo;
339                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "SAVE_FILE", RT_DIALOGA)))
340                 {
341                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
342                     return FALSE;
343                 }
344                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
345                     !(template = LockResource( hDlgTmpl )))
346                 {
347                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
348                     return FALSE;
349                 }
350                 win32Format = TRUE;
351             }
352     } else {
353             if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE)
354             {
355                 if (!(template = LockResource16( lpofn->hInstance )))
356                 {
357                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
358                     return FALSE;
359                 }
360             }
361             else if (lpofn->Flags & OFN_ENABLETEMPLATE)
362             {
363                 HANDLE16 hResInfo;
364                 if (!(hResInfo = FindResource16(lpofn->hInstance,
365                                                 lpofn->lpTemplateName,
366                                                 RT_DIALOG16)))
367                 {
368                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
369                     return FALSE;
370                 }
371                 if (!(hDlgTmpl = LoadResource16( lpofn->hInstance, hResInfo )) ||
372                     !(template = LockResource16( hDlgTmpl )))
373                 {
374                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
375                     return FALSE;
376                 }
377         } else {
378                 HANDLE hResInfo;
379                 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "SAVE_FILE", RT_DIALOGA)))
380                 {
381                     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
382                     return FALSE;
383                 }
384                 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
385                     !(template = LockResource( hDlgTmpl )))
386                 {
387                     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
388                     return FALSE;
389                 }
390                 win32Format = TRUE;
391         }
392     }
393
394     hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
395
396     if (!(lpofn->lpstrFilter))
397       {
398        str = SEGPTR_ALLOC(sizeof(defaultfilter));
399        TRACE("Alloc default for Filetype in GetSaveFileName\n");
400        memcpy(str,defaultfilter,sizeof(defaultfilter));
401        lpofn->lpstrFilter=SEGPTR_GET(str);
402       }
403
404     if (!(lpofn->lpstrTitle))
405       {
406        str1 = SEGPTR_ALLOC(sizeof(defaultsave)+1);
407        TRACE("Alloc default for Title in GetSaveFileName\n");
408        strcpy(str1,defaultsave);
409        lpofn->lpstrTitle=SEGPTR_GET(str1);
410       }
411
412     hwndDialog = DIALOG_CreateIndirect( hInst, template, win32Format,
413                                         lpofn->hwndOwner,
414                                         (DLGPROC16)FileSaveDlgProc,
415                                         ofn, WIN_PROC_32A );
416     if (hwndDialog) bRet = DIALOG_DoDialogBox( hwndDialog, lpofn->hwndOwner );
417
418     if (str1)
419       {
420        TRACE("Freeing %p default for Title in GetSaveFileName\n",str1);
421         SEGPTR_FREE(str1);
422        lpofn->lpstrTitle=0;
423       }
424  
425     if (str)
426       {
427        TRACE("Freeing %p default for Filetype in GetSaveFileName\n",str);
428         SEGPTR_FREE(str);
429        lpofn->lpstrFilter=0;
430       }
431     
432     if (hDlgTmpl) {
433             if (lpofn->Flags & OFN_WINE)
434                     FreeResource( hDlgTmpl );
435             else
436                     FreeResource16( hDlgTmpl );
437     }
438
439     TRACE("return lpstrFile='%s' !\n", 
440             (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
441     return bRet;
442 }
443
444 /***********************************************************************
445  *                              FILEDLG_StripEditControl        [internal]
446  * Strip pathnames off the contents of the edit control.
447  */
448 static void FILEDLG_StripEditControl(HWND16 hwnd)
449 {
450     char temp[512], *cp;
451
452     GetDlgItemTextA( hwnd, edt1, temp, sizeof(temp) );
453     cp = strrchr(temp, '\\');
454     if (cp != NULL) {
455         strcpy(temp, cp+1);
456     }
457     cp = strrchr(temp, ':');
458     if (cp != NULL) {
459         strcpy(temp, cp+1);
460     }
461     /* FIXME: shouldn't we do something with the result here? ;-) */
462 }
463
464 /***********************************************************************
465  *                              FILEDLG_ScanDir                 [internal]
466  */
467 static BOOL FILEDLG_ScanDir(HWND16 hWnd, LPSTR newPath)
468 {
469     char                buffer[512];
470          char*                  str = buffer;
471     int                         drive;
472     HWND                hlb;
473
474     lstrcpynA(buffer, newPath, sizeof(buffer));
475
476     if (str[0] && (str[1] == ':')) {
477         drive = toupper(str[0]) - 'A';
478         str += 2;
479         if (!DRIVE_SetCurrentDrive(drive)) 
480                           return FALSE;
481     } else {
482                  drive = DRIVE_GetCurrentDrive();
483          }
484
485     if (str[0] && !DRIVE_Chdir(drive, str)) {
486                  return FALSE;
487     }
488
489     GetDlgItemTextA(hWnd, edt1, buffer, sizeof(buffer));
490     if ((hlb = GetDlgItem(hWnd, lst1)) != 0) {
491                  char*  scptr; /* ptr on semi-colon */
492                  char*  filter = buffer;
493
494                  TRACE("Using filter %s\n", filter);
495                  SendMessageA(hlb, LB_RESETCONTENT, 0, 0);
496                  while (filter) {
497                          scptr = strchr(filter, ';');
498                          if (scptr)     *scptr = 0;
499                          TRACE("Using file spec %s\n", filter);
500                          if (SendMessageA(hlb, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
501                                  return FALSE;
502                          if (scptr) *scptr = ';';
503                          filter = (scptr) ? (scptr + 1) : 0;
504                  }
505          }
506
507     strcpy(buffer, "*.*");
508     return DlgDirListA(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
509 }
510
511 /***********************************************************************
512  *                              FILEDLG_GetFileType             [internal]
513  */
514
515 static LPSTR FILEDLG_GetFileType(LPSTR cfptr, LPSTR fptr, WORD index)
516 {
517   int n, i;
518   i = 0;
519   if (cfptr)
520     for ( ;(n = strlen(cfptr)) != 0; i++) 
521       {
522         cfptr += n + 1;
523         if (i == index)
524           return cfptr;
525         cfptr += strlen(cfptr) + 1;
526       }
527   if (fptr)
528     for ( ;(n = strlen(fptr)) != 0; i++) 
529       {
530         fptr += n + 1;
531         if (i == index)
532           return fptr;
533         fptr += strlen(fptr) + 1;
534     }
535   return "*.*"; /* FIXME */
536 }
537
538 /***********************************************************************
539  *                              FILEDLG_WMDrawItem              [internal]
540  */
541 static LONG FILEDLG_WMDrawItem(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam,int savedlg)
542 {
543     LPDRAWITEMSTRUCT16 lpdis = (LPDRAWITEMSTRUCT16)PTR_SEG_TO_LIN(lParam);
544     char *str;
545     HICON16 hIcon;
546     COLORREF oldText = 0, oldBk = 0;
547
548     if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
549     {
550         if (!(str = SEGPTR_ALLOC(512))) return FALSE;
551         SendMessage16(lpdis->hwndItem, LB_GETTEXT16, lpdis->itemID, 
552                       (LPARAM)SEGPTR_GET(str));
553
554         if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
555         {
556             oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
557             oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
558         }
559         if (savedlg)
560             SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
561
562         ExtTextOut16(lpdis->hDC, lpdis->rcItem.left + 1,
563                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
564                   &(lpdis->rcItem), str, strlen(str), NULL);
565
566         if (lpdis->itemState & ODS_SELECTED)
567             DrawFocusRect16( lpdis->hDC, &(lpdis->rcItem) );
568
569         if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
570         {
571             SetBkColor( lpdis->hDC, oldBk );
572             SetTextColor( lpdis->hDC, oldText );
573         }
574         SEGPTR_FREE(str);
575         return TRUE;
576     }
577
578     if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
579     {
580         if (!(str = SEGPTR_ALLOC(512))) return FALSE;
581         SendMessage16(lpdis->hwndItem, LB_GETTEXT16, lpdis->itemID, 
582                       (LPARAM)SEGPTR_GET(str));
583
584         if (lpdis->itemState & ODS_SELECTED)
585         {
586             oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
587             oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
588         }
589         ExtTextOut16(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
590                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
591                   &(lpdis->rcItem), str, strlen(str), NULL);
592
593         if (lpdis->itemState & ODS_SELECTED)
594             DrawFocusRect16( lpdis->hDC, &(lpdis->rcItem) );
595
596         if (lpdis->itemState & ODS_SELECTED)
597         {
598             SetBkColor( lpdis->hDC, oldBk );
599             SetTextColor( lpdis->hDC, oldText );
600         }
601         DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
602         SEGPTR_FREE(str);
603         return TRUE;
604     }
605     if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
606     {
607         if (!(str = SEGPTR_ALLOC(512))) return FALSE;
608         SendMessage16(lpdis->hwndItem, CB_GETLBTEXT16, lpdis->itemID, 
609                       (LPARAM)SEGPTR_GET(str));
610         switch(DRIVE_GetType( str[2] - 'a' ))
611         {
612         case TYPE_FLOPPY:  hIcon = hFloppy; break;
613         case TYPE_CDROM:   hIcon = hCDRom; break;
614         case TYPE_NETWORK: hIcon = hNet; break;
615         case TYPE_HD:
616         default:           hIcon = hHDisk; break;
617         }
618         if (lpdis->itemState & ODS_SELECTED)
619         {
620             oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
621             oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
622         }
623         ExtTextOut16(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
624                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
625                   &(lpdis->rcItem), str, strlen(str), NULL);
626
627         if (lpdis->itemState & ODS_SELECTED)
628         {
629             SetBkColor( lpdis->hDC, oldBk );
630             SetTextColor( lpdis->hDC, oldText );
631         }
632         DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
633         SEGPTR_FREE(str);
634         return TRUE;
635     }
636     return FALSE;
637 }
638
639 /***********************************************************************
640  *                              FILEDLG_WMMeasureItem           [internal]
641  */
642 static LONG FILEDLG_WMMeasureItem(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam) 
643 {
644     LPMEASUREITEMSTRUCT16 lpmeasure;
645     
646     lpmeasure = (LPMEASUREITEMSTRUCT16)PTR_SEG_TO_LIN(lParam);
647     lpmeasure->itemHeight = fldrHeight;
648     return TRUE;
649 }
650
651 /***********************************************************************
652  *                              FILEDLG_HookCallChk             [internal]
653  */
654 static int FILEDLG_HookCallChk(LPOPENFILENAME16 lpofn)
655 {
656  if (lpofn)
657   if (lpofn->Flags & OFN_ENABLEHOOK)
658    if (lpofn->lpfnHook)
659     return 1;
660  return 0;   
661
662
663 /***********************************************************************
664  *                              FILEDLG_CallWindowProc             [internal]
665  *
666  * Adapt the structures back for win32 calls so the callee can read lpCustData
667  */
668 static BOOL FILEDLG_CallWindowProc(LPOPENFILENAME16 lpofn,HWND hwnd,
669         UINT wMsg,WPARAM wParam,LPARAM lParam
670
671 ) {
672         BOOL            needstruct;
673         BOOL          result = FALSE;
674         WINDOWPROCTYPE  ProcType;               /* Type of Hook Function to be called. */
675
676         /* TRUE if lParam points to the OPENFILENAME16 Structure */
677         needstruct = (PTR_SEG_TO_LIN(lParam) == lpofn);
678
679         ProcType   = (lpofn->Flags & OFN_WINE)
680                      ? (lpofn->Flags & OFN_UNICODE)             /* 32-Bit call to GetOpenFileName */
681                        ? WIN_PROC_32W : WIN_PROC_32A
682                      : WIN_PROC_16;                             /* 16-Bit call to GetOpenFileName */
683
684         if (!(lpofn->Flags & OFN_WINE))
685                 /* Call to 16-Bit Hooking function... No Problem at all. */
686                 return (BOOL)CallWindowProc16(
687                         (WNDPROC16)lpofn->lpfnHook,hwnd,(UINT16)wMsg,(WPARAM16)wParam,lParam
688                 );
689         /* |OFN_WINE32 */
690         if (needstruct)
691         {
692            /* Parameter lParam points to lpofn... Convert Structure Data... */
693            if (lpofn->Flags & OFN_UNICODE)
694            {
695                 OPENFILENAMEW ofnw;
696
697                 /* FIXME: probably needs more converted */
698                 ofnw.lCustData = lpofn->lCustData;
699                 return (BOOL)CallWindowProcW(
700                          (WNDPROC)lpofn->lpfnHook,hwnd,wMsg,wParam,(LPARAM)&ofnw
701                 );
702            }
703            else /* ! |OFN_UNICODE */
704            {
705                 OPENFILENAMEA ofna;
706
707                 /* FIXME: probably needs more converted */
708                 ofna.lCustData = lpofn->lCustData;
709                 return (BOOL)CallWindowProcA(
710                         (WNDPROC)lpofn->lpfnHook,hwnd,wMsg,wParam,(LPARAM)&ofna
711                 );
712            }
713         }
714         else /* ! needstruct */
715         {
716                 HWINDOWPROC     hWindowProc=NULL;
717
718                 if (WINPROC_SetProc(&hWindowProc, (WNDPROC16)lpofn->lpfnHook, ProcType, WIN_PROC_WINDOW))
719                 {
720                     /* Call Window Procedure converting 16-Bit Type Parameters to 32-Bit Type Parameters */
721                     result = CallWindowProc16( (WNDPROC16)hWindowProc,
722                                                       hwnd, wMsg, wParam, lParam );
723
724                     result = LOWORD(result);
725
726                     WINPROC_FreeProc( hWindowProc, WIN_PROC_WINDOW );
727                 }
728
729                 return result;
730
731         }
732 }
733
734
735 /***********************************************************************
736  *                              FILEDLG_WMInitDialog            [internal]
737  */
738
739 static LONG FILEDLG_WMInitDialog(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam) 
740 {
741   int i, n;
742   LPOPENFILENAME16 lpofn;
743   char tmpstr[512];
744   LPSTR pstr, old_pstr;
745   SetPropA(hWnd,OFN_PROP,lParam);
746   lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(lParam);
747   if (lpofn->lpstrTitle) SetWindowText16( hWnd, lpofn->lpstrTitle );
748   /* read custom filter information */
749   if (lpofn->lpstrCustomFilter)
750     {
751       pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrCustomFilter);
752       n = 0;
753       TRACE("lpstrCustomFilter = %p\n", pstr);
754       while(*pstr)
755         {
756           old_pstr = pstr;
757           i = SendDlgItemMessage16(hWnd, cmb1, CB_ADDSTRING16, 0,
758                                    (LPARAM)lpofn->lpstrCustomFilter + n );
759           n += strlen(pstr) + 1;
760           pstr += strlen(pstr) + 1;
761           TRACE("add str='%s' "
762                           "associated to '%s'\n", old_pstr, pstr);
763           SendDlgItemMessage16(hWnd, cmb1, CB_SETITEMDATA16, i, (LPARAM)pstr);
764           n += strlen(pstr) + 1;
765           pstr += strlen(pstr) + 1;
766         }
767     }
768   /* read filter information */
769   if (lpofn->lpstrFilter) {
770         pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
771         n = 0;
772         while(*pstr) {
773           old_pstr = pstr;
774           i = SendDlgItemMessage16(hWnd, cmb1, CB_ADDSTRING16, 0,
775                                        (LPARAM)lpofn->lpstrFilter + n );
776           n += strlen(pstr) + 1;
777           pstr += strlen(pstr) + 1;
778           TRACE("add str='%s' "
779                           "associated to '%s'\n", old_pstr, pstr);
780           SendDlgItemMessage16(hWnd, cmb1, CB_SETITEMDATA16, i, (LPARAM)pstr);
781           n += strlen(pstr) + 1;
782           pstr += strlen(pstr) + 1;
783         }
784   }
785   /* set default filter */
786   if (lpofn->nFilterIndex == 0 && lpofn->lpstrCustomFilter == (SEGPTR)NULL)
787         lpofn->nFilterIndex = 1;
788   SendDlgItemMessage16(hWnd, cmb1, CB_SETCURSEL16, lpofn->nFilterIndex - 1, 0);    
789   lstrcpynA(tmpstr, FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrCustomFilter),
790              PTR_SEG_TO_LIN(lpofn->lpstrFilter), lpofn->nFilterIndex - 1),512);
791   TRACE("nFilterIndex = %ld, SetText of edt1 to '%s'\n", 
792                         lpofn->nFilterIndex, tmpstr);
793   SetDlgItemTextA( hWnd, edt1, tmpstr );
794   /* get drive list */
795   *tmpstr = 0;
796   DlgDirListComboBoxA(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
797   /* read initial directory */
798   if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) 
799     {
800       int len;
801       lstrcpynA(tmpstr, PTR_SEG_TO_LIN(lpofn->lpstrInitialDir), 511);
802       len=strlen(tmpstr);
803       if (len > 0 && tmpstr[len-1] != '\\'  && tmpstr[len-1] != ':') {
804         tmpstr[len]='\\';
805         tmpstr[len+1]='\0';
806       }
807     }
808   else
809     *tmpstr = 0;
810   if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
811     *tmpstr = 0;
812     if (!FILEDLG_ScanDir(hWnd, tmpstr))
813       WARN("Couldn't read initial directory %s!\n",tmpstr);
814   }
815   /* select current drive in combo 2, omit missing drives */
816   for(i=0, n=-1; i<=DRIVE_GetCurrentDrive(); i++)
817     if (DRIVE_IsValid(i))                  n++;
818   SendDlgItemMessage16(hWnd, cmb2, CB_SETCURSEL16, n, 0);
819   if (!(lpofn->Flags & OFN_SHOWHELP))
820     ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
821   if (lpofn->Flags & OFN_HIDEREADONLY)
822     ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 
823   if (FILEDLG_HookCallChk(lpofn))
824      return (BOOL16)FILEDLG_CallWindowProc(lpofn,hWnd,WM_INITDIALOG,wParam,lParam );
825   else  
826      return TRUE;
827 }
828
829 /***********************************************************************
830  *                              FILEDLG_WMCommand               [internal]
831  */
832 BOOL in_update=FALSE;
833
834 static LRESULT FILEDLG_WMCommand(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam) 
835 {
836   LONG lRet;
837   LPOPENFILENAME16 lpofn;
838   OPENFILENAME16 ofn2;
839   char tmpstr[512], tmpstr2[512];
840   LPSTR pstr, pstr2;
841   UINT16 control,notification;
842
843   /* Notifications are packaged differently in Win32 */
844   control = wParam;
845   notification = HIWORD(lParam);
846     
847   lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(GetPropA(hWnd,OFN_PROP));
848   switch (control)
849     {
850     case lst1: /* file list */
851       FILEDLG_StripEditControl(hWnd);
852       if (notification == LBN_DBLCLK)
853         goto almost_ok;
854       lRet = SendDlgItemMessage16(hWnd, lst1, LB_GETCURSEL16, 0, 0);
855       if (lRet == LB_ERR) return TRUE;
856       if ((pstr = SEGPTR_ALLOC(512)))
857       {
858           SendDlgItemMessage16(hWnd, lst1, LB_GETTEXT16, lRet,
859                                (LPARAM)SEGPTR_GET(pstr));
860           SetDlgItemTextA( hWnd, edt1, pstr );
861           SEGPTR_FREE(pstr);
862       }
863       if (FILEDLG_HookCallChk(lpofn))
864        FILEDLG_CallWindowProc(lpofn,hWnd,
865                   RegisterWindowMessageA( LBSELCHSTRING ),
866                   control, MAKELONG(lRet,CD_LBSELCHANGE));       
867       /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD, CD_LBSELNOITEMS */                  
868       return TRUE;
869     case lst2: /* directory list */
870       FILEDLG_StripEditControl(hWnd);
871       if (notification == LBN_DBLCLK)
872         {
873           lRet = SendDlgItemMessage16(hWnd, lst2, LB_GETCURSEL16, 0, 0);
874           if (lRet == LB_ERR) return TRUE;
875           pstr = SEGPTR_ALLOC(512);
876           SendDlgItemMessage16(hWnd, lst2, LB_GETTEXT16, lRet,
877                              (LPARAM)SEGPTR_GET(pstr));
878           strcpy( tmpstr, pstr );
879           SEGPTR_FREE(pstr);
880           if (tmpstr[0] == '[')
881             {
882               tmpstr[strlen(tmpstr) - 1] = 0;
883               strcpy(tmpstr,tmpstr+1);
884             }
885           strcat(tmpstr, "\\");
886           goto reset_scan;
887         }
888       return TRUE;
889     case cmb1: /* file type drop list */
890       if (notification == CBN_SELCHANGE) 
891         {
892           *tmpstr = 0;
893           goto reset_scan;
894         }
895       return TRUE;
896     case chx1:
897       return TRUE;
898     case pshHelp:
899       return TRUE;
900     case cmb2: /* disk drop list */
901       FILEDLG_StripEditControl(hWnd);
902       lRet = SendDlgItemMessage16(hWnd, cmb2, CB_GETCURSEL16, 0, 0L);
903       if (lRet == LB_ERR) return 0;
904       pstr = SEGPTR_ALLOC(512);
905       SendDlgItemMessage16(hWnd, cmb2, CB_GETLBTEXT16, lRet,
906                            (LPARAM)SEGPTR_GET(pstr));
907       sprintf(tmpstr, "%c:", pstr[2]);
908       SEGPTR_FREE(pstr);
909     reset_scan:
910       lRet = SendDlgItemMessage16(hWnd, cmb1, CB_GETCURSEL16, 0, 0);
911       if (lRet == LB_ERR)
912         return TRUE;
913       pstr = (LPSTR)SendDlgItemMessage16(hWnd, cmb1, CB_GETITEMDATA16, lRet, 0);
914       TRACE("Selected filter : %s\n", pstr);
915       SetDlgItemTextA( hWnd, edt1, pstr );
916       FILEDLG_ScanDir(hWnd, tmpstr);
917       in_update=TRUE;
918     case IDOK:
919     almost_ok:
920       ofn2=*lpofn; /* for later restoring */
921       GetDlgItemTextA( hWnd, edt1, tmpstr, sizeof(tmpstr) );
922       pstr = strrchr(tmpstr, '\\');
923       if (pstr == NULL)
924         pstr = strrchr(tmpstr, ':');
925       if (strchr(tmpstr,'*') != NULL || strchr(tmpstr,'?') != NULL)
926         {
927           /* edit control contains wildcards */
928           if (pstr != NULL)
929             {
930               lstrcpynA(tmpstr2, pstr+1, 512);
931               *(pstr+1) = 0;
932             }
933           else
934             {
935               strcpy(tmpstr2, tmpstr);
936               *tmpstr=0;
937             }
938           TRACE("tmpstr=%s, tmpstr2=%s\n", tmpstr, tmpstr2);
939           SetDlgItemTextA( hWnd, edt1, tmpstr2 );
940           FILEDLG_ScanDir(hWnd, tmpstr);
941           return TRUE;
942         }
943       /* no wildcards, we might have a directory or a filename */
944       /* try appending a wildcard and reading the directory */
945       pstr2 = tmpstr + strlen(tmpstr);
946       if (pstr == NULL || *(pstr+1) != 0)
947         strcat(tmpstr, "\\");
948       lRet = SendDlgItemMessage16(hWnd, cmb1, CB_GETCURSEL16, 0, 0);
949       if (lRet == LB_ERR) return TRUE;
950       lpofn->nFilterIndex = lRet + 1;
951       TRACE("lpofn->nFilterIndex=%ld\n", lpofn->nFilterIndex);
952       lstrcpynA(tmpstr2, 
953              FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrCustomFilter),
954                                  PTR_SEG_TO_LIN(lpofn->lpstrFilter),
955                                  lRet), sizeof(tmpstr2));
956       SetDlgItemTextA( hWnd, edt1, tmpstr2 );
957       if (!in_update)
958       /* if ScanDir succeeds, we have changed the directory */
959       if (FILEDLG_ScanDir(hWnd, tmpstr)) return TRUE;
960       /* if not, this must be a filename */
961       *pstr2 = 0;
962       if (pstr != NULL)
963         {
964           /* strip off the pathname */
965           *pstr = 0;
966           SetDlgItemTextA( hWnd, edt1, pstr + 1 );
967           lstrcpynA(tmpstr2, pstr+1, sizeof(tmpstr2) );
968           /* Should we MessageBox() if this fails? */
969           if (!FILEDLG_ScanDir(hWnd, tmpstr)) return TRUE;
970           strcpy(tmpstr, tmpstr2);
971         }
972       else SetDlgItemTextA( hWnd, edt1, tmpstr );
973 #if 0
974       ShowWindow16(hWnd, SW_HIDE);   /* this should not be necessary ?! (%%%) */
975 #endif
976       {
977         int lenstr2;
978         int drive = DRIVE_GetCurrentDrive();
979         tmpstr2[0] = 'A'+ drive;
980         tmpstr2[1] = ':';
981         tmpstr2[2] = '\\';
982         lstrcpynA(tmpstr2 + 3, DRIVE_GetDosCwd(drive), 507);
983         lenstr2=strlen(tmpstr2);
984         if (lenstr2 > 3)
985            tmpstr2[lenstr2++]='\\';
986         lstrcpynA(tmpstr2+lenstr2, tmpstr, 512-lenstr2);
987         if (lpofn->lpstrFile)
988           lstrcpynA(PTR_SEG_TO_LIN(lpofn->lpstrFile), tmpstr2,lpofn->nMaxFile);
989       }
990       lpofn->nFileOffset = strrchr(tmpstr2,'\\') - tmpstr2 +1;
991       lpofn->nFileExtension = 0;
992       while(tmpstr2[lpofn->nFileExtension] != '.' && tmpstr2[lpofn->nFileExtension] != '\0')
993         lpofn->nFileExtension++;
994       if (tmpstr2[lpofn->nFileExtension] == '\0')
995         lpofn->nFileExtension = 0;
996       else
997         lpofn->nFileExtension++;
998
999       if(in_update)
1000        {
1001          if (FILEDLG_HookCallChk(lpofn))
1002            FILEDLG_CallWindowProc(lpofn,hWnd,
1003                                   RegisterWindowMessageA( LBSELCHSTRING ),
1004                                   control, MAKELONG(lRet,CD_LBSELCHANGE));
1005
1006          in_update = FALSE;
1007          return TRUE;
1008        }
1009       if (PTR_SEG_TO_LIN(lpofn->lpstrFileTitle) != NULL) 
1010         {
1011           lRet = SendDlgItemMessage16(hWnd, lst1, LB_GETCURSEL16, 0, 0);
1012           SendDlgItemMessage16(hWnd, lst1, LB_GETTEXT16, lRet,
1013                                lpofn->lpstrFileTitle );
1014         }
1015       if (FILEDLG_HookCallChk(lpofn))
1016       {
1017        lRet= (BOOL16)FILEDLG_CallWindowProc(lpofn,
1018                hWnd, RegisterWindowMessageA( FILEOKSTRING ), 0, lParam );
1019        if (lRet)       
1020        {
1021          *lpofn=ofn2; /* restore old state */
1022 #if 0
1023          ShowWindow16(hWnd, SW_SHOW);               /* only if above (%%%) SW_HIDE used */
1024 #endif         
1025          break;
1026        }
1027       }
1028       if ((lpofn->Flags & OFN_ALLOWMULTISELECT) && (lpofn->Flags & OFN_EXPLORER)) {
1029          if (lpofn->lpstrFile) {
1030             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile);
1031             LPSTR ptr = strrchr(str, '\\');
1032             str[strlen(str) + 1] = '\0';
1033             *ptr = 0;
1034          }
1035       }
1036       EndDialog(hWnd, TRUE);
1037       return TRUE;
1038     case IDCANCEL:
1039       EndDialog(hWnd, FALSE);
1040       return TRUE;
1041     }
1042   return FALSE;
1043 }
1044
1045 /***********************************************************************
1046  *           FileOpenDlgProc16   (COMMDLG.6)
1047  */
1048 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1049                                LPARAM lParam)
1050 {  
1051  LPOPENFILENAME16 lpofn =(LPOPENFILENAME16)PTR_SEG_TO_LIN(GetPropA(hWnd,OFN_PROP));
1052  
1053  if (wMsg!=WM_INITDIALOG)
1054   if (FILEDLG_HookCallChk(lpofn))
1055   {
1056    LRESULT  lRet=(BOOL16)FILEDLG_CallWindowProc(lpofn,hWnd,wMsg,wParam,lParam);
1057    if (lRet)   
1058     return lRet;         /* else continue message processing */
1059   }             
1060   switch (wMsg)
1061     {
1062     case WM_INITDIALOG:
1063       return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1064     case WM_MEASUREITEM:
1065       return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1066     case WM_DRAWITEM:
1067       return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE);
1068     case WM_COMMAND:
1069       return FILEDLG_WMCommand(hWnd, wParam, lParam);
1070 #if 0
1071     case WM_CTLCOLOR:
1072       SetBkColor((HDC16)wParam, 0x00C0C0C0);
1073       switch (HIWORD(lParam))
1074         {
1075         case CTLCOLOR_BTN:
1076           SetTextColor((HDC16)wParam, 0x00000000);
1077           return hGRAYBrush;
1078         case CTLCOLOR_STATIC:
1079           SetTextColor((HDC16)wParam, 0x00000000);
1080           return hGRAYBrush;
1081         }
1082       break;
1083 #endif
1084     }
1085   return FALSE;
1086 }
1087
1088 /***********************************************************************
1089  *           FileSaveDlgProc16   (COMMDLG.7)
1090  */
1091 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1092                                LPARAM lParam)
1093 {
1094  LPOPENFILENAME16 lpofn =(LPOPENFILENAME16)PTR_SEG_TO_LIN(GetPropA(hWnd,OFN_PROP));
1095  
1096  if (wMsg!=WM_INITDIALOG)
1097   if (FILEDLG_HookCallChk(lpofn))
1098   {
1099    LRESULT  lRet=(BOOL16)FILEDLG_CallWindowProc(lpofn,hWnd,wMsg,wParam,lParam);
1100    if (lRet)   
1101     return lRet;         /* else continue message processing */
1102   }             
1103   switch (wMsg) {
1104    case WM_INITDIALOG:
1105       return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1106       
1107    case WM_MEASUREITEM:
1108       return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1109     
1110    case WM_DRAWITEM:
1111       return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE);
1112
1113    case WM_COMMAND:
1114       return FILEDLG_WMCommand(hWnd, wParam, lParam);
1115   }
1116   
1117   /*
1118   case WM_CTLCOLOR:
1119    SetBkColor((HDC16)wParam, 0x00C0C0C0);
1120    switch (HIWORD(lParam))
1121    {
1122     case CTLCOLOR_BTN:
1123      SetTextColor((HDC16)wParam, 0x00000000);
1124      return hGRAYBrush;
1125     case CTLCOLOR_STATIC:
1126      SetTextColor((HDC16)wParam, 0x00000000);
1127      return hGRAYBrush;
1128    }
1129    return FALSE;
1130    
1131    */
1132   return FALSE;
1133 }
1134
1135 static BOOL Commdlg_GetFileNameA( BOOL16 (CALLBACK *dofunction)(SEGPTR x),
1136                                       LPOPENFILENAMEA ofn )
1137 {
1138         BOOL16 ret;
1139         LPOPENFILENAME16 ofn16 = SEGPTR_ALLOC(sizeof(OPENFILENAME16));
1140
1141         memset(ofn16,'\0',sizeof(*ofn16));
1142         ofn16->lStructSize = sizeof(*ofn16);
1143         ofn16->hwndOwner = ofn->hwndOwner;
1144         ofn16->hInstance = MapHModuleLS(ofn->hInstance);
1145         if (ofn->lpstrFilter) {
1146                 LPSTR   s,x;
1147
1148                 /* filter is a list...  title\0ext\0......\0\0 */
1149                 s = (LPSTR)ofn->lpstrFilter;
1150                 while (*s)
1151                         s = s+strlen(s)+1;
1152                 s++;
1153                 x = (LPSTR)SEGPTR_ALLOC(s-ofn->lpstrFilter);
1154                 memcpy(x,ofn->lpstrFilter,s-ofn->lpstrFilter);
1155                 ofn16->lpstrFilter = SEGPTR_GET(x);
1156         }
1157         if (ofn->lpstrCustomFilter) {
1158                 LPSTR   s,x;
1159
1160                 /* filter is a list...  title\0ext\0......\0\0 */
1161                 s = (LPSTR)ofn->lpstrCustomFilter;
1162                 while (*s)
1163                         s = s+strlen(s)+1;
1164                 s++;
1165                 x = SEGPTR_ALLOC(s-ofn->lpstrCustomFilter);
1166                 memcpy(x,ofn->lpstrCustomFilter,s-ofn->lpstrCustomFilter);
1167                 ofn16->lpstrCustomFilter = SEGPTR_GET(x);
1168         }
1169         ofn16->nMaxCustFilter = ofn->nMaxCustFilter;
1170         ofn16->nFilterIndex = ofn->nFilterIndex;
1171         if (ofn->nMaxFile)
1172             ofn16->lpstrFile = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFile));
1173         ofn16->nMaxFile = ofn->nMaxFile;
1174         ofn16->nMaxFileTitle = ofn->nMaxFileTitle;
1175         if (ofn16->nMaxFileTitle)
1176             ofn16->lpstrFileTitle = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFileTitle));
1177         if (ofn->lpstrInitialDir)
1178             ofn16->lpstrInitialDir = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpstrInitialDir));
1179         if (ofn->lpstrTitle)
1180             ofn16->lpstrTitle = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpstrTitle));
1181         ofn16->Flags = ofn->Flags|OFN_WINE;
1182         ofn16->nFileOffset = ofn->nFileOffset;
1183         ofn16->nFileExtension = ofn->nFileExtension;
1184         if (ofn->lpstrDefExt)
1185             ofn16->lpstrDefExt = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpstrDefExt));
1186         ofn16->lCustData = ofn->lCustData;
1187         ofn16->lpfnHook = (LPOFNHOOKPROC16)ofn->lpfnHook;
1188
1189         if (ofn->lpTemplateName)
1190             ofn16->lpTemplateName = SEGPTR_GET(SEGPTR_STRDUP(ofn->lpTemplateName));
1191
1192         ret = dofunction(SEGPTR_GET(ofn16));
1193
1194         ofn->nFileOffset = ofn16->nFileOffset;
1195         ofn->nFileExtension = ofn16->nFileExtension;
1196         if (ofn16->lpstrFilter)
1197             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFilter));
1198         if (ofn16->lpTemplateName)
1199             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpTemplateName));
1200         if (ofn16->lpstrDefExt)
1201             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrDefExt));
1202         if (ofn16->lpstrTitle)
1203             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrTitle));
1204         if (ofn16->lpstrInitialDir)
1205             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrInitialDir));
1206         if (ofn16->lpstrCustomFilter)
1207             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrCustomFilter));
1208
1209         if (ofn16->lpstrFile) 
1210           {
1211             LPCSTR      src = PTR_SEG_TO_LIN(ofn16->lpstrFile);
1212             LPSTR       dst = ofn->lpstrFile;
1213
1214             if ((ofn->Flags & OFN_ALLOWMULTISELECT) && (ofn->Flags & OFN_EXPLORER)) {
1215                /* FIXME(EPP): I tried to use:
1216                 * memcpy(ofn->lpstrFile, PTR_SEG_TO_LIN(ofn16->lpstrFile, ofn->nMaxFile)
1217                 * but it did crash with winamp 2.21, so copy string by string
1218                 */
1219                int      len;
1220                do {
1221                   strcpy(dst, src);
1222                   len = strlen(dst) + 1;        /* strlen(dst) == strlen(src) */
1223                   dst += len;
1224                   src += len;
1225                } while (len > 1);
1226             } else {
1227                strcpy(dst, src);
1228             }
1229             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFile));
1230           }
1231
1232         if (ofn16->lpstrFileTitle) 
1233           {
1234             if (ofn->lpstrFileTitle)
1235                 strcpy(ofn->lpstrFileTitle,
1236                         PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1237             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1238           }
1239         SEGPTR_FREE(ofn16);
1240         return ret;
1241 }
1242
1243 static BOOL Commdlg_GetFileNameW( BOOL16 (CALLBACK *dofunction)(SEGPTR x), 
1244                                       LPOPENFILENAMEW ofn )
1245 {
1246         BOOL16 ret;
1247         LPOPENFILENAME16 ofn16 = SEGPTR_ALLOC(sizeof(OPENFILENAME16));
1248
1249         memset(ofn16,'\0',sizeof(*ofn16));
1250         ofn16->lStructSize = sizeof(*ofn16);
1251         ofn16->hwndOwner = ofn->hwndOwner;
1252         ofn16->hInstance = MapHModuleLS(ofn->hInstance);
1253         if (ofn->lpstrFilter) {
1254                 LPWSTR  s;
1255                 LPSTR   x,y;
1256                 int     n;
1257
1258                 /* filter is a list...  title\0ext\0......\0\0 */
1259                 s = (LPWSTR)ofn->lpstrFilter;
1260                 while (*s)
1261                         s = s+lstrlenW(s)+1;
1262                 s++;
1263                 n = s - ofn->lpstrFilter; /* already divides by 2. ptr magic */
1264                 x = y = (LPSTR)SEGPTR_ALLOC(n);
1265                 s = (LPWSTR)ofn->lpstrFilter;
1266                 while (*s) {
1267                         lstrcpyWtoA(x,s);
1268                         x+=lstrlenA(x)+1;
1269                         s+=lstrlenW(s)+1;
1270                 }
1271                 *x=0;
1272                 ofn16->lpstrFilter = SEGPTR_GET(y);
1273 }
1274         if (ofn->lpstrCustomFilter) {
1275                 LPWSTR  s;
1276                 LPSTR   x,y;
1277                 int     n;
1278
1279                 /* filter is a list...  title\0ext\0......\0\0 */
1280                 s = (LPWSTR)ofn->lpstrCustomFilter;
1281                 while (*s)
1282                         s = s+lstrlenW(s)+1;
1283                 s++;
1284                 n = s - ofn->lpstrCustomFilter;
1285                 x = y = (LPSTR)SEGPTR_ALLOC(n);
1286                 s = (LPWSTR)ofn->lpstrCustomFilter;
1287                 while (*s) {
1288                         lstrcpyWtoA(x,s);
1289                         x+=lstrlenA(x)+1;
1290                         s+=lstrlenW(s)+1;
1291                 }
1292                 *x=0;
1293                 ofn16->lpstrCustomFilter = SEGPTR_GET(y);
1294         }
1295         ofn16->nMaxCustFilter = ofn->nMaxCustFilter;
1296         ofn16->nFilterIndex = ofn->nFilterIndex;
1297         if (ofn->nMaxFile) 
1298            ofn16->lpstrFile = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFile));
1299         ofn16->nMaxFile = ofn->nMaxFile;
1300         ofn16->nMaxFileTitle = ofn->nMaxFileTitle;
1301         if (ofn->nMaxFileTitle)
1302                 ofn16->lpstrFileTitle = SEGPTR_GET(SEGPTR_ALLOC(ofn->nMaxFileTitle));
1303         if (ofn->lpstrInitialDir)
1304                 ofn16->lpstrInitialDir = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpstrInitialDir));
1305         if (ofn->lpstrTitle)
1306                 ofn16->lpstrTitle = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpstrTitle));
1307         ofn16->Flags = ofn->Flags|OFN_WINE|OFN_UNICODE;
1308         ofn16->nFileOffset = ofn->nFileOffset;
1309         ofn16->nFileExtension = ofn->nFileExtension;
1310         if (ofn->lpstrDefExt)
1311                 ofn16->lpstrDefExt = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpstrDefExt));
1312         ofn16->lCustData = ofn->lCustData;
1313         ofn16->lpfnHook = (LPOFNHOOKPROC16)ofn->lpfnHook;
1314         if (ofn->lpTemplateName) 
1315                 ofn16->lpTemplateName = SEGPTR_GET(SEGPTR_STRDUP_WtoA(ofn->lpTemplateName));
1316         ret = dofunction(SEGPTR_GET(ofn16));
1317
1318         ofn->nFileOffset = ofn16->nFileOffset;
1319         ofn->nFileExtension = ofn16->nFileExtension;
1320         if (ofn16->lpstrFilter)
1321                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFilter));
1322         if (ofn16->lpTemplateName)
1323                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpTemplateName));
1324         if (ofn16->lpstrDefExt)
1325                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrDefExt));
1326         if (ofn16->lpstrTitle)
1327                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrTitle));
1328         if (ofn16->lpstrInitialDir)
1329                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrInitialDir));
1330         if (ofn16->lpstrCustomFilter)
1331                 SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrCustomFilter));
1332
1333         if (ofn16->lpstrFile)
1334           {
1335             LPCSTR      src = PTR_SEG_TO_LIN(ofn16->lpstrFile);
1336             LPWSTR      dst = ofn->lpstrFile;
1337
1338             if ((ofn->Flags & OFN_ALLOWMULTISELECT) && (ofn->Flags & OFN_EXPLORER)) {
1339                int      len;
1340                do {
1341                   lstrcpyAtoW(dst, src);
1342                   dst += lstrlenW(dst) + 1;
1343                   src += (len = strlen(src) + 1);
1344                } while (len > 1);
1345             } else {
1346                lstrcpyAtoW(ofn->lpstrFile,PTR_SEG_TO_LIN(ofn16->lpstrFile));
1347             }
1348             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFile));
1349           }
1350
1351         if (ofn16->lpstrFileTitle) {
1352             if (ofn->lpstrFileTitle)
1353                 lstrcpyAtoW(ofn->lpstrFileTitle,
1354                         PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1355             SEGPTR_FREE(PTR_SEG_TO_LIN(ofn16->lpstrFileTitle));
1356         }
1357         SEGPTR_FREE(ofn16);
1358         return ret;
1359 }
1360 /***********************************************************************
1361  *            GetOpenFileNameA  (COMDLG32.10)
1362  *
1363  * Creates a dialog box for the user to select a file to open.
1364  *
1365  * RETURNS
1366  *    TRUE on succes: user enters a valid file
1367  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1368  *
1369  * BUGS
1370  *    unknown, calls its 16-bit equivalent.
1371  */
1372 BOOL WINAPI GetOpenFileNameA(
1373                              LPOPENFILENAMEA ofn /* address of init structure */
1374                              )
1375 {
1376     if(TWEAK_WineLook > WIN31_LOOK)
1377     {
1378         return GetFileDialog95A(ofn, OPEN_DIALOG);
1379     }
1380     else
1381     {
1382    BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetOpenFileName16;
1383    return Commdlg_GetFileNameA(dofunction,ofn);
1384 }
1385 }
1386
1387 /***********************************************************************
1388  *            GetOpenFileNameW (COMDLG32.11)
1389  *
1390  * Creates a dialog box for the user to select a file to open.
1391  *
1392  * RETURNS
1393  *    TRUE on succes: user enters a valid file
1394  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1395  *
1396  * BUGS
1397  *    unknown, calls its 16-bit equivalent.
1398  */
1399 BOOL WINAPI GetOpenFileNameW(
1400                              LPOPENFILENAMEW ofn /* address of init structure */
1401                              )
1402 {
1403     if(TWEAK_WineLook > WIN31_LOOK)
1404     {
1405         return GetFileDialog95W(ofn, OPEN_DIALOG);
1406     }
1407     else
1408     {
1409    BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetOpenFileName16;
1410    return Commdlg_GetFileNameW(dofunction,ofn);
1411 }
1412 }
1413
1414 /***********************************************************************
1415  *            GetSaveFileNameA  (COMDLG32.12)
1416  *
1417  * Creates a dialog box for the user to select a file to save.
1418  *
1419  * RETURNS
1420  *    TRUE on succes: user enters a valid file
1421  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1422  *
1423  * BUGS
1424  *    unknown, calls its 16-bit equivalent.
1425  */
1426 BOOL WINAPI GetSaveFileNameA(
1427                              LPOPENFILENAMEA ofn /* address of init structure */
1428                              )
1429 {
1430     if(TWEAK_WineLook > WIN31_LOOK)
1431     {
1432         return GetFileDialog95A(ofn, SAVE_DIALOG);
1433     }
1434     else
1435     {
1436    BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetSaveFileName16;
1437    return Commdlg_GetFileNameA(dofunction,ofn);
1438 }
1439
1440 }
1441
1442 /***********************************************************************
1443  *            GetSaveFileNameW  (COMDLG32.13)
1444  *
1445  * Creates a dialog box for the user to select a file to save.
1446  *
1447  * RETURNS
1448  *    TRUE on succes: user enters a valid file
1449  *    FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1450  *
1451  * BUGS
1452  *    unknown, calls its 16-bit equivalent.
1453  */
1454 BOOL WINAPI GetSaveFileNameW(
1455                              LPOPENFILENAMEW ofn /* address of init structure */
1456                              )
1457 {
1458     if(TWEAK_WineLook > WIN31_LOOK)
1459     {
1460         return GetFileDialog95W(ofn, SAVE_DIALOG);
1461     }
1462     else
1463     {
1464    BOOL16 (CALLBACK * dofunction)(SEGPTR ofn16) = GetSaveFileName16;
1465    return Commdlg_GetFileNameW(dofunction,ofn);
1466 }
1467
1468 }