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.

586 lines
22 KiB

  1. #include <windowsx.h>
  2. #include <shlobj.h>
  3. #include <shlwapi.h>
  4. #include <shellapi.h>
  5. #include <stdio.h>
  6. #include <winioctl.h>
  7. #include "resource.h"
  8. #include "migtask.h"
  9. #include "migwiz.h"
  10. #include "migwnprc.h"
  11. #include "migutil.h"
  12. #include "miginf.h"
  13. #include "migeng.h"
  14. extern "C" {
  15. #include "cablib.h"
  16. }
  17. #define MAX_LOADSTRING 1024
  18. extern BOOL g_fUberCancel;
  19. CCABHANDLE g_hCabHandle = NULL;
  20. #define S_MIGWIZCAB TEXT("migwiz.cab")
  21. #define S_TOOLDISK TEXT("DSK%05X")
  22. #define S_DONOTCOMPRESS TEXT("NO_COMPRESS")
  23. #define S_DONOTFAIL TEXT("NO_FAIL")
  24. typedef struct {
  25. HWND hwndProgress;
  26. HWND hwndPropSheet;
  27. BOOL fSource;
  28. BOOL* pfHasUserCancelled;
  29. } PROGRESSCALLBACKSTRUCT;
  30. #define PHASEWIDTH_S_BEGINGAP 200
  31. #define PHASEWIDTH_S_ENDGAP 200
  32. #define PHASEWIDTH_S_QUEUE_HIGHPRIORITY 200
  33. #define PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY 200
  34. #define PHASEWIDTH_S_GATHER_HIGHPRIORITY 400
  35. #define PHASEWIDTH_S_QUEUE_GATHER 800
  36. #define PHASEWIDTH_S_ESTIMATE_GATHER 800
  37. #define PHASEWIDTH_S_GATHER_GATHER 2400
  38. #define PHASEWIDTH_S_ANALYSIS 200
  39. #define PHASEWIDTH_S_TRANSPORT 5000
  40. #define PHASEWIDTH_S_TOTAL (PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  41. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY + PHASEWIDTH_S_GATHER_HIGHPRIORITY \
  42. + PHASEWIDTH_S_QUEUE_GATHER + PHASEWIDTH_S_ESTIMATE_GATHER \
  43. + PHASEWIDTH_S_GATHER_GATHER + PHASEWIDTH_S_ANALYSIS \
  44. + PHASEWIDTH_S_TRANSPORT + PHASEWIDTH_S_ENDGAP)
  45. #define PHASEWIDTH_D_BEGINGAP 150
  46. #define PHASEWIDTH_D_ENDGAP 150
  47. #define PHASEWIDTH_D_TRANSPORT 2000
  48. #define PHASEWIDTH_D_QUEUE_HIGHPRIORITY 50
  49. #define PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY 50
  50. #define PHASEWIDTH_D_GATHER_HIGHPRIORITY 100
  51. #define PHASEWIDTH_D_QUEUE_GATHER 50
  52. #define PHASEWIDTH_D_ESTIMATE_GATHER 50
  53. #define PHASEWIDTH_D_GATHER_GATHER 100
  54. #define PHASEWIDTH_D_ANALYSIS 500
  55. #define PHASEWIDTH_D_APPLY 5000
  56. #define PHASEWIDTH_D_TOTAL (PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  57. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY \
  58. + PHASEWIDTH_D_GATHER_HIGHPRIORITY + PHASEWIDTH_D_QUEUE_GATHER \
  59. + PHASEWIDTH_D_ESTIMATE_GATHER + PHASEWIDTH_D_GATHER_GATHER \
  60. + PHASEWIDTH_D_ANALYSIS + PHASEWIDTH_D_APPLY \
  61. + PHASEWIDTH_D_ENDGAP)
  62. VOID WINAPI ProgressCallback (MIG_PROGRESSPHASE Phase, MIG_PROGRESSSTATE State, UINT uiWorkDone, UINT uiTotalWork, ULONG_PTR pArg)
  63. {
  64. PROGRESSCALLBACKSTRUCT* ppcs = (PROGRESSCALLBACKSTRUCT*)pArg;
  65. if (!g_fUberCancel) {
  66. INT iWork = 0;
  67. INT iPhaseWidth = 0;
  68. INT iTotal = ppcs->fSource ? PHASEWIDTH_S_TOTAL : PHASEWIDTH_D_TOTAL;
  69. if (ppcs->fSource)
  70. {
  71. switch (Phase)
  72. {
  73. case MIG_HIGHPRIORITYQUEUE_PHASE:
  74. iWork = PHASEWIDTH_S_BEGINGAP;
  75. iPhaseWidth = PHASEWIDTH_S_QUEUE_HIGHPRIORITY;
  76. break;
  77. case MIG_HIGHPRIORITYESTIMATE_PHASE:
  78. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY;
  79. iPhaseWidth = PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY;
  80. break;
  81. case MIG_HIGHPRIORITYGATHER_PHASE:
  82. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  83. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY;
  84. iPhaseWidth = PHASEWIDTH_S_GATHER_HIGHPRIORITY;
  85. break;
  86. case MIG_GATHERQUEUE_PHASE:
  87. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  88. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY + PHASEWIDTH_S_GATHER_HIGHPRIORITY;
  89. iPhaseWidth = PHASEWIDTH_S_QUEUE_GATHER;
  90. break;
  91. case MIG_GATHERESTIMATE_PHASE:
  92. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  93. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY + PHASEWIDTH_S_GATHER_HIGHPRIORITY \
  94. + PHASEWIDTH_S_QUEUE_GATHER;
  95. iPhaseWidth = PHASEWIDTH_S_ESTIMATE_GATHER;
  96. break;
  97. case MIG_GATHER_PHASE:
  98. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  99. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY + PHASEWIDTH_S_GATHER_HIGHPRIORITY \
  100. + PHASEWIDTH_S_QUEUE_GATHER + PHASEWIDTH_S_ESTIMATE_GATHER;
  101. iPhaseWidth = PHASEWIDTH_S_GATHER_GATHER;
  102. break;
  103. case MIG_ANALYSIS_PHASE:
  104. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  105. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY + PHASEWIDTH_S_GATHER_HIGHPRIORITY \
  106. + PHASEWIDTH_S_QUEUE_GATHER + PHASEWIDTH_S_ESTIMATE_GATHER \
  107. + PHASEWIDTH_S_GATHER_GATHER;
  108. iPhaseWidth = PHASEWIDTH_S_ANALYSIS;
  109. break;
  110. case MIG_TRANSPORT_PHASE:
  111. iWork = PHASEWIDTH_S_BEGINGAP + PHASEWIDTH_S_QUEUE_HIGHPRIORITY \
  112. + PHASEWIDTH_S_ESTIMATE_HIGHPRIORITY + PHASEWIDTH_S_GATHER_HIGHPRIORITY \
  113. + PHASEWIDTH_S_QUEUE_GATHER + PHASEWIDTH_S_ESTIMATE_GATHER \
  114. + PHASEWIDTH_S_GATHER_GATHER + PHASEWIDTH_S_ANALYSIS;
  115. iPhaseWidth = PHASEWIDTH_S_TRANSPORT;
  116. break;
  117. }
  118. }
  119. else
  120. {
  121. switch (Phase)
  122. {
  123. case MIG_TRANSPORT_PHASE:
  124. iWork = PHASEWIDTH_D_BEGINGAP;
  125. iPhaseWidth = PHASEWIDTH_D_TRANSPORT;
  126. break;
  127. case MIG_HIGHPRIORITYQUEUE_PHASE:
  128. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT;
  129. iPhaseWidth = PHASEWIDTH_D_QUEUE_HIGHPRIORITY;
  130. break;
  131. case MIG_HIGHPRIORITYESTIMATE_PHASE:
  132. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  133. +PHASEWIDTH_D_QUEUE_HIGHPRIORITY;
  134. iPhaseWidth = PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY;
  135. break;
  136. case MIG_HIGHPRIORITYGATHER_PHASE:
  137. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  138. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY;
  139. iPhaseWidth = PHASEWIDTH_D_GATHER_HIGHPRIORITY;
  140. break;
  141. case MIG_GATHERQUEUE_PHASE:
  142. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  143. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY \
  144. + PHASEWIDTH_D_GATHER_HIGHPRIORITY;
  145. iPhaseWidth = PHASEWIDTH_D_QUEUE_GATHER;
  146. break;
  147. case MIG_GATHERESTIMATE_PHASE:
  148. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  149. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY \
  150. + PHASEWIDTH_D_GATHER_HIGHPRIORITY + PHASEWIDTH_D_QUEUE_GATHER;
  151. iPhaseWidth = PHASEWIDTH_D_ESTIMATE_GATHER;
  152. break;
  153. case MIG_GATHER_PHASE:
  154. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  155. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY \
  156. + PHASEWIDTH_D_GATHER_HIGHPRIORITY + PHASEWIDTH_D_QUEUE_GATHER \
  157. + PHASEWIDTH_D_ESTIMATE_GATHER;
  158. iPhaseWidth = PHASEWIDTH_D_GATHER_GATHER;
  159. break;
  160. case MIG_ANALYSIS_PHASE:
  161. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  162. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY \
  163. + PHASEWIDTH_D_GATHER_HIGHPRIORITY + PHASEWIDTH_D_QUEUE_GATHER \
  164. + PHASEWIDTH_D_ESTIMATE_GATHER + PHASEWIDTH_D_GATHER_GATHER;
  165. iPhaseWidth = PHASEWIDTH_D_ANALYSIS;
  166. break;
  167. case MIG_APPLY_PHASE:
  168. iWork = PHASEWIDTH_D_BEGINGAP + PHASEWIDTH_D_TRANSPORT \
  169. + PHASEWIDTH_D_QUEUE_HIGHPRIORITY + PHASEWIDTH_D_ESTIMATE_HIGHPRIORITY \
  170. + PHASEWIDTH_D_GATHER_HIGHPRIORITY + PHASEWIDTH_D_QUEUE_GATHER \
  171. + PHASEWIDTH_D_ESTIMATE_GATHER + PHASEWIDTH_D_GATHER_GATHER \
  172. + PHASEWIDTH_D_ANALYSIS;
  173. iPhaseWidth = PHASEWIDTH_D_APPLY;
  174. break;
  175. }
  176. }
  177. if (State == MIG_END_PHASE)
  178. {
  179. iWork += iPhaseWidth;
  180. }
  181. else if (uiTotalWork && uiWorkDone)
  182. {
  183. iWork += (iPhaseWidth * uiWorkDone) / uiTotalWork;
  184. }
  185. SendMessage(ppcs->hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, iTotal));
  186. SendMessage(ppcs->hwndProgress, PBM_SETPOS, iWork, 0);
  187. }
  188. }
  189. VOID WINAPI pFillProgressBar (ULONG_PTR pArg)
  190. {
  191. PROGRESSCALLBACKSTRUCT* ppcs = (PROGRESSCALLBACKSTRUCT*)pArg;
  192. if (!g_fUberCancel) {
  193. INT iWork = ppcs->fSource ? PHASEWIDTH_S_TOTAL : PHASEWIDTH_D_TOTAL;
  194. INT iTotal = ppcs->fSource ? PHASEWIDTH_S_TOTAL : PHASEWIDTH_D_TOTAL;
  195. SendMessage(ppcs->hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, iTotal));
  196. SendMessage(ppcs->hwndProgress, PBM_SETPOS, iWork, 0);
  197. }
  198. }
  199. //////////////////////////////////////////////////////////
  200. // prepare data
  201. HRESULT _DoCopy(LPTSTR tszTransportPath, HWND hwndProgress, HWND hwndPropSheet, BOOL* pfHasUserCancelled)
  202. {
  203. HRESULT hr = E_OUTOFMEMORY;
  204. PROGRESSCALLBACKSTRUCT* ppcs = (PROGRESSCALLBACKSTRUCT*)CoTaskMemAlloc(sizeof(PROGRESSCALLBACKSTRUCT));
  205. if (ppcs)
  206. {
  207. ppcs->hwndProgress = hwndProgress;
  208. ppcs->hwndPropSheet = hwndPropSheet;
  209. ppcs->fSource = TRUE;
  210. ppcs->pfHasUserCancelled = pfHasUserCancelled;
  211. hr = Engine_RegisterProgressBarCallback (ProgressCallback, (ULONG_PTR)ppcs);
  212. }
  213. if (SUCCEEDED(hr))
  214. {
  215. // start the transport
  216. hr = Engine_StartTransport (TRUE, tszTransportPath, NULL, NULL); // start non-network transport
  217. if (SUCCEEDED(hr))
  218. {
  219. hr = Engine_Execute(TRUE);
  220. }
  221. if (SUCCEEDED(hr))
  222. {
  223. Engine_Terminate();
  224. }
  225. }
  226. if (ppcs) {
  227. pFillProgressBar ((ULONG_PTR)ppcs);
  228. }
  229. return hr;
  230. }
  231. //////////////////////////////////////////////////////////
  232. // apply data
  233. HRESULT _DoApply(LPTSTR tszTransportPath, HWND hwndProgress, HWND hwndPropSheet, BOOL* pfHasUserCancelled,
  234. PROGRESSBARFN pAltProgressFunction, ULONG_PTR puAltProgressParam)
  235. {
  236. HRESULT hr;
  237. PROGRESSCALLBACKSTRUCT* ppcs = NULL;
  238. BOOL imageIsValid = FALSE, imageExists = FALSE;
  239. if (NULL != pAltProgressFunction)
  240. {
  241. hr = Engine_RegisterProgressBarCallback(pAltProgressFunction, puAltProgressParam);
  242. }
  243. else
  244. {
  245. hr = E_OUTOFMEMORY;
  246. ppcs = (PROGRESSCALLBACKSTRUCT*)CoTaskMemAlloc(sizeof(PROGRESSCALLBACKSTRUCT));
  247. if (ppcs)
  248. {
  249. ppcs->hwndProgress = hwndProgress;
  250. ppcs->hwndPropSheet = hwndPropSheet;
  251. ppcs->fSource = FALSE;
  252. ppcs->pfHasUserCancelled = pfHasUserCancelled;
  253. hr = Engine_RegisterProgressBarCallback(ProgressCallback, (ULONG_PTR)ppcs);
  254. }
  255. }
  256. if (SUCCEEDED(hr))
  257. {
  258. if (tszTransportPath) // if not network
  259. {
  260. hr = Engine_StartTransport(FALSE, tszTransportPath, &imageIsValid, &imageExists); // start non-network transport
  261. }
  262. else
  263. {
  264. // it's network
  265. imageIsValid = TRUE;
  266. imageExists = TRUE;
  267. }
  268. if (SUCCEEDED(hr) && imageIsValid && imageExists)
  269. {
  270. hr = Engine_Execute(FALSE);
  271. if (SUCCEEDED(hr))
  272. {
  273. Engine_Terminate();
  274. }
  275. }
  276. }
  277. if (ppcs)
  278. {
  279. pFillProgressBar ((ULONG_PTR)ppcs);
  280. }
  281. return hr;
  282. }
  283. //////////////////////////////////////////////////////////
  284. // create tool disk data
  285. BOOL _CopyFileToDisk(LPCTSTR pctszSrcFname, LPCTSTR pctszSrcPath, LPCTSTR pctszDestPath, LPCTSTR pctszDestFname,
  286. HINSTANCE hInstance, HWND hwndParent,
  287. BOOL fCompress, BOOL fFailOnError)
  288. {
  289. TCHAR tszSysDir[MAX_PATH];
  290. TCHAR tszFnameSrc[MAX_PATH];
  291. TCHAR tszFnameDest[MAX_PATH];
  292. UINT uFnameTchars;
  293. BOOL fCopySuccess = FALSE;
  294. if (pctszDestFname == NULL ||
  295. *pctszDestFname == NULL)
  296. {
  297. pctszDestFname = pctszSrcFname;
  298. }
  299. uFnameTchars = lstrlen (pctszSrcFname) + 1;
  300. // Build Source path+filename
  301. StrCpyN(tszFnameSrc, pctszSrcPath, ARRAYSIZE(tszFnameSrc) - uFnameTchars);
  302. PathAppend(tszFnameSrc, pctszSrcFname);
  303. if (!fCompress)
  304. {
  305. // Build Dest path+filename
  306. StrCpyN(tszFnameDest, pctszDestPath, ARRAYSIZE(tszFnameDest) - uFnameTchars);
  307. PathAppend(tszFnameDest, pctszDestFname);
  308. }
  309. // if source file does not exist, try using the system directory (case is shfolder.dll)
  310. if (0xFFFFFFFF == GetFileAttributes (tszFnameSrc))
  311. {
  312. GetSystemDirectory (tszSysDir, ARRAYSIZE(tszSysDir));
  313. StrCpyN(tszFnameSrc, tszSysDir, ARRAYSIZE(tszFnameSrc) - uFnameTchars);
  314. PathAppend(tszFnameSrc, pctszSrcFname);
  315. }
  316. if (fCompress)
  317. {
  318. // Add to migwiz.cab
  319. fCopySuccess = CabAddFileToCabinet( g_hCabHandle, tszFnameSrc, pctszDestFname );
  320. }
  321. else
  322. {
  323. // do the actual copy
  324. fCopySuccess = CopyFile(tszFnameSrc, tszFnameDest, FALSE);
  325. }
  326. if (fFailOnError) {
  327. return fCopySuccess;
  328. }
  329. return TRUE;
  330. }
  331. VOID
  332. pDisplayCopyError (
  333. HWND hwndParent,
  334. HINSTANCE hInstance,
  335. DWORD Error
  336. )
  337. {
  338. UINT resId;
  339. TCHAR szMigrationWizardTitle[MAX_LOADSTRING];
  340. LoadString(hInstance, IDS_MIGWIZTITLE, szMigrationWizardTitle, ARRAYSIZE(szMigrationWizardTitle));
  341. if (hwndParent) // Stand-alone wizard mode
  342. {
  343. TCHAR szErrDiskLoad[MAX_LOADSTRING];
  344. resId = IDS_ERRORDISK;
  345. if (Error == ERROR_WRITE_PROTECT) {
  346. resId = IDS_ENGERR_WRITEPROTECT;
  347. }
  348. if (Error == ERROR_NOT_READY) {
  349. resId = IDS_ENGERR_NOTREADY;
  350. }
  351. if (Error == ERROR_DISK_FULL) {
  352. resId = IDS_ENGERR_FULL;
  353. }
  354. LoadString(hInstance, resId, szErrDiskLoad, ARRAYSIZE(szErrDiskLoad));
  355. _ExclusiveMessageBox(hwndParent, szErrDiskLoad, szMigrationWizardTitle, MB_OK);
  356. }
  357. }
  358. HRESULT _CopyInfToDisk(LPCTSTR pctszDestPath, LPCTSTR pctszSourcePath, LPCTSTR pctszInfPath,
  359. PMESSAGECALLBACK2 progressCallback, LPVOID lpparam,
  360. HWND hwndProgressBar, HWND hwndParent, HINSTANCE hInstance,
  361. BOOL* pfHasUserCancelled, DWORD* pfError)
  362. {
  363. HRESULT hr = S_OK;
  364. TCHAR szCabPath [MAX_PATH];
  365. if (pfError) {
  366. *pfError = ERROR_SUCCESS;
  367. }
  368. __try {
  369. // copy the actual files over
  370. OpenAppInf((LPTSTR)pctszInfPath);
  371. if (INVALID_HANDLE_VALUE != g_hMigWizInf)
  372. {
  373. INFCONTEXT context;
  374. LONG cLinesProcessed = 0;
  375. LONG cLines = SetupGetLineCount(g_hMigWizInf, TEXT("CopyFiles")) + 1; // Last one is for closing the CAB
  376. if (SetupFindFirstLine(g_hMigWizInf, TEXT("CopyFiles"), NULL, &context))
  377. {
  378. if (!pctszDestPath) {
  379. hr = E_FAIL;
  380. __leave;
  381. }
  382. if (_tcslen(pctszDestPath) + _tcslen(S_MIGWIZCAB) + 1 >= MAX_PATH) {
  383. hr = E_FAIL;
  384. __leave;
  385. }
  386. // Delete the existing CAB that might be on the disk
  387. StrCpy (szCabPath, pctszDestPath);
  388. StrCat (szCabPath, S_MIGWIZCAB);
  389. SetFileAttributes (szCabPath, FILE_ATTRIBUTE_NORMAL);
  390. if (!DeleteFile (szCabPath)) {
  391. if (GetLastError () != ERROR_FILE_NOT_FOUND) {
  392. if (pfError) {
  393. *pfError = GetLastError ();
  394. }
  395. hr = E_FAIL;
  396. __leave;
  397. }
  398. }
  399. g_hCabHandle = CabCreateCabinet( pctszDestPath, S_MIGWIZCAB, S_TOOLDISK, IsmGetTempFile, 0 );
  400. if (g_hCabHandle)
  401. {
  402. do
  403. {
  404. TCHAR szFname[MAX_PATH];
  405. if (*pfHasUserCancelled) {
  406. hr = E_ABORT;
  407. __leave;
  408. }
  409. if (SetupGetStringField(&context, 1, szFname, ARRAYSIZE(szFname), NULL))
  410. {
  411. TCHAR szDestFname[MAX_PATH] = TEXT("");
  412. BOOL fCompress = TRUE;
  413. BOOL fFailOnError = TRUE;
  414. if (SetupGetStringField(&context, 2, szDestFname, ARRAYSIZE(szDestFname), NULL))
  415. {
  416. if (!StrCmpI(szDestFname, S_DONOTCOMPRESS))
  417. {
  418. fCompress = FALSE;
  419. *szDestFname = 0;
  420. }
  421. else if (!StrCmpI(szDestFname, S_DONOTFAIL))
  422. {
  423. fFailOnError = FALSE;
  424. *szDestFname = 0;
  425. }
  426. else
  427. {
  428. TCHAR szCompress[MAX_PATH];
  429. if (SetupGetStringField(&context, 3, szCompress, ARRAYSIZE(szCompress), NULL))
  430. {
  431. if (!StrCmpI(szCompress, S_DONOTCOMPRESS))
  432. {
  433. fCompress = FALSE;
  434. *szCompress = 0;
  435. }
  436. else if (!StrCmpI(szDestFname, S_DONOTFAIL))
  437. {
  438. fFailOnError = FALSE;
  439. *szCompress = 0;
  440. }
  441. }
  442. }
  443. }
  444. if (!_CopyFileToDisk(szFname, pctszSourcePath, pctszDestPath, szDestFname,
  445. hInstance, hwndParent, fCompress, fFailOnError))
  446. {
  447. if (pfError) {
  448. *pfError = GetLastError ();
  449. }
  450. hr = E_FAIL;
  451. }
  452. cLinesProcessed++;
  453. if (hwndProgressBar) // Stand-alone wizard mode
  454. {
  455. SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, cLines));
  456. SendMessage(hwndProgressBar, PBM_SETPOS, cLinesProcessed, 0);
  457. }
  458. if (progressCallback) // OOBE mode
  459. {
  460. progressCallback(lpparam, cLinesProcessed, cLines);
  461. }
  462. }
  463. } while (SetupFindNextLine(&context, &context));
  464. if (*pfHasUserCancelled) {
  465. hr = E_ABORT;
  466. __leave;
  467. }
  468. if (!CabFlushAndCloseCabinet(g_hCabHandle)) {
  469. if (pfError) {
  470. *pfError = GetLastError ();
  471. }
  472. hr = E_FAIL;
  473. __leave;
  474. };
  475. if (*pfHasUserCancelled) {
  476. hr = E_ABORT;
  477. __leave;
  478. }
  479. // Now that the CAB is complete, show the progress bar as finished
  480. if (hwndProgressBar) // Stand-alone wizard mode
  481. {
  482. SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, cLines));
  483. SendMessage(hwndProgressBar, PBM_SETPOS, cLines, 0);
  484. }
  485. if (progressCallback) // OOBE mode
  486. {
  487. progressCallback(lpparam, cLines, cLines);
  488. }
  489. } else {
  490. if (pfError) {
  491. *pfError = GetLastError ();
  492. }
  493. hr = E_FAIL;
  494. __leave;
  495. }
  496. }
  497. } else {
  498. if (pfError) {
  499. *pfError = ERROR_INTERNAL_ERROR;
  500. }
  501. hr = E_FAIL;
  502. __leave;
  503. }
  504. }
  505. __finally {
  506. }
  507. if (hwndParent)
  508. {
  509. if (!SUCCEEDED(hr) && (hr != E_ABORT)) {
  510. pDisplayCopyError (hwndParent, hInstance, *pfError);
  511. SendMessage(hwndParent, WM_USER_CANCELLED, 0, 0);
  512. } else {
  513. SendMessage(hwndParent, WM_USER_FINISHED, 0, 0);
  514. }
  515. }
  516. return hr;
  517. }