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