Leaked source code of windows server 2003
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.

666 lines
25 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. BOOL
  359. CanCreateWizardDisk (
  360. IN PCTSTR SourcePath,
  361. IN PCTSTR InfPath
  362. )
  363. {
  364. INFCONTEXT context;
  365. TCHAR sourcePath [MAX_PATH];
  366. TCHAR systemDir [MAX_PATH];
  367. TCHAR fullFileName [MAX_PATH];
  368. PTSTR filePtr = NULL;
  369. PTSTR sysFilePtr = NULL;
  370. TCHAR destName [MAX_PATH];
  371. DWORD attribs;
  372. BOOL result = FALSE;
  373. if (!SourcePath) {
  374. if (GetModuleFileName (NULL, sourcePath, ARRAYSIZE(sourcePath))) {
  375. filePtr = _tcsrchr (sourcePath, TEXT('\\'));
  376. if (filePtr) {
  377. *filePtr = 0;
  378. SourcePath = sourcePath;
  379. } else {
  380. return FALSE;
  381. }
  382. } else {
  383. return FALSE;
  384. }
  385. }
  386. OpenAppInf ((LPTSTR)InfPath);
  387. if (g_hMigWizInf != INVALID_HANDLE_VALUE) {
  388. GetSystemDirectory (systemDir, ARRAYSIZE(systemDir));
  389. sysFilePtr = _tcschr (systemDir, 0);
  390. if (sysFilePtr) {
  391. _tcscpy (sysFilePtr, TEXT("\\"));
  392. sysFilePtr = _tcschr (sysFilePtr, 0);
  393. }
  394. _tcsncpy (fullFileName, SourcePath, MAX_PATH - 2);
  395. filePtr = _tcschr (fullFileName, 0);
  396. if (filePtr) {
  397. _tcscpy (filePtr, TEXT("\\"));
  398. filePtr = _tcschr (filePtr, 0);
  399. }
  400. if (filePtr && sysFilePtr) {
  401. if (SetupFindFirstLine(g_hMigWizInf, TEXT("CopyFiles"), NULL, &context)) {
  402. result = TRUE;
  403. do {
  404. if (!SetupGetStringField (&context, 1, filePtr, ARRAYSIZE(fullFileName) - (filePtr - fullFileName), NULL)) {
  405. result = FALSE;
  406. break;
  407. }
  408. if (SetupGetStringField (&context, 2, destName, ARRAYSIZE(destName), NULL)) {
  409. if (!StrCmpI (destName, S_DONOTFAIL)) {
  410. // we don't care about this file
  411. continue;
  412. }
  413. }
  414. // let's see if this file exists on the source path
  415. attribs = GetFileAttributes (fullFileName);
  416. if (attribs == INVALID_FILE_ATTRIBUTES) {
  417. _tcsncpy (sysFilePtr, filePtr, ARRAYSIZE(systemDir) - (sysFilePtr - systemDir));
  418. attribs = GetFileAttributes (systemDir);
  419. if (attribs == INVALID_FILE_ATTRIBUTES) {
  420. result = FALSE;
  421. break;
  422. }
  423. }
  424. } while (SetupFindNextLine (&context, &context));
  425. }
  426. }
  427. CloseAppInf ();
  428. }
  429. return result;
  430. }
  431. HRESULT _CopyInfToDisk(LPCTSTR pctszDestPath, LPCTSTR pctszSourcePath, LPCTSTR pctszInfPath,
  432. PMESSAGECALLBACK2 progressCallback, LPVOID lpparam,
  433. HWND hwndProgressBar, HWND hwndParent, HINSTANCE hInstance,
  434. BOOL* pfHasUserCancelled, DWORD* pfError)
  435. {
  436. HRESULT hr = S_OK;
  437. TCHAR szCabPath [MAX_PATH];
  438. if (pfError) {
  439. *pfError = ERROR_SUCCESS;
  440. }
  441. __try {
  442. // copy the actual files over
  443. OpenAppInf((LPTSTR)pctszInfPath);
  444. if (INVALID_HANDLE_VALUE != g_hMigWizInf)
  445. {
  446. INFCONTEXT context;
  447. LONG cLinesProcessed = 0;
  448. LONG cLines = SetupGetLineCount(g_hMigWizInf, TEXT("CopyFiles")) + 1; // Last one is for closing the CAB
  449. if (SetupFindFirstLine(g_hMigWizInf, TEXT("CopyFiles"), NULL, &context))
  450. {
  451. if (!pctszDestPath) {
  452. hr = E_FAIL;
  453. __leave;
  454. }
  455. if (_tcslen(pctszDestPath) + _tcslen(S_MIGWIZCAB) + 1 >= MAX_PATH) {
  456. hr = E_FAIL;
  457. __leave;
  458. }
  459. // Delete the existing CAB that might be on the disk
  460. StrCpy (szCabPath, pctszDestPath);
  461. StrCat (szCabPath, S_MIGWIZCAB);
  462. SetFileAttributes (szCabPath, FILE_ATTRIBUTE_NORMAL);
  463. if (!DeleteFile (szCabPath)) {
  464. if (GetLastError () != ERROR_FILE_NOT_FOUND) {
  465. if (pfError) {
  466. *pfError = GetLastError ();
  467. }
  468. hr = E_FAIL;
  469. __leave;
  470. }
  471. }
  472. g_hCabHandle = CabCreateCabinet( pctszDestPath, S_MIGWIZCAB, S_TOOLDISK, IsmGetTempFile, 0 );
  473. if (g_hCabHandle)
  474. {
  475. do
  476. {
  477. TCHAR szFname[MAX_PATH];
  478. if (*pfHasUserCancelled) {
  479. hr = E_ABORT;
  480. __leave;
  481. }
  482. if (SetupGetStringField(&context, 1, szFname, ARRAYSIZE(szFname), NULL))
  483. {
  484. TCHAR szDestFname[MAX_PATH] = TEXT("");
  485. BOOL fCompress = TRUE;
  486. BOOL fFailOnError = TRUE;
  487. if (SetupGetStringField(&context, 2, szDestFname, ARRAYSIZE(szDestFname), NULL))
  488. {
  489. if (!StrCmpI(szDestFname, S_DONOTCOMPRESS))
  490. {
  491. fCompress = FALSE;
  492. *szDestFname = 0;
  493. }
  494. else if (!StrCmpI(szDestFname, S_DONOTFAIL))
  495. {
  496. fFailOnError = FALSE;
  497. *szDestFname = 0;
  498. }
  499. else
  500. {
  501. TCHAR szCompress[MAX_PATH];
  502. if (SetupGetStringField(&context, 3, szCompress, ARRAYSIZE(szCompress), NULL))
  503. {
  504. if (!StrCmpI(szCompress, S_DONOTCOMPRESS))
  505. {
  506. fCompress = FALSE;
  507. *szCompress = 0;
  508. }
  509. else if (!StrCmpI(szDestFname, S_DONOTFAIL))
  510. {
  511. fFailOnError = FALSE;
  512. *szCompress = 0;
  513. }
  514. }
  515. }
  516. }
  517. if (!_CopyFileToDisk(szFname, pctszSourcePath, pctszDestPath, szDestFname,
  518. hInstance, hwndParent, fCompress, fFailOnError))
  519. {
  520. if (pfError) {
  521. *pfError = GetLastError ();
  522. }
  523. hr = E_FAIL;
  524. }
  525. cLinesProcessed++;
  526. if (hwndProgressBar) // Stand-alone wizard mode
  527. {
  528. SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, cLines));
  529. SendMessage(hwndProgressBar, PBM_SETPOS, cLinesProcessed, 0);
  530. }
  531. if (progressCallback) // OOBE mode
  532. {
  533. progressCallback(lpparam, cLinesProcessed, cLines);
  534. }
  535. }
  536. } while (SetupFindNextLine(&context, &context));
  537. if (*pfHasUserCancelled) {
  538. hr = E_ABORT;
  539. __leave;
  540. }
  541. if (!CabFlushAndCloseCabinet(g_hCabHandle)) {
  542. if (pfError) {
  543. *pfError = GetLastError ();
  544. }
  545. hr = E_FAIL;
  546. __leave;
  547. };
  548. if (*pfHasUserCancelled) {
  549. hr = E_ABORT;
  550. __leave;
  551. }
  552. // Now that the CAB is complete, show the progress bar as finished
  553. if (hwndProgressBar) // Stand-alone wizard mode
  554. {
  555. SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, cLines));
  556. SendMessage(hwndProgressBar, PBM_SETPOS, cLines, 0);
  557. }
  558. if (progressCallback) // OOBE mode
  559. {
  560. progressCallback(lpparam, cLines, cLines);
  561. }
  562. } else {
  563. if (pfError) {
  564. *pfError = GetLastError ();
  565. }
  566. hr = E_FAIL;
  567. __leave;
  568. }
  569. }
  570. } else {
  571. if (pfError) {
  572. *pfError = ERROR_INTERNAL_ERROR;
  573. }
  574. hr = E_FAIL;
  575. __leave;
  576. }
  577. }
  578. __finally {
  579. }
  580. if (hwndParent)
  581. {
  582. if (!SUCCEEDED(hr) && (hr != E_ABORT)) {
  583. pDisplayCopyError (hwndParent, hInstance, *pfError);
  584. SendMessage(hwndParent, WM_USER_CANCELLED, 0, 0);
  585. } else {
  586. SendMessage(hwndParent, WM_USER_FINISHED, 0, 0);
  587. }
  588. }
  589. return hr;
  590. }