Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4124 lines
104 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. prompt.c
  5. Abstract:
  6. Disk/file prompt and file error prompt dialogs.
  7. Author:
  8. Ted Miller (tedm) 8-Feb-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <winnetwk.h>
  14. #include <winnetp.h>
  15. #include <winioctl.h>
  16. //
  17. // Structure used internally to store information
  18. // about the file/disk being prompted for or the copy error
  19. // that has occured. We store a pointer to one of these as
  20. // a window property of the prompt dialog box. This eliminates
  21. // the need for our own dialog class and for global/static variables.
  22. //
  23. typedef struct _PROMPTPARAMS {
  24. //
  25. // Reason we are displaying the dialog. One of DLGTYPE_ERROR or
  26. // DLGTYPE_PROMPT. Used to modify controls and dialog's behavior.
  27. //
  28. UINT DialogType;
  29. //
  30. // For error dialogs, these values tell us the win32 error code
  31. // that indicated failure. Used in the details message box.
  32. //
  33. UINT Win32Error;
  34. //
  35. // Window handle of the prompt/error dialog, and of its owner window,
  36. // if any.
  37. //
  38. HWND hdlg;
  39. HWND Owner;
  40. //
  41. // String to be used as the caption for the prompt/error dialog.
  42. //
  43. PCTSTR DialogTitle;
  44. //
  45. // Disk tag file. Used when prompting for a disk. We look for
  46. // this file at the root of the drive to verify presence of the disk.
  47. //
  48. PCTSTR TagFile;
  49. //
  50. // Desriptive name for the disk where we expect the file to be.
  51. // This is used even when the source location is non-removable,
  52. // because the user might elect to furnish the file on disk, etc.
  53. //
  54. PCTSTR DiskName;
  55. //
  56. // The path to the source file (not including the file name)
  57. // and the filename part of the source file. This filename is
  58. // displayed when the user elects to browse and in certain other
  59. // messages we may display in the dialog box.
  60. //
  61. PCTSTR PathToSource;
  62. PCTSTR FileSought;
  63. //
  64. // Full path of the target file, if any. Used for copy errors and rename,
  65. // so we can tell the user the name of the target file in the details
  66. // message box.
  67. //
  68. PCTSTR TargetFile;
  69. //
  70. // IDF_xxx style bits that control behavior of the promt dialog.
  71. //
  72. DWORD PromptStyle;
  73. //
  74. // Drive type for PathToSource and flag indicating whether
  75. // it's for removable media.
  76. //
  77. UINT DriveType;
  78. BOOL IsRemovable;
  79. //
  80. // List of installation paths, from the registry.
  81. // Access to that list is not synchronized among processes;
  82. // oh well.
  83. //
  84. PTSTR *PathList;
  85. UINT PathCount;
  86. //
  87. // Flag indicating whether the user has browsed (Browse button)
  88. // during the lifetime of the dialog invocation.
  89. //
  90. BOOL UserBrowsed;
  91. //
  92. // Flag indicating whether the user is allowed to type in the combo box
  93. // edit control.
  94. //
  95. BOOL ReadOnlyMru;
  96. //
  97. // Identifier of the combo box in use.
  98. //
  99. UINT ComboBoxId;
  100. //
  101. // Value used to indicate whether or not we're doing a presence check and,
  102. // if so, whether there's a pending cancel to be processed once we're done
  103. // (i.e., upon receipt of a WMX_PRESENCE_RESULT message posted from the
  104. // AuxPromptThread).
  105. //
  106. // Possible values are:
  107. // == 0 -- not currently doing a presence check--no pending cancels.
  108. // == 1 -- currently doing a presence check--no pending cancels.
  109. // >= 2 -- currently doing a presence check--one or more pending cancels.
  110. //
  111. BOOL PresenceCheckState;
  112. BOOL BrowseAutoComplete;
  113. #if ASSERTS_ON
  114. //
  115. // Make sure that if we fired off a presence check thread, that it has
  116. // notified us of its completion prior to our processing of WM_DESTROY.
  117. //
  118. BOOL PresenceCheckThreadRunning;
  119. //
  120. // Keep track of when the dialog's controls are disabled (hence we don't
  121. // expect to see the OK button pressed).
  122. //
  123. BOOL ControlsDisabled;
  124. #endif // ASSERTS_ON
  125. //
  126. // Parameters that are passed to the simple message box
  127. //
  128. MSGBOXPARAMS MsgBoxParams;
  129. } PROMPTPARAMS, *PPROMPTPARAMS;
  130. //
  131. // PROMPTPARAMS.DialogType
  132. //
  133. #define DLGTYPE_PROMPT 0
  134. #define DLGTYPE_ERROR 1
  135. //
  136. // Define a signature for WMX_PRESENCE_RESULT (contained in lParam) that is
  137. // used to validate the sender as being our own AuxPromptThread.
  138. //
  139. #define PRESENCE_RESULT_SIG 0x52504D53 // "SMPR" (Setupapi Message Presence Result)
  140. //
  141. // Structure used in delete/rename error dialog.
  142. //
  143. typedef struct _FILEERRDLGPARAMS {
  144. PCTSTR MessageText;
  145. DWORD Style;
  146. PCTSTR Caption;
  147. } FILEERRDLGPARAMS, *PFILEERRDLGPARAMS;
  148. //
  149. // Text constants.
  150. //
  151. TCHAR pszDiskPromptPropName[] = TEXT("_diskpromptparams");
  152. //
  153. // Custom window messages
  154. //
  155. #define WMX_PRESENCE_RESULT (WM_USER+121)
  156. #define WMX_HELLO (WM_USER+122)
  157. #define WMX_FIXUP_FILENAME (WM_USER+123)
  158. //
  159. // Linked-list node structure that tracks what temporary connections we
  160. // need to clean up on unload (connections made as a result of user doing
  161. // a "Connect As").
  162. //
  163. typedef struct _TEMP_NET_CONNECTION {
  164. struct _TEMP_NET_CONNECTION *Next;
  165. TCHAR NetResourceName[MAX_PATH];
  166. } TEMP_NET_CONNECTION, *PTEMP_NET_CONNECTION;
  167. //
  168. // Global variables that track temporary net connections.
  169. //
  170. PTEMP_NET_CONNECTION NetConnectionList;
  171. //
  172. // global window message for cancelling autoplay.
  173. //
  174. UINT g_uQueryCancelAutoPlay = 0;
  175. //
  176. // Private routine prototypes.
  177. //
  178. BOOL
  179. ConnectToNetShare(
  180. IN PCTSTR FileName,
  181. IN HWND hwndParent
  182. );
  183. BOOL
  184. IsDriveReallyAHardDrive(
  185. IN TCHAR DriveLetter
  186. )
  187. {
  188. TCHAR DriveNameNt[7];
  189. HANDLE hDisk;
  190. DWORD DataSize;
  191. DISK_GEOMETRY MediaInfo;
  192. BOOL b;
  193. #ifdef _X86_
  194. if(OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) {
  195. //
  196. // Blow off the win9x case since the win32 support
  197. // for making this determination is poor at best.
  198. // A nauseating hack lets this work at least some of
  199. // the time but PC98 is hosed since the basic assumption that
  200. // floppies are generally A: and B: is invalid.
  201. //
  202. return(!IsNEC98() && (DriveLetter >= TEXT('C')));
  203. }
  204. #endif
  205. //
  206. // NT case allows us to make the determination reliably by opening
  207. // the drive and reading some attributes.
  208. //
  209. wsprintf(DriveNameNt,TEXT("\\\\.\\%c:"),DriveLetter);
  210. hDisk = CreateFile(
  211. DriveNameNt,
  212. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  213. FILE_SHARE_READ | FILE_SHARE_WRITE,
  214. NULL,
  215. OPEN_EXISTING,
  216. 0,
  217. NULL
  218. );
  219. if(hDisk == INVALID_HANDLE_VALUE) {
  220. return(FALSE);
  221. }
  222. b = DeviceIoControl(
  223. hDisk,
  224. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  225. NULL,
  226. 0,
  227. &MediaInfo,
  228. sizeof(MediaInfo),
  229. &DataSize,
  230. NULL
  231. );
  232. CloseHandle(hDisk);
  233. //
  234. // It's really a hard disk if the media type is removable.
  235. //
  236. return(b && (MediaInfo.MediaType == RemovableMedia));
  237. }
  238. VOID
  239. DiskPromptGetDriveType(
  240. IN PCTSTR PathToSource,
  241. OUT PUINT DriveType,
  242. OUT PBOOL IsRemovable
  243. )
  244. /*++
  245. Routine Description:
  246. Determine the drive type of the drive on which a path resides.
  247. If the path starts with x: we call GetDriveType() on it.
  248. If GetDriveType fails we assume it's removable.
  249. If the path starts with \\ we assume it's remote.
  250. Otherwise we assume it's a relative path on a hard drive.
  251. Arguments:
  252. PathToSource - pathname of path whose drive type is needed.
  253. DriveType - receives value indicating drive type. The set of
  254. possible values is the same as the named constants that can
  255. be returned by GetDriveType().
  256. IsRemovable - receives flag indicating whether DriveType
  257. is a removable media type (floppy, cd-rom).
  258. Return Value:
  259. None.
  260. --*/
  261. {
  262. TCHAR DriveRoot[4];
  263. TCHAR c;
  264. c = (TCHAR)CharUpper((PTSTR)PathToSource[0]);
  265. if((c >= TEXT('A')) && (c <= TEXT('Z')) && (PathToSource[1] == TEXT(':'))) {
  266. DriveRoot[0] = PathToSource[0];
  267. DriveRoot[1] = PathToSource[1];
  268. DriveRoot[2] = TEXT('\\');
  269. DriveRoot[3] = 0;
  270. *DriveType = GetDriveType(DriveRoot);
  271. if(*DriveType == DRIVE_NO_ROOT_DIR) {
  272. //
  273. // Typically indicates that this drive-letter is invalid
  274. // we will not get this if drive-letter is valid
  275. // but media is not inserted.
  276. //
  277. *DriveType = DRIVE_UNKNOWN;
  278. }
  279. *IsRemovable = ((*DriveType == DRIVE_REMOVABLE) || (*DriveType == DRIVE_CDROM) || (*DriveType == DRIVE_UNKNOWN));
  280. //
  281. // If the drive is really a removeable hard drive as opposed to a
  282. // floppy drive, change the drive type field to indicate a fixed
  283. // drive, but don't change the removable flag. This allows callers
  284. // to make this distinction if they need to.
  285. //
  286. // If the system is installed on the drive in question, then leave
  287. // the drive type alone, but indicate that the media is not actually
  288. // removable.
  289. //
  290. if(*DriveType == DRIVE_REMOVABLE) {
  291. if(IsDriveReallyAHardDrive(c)) {
  292. *DriveType = DRIVE_FIXED;
  293. }
  294. if((WindowsDirectory[0] == PathToSource[0]) && (WindowsDirectory[1] == TEXT(':'))) {
  295. *IsRemovable = FALSE;
  296. }
  297. }
  298. } else {
  299. //
  300. // Not drive letter: so try unc.
  301. //
  302. if((PathToSource[0] == TEXT('\\')) && (PathToSource[1] == TEXT('\\'))) {
  303. *DriveType = DRIVE_REMOTE;
  304. } else {
  305. //
  306. // Not recognized full path spec; assume relative path on HD.
  307. //
  308. *DriveType = DRIVE_FIXED;
  309. }
  310. *IsRemovable = FALSE;
  311. }
  312. }
  313. typedef struct _MYOPENPARAMS {
  314. PCTSTR Filename1;
  315. PCTSTR Filename2;
  316. PCTSTR Filename3;
  317. } MYOPENPARAMS, *PMYOPENPARAMS;
  318. UINT_PTR
  319. APIENTRY
  320. BrowseHookProc(
  321. IN HWND hdlg,
  322. IN UINT msg,
  323. IN WPARAM wParam,
  324. IN LPARAM lParam
  325. )
  326. /*++
  327. Routine Description:
  328. Hook procedure used with the OpenFile common dialog
  329. for file browsing. We use a hook proc so that the user
  330. is forced to look for only one particular file, and can't
  331. look at any other file.
  332. Arguments:
  333. Standard Window Procedure arguments.
  334. Return Value:
  335. Always FALSE, to indicate that the common dialog should
  336. process the message.
  337. --*/
  338. {
  339. HWND hwnd;
  340. LPOFNOTIFY NotifyParams;
  341. LPOPENFILENAME OpenParams;
  342. PMYOPENPARAMS MyOpenParams;
  343. TCHAR Path[MAX_PATH];
  344. WIN32_FIND_DATA FindData;
  345. BOOL b;
  346. UINT NotifyCode;
  347. UNREFERENCED_PARAMETER(wParam);
  348. switch(msg) {
  349. case WM_INITDIALOG:
  350. //
  351. // Save away the OPENFILENAME structure for later.
  352. //
  353. SetWindowLongPtr(hdlg,GWLP_USERDATA,lParam);
  354. break;
  355. case WMX_FIXUP_FILENAME:
  356. case WM_NOTIFY:
  357. if(msg == WM_NOTIFY) {
  358. NotifyParams = (LPOFNOTIFY)lParam;
  359. NotifyCode = NotifyParams->hdr.code;
  360. } else {
  361. NotifyCode = CDN_FOLDERCHANGE;
  362. }
  363. hwnd = GetParent(hdlg);
  364. switch(NotifyCode) {
  365. case CDN_INITDONE:
  366. //
  367. // Make the "files of type" combo box read-only.
  368. //
  369. EnableWindow(GetDlgItem(hwnd,cmb1),FALSE);
  370. //
  371. // Post ourselves a message, so that we'll initialize the editbox
  372. // correctly (we can't do it here, because it's too early).
  373. //
  374. PostMessage(hdlg, WMX_FIXUP_FILENAME, 0, 0);
  375. break;
  376. case CDN_FOLDERCHANGE:
  377. case CDN_FILEOK:
  378. //
  379. // See if the file actually exists and if so
  380. // set up the edit control.
  381. //
  382. OpenParams = (LPOPENFILENAME)GetWindowLongPtr(hdlg,GWLP_USERDATA);
  383. MyOpenParams = (PMYOPENPARAMS)OpenParams->lCustData;
  384. CommDlg_OpenSave_GetFolderPath(hwnd,Path,MAX_PATH);
  385. pSetupConcatenatePaths(Path,MyOpenParams->Filename1,MAX_PATH,NULL);
  386. if(FileExists(Path,&FindData)) {
  387. b = TRUE;
  388. } else {
  389. if(MyOpenParams->Filename2) {
  390. CommDlg_OpenSave_GetFolderPath(hwnd,Path,MAX_PATH);
  391. pSetupConcatenatePaths(Path,MyOpenParams->Filename2,MAX_PATH,NULL);
  392. if(FileExists(Path,&FindData)) {
  393. b = TRUE;
  394. } else {
  395. if(MyOpenParams->Filename3) {
  396. CommDlg_OpenSave_GetFolderPath(hwnd,Path,MAX_PATH);
  397. pSetupConcatenatePaths(Path,MyOpenParams->Filename3,MAX_PATH,NULL);
  398. b = FileExists(Path,&FindData);
  399. } else {
  400. b = FALSE;
  401. }
  402. }
  403. } else {
  404. b = FALSE;
  405. }
  406. }
  407. if(NotifyCode == CDN_FOLDERCHANGE) {
  408. if(b) {
  409. CommDlg_OpenSave_SetControlText(hwnd, edt1, FindData.cFileName);
  410. }
  411. } else {
  412. if(!b) {
  413. MessageBeep(MB_ICONASTERISK);
  414. SetWindowLongPtr(hdlg,DWLP_MSGRESULT,TRUE);
  415. return(TRUE);
  416. }
  417. }
  418. break;
  419. }
  420. break;
  421. }
  422. //
  423. // Let commdlg process it
  424. //
  425. return(FALSE);
  426. }
  427. BOOL
  428. DoBrowse(
  429. IN HWND hdlg,
  430. IN PPROMPTPARAMS Params
  431. )
  432. /*++
  433. Routine Description:
  434. Allow the user to browse for a file. The user is allowed to look
  435. only for the file in question -- he is not allowed to change the filter,
  436. select an alternate file, etc.
  437. Arguments:
  438. hdlg - supplies the window handle of the window to own the
  439. browse dialog.
  440. File - supplies the filename (no path) of the file being looked for.
  441. Return Value:
  442. TRUE if the user located the file. FALSE otherwise.
  443. If TRUE, the edit control of the combo box in hdlg has been given the
  444. final path entered by the user in the browse dialog.
  445. --*/
  446. {
  447. OPENFILENAME ofn;
  448. TCHAR Path[MAX_PATH];
  449. TCHAR Filter[2*MAX_PATH];
  450. TCHAR InitialDir[MAX_PATH];
  451. UINT InitialDirDriveType;
  452. BOOL IsInitialDirOnRemovableDrive, InitialDirMediaPresent;
  453. PTSTR CompressedFormName;
  454. BOOL found=FALSE;
  455. PTSTR p;
  456. LPCTSTR q;
  457. PCTSTR File;
  458. LONG l;
  459. HKEY hKey1,hKey2;
  460. DWORD Type;
  461. DWORD Size;
  462. BOOL GotDesc;
  463. MYOPENPARAMS MyParams;
  464. File = Params->FileSought;
  465. //
  466. // Create the compressed-form name of the source file.
  467. //
  468. CompressedFormName = (Params->PromptStyle & IDF_NOCOMPRESSED)
  469. ? NULL
  470. : SetupGenerateCompressedName(File);
  471. //
  472. // Build a filter that contains the file we're looking for
  473. // and its compressed form name, if any. If the file is of
  474. // the form *.ext then we'll build a more descriptive name.
  475. //
  476. GotDesc = FALSE;
  477. if(!CompressedFormName
  478. && (File[0] == TEXT('*'))
  479. && (File[1] == TEXT('.'))
  480. && File[2]
  481. && !_tcschr(File+2,TEXT('.'))) {
  482. l = RegOpenKeyEx(HKEY_CLASSES_ROOT,File+1,0,KEY_QUERY_VALUE,&hKey1);
  483. if(l == NO_ERROR) {
  484. Size = sizeof(Filter);
  485. l = RegQueryValueEx(hKey1,TEXT(""),NULL,&Type,(LPBYTE)Filter,&Size);
  486. if((l == NO_ERROR) && (Type == REG_SZ)) {
  487. l = RegOpenKeyEx(HKEY_CLASSES_ROOT,Filter,0,KEY_QUERY_VALUE,&hKey2);
  488. if(l == NO_ERROR) {
  489. Size = sizeof(Filter);
  490. l = RegQueryValueEx(hKey2,TEXT(""),NULL,&Type,(LPBYTE)Filter,&Size);
  491. if((l == NO_ERROR) && (Type == REG_SZ)) {
  492. lstrcat(Filter,TEXT(" ("));
  493. lstrcat(Filter,File);
  494. lstrcat(Filter,TEXT(")"));
  495. p = Filter + lstrlen(Filter) + 1;
  496. p += wsprintf(p,File);
  497. GotDesc = TRUE;
  498. }
  499. RegCloseKey(hKey2);
  500. }
  501. }
  502. RegCloseKey(hKey1);
  503. }
  504. }
  505. if(!GotDesc) {
  506. //
  507. // Not able to fetch a meaningful description. Use the filenames.
  508. // The filter has the description and the filespec set to
  509. // the filename, for both the filename and its compressed form like so:
  510. // foo.exe;foo.ex_ foo.exe;foo.ex_
  511. //
  512. p = Filter + wsprintf(Filter,File);
  513. if(CompressedFormName) {
  514. *p++ = TEXT(';');
  515. p += wsprintf(p,CompressedFormName) + 1;
  516. } else {
  517. p++;
  518. }
  519. p += wsprintf(p,File);
  520. if(CompressedFormName) {
  521. *p++ = TEXT(';');
  522. p += wsprintf(p,CompressedFormName);
  523. }
  524. }
  525. //
  526. // Stick the cabinet name in there if we think there is one.
  527. // We do a dirty hackola to tell the difference between a tag file
  528. // and a cabinet, namely we look for a .cab extension.
  529. //
  530. // Note that at this point p points at the terminating nul
  531. // of the last filename placed into Filter.
  532. //
  533. if(Params->TagFile) {
  534. l = lstrlen(q = pSetupGetFileTitle(Params->TagFile));
  535. if((l > 4) && !lstrcmpi((q+l)-4,TEXT(".cab"))) {
  536. *p++ = TEXT(';');
  537. p += wsprintf(p,q);
  538. } else {
  539. q = NULL;
  540. }
  541. } else {
  542. q = NULL;
  543. }
  544. //
  545. // Add final terminating nul
  546. //
  547. *(++p) = 0;
  548. MyParams.Filename1 = File;
  549. MyParams.Filename2 = CompressedFormName;
  550. MyParams.Filename3 = q;
  551. lstrcpyn(Path,File,MAX_PATH);
  552. InitialDir[0] = TEXT('\0');
  553. GetDlgItemText(hdlg,Params->ComboBoxId,InitialDir,MAX_PATH);
  554. InitialDir[MAX_PATH-1] = TEXT('\0');
  555. //
  556. // If the initial directory is on removable media, make sure that the media
  557. // is present prior to firing off the common dialog. Otherwise, the user
  558. // will a popup that the media isn't accessible.
  559. //
  560. DiskPromptGetDriveType(InitialDir,
  561. &InitialDirDriveType,
  562. &IsInitialDirOnRemovableDrive
  563. );
  564. if(IsInitialDirOnRemovableDrive) {
  565. //
  566. // We have a removable drive--make sure the media is present.
  567. // if it's not, we'll probably get ERROR_INVALID_DRIVE
  568. // if it is, we'll either succeed or get ERROR_FILE_NOT_FOUND
  569. //
  570. InitialDirMediaPresent = (FileExists(InitialDir, NULL) ||
  571. GetLastError() == ERROR_FILE_NOT_FOUND);
  572. } else {
  573. InitialDirMediaPresent = TRUE;
  574. }
  575. #ifdef ANSI_SETUPAPI
  576. ofn.lStructSize = sizeof(OPENFILENAME);
  577. #else
  578. ofn.lStructSize = GuiSetupInProgress
  579. ? OPENFILENAME_SIZE_VERSION_400
  580. : sizeof(OPENFILENAME);
  581. #endif
  582. ofn.hwndOwner = hdlg;
  583. ofn.hInstance = NULL;
  584. ofn.lpstrFilter = Filter;
  585. ofn.lpstrCustomFilter = NULL;
  586. ofn.nMaxCustFilter = 0;
  587. ofn.nFilterIndex = 1;
  588. ofn.lpstrFile = Path;
  589. ofn.nMaxFile = MAX_PATH;
  590. ofn.lpstrFileTitle = NULL;
  591. ofn.nMaxFileTitle = 0;
  592. ofn.lpstrInitialDir = InitialDirMediaPresent ? InitialDir : NULL;
  593. ofn.lpstrTitle = MyLoadString(IDS_LOCATEFILE);
  594. #ifdef ANSI_SETUPAPI
  595. ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_NOCHANGEDIR
  596. | OFN_PATHMUSTEXIST | OFN_EXPLORER;
  597. #else
  598. ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_NOCHANGEDIR | OFN_ENABLESIZING
  599. | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_FORCESHOWHIDDEN;
  600. #endif
  601. ofn.nFileOffset = 0;
  602. ofn.nFileExtension = 0;
  603. ofn.lpstrDefExt = NULL;
  604. ofn.lCustData = (LPARAM)&MyParams;
  605. ofn.lpfnHook = BrowseHookProc;
  606. ofn.lpTemplateName = NULL;
  607. found = GetOpenFileName(&ofn);
  608. if(ofn.lpstrTitle) {
  609. MyFree(ofn.lpstrTitle);
  610. }
  611. if(CompressedFormName) {
  612. MyFree(CompressedFormName);
  613. }
  614. UpdateWindow(hdlg);
  615. if(found) {
  616. //
  617. // Remove file part, put the resulting directory in the path field
  618. // This does not cause the string to be added to the combo box list.
  619. //
  620. if(ofn.nFileOffset<MAX_PATH) {
  621. Path[ofn.nFileOffset - 1] = TEXT('\0');
  622. } else {
  623. Path[MAX_PATH-1] = TEXT('\0');
  624. }
  625. SetDlgItemText(hdlg,Params->ComboBoxId,Path);
  626. return(TRUE);
  627. }
  628. return(FALSE);
  629. }
  630. PTSTR
  631. GetErrorDetails(
  632. IN PPROMPTPARAMS Params
  633. )
  634. /*++
  635. Routine Description:
  636. Display a message box with details about a file copy error.
  637. Arguments:
  638. Params - supplies file error dialog parameters.
  639. Return Value:
  640. None.
  641. --*/
  642. {
  643. PTSTR Message;
  644. TCHAR FullPath[MAX_PATH];
  645. PTSTR ErrorName;
  646. PTCHAR p;
  647. DWORD chars;
  648. PTSTR ShorterText = NULL;
  649. TCHAR TargetPath[MAX_PATH];
  650. //
  651. // Form full path name.
  652. //
  653. lstrcpyn(FullPath,Params->PathToSource,SIZECHARS(FullPath));
  654. pSetupConcatenatePaths(FullPath,Params->FileSought,MAX_PATH,NULL);
  655. //
  656. // try to make the path fit in our dialog
  657. //
  658. chars = ExtraChars(GetDlgItem(Params->hdlg,IDT_TEXT2),FullPath);
  659. if (chars) {
  660. ShorterText = CompactFileName(FullPath,chars);
  661. if (ShorterText) {
  662. lstrcpyn(FullPath, ShorterText,SIZECHARS(FullPath));
  663. MyFree(ShorterText);
  664. ShorterText = NULL;
  665. }
  666. }
  667. lstrcpyn(TargetPath, Params->TargetFile,SIZECHARS(TargetPath));
  668. chars = ExtraChars(GetDlgItem(Params->hdlg,IDT_TEXT2),Params->TargetFile);
  669. if (chars) {
  670. ShorterText = CompactFileName(Params->TargetFile,chars);
  671. if (ShorterText) {
  672. lstrcpyn(TargetPath, ShorterText,SIZECHARS(TargetPath));
  673. MyFree(ShorterText);
  674. ShorterText = NULL;
  675. }
  676. }
  677. //
  678. // Fetch error description. Remove trailing cr/lf if present.
  679. //
  680. ErrorName = RetreiveAndFormatMessage(Params->Win32Error);
  681. if(ErrorName) {
  682. p = ErrorName + lstrlen(ErrorName) - 1;
  683. while((p > ErrorName) && (*p <= TEXT(' '))) {
  684. *p-- = 0;
  685. }
  686. } else {
  687. return NULL;
  688. }
  689. Message = RetreiveAndFormatMessage(
  690. MSG_FILEERROR_DETAILS1,
  691. ErrorName,
  692. Params->Win32Error,
  693. FullPath,
  694. TargetPath
  695. );
  696. MyFree(ErrorName);
  697. return Message;
  698. }
  699. BOOL
  700. DoPresenceCheck(
  701. IN PPROMPTPARAMS Params,
  702. IN BOOL AllowConnectAs
  703. )
  704. /*++
  705. Routine Description:
  706. Check for the presence of a source file or source disk.
  707. If the source path is on removable media and a tag file is
  708. specified, we attempt to locate the tag file on the root of
  709. the drive specified by the source path.
  710. If the source path is not on removable media or a tag file
  711. is not specified, we look for the file (including compressed-form
  712. names) in the given path.
  713. Arguments:
  714. Params - supplies pointer to disk prompt dialog parameters.
  715. AllowConnectAs - supplies a boolean indicating whether or not this
  716. routine should give the user a "Connect as:" dialog if they've
  717. typed in a UNC path that they currently don't have access to.
  718. Return Value:
  719. TRUE if the disk/file is present and accessible. FALSE if not.
  720. --*/
  721. {
  722. BOOL b;
  723. TCHAR FileName[MAX_PATH];
  724. DWORD d;
  725. WIN32_FIND_DATA FindData;
  726. PTSTR p;
  727. //
  728. // If there's a tagfile then look for the tag file.
  729. // Otherwise look for the file in the target path -- note that the
  730. // file's name could be in compressed form.
  731. //
  732. if(Params->TagFile && !Params->UserBrowsed) {
  733. if(Params->IsRemovable) {
  734. //
  735. // Removable media. Look for tag at root.
  736. // If tag not found at root, look in actual directory.
  737. //
  738. MYASSERT(Params->PathToSource[0]);
  739. MYASSERT(Params->PathToSource[1] == TEXT(':'));
  740. lstrcpyn(FileName,Params->PathToSource,3);
  741. pSetupConcatenatePaths(FileName,Params->TagFile,MAX_PATH,NULL);
  742. b = FileExists(FileName,NULL);
  743. //
  744. // If we couldn't find the tagfile at the root and the path
  745. // is not for the root, look for the file in the path also.
  746. //
  747. // If we get here, we already know that PathToSource starts
  748. // with x:. We could have a path of the form x:\foo\bar
  749. // or x:foo\bar.
  750. //
  751. if(!b
  752. && Params->PathToSource[2]
  753. && !((Params->PathToSource[2] == TEXT('\\')) && !Params->PathToSource[3])) {
  754. lstrcpy(FileName,Params->PathToSource);
  755. pSetupConcatenatePaths(FileName,Params->TagFile,MAX_PATH,NULL);
  756. b = FileExists(FileName,NULL);
  757. }
  758. //
  759. // Additional check for removeable hard drives to allow winnt32
  760. // to work, because in that case there's no tagfiles!
  761. //
  762. if(Params->DriveType == DRIVE_FIXED) {
  763. goto check1;
  764. }
  765. } else {
  766. //
  767. // Fixed media. Look for tag in the path where the file
  768. // is being sought. If it's not found there, look for
  769. // the file itself. This logic makes cabinets work right.
  770. //
  771. lstrcpy(FileName,Params->PathToSource);
  772. pSetupConcatenatePaths(FileName,Params->TagFile,MAX_PATH,NULL);
  773. b = FileExists(FileName,NULL);
  774. if(!b && (Params->DriveType == DRIVE_REMOTE)) {
  775. d = GetLastError();
  776. if((d == ERROR_ACCESS_DENIED) || (d == ERROR_WRONG_PASSWORD) ||
  777. (d == ERROR_LOGON_FAILURE) || (d == ERROR_NOT_AUTHENTICATED) ||
  778. (d == ERROR_INVALID_PASSWORD) || (d == ERROR_BAD_NETPATH)) {
  779. //
  780. // If this is a network path, and we got 'access denied'-type of error,
  781. // then give the user "Connect As" dialog (if caller specified it's OK).
  782. //
  783. if(AllowConnectAs && ConnectToNetShare(FileName, Params->hdlg)) {
  784. //
  785. // We successfully connected to the network share--now try our
  786. // file existence check again.
  787. //
  788. b = FileExists(FileName,NULL);
  789. }
  790. }
  791. }
  792. check1:
  793. if(!b && lstrcmpi(Params->TagFile,Params->FileSought)) {
  794. //
  795. // We couldn't find the tagfile and the file we're seeking is
  796. // not the tagfile. So now we look for the file itself
  797. // in the path given to us. Note that the name of the file
  798. // could be the compressed form.
  799. //
  800. lstrcpy(FileName,Params->PathToSource);
  801. pSetupConcatenatePaths(FileName,Params->FileSought,MAX_PATH,NULL);
  802. d = SetupDetermineSourceFileName(FileName,&b,&p,&FindData);
  803. if(d == NO_ERROR) {
  804. MyFree(p);
  805. b = TRUE;
  806. } else {
  807. b = FALSE;
  808. }
  809. }
  810. }
  811. } else {
  812. lstrcpy(FileName,Params->PathToSource);
  813. pSetupConcatenatePaths(FileName,Params->FileSought,MAX_PATH,NULL);
  814. d = SetupDetermineSourceFileName(FileName,&b,&p,&FindData);
  815. if(Params->DriveType == DRIVE_REMOTE) {
  816. //
  817. // This is a network path. If we got an 'access denied'-type of error, then
  818. // give the user "Connect As" dialog (if caller specified it's OK).
  819. //
  820. if((d == ERROR_ACCESS_DENIED) || (d == ERROR_WRONG_PASSWORD) ||
  821. (d == ERROR_LOGON_FAILURE) || (d == ERROR_NOT_AUTHENTICATED) ||
  822. (d == ERROR_INVALID_PASSWORD) || (d == ERROR_BAD_NETPATH)) {
  823. if(AllowConnectAs && ConnectToNetShare(FileName, Params->hdlg)) {
  824. //
  825. // We successfully connected to the network share--now try to find
  826. // the source file again.
  827. //
  828. d = SetupDetermineSourceFileName(FileName,&b,&p,&FindData);
  829. }
  830. }
  831. }
  832. if(d == NO_ERROR) {
  833. MyFree(p);
  834. b = TRUE;
  835. } else {
  836. //
  837. // Make cabinet-based browse work by also looking for the tag file.
  838. // Note sleazy hack that matches a similar sleazy hack in DoBrowse(),
  839. // namely looking at extension to see if it's .cab.
  840. //
  841. b = FALSE;
  842. if(Params->TagFile) {
  843. d = lstrlen(Params->TagFile);
  844. if((d > 4) && !lstrcmpi((Params->TagFile+d)-4,TEXT(".cab"))) {
  845. lstrcpy(FileName,Params->PathToSource);
  846. pSetupConcatenatePaths(FileName,Params->TagFile,MAX_PATH,NULL);
  847. d = SetupDetermineSourceFileName(FileName,&b,&p,&FindData);
  848. if(b = (d == NO_ERROR)) {
  849. MyFree(p);
  850. }
  851. }
  852. }
  853. }
  854. }
  855. return(b);
  856. }
  857. void
  858. __cdecl
  859. AuxPromptThread(
  860. IN void *args
  861. )
  862. /*++
  863. Routine Description:
  864. Thread entry point to wrap DoPresenceCheck.
  865. Calls DoPresenceCheck and then posts a message to the prompt
  866. dialog indicating the outcome.
  867. Arguments:
  868. args - supplies file error dialog parameters.
  869. Return Value:
  870. None.
  871. --*/
  872. {
  873. PPROMPTPARAMS Params;
  874. BOOL b;
  875. HWND hwnd;
  876. Params = args;
  877. #if ASSERTS_ON
  878. //
  879. // Set a flag to indicate that our presence check thread is up and running.
  880. //
  881. MYASSERT(!Params->PresenceCheckThreadRunning);
  882. Params->PresenceCheckThreadRunning = TRUE;
  883. #endif // ASSERTS_ON
  884. hwnd = Params->hdlg;
  885. b = DoPresenceCheck(Params, TRUE);
  886. #if ASSERTS_ON
  887. //
  888. // The window had better not have gone away!
  889. //
  890. MYASSERT(IsWindow(hwnd));
  891. //
  892. // Now reset the flag to indicate that our presence check thread is
  893. // finished.
  894. //
  895. Params->PresenceCheckThreadRunning = FALSE;
  896. #endif // ASSERTS_ON
  897. //
  898. // Tell the dialog what we found.
  899. //
  900. PostMessage(hwnd, WMX_PRESENCE_RESULT, b, PRESENCE_RESULT_SIG);
  901. }
  902. VOID
  903. PresenceCheckSetControls(
  904. IN PPROMPTPARAMS Params,
  905. IN BOOL Starting
  906. )
  907. /*++
  908. Routine Description:
  909. Disable or re-enable various controls in the error/prompt dialog
  910. in preparation for or upon return from a file presence check.
  911. We do this because the presence check occurs in another thread,
  912. so the main dialog remains responsive. We don't want the user
  913. to click OK again while we're checking, etc.
  914. Arguments:
  915. Params - supplies file error/disk prompt dialog parameters.
  916. Starting - indicates whether we are preparing for a presence check
  917. (TRUE) or returning from one (FALSE).
  918. Return Value:
  919. None.
  920. --*/
  921. {
  922. #if ASSERTS_ON
  923. if(!Starting) {
  924. Params->ControlsDisabled = FALSE;
  925. }
  926. #endif // ASSERTS_ON
  927. EnableWindow(GetDlgItem(Params->hdlg,IDOK),!Starting);
  928. EnableWindow(GetDlgItem(Params->hdlg,IDCANCEL),!Starting);
  929. EnableWindow(GetDlgItem(Params->hdlg,Params->ComboBoxId),!Starting);
  930. EnableWindow(
  931. GetDlgItem(Params->hdlg,IDB_BROWSE),
  932. Starting ? FALSE : !(Params->PromptStyle & IDF_NOBROWSE)
  933. );
  934. #if ASSERTS_ON
  935. if(Starting) {
  936. Params->ControlsDisabled = TRUE;
  937. }
  938. #endif // ASSERTS_ON
  939. }
  940. BOOL
  941. StartPresenceCheck(
  942. IN PPROMPTPARAMS Params
  943. )
  944. /*++
  945. Routine Description:
  946. Perform a presence check, doing the real work asynchronously
  947. in another thread. See AuxPromptThread().
  948. Arguments:
  949. Params - supplies file error/disk prompt dialog parameters.
  950. Return Value:
  951. Boolean value indicating whether the check could be started.
  952. If FALSE, assume out of memory.
  953. --*/
  954. {
  955. //
  956. // need to disable controls so user can't do anything
  957. // while we're off performing the file presence check.
  958. //
  959. PresenceCheckSetControls(Params,TRUE);
  960. //
  961. // Make sure we don't already have a presence check going on...
  962. //
  963. MYASSERT(Params->PresenceCheckState == 0);
  964. //
  965. // Set flag in prompt params to indicate we're doing a presence check.
  966. //
  967. Params->PresenceCheckState = 1;
  968. return(_beginthread(AuxPromptThread,0,Params) != -1);
  969. }
  970. BOOL
  971. InitDiskPromptDialog(
  972. IN OUT PPROMPTPARAMS Params
  973. )
  974. /*++
  975. Routine Description:
  976. Initialize the disk prompt dialog. This involves hiding buttons
  977. and other control, and setting up static text controls, based on the
  978. prompt style specified by the caller.
  979. Arguments:
  980. Params - supplies parameters for the disk prompting
  981. Return Value:
  982. TRUE if success; FALSE if out of memory.
  983. --*/
  984. {
  985. int i;
  986. PTCHAR p,q;
  987. BOOL b;
  988. UINT IconId;
  989. HICON hIcon;
  990. HWND ComboBox;
  991. UINT ComboBoxId;
  992. HWND OtherComboBox;
  993. //
  994. // Remember parameter list
  995. //
  996. if(!SetProp(Params->hdlg,pszDiskPromptPropName,(HANDLE)Params)) {
  997. return(FALSE);
  998. }
  999. if(!SetWindowText(Params->hdlg,Params->DialogTitle)) {
  1000. return(FALSE);
  1001. }
  1002. //
  1003. // Figure out which combo box to use. This depends on whether
  1004. // we're supposed to have an editable mru.
  1005. //
  1006. ComboBoxId = Params->ReadOnlyMru ? IDC_COMBO2 : IDC_COMBO1;
  1007. ComboBox = GetDlgItem(Params->hdlg,ComboBoxId);
  1008. OtherComboBox = GetDlgItem(Params->hdlg,Params->ReadOnlyMru ? IDC_COMBO1 : IDC_COMBO2);
  1009. Params->ComboBoxId = ComboBoxId;
  1010. ShowWindow(OtherComboBox,SW_HIDE);
  1011. EnableWindow(OtherComboBox,FALSE);
  1012. //
  1013. // Set up combo box title.
  1014. //
  1015. p = MyLoadString((Params->PromptStyle & IDF_OEMDISK) ? IDS_COPYFROMOEM : IDS_COPYFROM);
  1016. if(!p) {
  1017. return(FALSE);
  1018. }
  1019. b = SetDlgItemText(Params->hdlg,IDT_TITLE1,p);
  1020. MyFree(p);
  1021. if(!b) {
  1022. return(FALSE);
  1023. }
  1024. //
  1025. // Set up the combo box.
  1026. //
  1027. for(i=0; i<(int)Params->PathCount; i++) {
  1028. if(SendMessage(ComboBox,CB_ADDSTRING,0,(LPARAM)Params->PathList[i]) < 0) {
  1029. return(FALSE);
  1030. }
  1031. }
  1032. SendMessage(ComboBox,CB_LIMITTEXT,MAX_PATH,0);
  1033. if(Params->ReadOnlyMru) {
  1034. //
  1035. // Select the first string in the list.
  1036. //
  1037. SendMessage(ComboBox,CB_SETCURSEL,0,0);
  1038. } else {
  1039. //
  1040. // Set text of combo box to the path we're searching along.
  1041. // This does not cause the string to be added to the combo box list.
  1042. //
  1043. if(!SetDlgItemText(Params->hdlg,ComboBoxId,Params->PathToSource)) {
  1044. return(FALSE);
  1045. }
  1046. #ifdef UNICODE
  1047. if(Params->BrowseAutoComplete) {
  1048. SHAutoComplete(GetWindow(ComboBox, GW_CHILD), SHACF_FILESYS_DIRS);
  1049. }
  1050. #endif
  1051. }
  1052. //
  1053. // Hide buttons if necessary.
  1054. //
  1055. if(Params->PromptStyle & IDF_NOBROWSE) {
  1056. ShowWindow(GetDlgItem(Params->hdlg,IDB_BROWSE),SW_HIDE);
  1057. EnableWindow(GetDlgItem(Params->hdlg,IDB_BROWSE),FALSE);
  1058. }
  1059. //
  1060. // Set icon.
  1061. //
  1062. if(Params->DialogType == DLGTYPE_ERROR) {
  1063. hIcon = LoadIcon(NULL,IDI_HAND);
  1064. } else {
  1065. switch(Params->DriveType) {
  1066. case DRIVE_REMOTE:
  1067. IconId = ICON_NETWORK;
  1068. break;
  1069. case DRIVE_CDROM:
  1070. IconId = ICON_CD;
  1071. break;
  1072. case DRIVE_FIXED:
  1073. IconId = ICON_HARD;
  1074. break;
  1075. case DRIVE_REMOVABLE:
  1076. default:
  1077. IconId = ICON_FLOPPY;
  1078. break;
  1079. }
  1080. hIcon = LoadIcon(MyDllModuleHandle,MAKEINTRESOURCE(IconId));
  1081. }
  1082. if(hIcon) {
  1083. SendDlgItemMessage(Params->hdlg,IDI_ICON1,STM_SETICON,(WPARAM)hIcon,0);
  1084. }
  1085. return(TRUE);
  1086. }
  1087. BOOL
  1088. SetDiskPromptDialogText(
  1089. IN OUT PPROMPTPARAMS Params
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. Set up static text fields that explain to the user what is requested
  1094. and what he has to do to continue. These fields depend on whether we're
  1095. prompting for an oem disk, whether the file is on removable media, and
  1096. whether a tag file has been specified.
  1097. Arguments:
  1098. Params - supplies parameters for the disk prompting
  1099. Return Value:
  1100. TRUE if success; FALSE if out of memory.
  1101. --*/
  1102. {
  1103. BOOL b;
  1104. PTSTR p;
  1105. if(Params->DialogType == DLGTYPE_PROMPT) {
  1106. //
  1107. // There are 2 text fields - the explanation and action.
  1108. // What the text looks like depends on the prompt style flags,
  1109. // whether the file is on removable media, etc.
  1110. //
  1111. // First handle the explanation text.
  1112. //
  1113. if (Params->PromptStyle & IDF_USEDISKNAMEASPROMPT) {
  1114. b = SetDlgItemText(Params->hdlg,IDT_TEXT1,Params->DiskName);
  1115. } else {
  1116. if(Params->PromptStyle & IDF_OEMDISK) {
  1117. p = MyLoadString(IDS_DISKPROMPTOEM);
  1118. } else {
  1119. if(Params->IsRemovable && Params->TagFile) {
  1120. p = FormatStringMessage(IDS_DISKPROMPT1,Params->DiskName);
  1121. } else {
  1122. p = FormatStringMessage(IDS_DISKPROMPT2,Params->FileSought,Params->DiskName);
  1123. }
  1124. }
  1125. if(!p) {
  1126. return(FALSE);
  1127. }
  1128. b = SetDlgItemText(Params->hdlg,IDT_TEXT1,p);
  1129. MyFree(p);
  1130. }
  1131. if(!b) {
  1132. return(FALSE);
  1133. }
  1134. //
  1135. // Now handle the explanation text. This is hidden for oem disks.
  1136. //
  1137. if(Params->PromptStyle & IDF_OEMDISK) {
  1138. ShowWindow(GetDlgItem(Params->hdlg,IDT_TEXT2),SW_HIDE);
  1139. EnableWindow(GetDlgItem(Params->hdlg,IDT_TEXT2),FALSE);
  1140. } else {
  1141. if(Params->IsRemovable && Params->TagFile) {
  1142. p = FormatStringMessage(IDS_PROMPTACTION1,Params->DiskName);
  1143. } else {
  1144. p = MyLoadString(IDS_PROMPTACTION2);
  1145. }
  1146. if(!p) {
  1147. return(FALSE);
  1148. }
  1149. b = SetDlgItemText(Params->hdlg,IDT_TEXT2,p);
  1150. MyFree(p);
  1151. if(!b) {
  1152. return(FALSE);
  1153. }
  1154. }
  1155. } else {
  1156. if(Params->DialogType != DLGTYPE_ERROR) {
  1157. return(FALSE);
  1158. }
  1159. p = MyLoadString(IDS_RETRY);
  1160. if (!p) {
  1161. return(FALSE);
  1162. }
  1163. b = SetDlgItemText(Params->hdlg,IDOK,p);
  1164. MyFree(p);
  1165. if (!b) {
  1166. return(FALSE);
  1167. }
  1168. //
  1169. // Explanation text -- "An error occurred copying a file" etc.
  1170. //
  1171. p = FormatStringMessage(IDS_FILEERRCOPY,Params->FileSought);
  1172. if(!p) {
  1173. return(FALSE);
  1174. }
  1175. b = SetDlgItemText(Params->hdlg,IDT_TEXT1,p);
  1176. MyFree(p);
  1177. if(!b) {
  1178. return(FALSE);
  1179. }
  1180. //
  1181. // Action text.
  1182. //
  1183. if (Params->Win32Error != ERROR_DIRECTORY &&
  1184. Params->Win32Error != ERROR_DISK_FULL) {
  1185. if(Params->PromptStyle & IDF_OEMDISK) {
  1186. p = MyLoadString(IDS_COPYERROROEM);
  1187. } else {
  1188. if(Params->IsRemovable) {
  1189. p = FormatStringMessage(IDS_COPYERROR1,Params->DiskName);
  1190. } else {
  1191. p = FormatStringMessage(IDS_COPYERROR2,Params->DiskName);
  1192. }
  1193. }
  1194. } else {
  1195. p = GetErrorDetails(Params);
  1196. }
  1197. if(!p) {
  1198. return(FALSE);
  1199. }
  1200. b = SetDlgItemText(Params->hdlg,IDT_TEXT2,p);
  1201. MyFree(p);
  1202. if(!b) {
  1203. return(FALSE);
  1204. }
  1205. }
  1206. return(TRUE);
  1207. }
  1208. BOOL
  1209. WarnSkip(
  1210. IN HWND hwnd,
  1211. IN BOOL Skip
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. Warn the user that skipping the file or cancelling
  1216. can tank the system.
  1217. Arguments:
  1218. hwnd - supplies window handle for window to own the message box
  1219. this routine will display.
  1220. Skip - if TRUE, user is trying to skip the file; FALSE means
  1221. he is trying to cancel.
  1222. Return Value:
  1223. TRUE if user wants to skip file/cancel; false otherwise.
  1224. --*/
  1225. {
  1226. PCTSTR Caption;
  1227. PCTSTR Message;
  1228. BOOL b;
  1229. b = TRUE;
  1230. if(Caption = MyLoadString(IDS_WARNING)) {
  1231. if(Message = MyLoadString(Skip ? IDS_SURESKIP : IDS_SURECANCEL)) {
  1232. b = (MessageBox(hwnd,Message,Caption,MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) == IDYES);
  1233. MyFree(Message);
  1234. }
  1235. MyFree(Caption);
  1236. }
  1237. return(b);
  1238. }
  1239. BOOL
  1240. CancelAllCopies(
  1241. IN HWND hwnd
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. ask the user if they want to cancel copying one file or all files
  1246. Arguments:
  1247. hwnd - supplies window handle for window to own the message box
  1248. this routine will display.
  1249. Return Value:
  1250. TRUE if user wants to cancel just this copy (really the same as skipping a file)
  1251. FALSE if user wants to cancel all copies;
  1252. --*/
  1253. {
  1254. PCTSTR Caption;
  1255. PCTSTR Message;
  1256. BOOL b;
  1257. b = TRUE;
  1258. if(Caption = MyLoadString(IDS_COPYERROR)) {
  1259. if(Message = MyLoadString(IDS_CANCELALL)) {
  1260. b = (MessageBox(hwnd,Message,Caption,MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) == IDYES);
  1261. MyFree(Message);
  1262. }
  1263. MyFree(Caption);
  1264. }
  1265. return(b);
  1266. }
  1267. INT_PTR
  1268. DlgProcSimplePrompt(
  1269. IN HWND hdlg,
  1270. IN UINT msg,
  1271. IN WPARAM wParam,
  1272. IN LPARAM lParam
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. Dialog procedure for disk prompting dialog.
  1277. The return value for the dialog is
  1278. DPROMPT_CANCEL - user cancelled
  1279. DPROMPT_SKIPFILE - user elected to skip file
  1280. DPROMPT_SUCCESS - disk is in the drive/we found the file we're looking for
  1281. DPROMPT_OUTOFMEMORY - out of memory
  1282. Arguments:
  1283. Standard dialog routine parameters.
  1284. Return Value:
  1285. TRUE if message processed; FALSE if not.
  1286. --*/
  1287. {
  1288. BOOL b = FALSE;
  1289. TCHAR Text[MAX_PATH];
  1290. PPROMPTPARAMS PromptParams;
  1291. BOOL WarnIfSkip;
  1292. BOOL ReallyCancel;
  1293. HICON hIcon;
  1294. static DWORD UnitMask = 0xFFFFFFFF;
  1295. switch(msg) {
  1296. case WM_INITDIALOG:
  1297. PromptParams = (PPROMPTPARAMS)lParam;
  1298. MYASSERT(PromptParams != NULL);
  1299. if(!SetProp(hdlg,pszDiskPromptPropName,(HANDLE)&(PromptParams->MsgBoxParams))) {
  1300. EndDialog(hdlg,DPROMPT_OUTOFMEMORY);
  1301. break;
  1302. }
  1303. if(!SetWindowText(hdlg,PromptParams->MsgBoxParams.lpszCaption)) {
  1304. EndDialog(hdlg,DPROMPT_OUTOFMEMORY);
  1305. break;
  1306. }
  1307. if(!SetWindowText(hdlg,PromptParams->MsgBoxParams.lpszCaption)) {
  1308. EndDialog(hdlg,DPROMPT_OUTOFMEMORY);
  1309. break;
  1310. }
  1311. if (!SetDlgItemText(hdlg,IDT_TEXT1,PromptParams->MsgBoxParams.lpszText)) {
  1312. EndDialog(hdlg,DPROMPT_OUTOFMEMORY);
  1313. break;
  1314. }
  1315. hIcon = LoadIcon(MyDllModuleHandle,PromptParams->MsgBoxParams.lpszIcon);
  1316. if(hIcon) {
  1317. SendDlgItemMessage(hdlg,IDI_ICON1,STM_SETICON,(WPARAM)hIcon,0);
  1318. }
  1319. pSetupCenterWindowRelativeToParent(hdlg);
  1320. if ((PromptParams->PathToSource[0] != TEXT('\0')) &&
  1321. _istalpha(PromptParams->PathToSource[0])) {
  1322. UnitMask = (1 << (_toupper(PromptParams->PathToSource[0]) - TEXT('A')));
  1323. }
  1324. b = FALSE;
  1325. break;
  1326. case WM_DEVICECHANGE:
  1327. if ((wParam == DBT_DEVICEARRIVAL) &&
  1328. (((PDEV_BROADCAST_VOLUME)lParam)->dbcv_devicetype == DBT_DEVTYP_VOLUME) &&
  1329. (((PDEV_BROADCAST_VOLUME)lParam)->dbcv_flags & DBTF_MEDIA) &&
  1330. (((PDEV_BROADCAST_VOLUME)lParam)->dbcv_unitmask == UnitMask)) {
  1331. //
  1332. // The user inserted a CD or removable media into the source drive,
  1333. // so do an automatic OK so we can check this new media.
  1334. //
  1335. PostMessage(hdlg, WM_COMMAND, MAKELPARAM(IDOK, BN_CLICKED), 0L);
  1336. }
  1337. break;
  1338. case WM_COMMAND:
  1339. if(HIWORD(wParam) == BN_CLICKED) {
  1340. b = TRUE;
  1341. EndDialog(hdlg,LOWORD(wParam));
  1342. break;
  1343. } else {
  1344. b = FALSE;
  1345. }
  1346. break;
  1347. case WM_DESTROY:
  1348. //
  1349. // Nothing to do about this if it fails.
  1350. // Note: the return value is typically a pointer to stack data
  1351. //
  1352. RemoveProp(hdlg,pszDiskPromptPropName);
  1353. //
  1354. // Let default processing take place by indicating that
  1355. // we didn't process this message
  1356. //
  1357. b = FALSE;
  1358. break;
  1359. default:
  1360. if (!g_uQueryCancelAutoPlay) {
  1361. g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  1362. }
  1363. if (msg == g_uQueryCancelAutoPlay) {
  1364. SetWindowLongPtr( hdlg, DWLP_MSGRESULT, 1 );
  1365. return 1; // cancel auto-play
  1366. }
  1367. b = FALSE;
  1368. break;
  1369. }
  1370. return(b);
  1371. }
  1372. INT_PTR
  1373. DlgProcDiskPrompt1(
  1374. IN HWND hdlg,
  1375. IN UINT msg,
  1376. IN WPARAM wParam,
  1377. IN LPARAM lParam
  1378. )
  1379. /*++
  1380. Routine Description:
  1381. Dialog procedure for disk prompting dialog.
  1382. The return value for the dialog is
  1383. DPROMPT_CANCEL - user cancelled
  1384. DPROMPT_SKIPFILE - user elected to skip file
  1385. DPROMPT_SUCCESS - disk is in the drive/we found the file we're looking for
  1386. DPROMPT_OUTOFMEMORY - out of memory
  1387. Arguments:
  1388. Standard dialog routine parameters.
  1389. Return Value:
  1390. TRUE if message processed; FALSE if not.
  1391. --*/
  1392. {
  1393. BOOL b = FALSE;
  1394. PPROMPTPARAMS PromptParams;
  1395. TCHAR Text[MAX_PATH];
  1396. BOOL WarnIfSkip;
  1397. BOOL ReallyCancel;
  1398. static DWORD UnitMask = 0xFFFFFFFF;
  1399. switch(msg) {
  1400. case WM_INITDIALOG:
  1401. PromptParams = (PPROMPTPARAMS)lParam;
  1402. MYASSERT( PromptParams != NULL );
  1403. PromptParams->hdlg = hdlg;
  1404. //
  1405. // Initialize the dialog.
  1406. //
  1407. if(InitDiskPromptDialog(PromptParams) && SetDiskPromptDialogText(PromptParams)) {
  1408. //
  1409. // Set focus to directory combobox and continue.
  1410. //
  1411. SetFocus(GetDlgItem(hdlg, PromptParams->ReadOnlyMru ? IDC_COMBO2 : IDC_COMBO1));
  1412. } else {
  1413. //
  1414. // Out of memory.
  1415. //
  1416. b = TRUE;
  1417. EndDialog(hdlg,DPROMPT_OUTOFMEMORY);
  1418. break;
  1419. }
  1420. //
  1421. // Indicate to windows that we set the focus.
  1422. //
  1423. b = FALSE;
  1424. if(!(PromptParams->PromptStyle & IDF_NOBEEP)) {
  1425. MessageBeep(MB_ICONASTERISK);
  1426. }
  1427. if ((PromptParams->PathToSource[0] != TEXT('\0')) &&
  1428. _istalpha(PromptParams->PathToSource[0])) {
  1429. UnitMask = (1 << (_toupper(PromptParams->PathToSource[0]) - TEXT('A')));
  1430. }
  1431. pSetupCenterWindowRelativeToParent(hdlg);
  1432. PostMessage(hdlg,WMX_HELLO,0,0);
  1433. break;
  1434. case WMX_HELLO:
  1435. b = TRUE;
  1436. PromptParams = (PPROMPTPARAMS)GetProp(hdlg,pszDiskPromptPropName);
  1437. MYASSERT(PromptParams != NULL);
  1438. if(PromptParams && !(PromptParams->PromptStyle & IDF_NOFOREGROUND)) {
  1439. SetForegroundWindow(hdlg);
  1440. }
  1441. break;
  1442. case WM_DEVICECHANGE:
  1443. if ((wParam == DBT_DEVICEARRIVAL) &&
  1444. (((PDEV_BROADCAST_VOLUME)lParam)->dbcv_devicetype == DBT_DEVTYP_VOLUME) &&
  1445. (((PDEV_BROADCAST_VOLUME)lParam)->dbcv_flags & DBTF_MEDIA) &&
  1446. (((PDEV_BROADCAST_VOLUME)lParam)->dbcv_unitmask == UnitMask)) {
  1447. //
  1448. // The user inserted a CD or removable media into the source drive,
  1449. // so do an automatic OK so we can check this new media.
  1450. //
  1451. PostMessage(hdlg, WM_COMMAND, MAKELPARAM(IDOK, BN_CLICKED), 0L);
  1452. }
  1453. break;
  1454. case WM_COMMAND:
  1455. if(HIWORD(wParam) == BN_CLICKED) {
  1456. PromptParams = (PPROMPTPARAMS)GetProp(hdlg,pszDiskPromptPropName);
  1457. MYASSERT(PromptParams != NULL);
  1458. WarnIfSkip = (PromptParams && (PromptParams->PromptStyle & IDF_WARNIFSKIP));
  1459. b = TRUE;
  1460. switch(LOWORD(wParam)) {
  1461. case IDOK:
  1462. //
  1463. // We'd better not get here if controls are disabled!
  1464. //
  1465. MYASSERT(!PromptParams->ControlsDisabled);
  1466. //
  1467. // User might have changed the source path.
  1468. // Get the current path from the combo's edit control
  1469. //
  1470. Text[0] = TEXT('\0'); // default value
  1471. GetDlgItemText(hdlg,PromptParams->ComboBoxId,Text,SIZECHARS(Text));
  1472. Text[SIZECHARS(Text)-1] = TEXT('\0'); // make sure it's terminated.
  1473. MyFree(PromptParams->PathToSource);
  1474. PromptParams->PathToSource = DuplicateString(Text);
  1475. DiskPromptGetDriveType(Text,&PromptParams->DriveType,&PromptParams->IsRemovable);
  1476. //
  1477. // See whether we can get at the file.
  1478. //
  1479. if(!PromptParams->PathToSource || !StartPresenceCheck(PromptParams)) {
  1480. EndDialog(hdlg,DPROMPT_OUTOFMEMORY);
  1481. }
  1482. break;
  1483. case IDCANCEL:
  1484. //
  1485. // We'd better not get here if controls are disabled!
  1486. //
  1487. MYASSERT(!PromptParams->ControlsDisabled);
  1488. //
  1489. // ask if they want to cancel all copies or just cancel one copy
  1490. //
  1491. if (PromptParams->DialogType != DLGTYPE_ERROR) {
  1492. ReallyCancel = TRUE;
  1493. } else {
  1494. if (PromptParams->PromptStyle & IDF_NOSKIP) {
  1495. ReallyCancel = TRUE;
  1496. } else {
  1497. ReallyCancel = !CancelAllCopies(hdlg);
  1498. }
  1499. }
  1500. if(WarnIfSkip ? WarnSkip(hdlg,!ReallyCancel) : TRUE) {
  1501. //
  1502. // If we're currently doing a file presence check, then
  1503. // just increment our PresenceCheckState value, and defer
  1504. // the EndDialog until receipt of WMX_PRESENCE_RESULT.
  1505. //
  1506. if (ReallyCancel) {
  1507. if(PromptParams->PresenceCheckState == 0) {
  1508. EndDialog(hdlg,DPROMPT_CANCEL);
  1509. } else {
  1510. (PromptParams->PresenceCheckState)++;
  1511. }
  1512. } else {
  1513. EndDialog(hdlg,DPROMPT_SKIPFILE);
  1514. }
  1515. }
  1516. break;
  1517. case IDB_BROWSE:
  1518. //
  1519. // We'd better not get here if controls are disabled!
  1520. //
  1521. MYASSERT(!PromptParams->ControlsDisabled);
  1522. if(DoBrowse(hdlg,PromptParams)) {
  1523. PromptParams->UserBrowsed = TRUE;
  1524. }
  1525. break;
  1526. default:
  1527. b = FALSE;
  1528. break;
  1529. }
  1530. } else {
  1531. b = FALSE;
  1532. }
  1533. break;
  1534. case WM_DESTROY:
  1535. #if ASSERTS_ON
  1536. //
  1537. // We'd better not have an outstanding presence check thread running!
  1538. //
  1539. PromptParams = (PPROMPTPARAMS)GetProp(hdlg, pszDiskPromptPropName);
  1540. MYASSERT(PromptParams != NULL);
  1541. if(PromptParams) {
  1542. MYASSERT(!PromptParams->PresenceCheckThreadRunning);
  1543. }
  1544. #endif // ASSERTS_ON
  1545. //
  1546. // Nothing to do about this if it fails.
  1547. //
  1548. RemoveProp(hdlg,pszDiskPromptPropName);
  1549. //
  1550. // Let default processing take place by indicating that
  1551. // we didn't process this message
  1552. //
  1553. b = FALSE;
  1554. break;
  1555. case WMX_PRESENCE_RESULT:
  1556. //
  1557. // Make sure this message came from AuxPromptThread--we've seen weird
  1558. // stress failures indicating that someone else was sending us this
  1559. // message from time to time.
  1560. //
  1561. MYASSERT(lParam == PRESENCE_RESULT_SIG);
  1562. //
  1563. // In case the above does happen, just ignore this message...
  1564. //
  1565. if(lParam != PRESENCE_RESULT_SIG) {
  1566. b = FALSE;
  1567. break;
  1568. }
  1569. b = TRUE;
  1570. PromptParams = (PPROMPTPARAMS)GetProp(hdlg,pszDiskPromptPropName);
  1571. //
  1572. // Also, we don't expect to get this message unless we actually had a
  1573. // presence check thread running.
  1574. //
  1575. MYASSERT(PromptParams != NULL);
  1576. MYASSERT(PromptParams->PresenceCheckState);
  1577. //
  1578. // If the user pressed cancel while we were off doing our presence
  1579. // check, then honor that request now.
  1580. //
  1581. if(PromptParams->PresenceCheckState > 1) {
  1582. EndDialog(hdlg, DPROMPT_CANCEL);
  1583. }
  1584. //
  1585. // Aux thread is telling us that it knows whether the file is present.
  1586. // wParam has the boolean.
  1587. // PromptParams->PathToSource is already set.
  1588. //
  1589. if(wParam) {
  1590. EndDialog(hdlg,DPROMPT_SUCCESS);
  1591. } else {
  1592. //
  1593. // File/disk is not accessible. Don't end the dialog.
  1594. //
  1595. if(!(PromptParams->PromptStyle & IDF_NOFOREGROUND)) {
  1596. SetForegroundWindow(hdlg);
  1597. }
  1598. //
  1599. // If we're searching for a directory containing INFs (e.g.,
  1600. // SetupDiSelectOEMDrv), then we want to popup a message informing
  1601. // the user that the location they've specified doesn't contain
  1602. // information about their hardware. Otherwise, we want to maintain
  1603. // the file prompt behavior of just beeping.
  1604. //
  1605. if(lstrcmpi(PromptParams->FileSought, pszInfWildcard)) {
  1606. if(!(PromptParams->PromptStyle & IDF_NOBEEP)) {
  1607. MessageBeep(MB_ICONASTERISK);
  1608. }
  1609. } else {
  1610. if(!LoadString(MyDllModuleHandle,
  1611. IDS_SELECT_DEVICE,
  1612. Text,
  1613. SIZECHARS(Text))) {
  1614. *Text = TEXT('\0');
  1615. }
  1616. FormatMessageBox(MyDllModuleHandle,
  1617. NULL,
  1618. MSG_NO_DEVICEINFO_ERROR,
  1619. Text,
  1620. MB_OK | MB_TASKMODAL
  1621. );
  1622. }
  1623. //
  1624. // Reset value indicating we're no longer doing a presence check.
  1625. //
  1626. PromptParams->PresenceCheckState = 0;
  1627. //
  1628. // Restore controls that were disabled when we started the presence check.
  1629. //
  1630. PresenceCheckSetControls(PromptParams,FALSE);
  1631. SetFocus(GetDlgItem(hdlg,PromptParams->ComboBoxId));
  1632. }
  1633. break;
  1634. default:
  1635. if (!g_uQueryCancelAutoPlay) {
  1636. g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  1637. }
  1638. if (msg == g_uQueryCancelAutoPlay) {
  1639. SetWindowLongPtr( hdlg, DWLP_MSGRESULT, 1 );
  1640. return 1; // cancel auto-play
  1641. }
  1642. b = FALSE;
  1643. break;
  1644. }
  1645. return(b);
  1646. }
  1647. VOID
  1648. ModifyPathList(
  1649. IN PPROMPTPARAMS Params
  1650. )
  1651. /*++
  1652. Routine Description:
  1653. Modifies a list of installation paths kept in the registry.
  1654. The existing list is scanned for the path the user accepted in the disk
  1655. prompt dialog. That path is added if not already in the list.
  1656. Arguments:
  1657. Params - supplies disk prompt dialog parameters.
  1658. Return Value:
  1659. None. If any part of the operation, the list simply doesn't get updated
  1660. in the registry.
  1661. --*/
  1662. {
  1663. //
  1664. // Params->PathToSource will be the final path entered by the user
  1665. // in the combo box. Add to list. If this fails, oh well.
  1666. //
  1667. SetupAddToSourceList(SRCLIST_SYSIFADMIN,Params->PathToSource);
  1668. }
  1669. UINT
  1670. _SetupPromptForDisk(
  1671. IN HWND hwndParent,
  1672. IN PCTSTR DialogTitle, OPTIONAL
  1673. IN PCTSTR DiskName, OPTIONAL
  1674. IN PCTSTR PathToSource, OPTIONAL
  1675. IN PCTSTR FileSought,
  1676. IN PCTSTR TagFile, OPTIONAL
  1677. IN DWORD DiskPromptStyle,
  1678. OUT PTSTR PathBuffer,
  1679. IN DWORD PathBufferSize,
  1680. OUT PDWORD PathRequiredSize OPTIONAL
  1681. )
  1682. {
  1683. PROMPTPARAMS Params;
  1684. INT_PTR i;
  1685. TCHAR Buffer[256];
  1686. DWORD d;
  1687. DWORD ResultPathLen;
  1688. PTSTR Message;
  1689. HANDLE hDialogEvent = NULL;
  1690. BOOL PromptUser = FALSE;
  1691. //
  1692. // If we're running non-interactive, bail now. Unless, that is, we've been
  1693. // instructed to check for the presence of the source file _before_ doing
  1694. // any UI, in which case we can hang around until we do our presence check
  1695. // down below.
  1696. //
  1697. if((GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP)) &&
  1698. !(DiskPromptStyle & IDF_CHECKFIRST)) {
  1699. SetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
  1700. return DPROMPT_CANCEL;
  1701. }
  1702. //
  1703. // It is illegal to specify both the IDF_USEDISKNAMEASPROMPT and the
  1704. // IDF_OEMDISK flag. This is due to the fact that they both cause
  1705. // a different style of UI text to be displayed that would conflict
  1706. // with itself.
  1707. //
  1708. if ((DiskPromptStyle & IDF_USEDISKNAMEASPROMPT) &&
  1709. (DiskPromptStyle & IDF_OEMDISK)) {
  1710. SetLastError(ERROR_INVALID_PARAMETER);
  1711. return DPROMPT_CANCEL;
  1712. }
  1713. ZeroMemory(&Params,sizeof(PROMPTPARAMS));
  1714. //
  1715. // Determine the path to the source. Start by fetching the entire
  1716. // installation locations list for the current user.
  1717. //
  1718. d = pSetupGetList(0,&Params.PathList,&Params.PathCount,&Params.ReadOnlyMru);
  1719. if(d != NO_ERROR) {
  1720. i = DPROMPT_OUTOFMEMORY;
  1721. goto c0;
  1722. }
  1723. if(PathToSource) {
  1724. //
  1725. // Code in dialog box relies on being able to free this
  1726. // so duplicate it here.
  1727. //
  1728. Params.PathToSource = DuplicateString(PathToSource);
  1729. } else {
  1730. if(Params.PathCount) {
  1731. Params.PathToSource = DuplicateString(Params.PathList[0]);
  1732. } else {
  1733. //
  1734. // Nothing in system path lists. Use a reasonable default.
  1735. //
  1736. Params.PathToSource = DuplicateString(pszOemInfDefaultPath);
  1737. }
  1738. }
  1739. if(!Params.PathToSource) {
  1740. i = DPROMPT_OUTOFMEMORY;
  1741. d = ERROR_NOT_ENOUGH_MEMORY;
  1742. goto c1;
  1743. }
  1744. //
  1745. // Determine the drive type of the source path.
  1746. //
  1747. DiskPromptGetDriveType(Params.PathToSource,&Params.DriveType,&Params.IsRemovable);
  1748. //
  1749. // If the disk name wasn't specified, fetch a default.
  1750. //
  1751. if(DiskName) {
  1752. Params.DiskName = DiskName;
  1753. } else {
  1754. Params.DiskName = MyLoadString(IDS_UNKNOWN_PARENS);
  1755. if(!Params.DiskName) {
  1756. i = DPROMPT_OUTOFMEMORY;
  1757. d = ERROR_NOT_ENOUGH_MEMORY;
  1758. goto c2;
  1759. }
  1760. }
  1761. //
  1762. // If a dialog title wasn't specified, try to get text from parent window.
  1763. //
  1764. if(DialogTitle) {
  1765. Params.DialogTitle = DialogTitle;
  1766. } else {
  1767. if(Params.Owner
  1768. && (i = GetWindowTextLength(Params.Owner))
  1769. && GetWindowText(Params.Owner,Buffer,sizeof(Buffer)/sizeof(TCHAR))) {
  1770. Params.DialogTitle = FormatStringMessage(IDS_FILESNEEDED2,Buffer);
  1771. } else {
  1772. Params.DialogTitle = MyLoadString(IDS_FILESNEEDED);
  1773. }
  1774. if(!Params.DialogTitle) {
  1775. i = DPROMPT_OUTOFMEMORY;
  1776. d = ERROR_NOT_ENOUGH_MEMORY;
  1777. goto c3;
  1778. }
  1779. }
  1780. Params.TagFile = TagFile;
  1781. //
  1782. // Validate parent window.
  1783. //
  1784. Params.Owner = IsWindow(hwndParent) ? hwndParent : NULL;
  1785. //
  1786. // Fill in other fields.
  1787. //
  1788. if((Params.FileSought = FileSought) == NULL) {
  1789. i = DPROMPT_CANCEL;
  1790. d = ERROR_INVALID_PARAMETER;
  1791. goto c4;
  1792. }
  1793. Params.Owner = hwndParent;
  1794. Params.PromptStyle = DiskPromptStyle | IDF_NODETAILS;
  1795. Params.hdlg = NULL;
  1796. Params.UserBrowsed = FALSE;
  1797. Params.DialogType = DLGTYPE_PROMPT;
  1798. Params.TargetFile = NULL;
  1799. if(Params.ReadOnlyMru) {
  1800. Params.PromptStyle |= IDF_NOBROWSE;
  1801. }
  1802. if (GuiSetupInProgress) {
  1803. hDialogEvent = CreateEvent(NULL,TRUE,FALSE,SETUP_HAS_OPEN_DIALOG_EVENT);
  1804. }
  1805. //
  1806. // If we're supposed to, check for the disk/file first.
  1807. //
  1808. if((DiskPromptStyle & IDF_CHECKFIRST) && DoPresenceCheck(&Params, FALSE)) {
  1809. i = DPROMPT_SUCCESS;
  1810. d = NO_ERROR;
  1811. } else if(GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP)) {
  1812. i = DPROMPT_CANCEL;
  1813. d = ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION;
  1814. } else {
  1815. //
  1816. // Before invoking the dialog, we will prompt the user with a simple
  1817. // message box in some cases to avoid the user ever actually seeing
  1818. // a path in the more complicated prompt dialog.
  1819. //
  1820. if(DiskName &&
  1821. !(DiskPromptStyle & IDF_NOREMOVABLEMEDIAPROMPT) &&
  1822. ((Params.DriveType == DRIVE_REMOVABLE) || (Params.DriveType == DRIVE_CDROM))) {
  1823. Message = RetreiveAndFormatMessage(
  1824. (Params.DriveType == DRIVE_CDROM)
  1825. ? ( GuiSetupInProgress ? MSG_CDPROMPT_NONETWORK : MSG_CDPROMPT )
  1826. : ( GuiSetupInProgress ? MSG_FLOPPYPROMPT_NONETWORK : MSG_FLOPPYPROMPT ),
  1827. DiskName,
  1828. (TCHAR)CharUpper((PTSTR)Params.PathToSource[0])
  1829. );
  1830. if(Message) {
  1831. LoadString(MyDllModuleHandle,IDS_PROMPTTITLE,Buffer,sizeof(Buffer)/sizeof(TCHAR));
  1832. if(!(DiskPromptStyle & IDF_NOBEEP)) {
  1833. MessageBeep(MB_ICONASTERISK);
  1834. }
  1835. reprompt:
  1836. Params.MsgBoxParams.cbSize = sizeof(MSGBOXPARAMS);
  1837. Params.MsgBoxParams.hwndOwner = hwndParent;
  1838. Params.MsgBoxParams.hInstance = MyDllModuleHandle;
  1839. Params.MsgBoxParams.lpszText = Message;
  1840. Params.MsgBoxParams.lpszCaption = Buffer;
  1841. Params.MsgBoxParams.dwStyle = MB_USERICON | MB_OKCANCEL;
  1842. Params.MsgBoxParams.lpszIcon = (Params.DriveType == DRIVE_CDROM)
  1843. ? MAKEINTRESOURCE(ICON_CD)
  1844. : MAKEINTRESOURCE(ICON_FLOPPY);
  1845. Params.MsgBoxParams.lpfnMsgBoxCallback = NULL;
  1846. Params.MsgBoxParams.dwLanguageId = LANG_NEUTRAL;
  1847. if (hDialogEvent) {
  1848. SetEvent(hDialogEvent);
  1849. }
  1850. switch(DialogBoxParam(
  1851. MyDllModuleHandle,
  1852. MAKEINTRESOURCE(IDD_SIMPLEPROMPT),
  1853. hwndParent,
  1854. DlgProcSimplePrompt,
  1855. (LPARAM)&Params
  1856. )) {
  1857. case DPROMPT_OUTOFMEMORY:
  1858. i = DPROMPT_OUTOFMEMORY;
  1859. d = ERROR_NOT_ENOUGH_MEMORY;
  1860. break;
  1861. case IDOK:
  1862. if(DoPresenceCheck(&Params, FALSE)) {
  1863. i = DPROMPT_SUCCESS;
  1864. d = NO_ERROR;
  1865. } else {
  1866. i = DPROMPT_SKIPFILE;
  1867. }
  1868. break;
  1869. case IDCANCEL:
  1870. d = ERROR_CANCELLED;
  1871. i = DPROMPT_CANCEL;
  1872. if((DiskPromptStyle & IDF_WARNIFSKIP) && !WarnSkip(hwndParent,FALSE)) {
  1873. goto reprompt;
  1874. }
  1875. break;
  1876. default:
  1877. MYASSERT( FALSE );
  1878. }
  1879. if (hDialogEvent) {
  1880. ResetEvent(hDialogEvent);
  1881. }
  1882. MyFree(Message);
  1883. } else {
  1884. i = DPROMPT_OUTOFMEMORY;
  1885. d = ERROR_NOT_ENOUGH_MEMORY;
  1886. goto c4;
  1887. }
  1888. } else {
  1889. i = DPROMPT_SKIPFILE;
  1890. }
  1891. if(i == DPROMPT_SKIPFILE) {
  1892. if (hDialogEvent) {
  1893. SetEvent(hDialogEvent);
  1894. }
  1895. Params.BrowseAutoComplete = FALSE;
  1896. if(!GuiSetupInProgress) {
  1897. d = OleInitialize(NULL);
  1898. if(SUCCEEDED(d)) {
  1899. Params.BrowseAutoComplete = TRUE;
  1900. }
  1901. }
  1902. i = DialogBoxParam(
  1903. MyDllModuleHandle,
  1904. MAKEINTRESOURCE(IDD_DISKPROMPT1),
  1905. hwndParent,
  1906. DlgProcDiskPrompt1,
  1907. (LPARAM)&Params
  1908. );
  1909. if(!GuiSetupInProgress && (d==NO_ERROR)) {
  1910. OleUninitialize();
  1911. }
  1912. if (hDialogEvent) {
  1913. ResetEvent(hDialogEvent);
  1914. }
  1915. switch(i) {
  1916. case DPROMPT_SUCCESS:
  1917. PromptUser = TRUE;
  1918. d = NO_ERROR;
  1919. break;
  1920. case DPROMPT_SKIPFILE:
  1921. d = NO_ERROR;
  1922. break;
  1923. case DPROMPT_CANCEL:
  1924. d = ERROR_CANCELLED;
  1925. break;
  1926. case DPROMPT_BUFFERTOOSMALL:
  1927. d = ERROR_INSUFFICIENT_BUFFER;
  1928. break;
  1929. default:
  1930. i = DPROMPT_OUTOFMEMORY;
  1931. d = ERROR_NOT_ENOUGH_MEMORY;
  1932. break;
  1933. }
  1934. }
  1935. }
  1936. //
  1937. // If success, we want to add the path string to the list of path strings
  1938. // if it's not already in there.
  1939. //
  1940. if(i == DPROMPT_SUCCESS) {
  1941. //
  1942. // Only add the file to the MRU list if we prompted the user and
  1943. // they entered a valid path.
  1944. //
  1945. if (PromptUser) {
  1946. ModifyPathList(&Params);
  1947. }
  1948. //
  1949. // Now determine what to return to the user depending on the
  1950. // buffer and sizes passed in.
  1951. //
  1952. ResultPathLen = lstrlen(Params.PathToSource)+1;
  1953. if(PathRequiredSize) {
  1954. *PathRequiredSize = ResultPathLen;
  1955. }
  1956. if(PathBuffer) {
  1957. if(ResultPathLen > PathBufferSize) {
  1958. i = DPROMPT_BUFFERTOOSMALL;
  1959. } else {
  1960. lstrcpy(PathBuffer,Params.PathToSource);
  1961. }
  1962. }
  1963. }
  1964. c4:
  1965. if (hDialogEvent) {
  1966. CloseHandle(hDialogEvent);
  1967. }
  1968. if(!DialogTitle) {
  1969. MyFree(Params.DialogTitle);
  1970. }
  1971. c3:
  1972. if(!DiskName) {
  1973. MyFree(Params.DiskName);
  1974. }
  1975. c2:
  1976. MyFree(Params.PathToSource);
  1977. c1:
  1978. SetupFreeSourceList(&Params.PathList,Params.PathCount);
  1979. c0:
  1980. SetLastError(d);
  1981. return((UINT)i);
  1982. }
  1983. #ifdef UNICODE
  1984. //
  1985. // ANSI version
  1986. //
  1987. UINT
  1988. SetupPromptForDiskA(
  1989. IN HWND hwndParent,
  1990. IN PCSTR DialogTitle, OPTIONAL
  1991. IN PCSTR DiskName, OPTIONAL
  1992. IN PCSTR PathToSource, OPTIONAL
  1993. IN PCSTR FileSought,
  1994. IN PCSTR TagFile, OPTIONAL
  1995. IN DWORD DiskPromptStyle,
  1996. OUT PSTR PathBuffer,
  1997. IN DWORD PathBufferSize,
  1998. OUT PDWORD PathRequiredSize OPTIONAL
  1999. )
  2000. {
  2001. PCWSTR dialogTitle;
  2002. PCWSTR diskName;
  2003. PCWSTR pathToSource;
  2004. PCWSTR fileSought;
  2005. PCWSTR tagFile;
  2006. WCHAR pathBuffer[MAX_PATH];
  2007. CHAR ansiBuffer[MAX_PATH];
  2008. DWORD rc;
  2009. UINT u;
  2010. DWORD Size;
  2011. dialogTitle = NULL;
  2012. diskName = NULL;
  2013. pathToSource = NULL;
  2014. fileSought = NULL;
  2015. tagFile = NULL;
  2016. rc = NO_ERROR;
  2017. if(DialogTitle) {
  2018. rc = pSetupCaptureAndConvertAnsiArg(DialogTitle,&dialogTitle);
  2019. }
  2020. if((rc == NO_ERROR) && DiskName) {
  2021. rc = pSetupCaptureAndConvertAnsiArg(DiskName,&diskName);
  2022. }
  2023. if((rc == NO_ERROR) && PathToSource) {
  2024. rc = pSetupCaptureAndConvertAnsiArg(PathToSource,&pathToSource);
  2025. }
  2026. if((rc == NO_ERROR) && FileSought) {
  2027. rc = pSetupCaptureAndConvertAnsiArg(FileSought,&fileSought);
  2028. }
  2029. if((rc == NO_ERROR) && TagFile) {
  2030. rc = pSetupCaptureAndConvertAnsiArg(TagFile,&tagFile);
  2031. }
  2032. if(rc == NO_ERROR) {
  2033. u = _SetupPromptForDisk(
  2034. hwndParent,
  2035. dialogTitle,
  2036. diskName,
  2037. pathToSource,
  2038. fileSought,
  2039. tagFile,
  2040. DiskPromptStyle,
  2041. pathBuffer,
  2042. MAX_PATH,
  2043. &Size
  2044. );
  2045. rc = GetLastError();
  2046. if(u == DPROMPT_SUCCESS) {
  2047. Size = (DWORD)WideCharToMultiByte(
  2048. CP_ACP,
  2049. 0,
  2050. pathBuffer,
  2051. (int)Size,
  2052. ansiBuffer,
  2053. MAX_PATH,
  2054. NULL,
  2055. NULL
  2056. );
  2057. if(PathRequiredSize) {
  2058. *PathRequiredSize = Size;
  2059. }
  2060. if(PathBuffer) {
  2061. if(Size > PathBufferSize) {
  2062. u = DPROMPT_BUFFERTOOSMALL;
  2063. } else {
  2064. lstrcpynA(PathBuffer,ansiBuffer,Size);
  2065. }
  2066. }
  2067. }
  2068. } else {
  2069. u = (rc == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  2070. }
  2071. if(dialogTitle) {
  2072. MyFree(dialogTitle);
  2073. }
  2074. if(diskName) {
  2075. MyFree(diskName);
  2076. }
  2077. if(pathToSource) {
  2078. MyFree(pathToSource);
  2079. }
  2080. if(fileSought) {
  2081. MyFree(fileSought);
  2082. }
  2083. if(tagFile) {
  2084. MyFree(tagFile);
  2085. }
  2086. SetLastError(rc);
  2087. return(u);
  2088. }
  2089. #else
  2090. //
  2091. // Unicode stub
  2092. //
  2093. UINT
  2094. SetupPromptForDiskW(
  2095. IN HWND hwndParent,
  2096. IN PCWSTR DialogTitle, OPTIONAL
  2097. IN PCWSTR DiskName, OPTIONAL
  2098. IN PCWSTR PathToSource, OPTIONAL
  2099. IN PCWSTR FileSought,
  2100. IN PCWSTR TagFile, OPTIONAL
  2101. IN DWORD DiskPromptStyle,
  2102. OUT PWSTR PathBuffer,
  2103. IN DWORD PathBufferSize,
  2104. OUT PDWORD PathRequiredSize OPTIONAL
  2105. )
  2106. {
  2107. UNREFERENCED_PARAMETER(hwndParent);
  2108. UNREFERENCED_PARAMETER(DialogTitle);
  2109. UNREFERENCED_PARAMETER(DiskName);
  2110. UNREFERENCED_PARAMETER(PathToSource);
  2111. UNREFERENCED_PARAMETER(FileSought);
  2112. UNREFERENCED_PARAMETER(TagFile);
  2113. UNREFERENCED_PARAMETER(DiskPromptStyle);
  2114. UNREFERENCED_PARAMETER(PathBuffer);
  2115. UNREFERENCED_PARAMETER(PathBufferSize);
  2116. UNREFERENCED_PARAMETER(PathRequiredSize);
  2117. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2118. return(DPROMPT_CANCEL);
  2119. }
  2120. #endif
  2121. UINT
  2122. SetupPromptForDisk(
  2123. IN HWND hwndParent,
  2124. IN PCTSTR DialogTitle, OPTIONAL
  2125. IN PCTSTR DiskName, OPTIONAL
  2126. IN PCTSTR PathToSource, OPTIONAL
  2127. IN PCTSTR FileSought,
  2128. IN PCTSTR TagFile, OPTIONAL
  2129. IN DWORD DiskPromptStyle,
  2130. OUT PTSTR PathBuffer,
  2131. IN DWORD PathBufferSize,
  2132. OUT PDWORD PathRequiredSize OPTIONAL
  2133. )
  2134. {
  2135. PCTSTR dialogTitle;
  2136. PCTSTR diskName;
  2137. PCTSTR pathToSource;
  2138. PCTSTR fileSought;
  2139. PCTSTR tagFile;
  2140. TCHAR pathBuffer[MAX_PATH];
  2141. DWORD rc;
  2142. UINT u;
  2143. DWORD Size;
  2144. dialogTitle = NULL;
  2145. diskName = NULL;
  2146. pathToSource = NULL;
  2147. fileSought = NULL;
  2148. tagFile = NULL;
  2149. rc = NO_ERROR;
  2150. if(DialogTitle) {
  2151. rc = CaptureStringArg(DialogTitle,&dialogTitle);
  2152. }
  2153. if((rc == NO_ERROR) && DiskName) {
  2154. rc = CaptureStringArg(DiskName,&diskName);
  2155. }
  2156. if((rc == NO_ERROR) && PathToSource) {
  2157. rc = CaptureStringArg(PathToSource,&pathToSource);
  2158. }
  2159. if((rc == NO_ERROR) && FileSought) {
  2160. rc = CaptureStringArg(FileSought,&fileSought);
  2161. }
  2162. if((rc == NO_ERROR) && TagFile) {
  2163. rc = CaptureStringArg(TagFile,&tagFile);
  2164. }
  2165. if(rc == NO_ERROR) {
  2166. u = _SetupPromptForDisk(
  2167. hwndParent,
  2168. dialogTitle,
  2169. diskName,
  2170. pathToSource,
  2171. fileSought,
  2172. tagFile,
  2173. DiskPromptStyle,
  2174. pathBuffer,
  2175. MAX_PATH,
  2176. &Size
  2177. );
  2178. rc = GetLastError();
  2179. if(u == DPROMPT_SUCCESS) {
  2180. if(PathRequiredSize) {
  2181. *PathRequiredSize = Size;
  2182. }
  2183. if(PathBuffer) {
  2184. if(Size > PathBufferSize) {
  2185. u = DPROMPT_BUFFERTOOSMALL;
  2186. } else {
  2187. lstrcpyn(PathBuffer,pathBuffer,Size);
  2188. }
  2189. }
  2190. }
  2191. } else {
  2192. u = (rc == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  2193. }
  2194. if(dialogTitle) {
  2195. MyFree(dialogTitle);
  2196. }
  2197. if(diskName) {
  2198. MyFree(diskName);
  2199. }
  2200. if(pathToSource) {
  2201. MyFree(pathToSource);
  2202. }
  2203. if(fileSought) {
  2204. MyFree(fileSought);
  2205. }
  2206. if(tagFile) {
  2207. MyFree(tagFile);
  2208. }
  2209. SetLastError(rc);
  2210. return(u);
  2211. }
  2212. INT_PTR
  2213. DlgProcFileError(
  2214. IN HWND hdlg,
  2215. IN UINT msg,
  2216. IN WPARAM wParam,
  2217. IN LPARAM lParam
  2218. )
  2219. /*++
  2220. Routine Description:
  2221. Dialog procedure for delete/rename error dialog.
  2222. The return value for the dialog is
  2223. DPROMPT_CANCEL - user cancelled
  2224. DPROMPT_SKIPFILE - user elected to skip file
  2225. DPROMPT_SUCCESS - user said retry
  2226. DPROMPT_OUTOFMEMORY - out of memory
  2227. Arguments:
  2228. Standard dialog routine parameters.
  2229. Return Value:
  2230. TRUE if message processed; FALSE if not.
  2231. --*/
  2232. {
  2233. static PFILEERRDLGPARAMS Params = NULL;
  2234. BOOL b;
  2235. switch(msg) {
  2236. case WM_INITDIALOG:
  2237. Params = (PFILEERRDLGPARAMS)lParam;
  2238. SetDlgItemText(hdlg,IDT_TEXT1,Params->MessageText);
  2239. SetWindowText(hdlg,Params->Caption);
  2240. SendDlgItemMessage(
  2241. hdlg,
  2242. IDI_ICON1,
  2243. STM_SETICON,
  2244. (WPARAM)LoadIcon(NULL,IDI_HAND),
  2245. 0
  2246. );
  2247. if(!(Params->Style & IDF_NOBEEP)) {
  2248. MessageBeep(MB_ICONASTERISK);
  2249. }
  2250. if(!(Params->Style & IDF_NOFOREGROUND)) {
  2251. PostMessage(hdlg,WMX_HELLO,0,0);
  2252. }
  2253. pSetupCenterWindowRelativeToParent(hdlg);
  2254. //
  2255. // Set focus to retry button and continue.
  2256. //
  2257. SetFocus(GetDlgItem(hdlg,IDOK));
  2258. b = FALSE;
  2259. break;
  2260. case WMX_HELLO:
  2261. SetForegroundWindow(hdlg);
  2262. b = TRUE;
  2263. break;
  2264. case WM_COMMAND:
  2265. if(HIWORD(wParam) == BN_CLICKED) {
  2266. b = TRUE;
  2267. switch(LOWORD(wParam)) {
  2268. case IDOK:
  2269. EndDialog(hdlg,DPROMPT_SUCCESS);
  2270. break;
  2271. case IDCANCEL:
  2272. if ( (Params->Style & IDF_NOSKIP) || !CancelAllCopies(hdlg)) {
  2273. EndDialog(hdlg,DPROMPT_CANCEL);
  2274. } else {
  2275. EndDialog(hdlg,DPROMPT_SKIPFILE);
  2276. }
  2277. break;
  2278. default:
  2279. b = FALSE;
  2280. break;
  2281. }
  2282. } else {
  2283. b = FALSE;
  2284. }
  2285. break;
  2286. default:
  2287. if (!g_uQueryCancelAutoPlay) {
  2288. g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  2289. }
  2290. if (msg == g_uQueryCancelAutoPlay) {
  2291. SetWindowLongPtr( hdlg, DWLP_MSGRESULT, 1 );
  2292. return 1; // cancel auto-play
  2293. }
  2294. b = FALSE;
  2295. break;
  2296. }
  2297. return(b);
  2298. }
  2299. #ifdef UNICODE
  2300. //
  2301. // ANSI version
  2302. //
  2303. UINT
  2304. SetupCopyErrorA(
  2305. IN HWND hwndParent,
  2306. IN PCSTR DialogTitle, OPTIONAL
  2307. IN PCSTR DiskName, OPTIONAL
  2308. IN PCSTR PathToSource,
  2309. IN PCSTR SourceFile,
  2310. IN PCSTR TargetPathFile, OPTIONAL
  2311. IN UINT Win32ErrorCode,
  2312. IN DWORD Style,
  2313. OUT PSTR PathBuffer, OPTIONAL
  2314. IN DWORD PathBufferSize,
  2315. OUT PDWORD PathRequiredSize OPTIONAL
  2316. )
  2317. {
  2318. PCWSTR dialogTitle;
  2319. PCWSTR diskName;
  2320. PCWSTR pathToSource;
  2321. PCWSTR sourceFile;
  2322. PCWSTR targetPathFile;
  2323. WCHAR pathBuffer[MAX_PATH];
  2324. CHAR ansiBuffer[MAX_PATH];
  2325. DWORD rc;
  2326. UINT u;
  2327. DWORD Size;
  2328. dialogTitle = NULL;
  2329. diskName = NULL;
  2330. pathToSource = NULL;
  2331. sourceFile = NULL;
  2332. targetPathFile = NULL;
  2333. rc = NO_ERROR;
  2334. if(DialogTitle) {
  2335. rc = pSetupCaptureAndConvertAnsiArg(DialogTitle,&dialogTitle);
  2336. }
  2337. if((rc == NO_ERROR) && DiskName) {
  2338. rc = pSetupCaptureAndConvertAnsiArg(DiskName,&diskName);
  2339. }
  2340. if((rc == NO_ERROR) && PathToSource) {
  2341. rc = pSetupCaptureAndConvertAnsiArg(PathToSource,&pathToSource);
  2342. }
  2343. if((rc == NO_ERROR) && SourceFile) {
  2344. rc = pSetupCaptureAndConvertAnsiArg(SourceFile,&sourceFile);
  2345. }
  2346. if((rc == NO_ERROR) && TargetPathFile) {
  2347. rc = pSetupCaptureAndConvertAnsiArg(TargetPathFile,&targetPathFile);
  2348. }
  2349. if(rc == NO_ERROR) {
  2350. u = SetupCopyErrorW(
  2351. hwndParent,
  2352. dialogTitle,
  2353. diskName,
  2354. pathToSource,
  2355. sourceFile,
  2356. targetPathFile,
  2357. Win32ErrorCode,
  2358. Style,
  2359. pathBuffer,
  2360. MAX_PATH,
  2361. &Size
  2362. );
  2363. rc = GetLastError();
  2364. if(u == DPROMPT_SUCCESS) {
  2365. Size = (DWORD)WideCharToMultiByte(
  2366. CP_ACP,
  2367. 0,
  2368. pathBuffer,
  2369. (int)Size,
  2370. ansiBuffer,
  2371. MAX_PATH,
  2372. NULL,
  2373. NULL
  2374. );
  2375. if(PathRequiredSize) {
  2376. *PathRequiredSize = Size;
  2377. }
  2378. if(PathBuffer) {
  2379. if(Size > PathBufferSize) {
  2380. u = DPROMPT_BUFFERTOOSMALL;
  2381. } else {
  2382. lstrcpynA(PathBuffer,ansiBuffer,Size);
  2383. }
  2384. }
  2385. }
  2386. } else {
  2387. u = (rc == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  2388. }
  2389. if(dialogTitle) {
  2390. MyFree(dialogTitle);
  2391. }
  2392. if(diskName) {
  2393. MyFree(diskName);
  2394. }
  2395. if(pathToSource) {
  2396. MyFree(pathToSource);
  2397. }
  2398. if(sourceFile) {
  2399. MyFree(sourceFile);
  2400. }
  2401. if(targetPathFile) {
  2402. MyFree(targetPathFile);
  2403. }
  2404. SetLastError(rc);
  2405. return(u);
  2406. }
  2407. #else
  2408. //
  2409. // Unicode stub
  2410. //
  2411. UINT
  2412. SetupCopyErrorW(
  2413. IN HWND hwndParent,
  2414. IN PCWSTR DialogTitle, OPTIONAL
  2415. IN PCWSTR DiskName, OPTIONAL
  2416. IN PCWSTR PathToSource,
  2417. IN PCWSTR SourceFile,
  2418. IN PCWSTR TargetPathFile, OPTIONAL
  2419. IN UINT Win32ErrorCode,
  2420. IN DWORD Style,
  2421. OUT PWSTR PathBuffer, OPTIONAL
  2422. IN DWORD PathBufferSize,
  2423. OUT PDWORD PathRequiredSize OPTIONAL
  2424. )
  2425. {
  2426. UNREFERENCED_PARAMETER(hwndParent);
  2427. UNREFERENCED_PARAMETER(DialogTitle);
  2428. UNREFERENCED_PARAMETER(DiskName);
  2429. UNREFERENCED_PARAMETER(PathToSource);
  2430. UNREFERENCED_PARAMETER(SourceFile);
  2431. UNREFERENCED_PARAMETER(TargetPathFile);
  2432. UNREFERENCED_PARAMETER(Win32ErrorCode);
  2433. UNREFERENCED_PARAMETER(Style);
  2434. UNREFERENCED_PARAMETER(PathBuffer);
  2435. UNREFERENCED_PARAMETER(PathBufferSize);
  2436. UNREFERENCED_PARAMETER(PathRequiredSize);
  2437. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2438. return(DPROMPT_CANCEL);
  2439. }
  2440. #endif
  2441. UINT
  2442. SetupCopyError(
  2443. IN HWND hwndParent,
  2444. IN PCTSTR DialogTitle, OPTIONAL
  2445. IN PCTSTR DiskName, OPTIONAL
  2446. IN PCTSTR PathToSource,
  2447. IN PCTSTR SourceFile,
  2448. IN PCTSTR TargetPathFile, OPTIONAL
  2449. IN UINT Win32ErrorCode,
  2450. IN DWORD Style,
  2451. OUT PTSTR PathBuffer, OPTIONAL
  2452. IN DWORD PathBufferSize,
  2453. OUT PDWORD PathRequiredSize OPTIONAL
  2454. )
  2455. /*++
  2456. Routine Description:
  2457. Inform the user about a file copy error.
  2458. Arguments:
  2459. hwndParent - supplies window handle of window/dialog to own the error dialog
  2460. displayed by this routine.
  2461. DialogTitle - if specified, supplies title for error dialog. If not specified
  2462. a default of "Copy Error" will be supplied.
  2463. DiskName - if specified, supplies name of the disk from which a source file
  2464. was expected. If not specified a default of "(Unknown)" will be supplied.
  2465. PathToSource - supplies full path part of source file name.
  2466. SourceFile - supplies filename part of the source file name.
  2467. TargetPathFile - if specified supplies the full pathname of the target.
  2468. Win32ErrorCode - supplies win32 error code of failure.
  2469. Style - supplies flags to control the behavior of the dialog.
  2470. Return Value:
  2471. DPROMPT_xxx indicating outcome.
  2472. --*/
  2473. {
  2474. INT_PTR i;
  2475. DWORD d = NO_ERROR;
  2476. DWORD TmpRequiredSize;
  2477. HANDLE hDialogEvent = NULL;
  2478. PCTSTR dialogTitle = NULL;
  2479. PCTSTR diskName = NULL;
  2480. PCTSTR pathToSource = NULL;
  2481. PCTSTR sourceFile = NULL;
  2482. PCTSTR targetPathFile = NULL;
  2483. PTSTR ErrorText = NULL;
  2484. PTSTR Message = NULL;
  2485. PTSTR p;
  2486. //
  2487. // If we're running non-interactive, bail now...
  2488. //
  2489. if(GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP)) {
  2490. SetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
  2491. return DPROMPT_CANCEL;
  2492. }
  2493. //
  2494. // verify & snap all parameters
  2495. //
  2496. if(DialogTitle) {
  2497. d = CaptureStringArg(DialogTitle,&dialogTitle);
  2498. } else {
  2499. dialogTitle = MyLoadString(IDS_COPYERROR);
  2500. if(!dialogTitle) {
  2501. d = ERROR_NOT_ENOUGH_MEMORY;
  2502. }
  2503. }
  2504. if(d == NO_ERROR) {
  2505. if(DiskName) {
  2506. d = CaptureStringArg(DiskName,&diskName);
  2507. } else {
  2508. diskName = MyLoadString(IDS_UNKNOWN_PARENS);
  2509. if(!diskName) {
  2510. d = ERROR_NOT_ENOUGH_MEMORY;
  2511. }
  2512. }
  2513. }
  2514. if(d == NO_ERROR) {
  2515. if(PathToSource) {
  2516. d = CaptureStringArg(PathToSource,&pathToSource);
  2517. } else {
  2518. d = ERROR_INVALID_PARAMETER;
  2519. }
  2520. }
  2521. if(d == NO_ERROR) {
  2522. if(SourceFile) {
  2523. d = CaptureStringArg(SourceFile,&sourceFile);
  2524. } else {
  2525. d = ERROR_INVALID_PARAMETER;
  2526. }
  2527. }
  2528. if((d == NO_ERROR) && TargetPathFile) {
  2529. d = CaptureStringArg(TargetPathFile,&targetPathFile);
  2530. }
  2531. if(d) {
  2532. if(d == ERROR_NOT_ENOUGH_MEMORY) {
  2533. i = DPROMPT_OUTOFMEMORY;
  2534. } else {
  2535. i = DPROMPT_CANCEL;
  2536. }
  2537. goto clean;
  2538. }
  2539. if(Win32ErrorCode == ERROR_INVALID_TARGET) {
  2540. FILEERRDLGPARAMS FileErrorDlgParams;
  2541. //
  2542. // Fatal copy error not fixed by changing source location
  2543. //
  2544. ErrorText = MyLoadString(IDS_COPY_INVALID_TARGET);
  2545. if(!ErrorText) {
  2546. i = DPROMPT_OUTOFMEMORY;
  2547. goto clean;
  2548. }
  2549. //
  2550. // don't display the error-code in this case
  2551. // just the error text
  2552. //
  2553. Message = RetreiveAndFormatMessage(
  2554. MSG_FILEERROR_COPY,
  2555. sourceFile,
  2556. ErrorText
  2557. );
  2558. if(!Message) {
  2559. i = DPROMPT_OUTOFMEMORY;
  2560. goto clean;
  2561. }
  2562. FileErrorDlgParams.MessageText = Message;
  2563. FileErrorDlgParams.Style = Style;
  2564. FileErrorDlgParams.Caption = dialogTitle;
  2565. if(!FileErrorDlgParams.Caption) {
  2566. i = DPROMPT_OUTOFMEMORY;
  2567. goto clean;
  2568. }
  2569. if (GuiSetupInProgress) {
  2570. hDialogEvent = CreateEvent(NULL,TRUE,FALSE,SETUP_HAS_OPEN_DIALOG_EVENT);
  2571. }
  2572. if ( hDialogEvent ) {
  2573. SetEvent( hDialogEvent );
  2574. }
  2575. d = NO_ERROR;
  2576. i = DialogBoxParam(
  2577. MyDllModuleHandle,
  2578. MAKEINTRESOURCE(IDD_FILEERROR2),
  2579. hwndParent,
  2580. DlgProcFileError,
  2581. (LPARAM)&FileErrorDlgParams
  2582. );
  2583. if ( hDialogEvent ) {
  2584. ResetEvent( hDialogEvent );
  2585. CloseHandle( hDialogEvent );
  2586. }
  2587. if(i == -1) {
  2588. i = DPROMPT_OUTOFMEMORY;
  2589. }
  2590. } else {
  2591. PROMPTPARAMS Params;
  2592. ZeroMemory(&Params,sizeof(PROMPTPARAMS));
  2593. //
  2594. // If the dialog title is not specified fetch a default.
  2595. //
  2596. Params.DialogTitle = dialogTitle;
  2597. Params.DiskName = diskName;
  2598. Params.FileSought = sourceFile;
  2599. Params.PathToSource = pathToSource;
  2600. Params.TargetFile = targetPathFile;
  2601. //
  2602. // assume dialog proc may change any of these
  2603. //
  2604. dialogTitle = NULL;
  2605. diskName = NULL;
  2606. sourceFile = NULL;
  2607. pathToSource = NULL;
  2608. targetPathFile = NULL;
  2609. //
  2610. // There is no tag file usage in the error dialog.
  2611. //
  2612. Params.TagFile = NULL;
  2613. //
  2614. // Determine drive type of source path
  2615. //
  2616. DiskPromptGetDriveType(Params.PathToSource,&Params.DriveType,&Params.IsRemovable);
  2617. //
  2618. // Fetch the installation path list.
  2619. //
  2620. d = pSetupGetList(
  2621. 0,
  2622. &Params.PathList,
  2623. &Params.PathCount,
  2624. &Params.ReadOnlyMru
  2625. );
  2626. if(d != NO_ERROR) {
  2627. i = (d == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  2628. goto clean;
  2629. }
  2630. //
  2631. // Other fields
  2632. //
  2633. Params.Owner = hwndParent;
  2634. Params.PromptStyle = Style;
  2635. Params.UserBrowsed = FALSE;
  2636. Params.DialogType = DLGTYPE_ERROR;
  2637. Params.Win32Error = Win32ErrorCode;
  2638. if(Params.ReadOnlyMru) {
  2639. Params.PromptStyle |= IDF_NOBROWSE;
  2640. }
  2641. if (GuiSetupInProgress) {
  2642. hDialogEvent = CreateEvent(NULL,TRUE,FALSE,SETUP_HAS_OPEN_DIALOG_EVENT);
  2643. }
  2644. if ( hDialogEvent ) {
  2645. SetEvent( hDialogEvent );
  2646. }
  2647. Params.BrowseAutoComplete = FALSE;
  2648. if(!GuiSetupInProgress) {
  2649. d = OleInitialize(NULL);
  2650. if(SUCCEEDED(d)) {
  2651. Params.BrowseAutoComplete = TRUE;
  2652. }
  2653. }
  2654. i = DialogBoxParam(
  2655. MyDllModuleHandle,
  2656. MAKEINTRESOURCE(IDD_DISKPROMPT1),
  2657. hwndParent,
  2658. DlgProcDiskPrompt1,
  2659. (LPARAM)&Params
  2660. );
  2661. if(!GuiSetupInProgress && (d==NO_ERROR)) {
  2662. OleUninitialize();
  2663. }
  2664. if ( hDialogEvent ) {
  2665. ResetEvent( hDialogEvent );
  2666. CloseHandle( hDialogEvent );
  2667. }
  2668. d = GetLastError();
  2669. if(i == DPROMPT_SUCCESS) {
  2670. ModifyPathList(&Params);
  2671. //
  2672. // Now determine what to return to the user depending on the
  2673. // buffer and sizes passed in.
  2674. //
  2675. TmpRequiredSize = lstrlen(Params.PathToSource)+1;
  2676. if(PathRequiredSize) {
  2677. *PathRequiredSize = TmpRequiredSize;
  2678. }
  2679. if(PathBuffer) {
  2680. if(TmpRequiredSize > PathBufferSize) {
  2681. i = DPROMPT_BUFFERTOOSMALL;
  2682. } else {
  2683. lstrcpy(PathBuffer,Params.PathToSource);
  2684. }
  2685. }
  2686. }
  2687. SetupFreeSourceList(&Params.PathList,Params.PathCount);
  2688. //
  2689. // release params (either we, or DlgProcDiskPrompt1 allocated the data)
  2690. //
  2691. if (Params.DialogTitle) {
  2692. MyFree(Params.DialogTitle);
  2693. }
  2694. if (Params.DiskName) {
  2695. MyFree(Params.DiskName);
  2696. }
  2697. if (Params.FileSought) {
  2698. MyFree(Params.FileSought);
  2699. }
  2700. if (Params.PathToSource) {
  2701. MyFree(Params.PathToSource);
  2702. }
  2703. if (Params.TargetFile) {
  2704. MyFree(Params.TargetFile);
  2705. }
  2706. }
  2707. clean:
  2708. if(dialogTitle) {
  2709. MyFree(dialogTitle);
  2710. }
  2711. if(diskName) {
  2712. MyFree(diskName);
  2713. }
  2714. if(pathToSource) {
  2715. MyFree(pathToSource);
  2716. }
  2717. if(sourceFile) {
  2718. MyFree(sourceFile);
  2719. }
  2720. if(targetPathFile) {
  2721. MyFree(targetPathFile);
  2722. }
  2723. if(ErrorText) {
  2724. MyFree(ErrorText);
  2725. }
  2726. if(Message) {
  2727. MyFree(Message);
  2728. }
  2729. SetLastError(d);
  2730. return((UINT)i);
  2731. }
  2732. #ifdef UNICODE
  2733. //
  2734. // ANSI version
  2735. //
  2736. UINT
  2737. SetupRenameErrorA(
  2738. IN HWND hwndParent,
  2739. IN PCSTR DialogTitle, OPTIONAL
  2740. IN PCSTR SourceFile,
  2741. IN PCSTR TargetFile,
  2742. IN UINT Win32ErrorCode,
  2743. IN DWORD Style
  2744. )
  2745. {
  2746. PCWSTR dialogTitle,sourceFile,targetFile;
  2747. DWORD rc;
  2748. UINT u;
  2749. dialogTitle = NULL;
  2750. sourceFile = NULL;
  2751. targetFile = NULL;
  2752. rc = NO_ERROR;
  2753. if(DialogTitle) {
  2754. rc = pSetupCaptureAndConvertAnsiArg(DialogTitle,&dialogTitle);
  2755. }
  2756. if((rc == NO_ERROR) && SourceFile) {
  2757. rc = pSetupCaptureAndConvertAnsiArg(SourceFile,&sourceFile);
  2758. }
  2759. if((rc == NO_ERROR) && TargetFile) {
  2760. rc = pSetupCaptureAndConvertAnsiArg(TargetFile,&targetFile);
  2761. }
  2762. if(rc == NO_ERROR) {
  2763. u = SetupRenameErrorW(
  2764. hwndParent,
  2765. dialogTitle,
  2766. sourceFile,
  2767. targetFile,
  2768. Win32ErrorCode,
  2769. Style
  2770. );
  2771. rc = GetLastError();
  2772. } else {
  2773. u = (rc == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  2774. }
  2775. if(dialogTitle) {
  2776. MyFree(dialogTitle);
  2777. }
  2778. if(sourceFile) {
  2779. MyFree(sourceFile);
  2780. }
  2781. if(targetFile) {
  2782. MyFree(targetFile);
  2783. }
  2784. SetLastError(rc);
  2785. return(u);
  2786. }
  2787. #else
  2788. //
  2789. // Unicode stub
  2790. //
  2791. UINT
  2792. SetupRenameErrorW(
  2793. IN HWND hwndParent,
  2794. IN PCWSTR DialogTitle, OPTIONAL
  2795. IN PCWSTR SourceFile,
  2796. IN PCWSTR TargetFile,
  2797. IN UINT Win32ErrorCode,
  2798. IN DWORD Style
  2799. )
  2800. {
  2801. UNREFERENCED_PARAMETER(hwndParent);
  2802. UNREFERENCED_PARAMETER(DialogTitle);
  2803. UNREFERENCED_PARAMETER(SourceFile);
  2804. UNREFERENCED_PARAMETER(TargetFile);
  2805. UNREFERENCED_PARAMETER(Win32ErrorCode);
  2806. UNREFERENCED_PARAMETER(Style);
  2807. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2808. return(DPROMPT_CANCEL);
  2809. }
  2810. #endif
  2811. UINT
  2812. SetupRenameError(
  2813. IN HWND hwndParent,
  2814. IN PCTSTR DialogTitle, OPTIONAL
  2815. IN PCTSTR SourceFile,
  2816. IN PCTSTR TargetFile,
  2817. IN UINT Win32ErrorCode,
  2818. IN DWORD Style
  2819. )
  2820. /*++
  2821. Routine Description:
  2822. Inform the user about a rename error.
  2823. Arguments:
  2824. hwndParent - supplies window handle of window/dialog to own the error dialog
  2825. displayed by this routine.
  2826. DialogTitle - if specified, supplies title for error dialog. If not specified
  2827. a default of "Rename Error" will be supplied.
  2828. SourceFile - supplies full path and filename of source.
  2829. TargetFile - supplies full path and filename of target.
  2830. Win32ErrorCode - supplies win32 error code of failure.
  2831. Style - supplies flags to control the behavior of the dialog.
  2832. Return Value:
  2833. DPROMPT_xxx indicating outcome.
  2834. --*/
  2835. {
  2836. PTSTR ErrorText;
  2837. PTSTR Message;
  2838. PTCHAR p;
  2839. INT_PTR i;
  2840. FILEERRDLGPARAMS FileErrorDlgParams;
  2841. //
  2842. // If we're running non-interactive, bail now...
  2843. //
  2844. if(GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP)) {
  2845. SetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
  2846. return DPROMPT_CANCEL;
  2847. }
  2848. ErrorText = RetreiveAndFormatMessage(Win32ErrorCode);
  2849. if(ErrorText) {
  2850. p = ErrorText + lstrlen(ErrorText) - 1;
  2851. while((p > ErrorText) && (*p <= TEXT(' '))) {
  2852. *p-- = 0;
  2853. }
  2854. } else {
  2855. return(DPROMPT_OUTOFMEMORY);
  2856. }
  2857. Message = RetreiveAndFormatMessage(
  2858. MSG_FILEERROR_RENAME,
  2859. ErrorText,
  2860. Win32ErrorCode,
  2861. SourceFile,
  2862. TargetFile
  2863. );
  2864. if(!Message) {
  2865. MyFree(ErrorText);
  2866. return(DPROMPT_OUTOFMEMORY);
  2867. }
  2868. FileErrorDlgParams.MessageText = Message;
  2869. FileErrorDlgParams.Style = Style;
  2870. FileErrorDlgParams.Caption = DialogTitle ? DialogTitle : MyLoadString(IDS_RENAMEERROR);
  2871. if(!FileErrorDlgParams.Caption) {
  2872. MyFree(ErrorText);
  2873. MyFree(Message);
  2874. SetLastError(NO_ERROR);
  2875. return(DPROMPT_OUTOFMEMORY);
  2876. }
  2877. i = DialogBoxParam(
  2878. MyDllModuleHandle,
  2879. MAKEINTRESOURCE(IDD_FILEERROR2),
  2880. hwndParent,
  2881. DlgProcFileError,
  2882. (LPARAM)&FileErrorDlgParams
  2883. );
  2884. MyFree(ErrorText);
  2885. MyFree(Message);
  2886. if(!DialogTitle) {
  2887. MyFree(FileErrorDlgParams.Caption);
  2888. }
  2889. if(i == -1) {
  2890. i = DPROMPT_OUTOFMEMORY;
  2891. }
  2892. SetLastError(NO_ERROR);
  2893. return((UINT)i);
  2894. }
  2895. #ifdef UNICODE
  2896. //
  2897. // ANSI version
  2898. //
  2899. UINT
  2900. SetupDeleteErrorA(
  2901. IN HWND hwndParent,
  2902. IN PCSTR DialogTitle, OPTIONAL
  2903. IN PCSTR File,
  2904. IN UINT Win32ErrorCode,
  2905. IN DWORD Style
  2906. )
  2907. {
  2908. PCWSTR dialogTitle,file;
  2909. DWORD rc;
  2910. UINT u;
  2911. dialogTitle = NULL;
  2912. file = NULL;
  2913. rc = NO_ERROR;
  2914. if(DialogTitle) {
  2915. rc = pSetupCaptureAndConvertAnsiArg(DialogTitle,&dialogTitle);
  2916. }
  2917. if((rc ==NO_ERROR) && File) {
  2918. rc = pSetupCaptureAndConvertAnsiArg(File,&file);
  2919. }
  2920. if(rc == NO_ERROR) {
  2921. u = SetupDeleteErrorW(hwndParent,dialogTitle,file,Win32ErrorCode,Style);
  2922. rc = GetLastError();
  2923. } else {
  2924. u = (rc == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  2925. }
  2926. if(dialogTitle) {
  2927. MyFree(dialogTitle);
  2928. }
  2929. if(file) {
  2930. MyFree(file);
  2931. }
  2932. SetLastError(rc);
  2933. return(u);
  2934. }
  2935. #else
  2936. //
  2937. // Unicode stub
  2938. //
  2939. UINT
  2940. SetupDeleteErrorW(
  2941. IN HWND hwndParent,
  2942. IN PCWSTR DialogTitle, OPTIONAL
  2943. IN PCWSTR File,
  2944. IN UINT Win32ErrorCode,
  2945. IN DWORD Style
  2946. )
  2947. {
  2948. UNREFERENCED_PARAMETER(hwndParent);
  2949. UNREFERENCED_PARAMETER(DialogTitle);
  2950. UNREFERENCED_PARAMETER(File);
  2951. UNREFERENCED_PARAMETER(Win32ErrorCode);
  2952. UNREFERENCED_PARAMETER(Style);
  2953. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2954. return(DPROMPT_CANCEL);
  2955. }
  2956. #endif
  2957. UINT
  2958. SetupDeleteError(
  2959. IN HWND hwndParent,
  2960. IN PCTSTR DialogTitle, OPTIONAL
  2961. IN PCTSTR File,
  2962. IN UINT Win32ErrorCode,
  2963. IN DWORD Style
  2964. )
  2965. /*++
  2966. Routine Description:
  2967. Inform the user about a rename error.
  2968. Arguments:
  2969. hwndParent - supplies window handle of window/dialog to own the error dialog
  2970. displayed by this routine.
  2971. DialogTitle - if specified, supplies title for error dialog. If not specified
  2972. a default of "Delete Error" will be supplied.
  2973. File - supplies full path and filename of file being deleted.
  2974. Win32ErrorCode - supplies win32 error code of failure.
  2975. Style - supplies flags to control the behavior of the dialog.
  2976. Return Value:
  2977. DPROMPT_xxx indicating outcome.
  2978. --*/
  2979. {
  2980. PTSTR ErrorText;
  2981. PTSTR Message;
  2982. PTCHAR p;
  2983. INT_PTR i;
  2984. FILEERRDLGPARAMS FileErrorDlgParams;
  2985. //
  2986. // If we're running non-interactive, bail now...
  2987. //
  2988. if(GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP)) {
  2989. SetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
  2990. return DPROMPT_CANCEL;
  2991. }
  2992. ErrorText = RetreiveAndFormatMessage(Win32ErrorCode);
  2993. if(ErrorText) {
  2994. p = ErrorText + lstrlen(ErrorText) - 1;
  2995. while((p > ErrorText) && (*p <= TEXT(' '))) {
  2996. *p-- = 0;
  2997. }
  2998. } else {
  2999. return(DPROMPT_OUTOFMEMORY);
  3000. }
  3001. Message = RetreiveAndFormatMessage(
  3002. MSG_FILEERROR_DELETE,
  3003. File,
  3004. ErrorText,
  3005. Win32ErrorCode
  3006. );
  3007. if(!Message) {
  3008. MyFree(ErrorText);
  3009. return(DPROMPT_OUTOFMEMORY);
  3010. }
  3011. FileErrorDlgParams.MessageText = Message;
  3012. FileErrorDlgParams.Style = Style;
  3013. FileErrorDlgParams.Caption = DialogTitle ? DialogTitle : MyLoadString(IDS_DELETEERROR);
  3014. if(!FileErrorDlgParams.Caption) {
  3015. MyFree(ErrorText);
  3016. MyFree(Message);
  3017. return(DPROMPT_OUTOFMEMORY);
  3018. }
  3019. i = DialogBoxParam(
  3020. MyDllModuleHandle,
  3021. MAKEINTRESOURCE(IDD_FILEERROR2),
  3022. hwndParent,
  3023. DlgProcFileError,
  3024. (LPARAM)&FileErrorDlgParams
  3025. );
  3026. MyFree(ErrorText);
  3027. MyFree(Message);
  3028. if(!DialogTitle) {
  3029. MyFree(FileErrorDlgParams.Caption);
  3030. }
  3031. if(i == -1) {
  3032. i = DPROMPT_OUTOFMEMORY;
  3033. }
  3034. return((UINT)i);
  3035. }
  3036. #ifdef UNICODE
  3037. //
  3038. // ANSI version
  3039. //
  3040. UINT
  3041. SetupBackupErrorA(
  3042. IN HWND hwndParent,
  3043. IN PCSTR DialogTitle, OPTIONAL
  3044. IN PCSTR SourceFile,
  3045. IN PCSTR TargetFile, OPTIONAL
  3046. IN UINT Win32ErrorCode,
  3047. IN DWORD Style
  3048. )
  3049. {
  3050. PCWSTR dialogTitle,sourceFile,targetFile;
  3051. DWORD rc;
  3052. UINT u;
  3053. dialogTitle = NULL;
  3054. sourceFile = NULL;
  3055. targetFile = NULL;
  3056. rc = NO_ERROR;
  3057. if(DialogTitle) {
  3058. rc = pSetupCaptureAndConvertAnsiArg(DialogTitle,&dialogTitle);
  3059. }
  3060. if((rc == NO_ERROR) && SourceFile) {
  3061. rc = pSetupCaptureAndConvertAnsiArg(SourceFile,&sourceFile);
  3062. }
  3063. if((rc == NO_ERROR) && TargetFile) {
  3064. rc = pSetupCaptureAndConvertAnsiArg(TargetFile,&targetFile);
  3065. }
  3066. if(rc == NO_ERROR) {
  3067. u = SetupBackupErrorW(
  3068. hwndParent,
  3069. dialogTitle,
  3070. sourceFile,
  3071. targetFile,
  3072. Win32ErrorCode,
  3073. Style
  3074. );
  3075. rc = GetLastError();
  3076. } else {
  3077. u = (rc == ERROR_NOT_ENOUGH_MEMORY) ? DPROMPT_OUTOFMEMORY : DPROMPT_CANCEL;
  3078. }
  3079. if(dialogTitle) {
  3080. MyFree(dialogTitle);
  3081. }
  3082. if(sourceFile) {
  3083. MyFree(sourceFile);
  3084. }
  3085. if(targetFile) {
  3086. MyFree(targetFile);
  3087. }
  3088. SetLastError(rc);
  3089. return(u);
  3090. }
  3091. #else
  3092. //
  3093. // Unicode stub
  3094. //
  3095. UINT
  3096. SetupBackupErrorW(
  3097. IN HWND hwndParent,
  3098. IN PCWSTR DialogTitle, OPTIONAL
  3099. IN PCWSTR SourceFile,
  3100. IN PCWSTR TargetFile, OPTIONAL
  3101. IN UINT Win32ErrorCode,
  3102. IN DWORD Style
  3103. )
  3104. {
  3105. UNREFERENCED_PARAMETER(hwndParent);
  3106. UNREFERENCED_PARAMETER(DialogTitle);
  3107. UNREFERENCED_PARAMETER(SourceFile);
  3108. UNREFERENCED_PARAMETER(TargetFile);
  3109. UNREFERENCED_PARAMETER(Win32ErrorCode);
  3110. UNREFERENCED_PARAMETER(Style);
  3111. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  3112. return(DPROMPT_CANCEL);
  3113. }
  3114. #endif
  3115. UINT
  3116. SetupBackupError(
  3117. IN HWND hwndParent,
  3118. IN PCTSTR DialogTitle, OPTIONAL
  3119. IN PCTSTR SourceFile,
  3120. IN PCTSTR TargetFile, OPTIONAL
  3121. IN UINT Win32ErrorCode,
  3122. IN DWORD Style
  3123. )
  3124. /*++
  3125. Routine Description:
  3126. Inform the user about a backup error.
  3127. Arguments:
  3128. hwndParent - supplies window handle of window/dialog to own the error dialog
  3129. displayed by this routine.
  3130. DialogTitle - if specified, supplies title for error dialog. If not specified
  3131. a default of "Rename Error" will be supplied.
  3132. SourceFile - supplies full path and filename of file to be backed up
  3133. TargetFile - supplies full path and filename of final name, if known
  3134. Win32ErrorCode - supplies win32 error code of failure.
  3135. Style - supplies flags to control the behavior of the dialog.
  3136. Return Value:
  3137. DPROMPT_xxx indicating outcome.
  3138. --*/
  3139. {
  3140. PTSTR ErrorText;
  3141. PTSTR Message;
  3142. PTCHAR p;
  3143. INT_PTR i;
  3144. FILEERRDLGPARAMS FileErrorDlgParams;
  3145. //
  3146. // If we're running non-interactive, bail now...
  3147. //
  3148. if(GlobalSetupFlags & (PSPGF_NONINTERACTIVE|PSPGF_UNATTENDED_SETUP)) {
  3149. SetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
  3150. return DPROMPT_CANCEL;
  3151. }
  3152. ErrorText = RetreiveAndFormatMessage(Win32ErrorCode);
  3153. if(ErrorText) {
  3154. p = ErrorText + lstrlen(ErrorText) - 1;
  3155. while((p > ErrorText) && (*p <= TEXT(' '))) {
  3156. *p-- = 0;
  3157. }
  3158. } else {
  3159. return(DPROMPT_OUTOFMEMORY);
  3160. }
  3161. Message = RetreiveAndFormatMessage(
  3162. MSG_FILEERROR_BACKUP,
  3163. SourceFile,
  3164. ErrorText,
  3165. Win32ErrorCode
  3166. );
  3167. if(!Message) {
  3168. MyFree(ErrorText);
  3169. return(DPROMPT_OUTOFMEMORY);
  3170. }
  3171. FileErrorDlgParams.MessageText = Message;
  3172. FileErrorDlgParams.Style = Style;
  3173. FileErrorDlgParams.Caption = DialogTitle ? DialogTitle : MyLoadString(IDS_BACKUPERROR);
  3174. if(!FileErrorDlgParams.Caption) {
  3175. MyFree(ErrorText);
  3176. MyFree(Message);
  3177. return(DPROMPT_OUTOFMEMORY);
  3178. }
  3179. i = DialogBoxParam(
  3180. MyDllModuleHandle,
  3181. MAKEINTRESOURCE(IDD_FILEERROR2),
  3182. hwndParent,
  3183. DlgProcFileError,
  3184. (LPARAM)&FileErrorDlgParams
  3185. );
  3186. MyFree(ErrorText);
  3187. MyFree(Message);
  3188. if(!DialogTitle) {
  3189. MyFree(FileErrorDlgParams.Caption);
  3190. }
  3191. if(i == -1) {
  3192. i = DPROMPT_OUTOFMEMORY;
  3193. }
  3194. return((UINT)i);
  3195. }
  3196. BOOL
  3197. ConnectToNetShare(
  3198. IN PCTSTR FileName,
  3199. IN HWND hwndParent
  3200. )
  3201. /*++
  3202. Routine Description:
  3203. This routine determines the network share component of the specified file path,
  3204. and give the user a "Connect As" dialog so that they can connect to this share.
  3205. Arguments:
  3206. FileName - supplies the path of a file contained in the network share to be
  3207. connected to.
  3208. hwndParent - supplies a handle to the window that should be the parent of the
  3209. "Connect As" dialog.
  3210. Return Value:
  3211. If the network share is successfully connected to, the return value is TRUE, otherwise,
  3212. it is FALSE.
  3213. --*/
  3214. {
  3215. TCHAR TempFileName[MAX_PATH];
  3216. NETRESOURCE NetResourceIn;
  3217. LPNETRESOURCE NetResourceOut = NULL;
  3218. PTSTR TempString;
  3219. DWORD BufferSize, d;
  3220. BOOL Success = FALSE;
  3221. BOOL locked = FALSE;
  3222. PTEMP_NET_CONNECTION NewConnectionNode;
  3223. //
  3224. // Surround this code in try/except, in case we get an exception going out to
  3225. // the network.
  3226. //
  3227. try {
  3228. //
  3229. // Copy the filename into a local (writable) buffer, because the WNet structure
  3230. // doesn't specify its string pointers as CONST, and we don't want to take any chances.
  3231. //
  3232. lstrcpyn(TempFileName, FileName, SIZECHARS(TempFileName));
  3233. ZeroMemory(&NetResourceIn, sizeof(NetResourceIn));
  3234. NetResourceIn.lpRemoteName = TempFileName;
  3235. NetResourceIn.dwType = RESOURCETYPE_DISK;
  3236. //
  3237. // Use a reasonable default buffer size in hopes of avoiding multiple calls to
  3238. // WNetGetResourceInformation.
  3239. //
  3240. BufferSize = sizeof(NETRESOURCE) + (MAX_PATH * sizeof(TCHAR));
  3241. while(TRUE) {
  3242. if(!(NetResourceOut = MyMalloc(BufferSize))) {
  3243. goto clean0;
  3244. }
  3245. d = WNetGetResourceInformation(&NetResourceIn, NetResourceOut, &BufferSize, &TempString);
  3246. if(d == WN_SUCCESS) {
  3247. break;
  3248. } else {
  3249. //
  3250. // Free the buffer currently allocated for the net resource information.
  3251. //
  3252. MyFree(NetResourceOut);
  3253. NetResourceOut = NULL;
  3254. if(d != WN_MORE_DATA) {
  3255. //
  3256. // The call failed for some reason other than too small a buffer, so we just
  3257. // need to bail.
  3258. //
  3259. goto clean0;
  3260. }
  3261. }
  3262. }
  3263. //
  3264. // If we get to this point, then we've successfully retrieved network resource information
  3265. // for the caller-supplied path. Now give the user a chance to connect to that network
  3266. // location.
  3267. //
  3268. if(WNetAddConnection3(hwndParent,
  3269. NetResourceOut,
  3270. NULL,
  3271. NULL,
  3272. CONNECT_INTERACTIVE | CONNECT_PROMPT) == NO_ERROR) {
  3273. Success = TRUE;
  3274. //
  3275. // Now, add a new node for this connection into our temporary network
  3276. // connections list, so that we can disconnect during DLL unload.
  3277. //
  3278. if(NewConnectionNode = MyMalloc(sizeof(TEMP_NET_CONNECTION))) {
  3279. lstrcpy(NewConnectionNode->NetResourceName, NetResourceOut->lpRemoteName);
  3280. try {
  3281. EnterCriticalSection(&NetConnectionListCritSect);
  3282. locked = TRUE;
  3283. NewConnectionNode->Next = NetConnectionList;
  3284. NetConnectionList = NewConnectionNode;
  3285. } except(EXCEPTION_EXECUTE_HANDLER) {
  3286. }
  3287. if(locked) {
  3288. LeaveCriticalSection(&NetConnectionListCritSect);
  3289. }
  3290. }
  3291. }
  3292. clean0: ; // nothing to do.
  3293. } except(EXCEPTION_EXECUTE_HANDLER) {
  3294. //
  3295. // Reference the following variable so the compiler will respect our statement
  3296. // ordering for it.
  3297. //
  3298. NetResourceOut = NetResourceOut;
  3299. }
  3300. if(NetResourceOut) {
  3301. MyFree(NetResourceOut);
  3302. }
  3303. return Success;
  3304. }
  3305. VOID
  3306. pSetupInitNetConnectionList(
  3307. IN BOOL Init
  3308. )
  3309. /*++
  3310. Routine Description:
  3311. This routine initializes/tears down the temporary network connection linked list that is
  3312. used to track what UNC connections the user has made (via "Connect As" dialog) that need
  3313. to be cleaned up on DLL unload. As the list is being torn down, the network connection
  3314. for each node is deleted.
  3315. Arguments:
  3316. Init - specifies whether we're initializing or tearing down this list.
  3317. Return Value:
  3318. None.
  3319. --*/
  3320. {
  3321. PTEMP_NET_CONNECTION CurNode, NextNode;
  3322. if(Init) {
  3323. NetConnectionList = NULL;
  3324. } else {
  3325. for(CurNode = NetConnectionList; CurNode; CurNode = NextNode) {
  3326. //
  3327. // First, attempt to disconnect from this network resource.
  3328. //
  3329. WNetCancelConnection2(CurNode->NetResourceName, 0, FALSE);
  3330. NextNode = CurNode->Next;
  3331. MyFree(CurNode);
  3332. }
  3333. }
  3334. }