1 /* 2 * Win 3.1 Style File Dialogs 3 * 4 * Copyright 1994 Martin Ayotte 5 * Copyright 1996 Albrecht Kleine 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 #include <ctype.h> 22 #include <stdlib.h> 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winnls.h" 29 #include "wingdi.h" 30 #include "winuser.h" 31 #include "wine/debug.h" 32 #include "wine/heap.h" 33 #include "winreg.h" 34 #include "winternl.h" 35 #include "commdlg.h" 36 #include "shlwapi.h" 37 #include "cderr.h" 38 39 WINE_DEFAULT_DEBUG_CHANNEL(commdlg); 40 41 #include "cdlg.h" 42 43 #define BUFFILE 512 44 #define BUFFILEALLOC 512 * sizeof(WCHAR) 45 46 static const WCHAR FILE_star[] = {'*','.','*', 0}; 47 static const WCHAR FILE_bslash[] = {'\\', 0}; 48 static const WCHAR FILE_specc[] = {'%','c',':', 0}; 49 static const int fldrHeight = 16; 50 static const int fldrWidth = 20; 51 52 static HICON hFolder = 0; 53 static HICON hFolder2 = 0; 54 static HICON hFloppy = 0; 55 static HICON hHDisk = 0; 56 static HICON hCDRom = 0; 57 static HICON hNet = 0; 58 59 #define FD31_OFN_PROP "FILEDLG_OFN" 60 61 typedef struct tagFD31_DATA 62 { 63 HWND hwnd; /* file dialog window handle */ 64 BOOL hook; /* TRUE if the dialog is hooked */ 65 UINT lbselchstring; /* registered message id */ 66 UINT fileokstring; /* registered message id */ 67 LPARAM lParam; /* save original lparam */ 68 LPCVOID template; /* template for 32 bits resource */ 69 BOOL open; /* TRUE if open dialog, FALSE if save dialog */ 70 LPOPENFILENAMEW ofnW; /* pointer either to the original structure or 71 a W copy for A/16 API */ 72 LPOPENFILENAMEA ofnA; /* original structure if 32bits ansi dialog */ 73 } FD31_DATA, *PFD31_DATA; 74 75 /*********************************************************************** 76 * FD31_Init [internal] 77 */ 78 static BOOL FD31_Init(void) 79 { 80 static BOOL initialized = FALSE; 81 82 if (!initialized) { 83 hFolder = LoadImageA( COMDLG32_hInstance, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED ); 84 hFolder2 = LoadImageA( COMDLG32_hInstance, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED ); 85 hFloppy = LoadImageA( COMDLG32_hInstance, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED ); 86 hHDisk = LoadImageA( COMDLG32_hInstance, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED ); 87 hCDRom = LoadImageA( COMDLG32_hInstance, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED ); 88 hNet = LoadImageA( COMDLG32_hInstance, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED ); 89 if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 90 hHDisk == 0 || hCDRom == 0 || hNet == 0) 91 { 92 ERR("Error loading icons!\n"); 93 return FALSE; 94 } 95 initialized = TRUE; 96 } 97 return TRUE; 98 } 99 100 /*********************************************************************** 101 * FD31_StripEditControl [internal] 102 * Strip pathnames off the contents of the edit control. 103 */ 104 static void FD31_StripEditControl(HWND hwnd) 105 { 106 WCHAR temp[BUFFILE], *cp; 107 108 GetDlgItemTextW( hwnd, edt1, temp, ARRAY_SIZE(temp)); 109 cp = wcsrchr(temp, '\\'); 110 if (cp != NULL) { 111 lstrcpyW(temp, cp+1); 112 } 113 cp = wcsrchr(temp, ':'); 114 if (cp != NULL) { 115 lstrcpyW(temp, cp+1); 116 } 117 /* FIXME: shouldn't we do something with the result here? ;-) */ 118 } 119 120 /*********************************************************************** 121 * FD31_CallWindowProc [internal] 122 * 123 * Call the appropriate hook 124 */ 125 static BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam, LPARAM lParam) 126 { 127 BOOL ret; 128 129 if (lfs->ofnA) 130 { 131 TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n", 132 lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 133 ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam); 134 TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n", 135 lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 136 return ret; 137 } 138 139 TRACE("Call hookW %p (%p, %04x, %08lx, %08lx)\n", 140 lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 141 ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam); 142 TRACE("Ret hookW %p (%p, %04x, %08lx, %08lx)\n", 143 lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 144 return ret; 145 } 146 147 /*********************************************************************** 148 * FD31_GetFileType [internal] 149 */ 150 static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index) 151 { 152 int n, i; 153 i = 0; 154 if (cfptr) 155 for ( ;(n = lstrlenW(cfptr)) != 0; i++) 156 { 157 cfptr += n + 1; 158 if (i == index) 159 return cfptr; 160 cfptr += lstrlenW(cfptr) + 1; 161 } 162 if (fptr) 163 for ( ;(n = lstrlenW(fptr)) != 0; i++) 164 { 165 fptr += n + 1; 166 if (i == index) 167 return fptr; 168 fptr += lstrlenW(fptr) + 1; 169 } 170 return FILE_star; /* FIXME */ 171 } 172 173 /*********************************************************************** 174 * FD31_ScanDir [internal] 175 */ 176 static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath) 177 { 178 WCHAR buffer[BUFFILE]; 179 HWND hdlg; 180 LRESULT lRet = TRUE; 181 HCURSOR hCursorWait, oldCursor; 182 183 TRACE("Trying to change to %s\n", debugstr_w(newPath)); 184 if ( newPath[0] && !SetCurrentDirectoryW( newPath )) 185 return FALSE; 186 187 /* get the list of spec files */ 188 lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter, 189 ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE); 190 191 hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT); 192 oldCursor = SetCursor(hCursorWait); 193 194 /* list of files */ 195 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) { 196 WCHAR* scptr; /* ptr on semi-colon */ 197 WCHAR* filter = buffer; 198 199 TRACE("Using filter %s\n", debugstr_w(filter)); 200 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0); 201 while (filter) { 202 scptr = wcschr(filter, ';'); 203 if (scptr) *scptr = 0; 204 while (*filter == ' ') filter++; 205 TRACE("Using file spec %s\n", debugstr_w(filter)); 206 SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter); 207 if (scptr) *scptr = ';'; 208 filter = (scptr) ? (scptr + 1) : 0; 209 } 210 } 211 212 /* list of directories */ 213 lstrcpyW(buffer, FILE_star); 214 215 if (GetDlgItem(hWnd, lst2) != 0) { 216 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY); 217 } 218 SetCursor(oldCursor); 219 return lRet; 220 } 221 222 /*********************************************************************** 223 * FD31_WMDrawItem [internal] 224 */ 225 static LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam, 226 int savedlg, const DRAWITEMSTRUCT *lpdis) 227 { 228 WCHAR *str; 229 HICON hIcon; 230 COLORREF oldText = 0, oldBk = 0; 231 232 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1) 233 { 234 if (!(str = heap_alloc(BUFFILEALLOC))) return FALSE; 235 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, 236 (LPARAM)str); 237 238 if ((lpdis->itemState & ODS_SELECTED) && !savedlg) 239 { 240 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); 241 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 242 } 243 if (savedlg) 244 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) ); 245 246 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1, 247 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED, 248 &(lpdis->rcItem), str, lstrlenW(str), NULL); 249 250 if (lpdis->itemState & ODS_SELECTED) 251 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) ); 252 253 if ((lpdis->itemState & ODS_SELECTED) && !savedlg) 254 { 255 SetBkColor( lpdis->hDC, oldBk ); 256 SetTextColor( lpdis->hDC, oldText ); 257 } 258 heap_free(str); 259 return TRUE; 260 } 261 262 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2) 263 { 264 if (!(str = heap_alloc(BUFFILEALLOC))) 265 return FALSE; 266 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, 267 (LPARAM)str); 268 269 if (lpdis->itemState & ODS_SELECTED) 270 { 271 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); 272 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 273 } 274 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth, 275 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED, 276 &(lpdis->rcItem), str, lstrlenW(str), NULL); 277 278 if (lpdis->itemState & ODS_SELECTED) 279 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) ); 280 281 if (lpdis->itemState & ODS_SELECTED) 282 { 283 SetBkColor( lpdis->hDC, oldBk ); 284 SetTextColor( lpdis->hDC, oldText ); 285 } 286 DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL ); 287 heap_free(str); 288 return TRUE; 289 } 290 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2) 291 { 292 char root[] = "a:"; 293 if (!(str = heap_alloc(BUFFILEALLOC))) 294 return FALSE; 295 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, 296 (LPARAM)str); 297 root[0] += str[2] - 'a'; 298 switch(GetDriveTypeA(root)) 299 { 300 case DRIVE_REMOVABLE: hIcon = hFloppy; break; 301 case DRIVE_CDROM: hIcon = hCDRom; break; 302 case DRIVE_REMOTE: hIcon = hNet; break; 303 case DRIVE_FIXED: 304 default: hIcon = hHDisk; break; 305 } 306 if (lpdis->itemState & ODS_SELECTED) 307 { 308 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); 309 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 310 } 311 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth, 312 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED, 313 &(lpdis->rcItem), str, lstrlenW(str), NULL); 314 315 if (lpdis->itemState & ODS_SELECTED) 316 { 317 SetBkColor( lpdis->hDC, oldBk ); 318 SetTextColor( lpdis->hDC, oldText ); 319 } 320 DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL ); 321 heap_free(str); 322 return TRUE; 323 } 324 return FALSE; 325 } 326 327 /*********************************************************************** 328 * FD31_UpdateResult [internal] 329 * update the displayed file name (with path) 330 */ 331 static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr) 332 { 333 int lenstr2; 334 LPOPENFILENAMEW ofnW = lfs->ofnW; 335 LPOPENFILENAMEA ofnA = lfs->ofnA; 336 WCHAR tmpstr2[BUFFILE]; 337 WCHAR *p; 338 339 TRACE("%s\n", debugstr_w(tmpstr)); 340 if(ofnW->Flags & OFN_NOVALIDATE) 341 tmpstr2[0] = '\0'; 342 else 343 GetCurrentDirectoryW(BUFFILE, tmpstr2); 344 lenstr2 = lstrlenW(tmpstr2); 345 if (lenstr2 > 3) 346 tmpstr2[lenstr2++]='\\'; 347 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2); 348 if (!ofnW->lpstrFile) 349 return; 350 351 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile); 352 353 /* set filename offset */ 354 p = PathFindFileNameW(ofnW->lpstrFile); 355 ofnW->nFileOffset = (p - ofnW->lpstrFile); 356 357 /* set extension offset */ 358 p = PathFindExtensionW(ofnW->lpstrFile); 359 ofnW->nFileExtension = (*p) ? (p - ofnW->lpstrFile) + 1 : 0; 360 361 TRACE("file %s, file offset %d, ext offset %d\n", 362 debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension); 363 364 /* update the real client structures if any */ 365 if (ofnA) 366 { 367 LPSTR lpszTemp; 368 if (ofnW->nMaxFile && 369 !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1, 370 ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL )) 371 ofnA->lpstrFile[ofnA->nMaxFile-1] = 0; 372 373 /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */ 374 /* set filename offset */ 375 lpszTemp = PathFindFileNameA(ofnA->lpstrFile); 376 ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile); 377 378 /* set extension offset */ 379 lpszTemp = PathFindExtensionA(ofnA->lpstrFile); 380 ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0; 381 } 382 } 383 384 /*********************************************************************** 385 * FD31_UpdateFileTitle [internal] 386 * update the displayed file name (without path) 387 */ 388 static void FD31_UpdateFileTitle(const FD31_DATA *lfs) 389 { 390 LONG lRet; 391 LPOPENFILENAMEW ofnW = lfs->ofnW; 392 LPOPENFILENAMEA ofnA = lfs->ofnA; 393 394 if (ofnW->lpstrFileTitle != NULL) 395 { 396 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0); 397 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet, 398 (LPARAM)ofnW->lpstrFileTitle ); 399 if (ofnA) 400 { 401 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1, 402 ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL )) 403 ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0; 404 } 405 } 406 } 407 408 /*********************************************************************** 409 * FD31_DirListDblClick [internal] 410 */ 411 static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs ) 412 { 413 LONG lRet; 414 HWND hWnd = lfs->hwnd; 415 LPWSTR pstr; 416 WCHAR tmpstr[BUFFILE]; 417 418 /* get the raw string (with brackets) */ 419 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0); 420 if (lRet == LB_ERR) return TRUE; 421 pstr = heap_alloc(BUFFILEALLOC); 422 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet, 423 (LPARAM)pstr); 424 lstrcpyW( tmpstr, pstr ); 425 heap_free(pstr); 426 /* get the selected directory in tmpstr */ 427 if (tmpstr[0] == '[') 428 { 429 tmpstr[lstrlenW(tmpstr) - 1] = 0; 430 lstrcpyW(tmpstr,tmpstr+1); 431 } 432 lstrcatW(tmpstr, FILE_bslash); 433 434 FD31_ScanDir(lfs->ofnW, hWnd, tmpstr); 435 /* notify the app */ 436 if (lfs->hook) 437 { 438 if (FD31_CallWindowProc(lfs, lfs->lbselchstring, lst2, 439 MAKELONG(lRet,CD_LBSELCHANGE))) 440 return TRUE; 441 } 442 return TRUE; 443 } 444 445 /*********************************************************************** 446 * FD31_FileListSelect [internal] 447 * called when a new item is picked in the file list 448 */ 449 static LRESULT FD31_FileListSelect( const FD31_DATA *lfs ) 450 { 451 LONG lRet; 452 HWND hWnd = lfs->hwnd; 453 LPWSTR pstr; 454 455 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0); 456 if (lRet == LB_ERR) 457 return TRUE; 458 459 /* set the edit control to the chosen file */ 460 if ((pstr = heap_alloc(BUFFILEALLOC))) 461 { 462 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet, 463 (LPARAM)pstr); 464 SetDlgItemTextW( hWnd, edt1, pstr ); 465 heap_free(pstr); 466 } 467 if (lfs->hook) 468 { 469 FD31_CallWindowProc(lfs, lfs->lbselchstring, lst1, 470 MAKELONG(lRet,CD_LBSELCHANGE)); 471 } 472 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD, 473 CD_LBSELNOITEMS */ 474 return TRUE; 475 } 476 477 /*********************************************************************** 478 * FD31_TestPath [internal] 479 * before accepting the file name, test if it includes wild cards 480 * tries to scan the directory and returns TRUE if no error. 481 */ 482 static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path ) 483 { 484 HWND hWnd = lfs->hwnd; 485 LPWSTR pBeginFileName, pstr2; 486 WCHAR tmpstr2[BUFFILE]; 487 488 pBeginFileName = wcsrchr(path, '\\'); 489 if (pBeginFileName == NULL) 490 pBeginFileName = wcsrchr(path, ':'); 491 492 if (wcschr(path,'*') != NULL || wcschr(path,'?') != NULL) 493 { 494 /* edit control contains wildcards */ 495 if (pBeginFileName != NULL) 496 { 497 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE); 498 *(pBeginFileName + 1) = 0; 499 } 500 else 501 { 502 lstrcpyW(tmpstr2, path); 503 if(!(lfs->ofnW->Flags & OFN_NOVALIDATE)) 504 *path = 0; 505 } 506 507 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2)); 508 SetDlgItemTextW( hWnd, edt1, tmpstr2 ); 509 FD31_ScanDir(lfs->ofnW, hWnd, path); 510 return (lfs->ofnW->Flags & OFN_NOVALIDATE) != 0; 511 } 512 513 /* no wildcards, we might have a directory or a filename */ 514 /* try appending a wildcard and reading the directory */ 515 516 pstr2 = path + lstrlenW(path); 517 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0) 518 lstrcatW(path, FILE_bslash); 519 520 /* if ScanDir succeeds, we have changed the directory */ 521 if (FD31_ScanDir(lfs->ofnW, hWnd, path)) 522 return FALSE; /* and path is not a valid file name */ 523 524 /* if not, this must be a filename */ 525 526 *pstr2 = 0; /* remove the wildcard added before */ 527 528 if (pBeginFileName != NULL) 529 { 530 /* strip off the pathname */ 531 *pBeginFileName = 0; 532 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 ); 533 534 lstrcpynW(tmpstr2, pBeginFileName + 1, ARRAY_SIZE(tmpstr2)); 535 /* Should we MessageBox() if this fails? */ 536 if (!FD31_ScanDir(lfs->ofnW, hWnd, path)) 537 { 538 return FALSE; 539 } 540 lstrcpyW(path, tmpstr2); 541 } 542 else 543 SetDlgItemTextW( hWnd, edt1, path ); 544 return TRUE; 545 } 546 547 /*********************************************************************** 548 * FD31_Validate [internal] 549 * called on: click Ok button, Enter in edit, DoubleClick in file list 550 */ 551 static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control, INT itemIndex, 552 BOOL internalUse ) 553 { 554 LONG lRet; 555 HWND hWnd = lfs->hwnd; 556 OPENFILENAMEW ofnsav; 557 LPOPENFILENAMEW ofnW = lfs->ofnW; 558 WCHAR filename[BUFFILE]; 559 int copied_size = min( ofnW->lStructSize, sizeof(ofnsav) ); 560 561 memcpy( &ofnsav, ofnW, copied_size ); /* for later restoring */ 562 563 /* get current file name */ 564 if (path) 565 lstrcpynW(filename, path, ARRAY_SIZE(filename)); 566 else 567 GetDlgItemTextW( hWnd, edt1, filename, ARRAY_SIZE(filename)); 568 569 TRACE("got filename = %s\n", debugstr_w(filename)); 570 /* if we did not click in file list to get there */ 571 if (control != lst1) 572 { 573 if (!FD31_TestPath( lfs, filename) ) 574 return FALSE; 575 } 576 FD31_UpdateResult(lfs, filename); 577 578 if (internalUse) 579 { /* called internally after a change in a combo */ 580 if (lfs->hook) 581 { 582 FD31_CallWindowProc(lfs, lfs->lbselchstring, control, 583 MAKELONG(itemIndex,CD_LBSELCHANGE)); 584 } 585 return TRUE; 586 } 587 588 FD31_UpdateFileTitle(lfs); 589 if (lfs->hook) 590 { 591 lRet = FD31_CallWindowProc(lfs, lfs->fileokstring, 592 0, lfs->lParam ); 593 if (lRet) 594 { 595 memcpy( ofnW, &ofnsav, copied_size ); /* restore old state */ 596 return FALSE; 597 } 598 } 599 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER)) 600 { 601 if (ofnW->lpstrFile) 602 { 603 LPWSTR str = ofnW->lpstrFile; 604 LPWSTR ptr = wcsrchr(str, '\\'); 605 str[lstrlenW(str) + 1] = '\0'; 606 *ptr = 0; 607 } 608 } 609 return TRUE; 610 } 611 612 /*********************************************************************** 613 * FD31_DiskChange [internal] 614 * called when a new item is picked in the disk selection combo 615 */ 616 static LRESULT FD31_DiskChange( const FD31_DATA *lfs ) 617 { 618 LONG lRet; 619 HWND hWnd = lfs->hwnd; 620 LPWSTR pstr; 621 WCHAR diskname[BUFFILE]; 622 623 FD31_StripEditControl(hWnd); 624 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L); 625 if (lRet == LB_ERR) 626 return 0; 627 pstr = heap_alloc(BUFFILEALLOC); 628 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet, 629 (LPARAM)pstr); 630 wsprintfW(diskname, FILE_specc, pstr[2]); 631 heap_free(pstr); 632 633 return FD31_Validate( lfs, diskname, cmb2, lRet, TRUE ); 634 } 635 636 /*********************************************************************** 637 * FD31_FileTypeChange [internal] 638 * called when a new item is picked in the file type combo 639 */ 640 static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs ) 641 { 642 LONG lRet; 643 LPWSTR pstr; 644 645 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0); 646 if (lRet == LB_ERR) 647 return TRUE; 648 lfs->ofnW->nFilterIndex = lRet + 1; 649 if (lfs->ofnA) 650 lfs->ofnA->nFilterIndex = lRet + 1; 651 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0); 652 TRACE("Selected filter : %s\n", debugstr_w(pstr)); 653 654 return FD31_Validate( lfs, pstr, cmb1, lRet, TRUE ); 655 } 656 657 /*********************************************************************** 658 * FD31_WMCommand [internal] 659 */ 660 static LRESULT FD31_WMCommand( HWND hWnd, LPARAM lParam, UINT notification, 661 UINT control, const FD31_DATA *lfs ) 662 { 663 switch (control) 664 { 665 case lst1: /* file list */ 666 FD31_StripEditControl(hWnd); 667 if (notification == LBN_DBLCLK) 668 { 669 return SendMessageW(hWnd, WM_COMMAND, IDOK, 0); 670 } 671 else if (notification == LBN_SELCHANGE) 672 return FD31_FileListSelect( lfs ); 673 break; 674 675 case lst2: /* directory list */ 676 FD31_StripEditControl(hWnd); 677 if (notification == LBN_DBLCLK) 678 return FD31_DirListDblClick( lfs ); 679 break; 680 681 case cmb1: /* file type drop list */ 682 if (notification == CBN_SELCHANGE) 683 return FD31_FileTypeChange( lfs ); 684 break; 685 686 case chx1: 687 break; 688 689 case pshHelp: 690 break; 691 692 case cmb2: /* disk dropdown combo */ 693 if (notification == CBN_SELCHANGE) 694 return FD31_DiskChange( lfs ); 695 break; 696 697 case IDOK: 698 TRACE("OK pressed\n"); 699 if (FD31_Validate( lfs, NULL, control, 0, FALSE )) 700 EndDialog(hWnd, TRUE); 701 return TRUE; 702 703 case IDCANCEL: 704 EndDialog(hWnd, FALSE); 705 return TRUE; 706 707 case IDABORT: /* can be sent by the hook procedure */ 708 EndDialog(hWnd, TRUE); 709 return TRUE; 710 } 711 return FALSE; 712 } 713 714 /************************************************************************ 715 * FD31_MapStringPairsToW [internal] 716 * map string pairs to Unicode 717 */ 718 static LPWSTR FD31_MapStringPairsToW(LPCSTR strA, UINT size) 719 { 720 LPCSTR s; 721 LPWSTR x; 722 unsigned int n, len; 723 724 s = strA; 725 while (*s) 726 s = s+strlen(s)+1; 727 s++; 728 n = s + 1 - strA; /* Don't forget the other \0 */ 729 if (n < size) n = size; 730 731 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 ); 732 x = heap_alloc(len * sizeof(WCHAR)); 733 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len ); 734 return x; 735 } 736 737 738 /************************************************************************ 739 * FD31_DupToW [internal] 740 * duplicates an Ansi string to unicode, with a buffer size 741 */ 742 static LPWSTR FD31_DupToW(LPCSTR str, DWORD size) 743 { 744 LPWSTR strW = NULL; 745 if (str && (size > 0)) 746 { 747 strW = heap_alloc(size * sizeof(WCHAR)); 748 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size ); 749 } 750 return strW; 751 } 752 753 /************************************************************************ 754 * FD31_MapOfnStructA [internal] 755 * map a 32 bits Ansi structure to a Unicode one 756 */ 757 static void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open) 758 { 759 UNICODE_STRING usBuffer; 760 761 ofnW->hwndOwner = ofnA->hwndOwner; 762 ofnW->hInstance = ofnA->hInstance; 763 if (ofnA->lpstrFilter) 764 ofnW->lpstrFilter = FD31_MapStringPairsToW(ofnA->lpstrFilter, 0); 765 766 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter))) 767 ofnW->lpstrCustomFilter = FD31_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter); 768 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter; 769 ofnW->nFilterIndex = ofnA->nFilterIndex; 770 ofnW->nMaxFile = ofnA->nMaxFile; 771 ofnW->lpstrFile = FD31_DupToW(ofnA->lpstrFile, ofnW->nMaxFile); 772 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle; 773 ofnW->lpstrFileTitle = FD31_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle); 774 if (ofnA->lpstrInitialDir) 775 { 776 RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpstrInitialDir); 777 ofnW->lpstrInitialDir = usBuffer.Buffer; 778 } 779 if (ofnA->lpstrTitle) { 780 RtlCreateUnicodeStringFromAsciiz (&usBuffer, ofnA->lpstrTitle); 781 ofnW->lpstrTitle = usBuffer.Buffer; 782 } else { 783 WCHAR buf[16]; 784 LPWSTR title_tmp; 785 int len; 786 LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS, buf, ARRAY_SIZE(buf)); 787 len = lstrlenW(buf)+1; 788 title_tmp = heap_alloc(len * sizeof(WCHAR)); 789 memcpy(title_tmp, buf, len * sizeof(WCHAR)); 790 ofnW->lpstrTitle = title_tmp; 791 } 792 ofnW->Flags = ofnA->Flags; 793 ofnW->nFileOffset = ofnA->nFileOffset; 794 ofnW->nFileExtension = ofnA->nFileExtension; 795 ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3); 796 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName)) 797 { 798 if (!IS_INTRESOURCE(ofnA->lpTemplateName)) 799 { 800 RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName); 801 ofnW->lpTemplateName = usBuffer.Buffer; 802 } 803 else /* numbered resource */ 804 ofnW->lpTemplateName = (LPCWSTR) ofnA->lpTemplateName; 805 } 806 if (ofnW->lStructSize > OPENFILENAME_SIZE_VERSION_400W) 807 { 808 ofnW->pvReserved = ofnA->pvReserved; 809 ofnW->dwReserved = ofnA->dwReserved; 810 ofnW->FlagsEx = ofnA->FlagsEx; 811 } 812 } 813 814 815 /************************************************************************ 816 * FD31_FreeOfnW [internal] 817 * Undo all allocations done by FD31_MapOfnStructA 818 */ 819 static void FD31_FreeOfnW(OPENFILENAMEW *ofnW) 820 { 821 heap_free((void *)ofnW->lpstrFilter); 822 heap_free(ofnW->lpstrCustomFilter); 823 heap_free(ofnW->lpstrFile); 824 heap_free(ofnW->lpstrFileTitle); 825 heap_free((void *)ofnW->lpstrInitialDir); 826 heap_free((void *)ofnW->lpstrTitle); 827 if (!IS_INTRESOURCE(ofnW->lpTemplateName)) 828 heap_free((void *)ofnW->lpTemplateName); 829 } 830 831 /************************************************************************ 832 * FD31_DestroyPrivate [internal] 833 * destroys the private object 834 */ 835 static void FD31_DestroyPrivate(PFD31_DATA lfs) 836 { 837 HWND hwnd; 838 if (!lfs) return; 839 hwnd = lfs->hwnd; 840 TRACE("destroying private allocation %p\n", lfs); 841 842 /* if ofnW has been allocated, have to free everything in it */ 843 if (lfs->ofnA) 844 { 845 FD31_FreeOfnW(lfs->ofnW); 846 heap_free(lfs->ofnW); 847 } 848 heap_free(lfs); 849 RemovePropA(hwnd, FD31_OFN_PROP); 850 } 851 852 /*********************************************************************** 853 * FD31_GetTemplate [internal] 854 * 855 * Get a template (or FALSE if failure) when 16 bits dialogs are used 856 * by a 32 bits application 857 * 858 */ 859 static BOOL FD31_GetTemplate(PFD31_DATA lfs) 860 { 861 LPOPENFILENAMEW ofnW = lfs->ofnW; 862 LPOPENFILENAMEA ofnA = lfs->ofnA; 863 HANDLE hDlgTmpl; 864 865 if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE) 866 { 867 if (!(lfs->template = LockResource( ofnW->hInstance ))) 868 { 869 COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE ); 870 return FALSE; 871 } 872 } 873 else if (ofnW->Flags & OFN_ENABLETEMPLATE) 874 { 875 HRSRC hResInfo; 876 if (ofnA) 877 hResInfo = FindResourceA( ofnA->hInstance, ofnA->lpTemplateName, (LPSTR)RT_DIALOG ); 878 else 879 hResInfo = FindResourceW( ofnW->hInstance, ofnW->lpTemplateName, (LPWSTR)RT_DIALOG ); 880 if (!hResInfo) 881 { 882 COMDLG32_SetCommDlgExtendedError( CDERR_FINDRESFAILURE ); 883 return FALSE; 884 } 885 if (!(hDlgTmpl = LoadResource( ofnW->hInstance, hResInfo )) || 886 !(lfs->template = LockResource( hDlgTmpl ))) 887 { 888 COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE ); 889 return FALSE; 890 } 891 } 892 else /* get it from internal Wine resource */ 893 { 894 HRSRC hResInfo; 895 if (!(hResInfo = FindResourceA( COMDLG32_hInstance, lfs->open ? "OPEN_FILE" : "SAVE_FILE", (LPSTR)RT_DIALOG ))) 896 { 897 COMDLG32_SetCommDlgExtendedError( CDERR_FINDRESFAILURE ); 898 return FALSE; 899 } 900 if (!(hDlgTmpl = LoadResource( COMDLG32_hInstance, hResInfo )) || 901 !(lfs->template = LockResource( hDlgTmpl ))) 902 { 903 COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE ); 904 return FALSE; 905 } 906 } 907 return TRUE; 908 } 909 910 /************************************************************************ 911 * FD31_AllocPrivate [internal] 912 * allocate a private object to hold 32 bits Unicode 913 * structure that will be used throughout the calls, while 914 * keeping available the original structures and a few variables 915 * On entry : type = dialog procedure type (16,32A,32W) 916 * dlgType = dialog type (open or save) 917 */ 918 static PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode) 919 { 920 FD31_DATA *lfs = heap_alloc_zero(sizeof(*lfs)); 921 922 TRACE("alloc private buf %p\n", lfs); 923 if (!lfs) return NULL; 924 lfs->hook = FALSE; 925 lfs->lParam = lParam; 926 lfs->open = (dlgType == OPEN_DIALOG); 927 928 if (IsUnicode) 929 { 930 lfs->ofnA = NULL; 931 lfs->ofnW = (LPOPENFILENAMEW) lParam; 932 if (lfs->ofnW->Flags & OFN_ENABLEHOOK) 933 if (lfs->ofnW->lpfnHook) 934 lfs->hook = TRUE; 935 } 936 else 937 { 938 lfs->ofnA = (LPOPENFILENAMEA) lParam; 939 if (lfs->ofnA->Flags & OFN_ENABLEHOOK) 940 if (lfs->ofnA->lpfnHook) 941 lfs->hook = TRUE; 942 lfs->ofnW = heap_alloc_zero(lfs->ofnA->lStructSize); 943 lfs->ofnW->lStructSize = lfs->ofnA->lStructSize; 944 FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open); 945 } 946 947 if (! FD31_GetTemplate(lfs)) 948 { 949 FD31_DestroyPrivate(lfs); 950 return NULL; 951 } 952 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA); 953 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA); 954 955 return lfs; 956 } 957 958 /*********************************************************************** 959 * FD31_WMInitDialog [internal] 960 */ 961 static LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam) 962 { 963 int i, n; 964 WCHAR tmpstr[BUFFILE]; 965 LPWSTR pstr, old_pstr; 966 LPOPENFILENAMEW ofn; 967 PFD31_DATA lfs = (PFD31_DATA) lParam; 968 969 if (!lfs) return FALSE; 970 SetPropA(hWnd, FD31_OFN_PROP, lfs); 971 lfs->hwnd = hWnd; 972 ofn = lfs->ofnW; 973 974 TRACE("flags=%x initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir)); 975 976 SetWindowTextW( hWnd, ofn->lpstrTitle ); 977 /* read custom filter information */ 978 if (ofn->lpstrCustomFilter) 979 { 980 pstr = ofn->lpstrCustomFilter; 981 n = 0; 982 TRACE("lpstrCustomFilter = %p\n", pstr); 983 while(*pstr) 984 { 985 old_pstr = pstr; 986 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0, 987 (LPARAM)(ofn->lpstrCustomFilter) + n ); 988 n += lstrlenW(pstr) + 1; 989 pstr += lstrlenW(pstr) + 1; 990 TRACE("add str=%s associated to %s\n", 991 debugstr_w(old_pstr), debugstr_w(pstr)); 992 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr); 993 n += lstrlenW(pstr) + 1; 994 pstr += lstrlenW(pstr) + 1; 995 } 996 } 997 /* read filter information */ 998 if (ofn->lpstrFilter) { 999 pstr = (LPWSTR) ofn->lpstrFilter; 1000 n = 0; 1001 while(*pstr) { 1002 old_pstr = pstr; 1003 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0, 1004 (LPARAM)(ofn->lpstrFilter + n) ); 1005 n += lstrlenW(pstr) + 1; 1006 pstr += lstrlenW(pstr) + 1; 1007 TRACE("add str=%s associated to %s\n", 1008 debugstr_w(old_pstr), debugstr_w(pstr)); 1009 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr); 1010 n += lstrlenW(pstr) + 1; 1011 pstr += lstrlenW(pstr) + 1; 1012 } 1013 } 1014 /* set default filter */ 1015 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL) 1016 ofn->nFilterIndex = 1; 1017 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0); 1018 if (ofn->lpstrFile && ofn->lpstrFile[0]) 1019 { 1020 TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) ); 1021 SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile ); 1022 } 1023 else 1024 { 1025 lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter, 1026 ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE); 1027 TRACE("nFilterIndex = %d, SetText of edt1 to %s\n", 1028 ofn->nFilterIndex, debugstr_w(tmpstr)); 1029 SetDlgItemTextW( hWnd, edt1, tmpstr ); 1030 } 1031 /* get drive list */ 1032 *tmpstr = 0; 1033 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE); 1034 /* read initial directory */ 1035 /* FIXME: Note that this is now very version-specific (See MSDN description of 1036 * the OPENFILENAME structure). For example under 2000/XP any path in the 1037 * lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME 1038 */ 1039 if (ofn->lpstrInitialDir != NULL) 1040 { 1041 int len; 1042 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511); 1043 len = lstrlenW(tmpstr); 1044 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') { 1045 tmpstr[len]='\\'; 1046 tmpstr[len+1]='\0'; 1047 } 1048 } 1049 else 1050 *tmpstr = 0; 1051 if (!FD31_ScanDir(ofn, hWnd, tmpstr)) { 1052 *tmpstr = 0; 1053 if (!FD31_ScanDir(ofn, hWnd, tmpstr)) 1054 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr)); 1055 } 1056 /* select current drive in combo 2, omit missing drives */ 1057 { 1058 char dir[MAX_PATH]; 1059 char str[4] = "a:\\"; 1060 GetCurrentDirectoryA( sizeof(dir), dir ); 1061 for(i = 0, n = -1; i < 26; i++) 1062 { 1063 str[0] = 'a' + i; 1064 if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++; 1065 if (toupper(str[0]) == toupper(dir[0])) break; 1066 } 1067 } 1068 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0); 1069 if (!(ofn->Flags & OFN_SHOWHELP)) 1070 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE); 1071 if (ofn->Flags & OFN_HIDEREADONLY) 1072 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 1073 if (lfs->hook) 1074 return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam); 1075 return TRUE; 1076 } 1077 1078 static int FD31_GetFldrHeight(void) 1079 { 1080 return fldrHeight; 1081 } 1082 1083 /*********************************************************************** 1084 * FD31_WMMeasureItem [internal] 1085 */ 1086 static LONG FD31_WMMeasureItem(LPARAM lParam) 1087 { 1088 LPMEASUREITEMSTRUCT lpmeasure; 1089 1090 lpmeasure = (LPMEASUREITEMSTRUCT)lParam; 1091 lpmeasure->itemHeight = FD31_GetFldrHeight(); 1092 return TRUE; 1093 } 1094 1095 1096 /*********************************************************************** 1097 * FileOpenDlgProc [internal] 1098 * Used for open and save, in fact. 1099 */ 1100 static INT_PTR CALLBACK FD31_FileOpenDlgProc(HWND hWnd, UINT wMsg, 1101 WPARAM wParam, LPARAM lParam) 1102 { 1103 PFD31_DATA lfs = (PFD31_DATA)GetPropA( hWnd, FD31_OFN_PROP ); 1104 1105 TRACE("msg=%x wparam=%lx lParam=%lx\n", wMsg, wParam, lParam); 1106 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook) 1107 { 1108 INT_PTR lRet; 1109 lRet = (INT_PTR)FD31_CallWindowProc( lfs, wMsg, wParam, lParam ); 1110 if (lRet) return lRet; /* else continue message processing */ 1111 } 1112 switch (wMsg) 1113 { 1114 case WM_INITDIALOG: 1115 return FD31_WMInitDialog( hWnd, wParam, lParam ); 1116 1117 case WM_MEASUREITEM: 1118 return FD31_WMMeasureItem( lParam ); 1119 1120 case WM_DRAWITEM: 1121 return FD31_WMDrawItem( hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam ); 1122 1123 case WM_COMMAND: 1124 return FD31_WMCommand( hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs ); 1125 #if 0 1126 case WM_CTLCOLOR: 1127 SetBkColor( (HDC16)wParam, 0x00C0C0C0 ); 1128 switch (HIWORD(lParam)) 1129 { 1130 case CTLCOLOR_BTN: 1131 SetTextColor( (HDC16)wParam, 0x00000000 ); 1132 return hGRAYBrush; 1133 case CTLCOLOR_STATIC: 1134 SetTextColor( (HDC16)wParam, 0x00000000 ); 1135 return hGRAYBrush; 1136 } 1137 break; 1138 #endif 1139 } 1140 return FALSE; 1141 } 1142 1143 /*********************************************************************** 1144 * GetFileName31A [internal] 1145 * 1146 * Creates a win31 style dialog box for the user to select a file to open/save. 1147 */ 1148 BOOL GetFileName31A( OPENFILENAMEA *lpofn, UINT dlgType ) 1149 { 1150 BOOL bRet = FALSE; 1151 PFD31_DATA lfs; 1152 1153 if (!lpofn || !FD31_Init()) return FALSE; 1154 1155 TRACE("ofn flags %08x\n", lpofn->Flags); 1156 lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, FALSE); 1157 if (lfs) 1158 { 1159 bRet = DialogBoxIndirectParamA( COMDLG32_hInstance, lfs->template, lpofn->hwndOwner, 1160 FD31_FileOpenDlgProc, (LPARAM)lfs); 1161 FD31_DestroyPrivate(lfs); 1162 } 1163 1164 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile); 1165 return bRet; 1166 } 1167 1168 /*********************************************************************** 1169 * GetFileName31W [internal] 1170 * 1171 * Creates a win31 style dialog box for the user to select a file to open/save 1172 */ 1173 BOOL GetFileName31W( OPENFILENAMEW *lpofn, UINT dlgType ) 1174 { 1175 BOOL bRet = FALSE; 1176 PFD31_DATA lfs; 1177 1178 if (!lpofn || !FD31_Init()) return FALSE; 1179 1180 lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, TRUE); 1181 if (lfs) 1182 { 1183 bRet = DialogBoxIndirectParamW( COMDLG32_hInstance, lfs->template, lpofn->hwndOwner, 1184 FD31_FileOpenDlgProc, (LPARAM)lfs); 1185 FD31_DestroyPrivate(lfs); 1186 } 1187 1188 TRACE("file %s, file offset %d, ext offset %d\n", 1189 debugstr_w(lpofn->lpstrFile), lpofn->nFileOffset, lpofn->nFileExtension); 1190 return bRet; 1191 } 1192