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.

1590 lines
50 KiB

  1. //--------------------------------------------------------------
  2. //
  3. // File: loadfiles
  4. //
  5. // Contents: Load files.
  6. //
  7. //---------------------------------------------------------------
  8. #include "loadhead.cxx"
  9. #pragma hdrstop
  10. #include <common.hxx>
  11. #include <loadstate.hxx>
  12. #include <bothchar.hxx>
  13. #include <section.hxx>
  14. #include <special.hxx>
  15. #include <fileutil.cxx>
  16. #define CREATE_DIRECTORY_MAX_PATH 248
  17. //---------------------------------------------------------------
  18. CSection *g_pcsSectionList = NULL;
  19. CSpecialDirectory g_csdCurrent;
  20. CSpecialDirectory g_csdOld;
  21. CRuleList g_crlExcludeWildcards;
  22. CRuleList g_crlIncludeWildcards;
  23. //---------------------------------------------------------------
  24. DWORD ComputeTemp()
  25. {
  26. return ERROR_SUCCESS;
  27. }
  28. //---------------------------------------------------------------
  29. void EraseTemp()
  30. {
  31. }
  32. DWORD FixShellShortcut(const TCHAR *ptsFile)
  33. {
  34. HRESULT hr;
  35. IShellLink *pisl = NULL;
  36. IPersistFile *pipf = NULL;
  37. TCHAR *ptsDest = NULL;
  38. WIN32_FIND_DATA wfd;
  39. if (DebugOutput)
  40. Win32Printf(LogFile,
  41. "Called FixShellShortcut for %s\r\n",
  42. ptsFile);
  43. hr = CoCreateInstance(CLSID_ShellLink,
  44. NULL,
  45. CLSCTX_INPROC_SERVER,
  46. IID_IShellLink,
  47. (void **)&pisl);
  48. if (FAILED(hr))
  49. goto cleanup;
  50. hr = pisl->QueryInterface(IID_IPersistFile,
  51. (void **)&pipf);
  52. if (FAILED(hr))
  53. goto cleanup;
  54. hr = pipf->Load(ptsFile,
  55. 0);
  56. if (FAILED(hr))
  57. goto cleanup;
  58. TCHAR ptsPath[MAX_PATH + 1];
  59. hr = pisl->GetPath(ptsPath,
  60. MAX_PATH + 1,
  61. &wfd,
  62. SLGP_RAWPATH);
  63. if (FAILED(hr))
  64. goto cleanup;
  65. if (DebugOutput)
  66. Win32Printf(LogFile,
  67. "Retrieved path %s from shell link %s\r\n",
  68. ptsPath,
  69. ptsFile);
  70. hr = WhereIsThisFile(ptsPath, &ptsDest);
  71. if (hr == ERROR_SUCCESS)
  72. {
  73. //Change the shortcut
  74. //Expand any environment strings in the original data with
  75. //the values for the user we're loading for. If the final
  76. //paths match, we'll retain the version of the data with the
  77. //unexpanded environment variables in it. Otherwise, we take
  78. //the full path.
  79. //We could be much smarter here if we wanted to.
  80. //For instance:
  81. // 1) Check the old path against the old special directories
  82. // list, and try to remap things that match.
  83. // 2) Double check to make sure the shortcut is actually
  84. // broken before we go ahead and fix it.
  85. TCHAR tsExpand[MAX_PATH + 1];
  86. TCHAR tsTemp[MAX_PATH + 1];
  87. TCHAR *ptsFinalDest;
  88. if (_tcslen(ptsPath) > MAX_PATH)
  89. {
  90. if (DebugOutput)
  91. Win32Printf(LogFile, "Error: ptsPath too long %s\r\n", ptsPath);
  92. goto cleanup;
  93. }
  94. _tcscpy(tsExpand, ptsPath);
  95. hr = ExpandEnvStringForUser(tsExpand,
  96. tsTemp,
  97. &ptsFinalDest);
  98. if (hr)
  99. goto cleanup;
  100. if (_tcsicmp(ptsDest, ptsFinalDest) == 0)
  101. {
  102. //They're the same, use the string with the environment
  103. //variables in it.
  104. ptsFinalDest = ptsPath;
  105. }
  106. else
  107. {
  108. ptsFinalDest = ptsDest;
  109. }
  110. hr = pisl->SetPath(ptsFinalDest);
  111. if (FAILED(hr))
  112. goto cleanup;
  113. if (DebugOutput)
  114. Win32Printf(LogFile,
  115. "FixShellShortcut fixed %s from %s to %s\r\n",
  116. ptsFile,
  117. ptsPath,
  118. ptsFinalDest);
  119. }
  120. //If this function failed, we leave the shortcut alone. A possible
  121. //change is to delete the shortcut for this case.
  122. cleanup:
  123. if (ptsDest != NULL)
  124. free(ptsDest);
  125. if (pipf != NULL)
  126. pipf->Release();
  127. if (pisl != NULL)
  128. pisl->Release();
  129. return ERROR_SUCCESS;
  130. }
  131. DWORD ExpandEnvStringForUser(TCHAR *ptsString,
  132. TCHAR *ptsTemp,
  133. TCHAR **pptsFinal)
  134. {
  135. return g_csdCurrent.ExpandMacro(ptsString,
  136. ptsTemp,
  137. pptsFinal,
  138. FALSE);
  139. }
  140. //---------------------------------------------------------------
  141. DWORD WhereIsThisFile( const TCHAR *ptsFile, TCHAR **pptsNewFile )
  142. {
  143. CSection *pcsCurrent = g_pcsSectionList;
  144. TCHAR tsExpName[MAX_PATH + 1];
  145. TCHAR tsTemp[MAX_PATH + 1];
  146. TCHAR *ptsFullName;
  147. DWORD dwErr;
  148. if (_tcslen(ptsFile) > MAX_PATH)
  149. {
  150. if (DebugOutput)
  151. Win32Printf(LogFile, "Error: ptsFile too long %s\r\n", ptsFile);
  152. return ERROR_FILENAME_EXCED_RANGE;
  153. }
  154. _tcscpy(tsExpName, ptsFile);
  155. dwErr = g_csdOld.ExpandMacro(tsExpName, tsTemp, &ptsFullName, FALSE);
  156. if (dwErr)
  157. return dwErr;
  158. while (pcsCurrent != NULL)
  159. {
  160. TCHAR *ptsFileOnly;
  161. ptsFileOnly = _tcsrchr(ptsFullName, '\\');
  162. if ((NULL == ptsFileOnly) ||
  163. (_tcsnicmp(ptsFullName,
  164. pcsCurrent->GetSectionPath(),
  165. pcsCurrent->GetSectionPathLength()) == 0))
  166. {
  167. //Section matches, search for file
  168. if (NULL == ptsFileOnly)
  169. {
  170. ptsFileOnly = ptsFullName;
  171. }
  172. else
  173. {
  174. ptsFileOnly = ptsFullName + pcsCurrent->GetSectionPathLength() + 1;
  175. }
  176. for (ULONG i = 0; i < pcsCurrent->GetNameCount(); i++)
  177. {
  178. const TCHAR *ptsCurrent = pcsCurrent->GetFullFileName(i);
  179. if (_tcsicmp(ptsFileOnly,
  180. ptsCurrent) == 0)
  181. {
  182. TCHAR tsDest[MAX_PATH + 1];
  183. const TCHAR *ptsDest = pcsCurrent->GetDestination(i);
  184. if (ptsDest == NULL)
  185. {
  186. DWORD dwDestLen = pcsCurrent->GetSectionDestLength();
  187. if (dwDestLen + _tcslen(ptsCurrent) + 1 > MAX_PATH)
  188. {
  189. if (Verbose)
  190. {
  191. Win32Printf(LogFile,
  192. "Error: destination too long %s\\%s\r\n",
  193. pcsCurrent->GetSectionDest(),
  194. ptsCurrent);
  195. }
  196. return ERROR_FILENAME_EXCED_RANGE;
  197. }
  198. _tcscpy(tsDest, pcsCurrent->GetSectionDest());
  199. tsDest[dwDestLen] = TEXT('\\');
  200. _tcscpy(tsDest + dwDestLen + 1, ptsCurrent);
  201. ptsDest = tsDest;
  202. }
  203. //Bingo, direct hit.
  204. *pptsNewFile = (TCHAR *) malloc(
  205. (_tcslen(ptsDest) + 1) * sizeof(TCHAR));
  206. if (*pptsNewFile == NULL)
  207. return ERROR_NOT_ENOUGH_MEMORY;
  208. _tcscpy( *pptsNewFile, ptsDest);
  209. if (DebugOutput)
  210. Win32Printf(LogFile,
  211. "WhereIsThisFile(%ws) found %ws\r\n",
  212. ptsFile,
  213. *pptsNewFile);
  214. return ERROR_SUCCESS;
  215. }
  216. }
  217. }
  218. pcsCurrent = pcsCurrent->GetNextSection();
  219. }
  220. return ERROR_NOT_FOUND;
  221. }
  222. DWORD AddInfSectionToRuleList(INFCONTEXT *pic,
  223. CRuleList *pfl,
  224. BOOL fAllowRename)
  225. {
  226. TCHAR buf[MAX_PATH + 1];
  227. TCHAR bufMacro[MAX_PATH + 1];
  228. TCHAR *ptsFinalName;
  229. TCHAR bufTag[MAX_PATH + 1];
  230. DWORD dwErr;
  231. CRuleList *prl;
  232. do
  233. {
  234. DWORD dwIndex;
  235. DWORD cFields;
  236. BOOL fDirectoryTag = FALSE;
  237. cFields = SetupGetFieldCount(pic);
  238. if (((cFields != 1) && !fAllowRename) ||
  239. ((cFields > 2) && fAllowRename))
  240. {
  241. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  242. if (Verbose)
  243. Win32Printf(STDERR,
  244. "Line contains more than one file name\r\n");
  245. return ERROR_INVALID_PARAMETER;
  246. }
  247. if (!SetupGetStringField(pic,
  248. 1,
  249. buf,
  250. MAX_PATH + 1,
  251. NULL))
  252. {
  253. dwErr = GetLastError();
  254. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  255. if (Verbose)
  256. Win32Printf(STDERR,
  257. "SetupGetStringField returned %lu\r\n",
  258. dwErr);
  259. return dwErr;
  260. }
  261. if (SetupGetStringField(pic,
  262. 0,
  263. bufTag,
  264. MAX_PATH + 1,
  265. NULL))
  266. {
  267. if (_tcsicmp(bufTag, buf))
  268. {
  269. //Someone put a field identifier on there. The only
  270. //one we recognize is 'dir'
  271. if (_tcsicmp(bufTag, TEXT("dir")))
  272. {
  273. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  274. if (Verbose)
  275. Win32Printf(STDERR,
  276. "Unknown tag %s\r\n",
  277. bufTag);
  278. return ERROR_INVALID_PARAMETER;
  279. }
  280. fDirectoryTag = TRUE;
  281. }
  282. }
  283. dwErr = g_csdOld.ExpandMacro(buf, bufMacro, &ptsFinalName, TRUE);
  284. if (dwErr)
  285. return dwErr;
  286. if (fDirectoryTag)
  287. {
  288. //Append a backslash
  289. if (_tcslen(ptsFinalName) >= MAX_PATH)
  290. {
  291. if (DebugOutput)
  292. {
  293. Win32Printf(LogFile, "Error: ptsFinalName too long %s\r\n", ptsFinalName);
  294. }
  295. return ERROR_FILENAME_EXCED_RANGE;
  296. }
  297. _tcscat(ptsFinalName, TEXT("\\"));
  298. }
  299. dwErr = pfl->SetName(ptsFinalName, &prl);
  300. if (dwErr)
  301. {
  302. return dwErr;
  303. }
  304. if (cFields == 2)
  305. {
  306. if (!SetupGetStringField(pic,
  307. 2,
  308. buf,
  309. MAX_PATH + 1,
  310. NULL))
  311. {
  312. dwErr = GetLastError();
  313. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  314. if (Verbose)
  315. Win32Printf(STDERR,
  316. "SetupGetStringField returned %lu\r\n",
  317. dwErr);
  318. return dwErr;
  319. }
  320. dwErr = prl->SetDestination(buf);
  321. if (dwErr)
  322. {
  323. return dwErr;
  324. }
  325. }
  326. }
  327. while (SetupFindNextLine(pic, pic));
  328. return ERROR_SUCCESS;
  329. }
  330. DWORD ProcessCopyFiles(HINF hi, const TCHAR *ptsName)
  331. {
  332. DWORD dwErr;
  333. INFCONTEXT ic;
  334. if (!SetupFindFirstLine(hi,
  335. ptsName,
  336. NULL,
  337. &ic))
  338. {
  339. dwErr = GetLastError();
  340. Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
  341. if (Verbose)
  342. Win32Printf(STDERR,
  343. "SetupFindFirstLine failed on section %s with %lu\r\n",
  344. ptsName,
  345. dwErr);
  346. return dwErr;
  347. }
  348. dwErr = AddInfSectionToRuleList(&ic, &g_crlIncludeWildcards, TRUE);
  349. return dwErr;
  350. }
  351. DWORD ProcessDelFiles(HINF hi, const TCHAR *ptsName)
  352. {
  353. DWORD dwErr;
  354. INFCONTEXT ic;
  355. if (!SetupFindFirstLine(hi,
  356. ptsName,
  357. NULL,
  358. &ic))
  359. {
  360. dwErr = GetLastError();
  361. Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
  362. if (Verbose)
  363. Win32Printf(STDERR,
  364. "SetupFindFirstLine failed on section %s with %lu\r\n",
  365. ptsName,
  366. dwErr);
  367. return dwErr;
  368. }
  369. dwErr = AddInfSectionToRuleList(&ic, &g_crlExcludeWildcards, FALSE);
  370. return dwErr;
  371. }
  372. DWORD ProcessRules(HINF hi)
  373. {
  374. DWORD dwErr;
  375. INFCONTEXT ic;
  376. if (!SetupFindFirstLine(hi,
  377. EXTENSION_SECTION,
  378. NULL,
  379. &ic))
  380. {
  381. //Ignore - this section is optional
  382. return ERROR_SUCCESS;
  383. }
  384. do
  385. {
  386. DWORD cFields;
  387. cFields = SetupGetFieldCount(&ic);
  388. TCHAR buf[MAX_PATH + 1];
  389. if (!SetupGetStringField(&ic,
  390. 0,
  391. buf,
  392. MAX_PATH + 1,
  393. NULL))
  394. {
  395. dwErr = GetLastError();
  396. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  397. if (Verbose)
  398. Win32Printf(STDERR,
  399. "SetupGetStringField failed with %lu\r\n",
  400. dwErr);
  401. return dwErr;
  402. }
  403. if (_tcsicmp(buf, COPYFILES_LABEL) == 0)
  404. {
  405. //Add files in all sections to the include list
  406. for (DWORD j = 1; j < cFields + 1; j++)
  407. {
  408. if (!SetupGetStringField(&ic,
  409. j,
  410. buf,
  411. MAX_PATH + 1,
  412. NULL))
  413. {
  414. dwErr = GetLastError();
  415. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  416. if (Verbose)
  417. Win32Printf(STDERR,
  418. "SetupGetStringField failed with %lu\r\n",
  419. dwErr);
  420. return dwErr;
  421. }
  422. dwErr = ProcessCopyFiles(hi, buf);
  423. if (dwErr != 0)
  424. return dwErr;
  425. }
  426. }
  427. else if (_tcsicmp(buf, DELFILES_LABEL) == 0)
  428. {
  429. //Add files in all sections to the include list
  430. for (DWORD j = 1; j < cFields + 1; j++)
  431. {
  432. if (!SetupGetStringField(&ic,
  433. j,
  434. buf,
  435. MAX_PATH + 1,
  436. NULL))
  437. {
  438. dwErr = GetLastError();
  439. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  440. if (Verbose)
  441. Win32Printf(STDERR,
  442. "SetupGetStringField failed with %lu\r\n",
  443. dwErr);
  444. return dwErr;
  445. }
  446. dwErr = ProcessDelFiles(hi, buf);
  447. if (dwErr != 0)
  448. return dwErr;
  449. }
  450. }
  451. }
  452. while (SetupFindNextLine(&ic, &ic));
  453. return ERROR_SUCCESS;
  454. }
  455. DWORD ProcessSpecialDirs(HINF hi)
  456. {
  457. DWORD dwErr;
  458. INFCONTEXT ic;
  459. if (!SetupFindFirstLine(hi,
  460. SPECIALDIRS_SECTION,
  461. NULL,
  462. &ic))
  463. {
  464. dwErr = GetLastError();
  465. Win32PrintfResource(LogFile,
  466. IDS_SECTION_NAME_NOT_FOUND,
  467. SPECIALDIRS_SECTION);
  468. if (Verbose)
  469. Win32Printf(STDERR,
  470. "SetupFindFirstLine failed with %lu\r\n",
  471. dwErr);
  472. return dwErr;
  473. }
  474. do
  475. {
  476. TCHAR bufName[MAX_PATH + 1];
  477. TCHAR bufPath[MAX_PATH + 2];
  478. DWORD cFields;
  479. cFields = SetupGetFieldCount(&ic);
  480. if (cFields != 1)
  481. {
  482. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  483. if (Verbose)
  484. Win32Printf(STDERR,
  485. "INF line contains too many fields in "
  486. "section %s\r\n",
  487. SPECIALDIRS_SECTION);
  488. return ERROR_INVALID_PARAMETER;
  489. }
  490. if (!SetupGetStringField(&ic,
  491. 0,
  492. bufName,
  493. MAX_PATH + 1,
  494. NULL))
  495. {
  496. dwErr = GetLastError();
  497. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  498. if (Verbose)
  499. Win32Printf(STDERR,
  500. "SetupGetStringField returned %lu\r\n",
  501. dwErr);
  502. return dwErr;
  503. }
  504. if (!SetupGetStringField(&ic,
  505. 1,
  506. bufPath,
  507. MAX_PATH + 1,
  508. NULL))
  509. {
  510. dwErr = GetLastError();
  511. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  512. if (Verbose)
  513. Win32Printf(STDERR,
  514. "SetupGetStringField returned %lu\r\n",
  515. dwErr);
  516. return dwErr;
  517. }
  518. dwErr = g_csdOld.InitFromInf(bufName, bufPath);
  519. if (dwErr)
  520. return dwErr;
  521. }
  522. while (SetupFindNextLine(&ic, &ic));
  523. return ERROR_SUCCESS;
  524. }
  525. DWORD AddLoadFileSection(HINF hi, TCHAR *ptsName, CSection **ppcs)
  526. {
  527. DWORD dwErr;
  528. INFCONTEXT ic;
  529. CSection *pcsSection;
  530. TCHAR tsSection[MAX_PATH + 1];
  531. TCHAR buf[MAX_PATH + 1];
  532. TCHAR bufDest[MAX_PATH + 1];
  533. TCHAR bufMacro[MAX_PATH + 1];
  534. TCHAR *ptsFinalName;
  535. pcsSection = new CSection;
  536. if (pcsSection == NULL)
  537. {
  538. Win32PrintfResource(LogFile, IDS_NOT_ENOUGH_MEMORY);
  539. return ERROR_OUTOFMEMORY;
  540. }
  541. if (ppcs)
  542. *ppcs = pcsSection;
  543. if (g_pcsSectionList == NULL)
  544. {
  545. g_pcsSectionList = pcsSection;
  546. }
  547. else
  548. {
  549. g_pcsSectionList->AddToList(pcsSection);
  550. }
  551. dwErr = pcsSection->SetSectionTitle(ptsName);
  552. if (dwErr)
  553. {
  554. return dwErr;
  555. }
  556. if (_tcslen(ptsName) > MAX_PATH)
  557. {
  558. if (DebugOutput)
  559. Win32Printf(LogFile, "Error: ptsName too long %s\r\n", ptsName);
  560. return ERROR_FILENAME_EXCED_RANGE;
  561. }
  562. _tcscpy(buf, ptsName);
  563. dwErr = g_csdOld.ExpandMacro(buf, bufMacro, &ptsFinalName, TRUE);
  564. if (dwErr)
  565. {
  566. //Try with the current list
  567. dwErr = g_csdCurrent.ExpandMacro(buf, bufMacro, &ptsFinalName, FALSE);
  568. if (dwErr)
  569. return dwErr;
  570. }
  571. dwErr = pcsSection->SetSectionPath(ptsFinalName);
  572. if (dwErr)
  573. {
  574. return dwErr;
  575. }
  576. const TCHAR *ptsSectionPath = pcsSection->GetSectionPath();
  577. if (_tcslen(ptsSectionPath) + 1 > MAX_PATH)
  578. {
  579. if (DebugOutput)
  580. Win32Printf(LogFile, "Error: ptsSectionPath too long %s\r\n", ptsSectionPath);
  581. return ERROR_FILENAME_EXCED_RANGE;
  582. }
  583. _tcscpy(tsSection, ptsSectionPath);
  584. _tcscat(tsSection, TEXT("\\"));
  585. if (!SetupFindFirstLine(hi,
  586. ptsName,
  587. NULL,
  588. &ic))
  589. {
  590. dwErr = GetLastError();
  591. Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
  592. if (Verbose)
  593. Win32Printf(STDERR,
  594. "SetupFindFirstLine failed on section %s with %lu\r\n",
  595. ptsName,
  596. dwErr);
  597. return dwErr;
  598. }
  599. do
  600. {
  601. DWORD cFields;
  602. cFields = SetupGetFieldCount(&ic);
  603. if ((cFields != 1) && (cFields != 2))
  604. {
  605. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  606. if (Verbose)
  607. Win32Printf(STDERR,
  608. "INF line contains too many fields in "
  609. "section %s\r\n",
  610. ptsName);
  611. return ERROR_INVALID_PARAMETER;
  612. }
  613. if (!SetupGetStringField(&ic,
  614. 1,
  615. buf,
  616. MAX_PATH + 1,
  617. NULL))
  618. {
  619. dwErr = GetLastError();
  620. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  621. if (Verbose)
  622. Win32Printf(STDERR,
  623. "SetupGetStringField returned %lu\r\n",
  624. dwErr);
  625. return dwErr;
  626. }
  627. dwErr = g_csdCurrent.ExpandMacro(buf,
  628. bufMacro,
  629. &ptsFinalName,
  630. TRUE);
  631. if (dwErr)
  632. return dwErr;
  633. //Check if we're supposed to exclude this file by a rule
  634. CRuleList *prl;
  635. if (!g_crlExcludeWildcards.MatchAgainstRuleList(tsSection,
  636. buf,
  637. &prl,
  638. NULL))
  639. {
  640. DWORD i;
  641. dwErr = pcsSection->SetName(ptsFinalName, &i, FALSE);
  642. if (dwErr)
  643. return dwErr;
  644. if (cFields == 2)
  645. {
  646. if (!SetupGetStringField(&ic,
  647. 2,
  648. bufDest,
  649. MAX_PATH + 1,
  650. NULL))
  651. {
  652. dwErr = GetLastError();
  653. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  654. if (Verbose)
  655. Win32Printf(STDERR,
  656. "SetupGetStringField returned %lu\r\n",
  657. dwErr);
  658. return dwErr;
  659. }
  660. dwErr = g_csdCurrent.ExpandMacro(bufDest,
  661. bufMacro,
  662. &ptsFinalName,
  663. TRUE);
  664. if (dwErr)
  665. return dwErr;
  666. dwErr = pcsSection->SetDestination(ptsFinalName, i);
  667. if (dwErr)
  668. return dwErr;
  669. }
  670. }
  671. else
  672. {
  673. if (Verbose)
  674. Win32Printf(LogFile,
  675. "Excluding %s by rule %s\r\n",
  676. buf,
  677. prl->GetFullName());
  678. }
  679. }
  680. while (SetupFindNextLine(&ic, &ic));
  681. return ERROR_SUCCESS;
  682. }
  683. DWORD CopyAllFiles(void)
  684. {
  685. DWORD dwErr;
  686. CSection *pcs = g_pcsSectionList;
  687. DWORD ccMigPath;
  688. TCHAR tsFinalSource[MAX_PATH + 1];
  689. TCHAR tsSectionDest[MAX_PATH + 1];
  690. TCHAR tsFinalDest[MAX_PATH + 1];
  691. TCHAR *ptsJustFile;
  692. DWORD ccPredictedLength;
  693. DWORD dwReturnUp = ERROR_SUCCESS;
  694. #ifdef UNICODE
  695. if (_tcslen(wcsMigrationPath) > MAX_PATH)
  696. {
  697. if (DebugOutput)
  698. Win32Printf(LogFile, "Error: wcsMigrationPath too long %s\r\n", wcsMigrationPath);
  699. return ERROR_FILENAME_EXCED_RANGE;
  700. }
  701. wcscpy(tsFinalSource, wcsMigrationPath);
  702. ccMigPath = wcslen(wcsMigrationPath);
  703. #else
  704. if (_tcslen(MigrationPath) > MAX_PATH)
  705. {
  706. if (DebugOutput)
  707. Win32Printf(LogFile, "Error: MigrationPath too long %s\r\n", MigrationPath);
  708. return ERROR_FILENAME_EXCED_RANGE;
  709. }
  710. strcpy(tsFinalSource, MigrationPath);
  711. ccMigPath = strlen(MigrationPath);
  712. #endif
  713. while (pcs != NULL)
  714. {
  715. ULONG ulNameCount = pcs->GetNameCount();
  716. //Add section to source path
  717. const TCHAR *ptsSection = pcs->GetSectionPath();
  718. DWORD ccSection = pcs->GetSectionPathLength() + ccMigPath;
  719. if ( ccSection + 1 > MAX_PATH )
  720. {
  721. Win32PrintfResource(LogFile,
  722. IDS_FILE_COPYERROR,
  723. ptsSection);
  724. if (Verbose)
  725. {
  726. Win32Printf(STDERR,
  727. "Skipping Too Long Source Filename: %s\\%s\r\n",
  728. tsFinalSource,
  729. ptsSection);
  730. }
  731. if (dwReturnUp == ERROR_SUCCESS)
  732. {
  733. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  734. }
  735. pcs = pcs->GetNextSection();
  736. continue;
  737. }
  738. tsFinalSource[ccMigPath] = TEXT('\\');
  739. tsFinalSource[ccMigPath + 1] = ptsSection[0];
  740. _tcscpy(tsFinalSource + ccMigPath + 2, ptsSection + 2);
  741. tsFinalSource[ccSection++] = TEXT('\\');
  742. tsFinalSource[ccSection] = 0;
  743. // Build Destination Path
  744. INT_PTR ccDest = pcs->GetSectionDestLength();
  745. if ( ccDest + 1 > MAX_PATH )
  746. {
  747. Win32PrintfResource(LogFile,
  748. IDS_FILE_COPYERROR,
  749. pcs->GetSectionDest);
  750. if (Verbose)
  751. {
  752. Win32Printf(STDERR,
  753. "Skipping Too Long Destination Filename: %s\r\n",
  754. pcs->GetSectionDest);
  755. }
  756. if (dwReturnUp == ERROR_SUCCESS)
  757. {
  758. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  759. }
  760. pcs = pcs->GetNextSection();
  761. continue;
  762. }
  763. _tcscpy(tsSectionDest, pcs->GetSectionDest());
  764. if (tsSectionDest[ccDest - 1] != TEXT('\\'))
  765. {
  766. tsSectionDest[ccDest++] = TEXT('\\');
  767. tsSectionDest[ccDest] = 0;
  768. }
  769. for (ULONG i = 0; i < ulNameCount; i++)
  770. {
  771. TCHAR *ptsDestFinal;
  772. const TCHAR *ptsName = pcs->GetFullFileName(i);
  773. const TCHAR *ptsDest = pcs->GetDestination(i);
  774. if (ptsDest != NULL)
  775. {
  776. TCHAR *ptsTopDir;
  777. // File is explicitly being migrated
  778. // Build the destination filename with these pieces:
  779. // - Destination dir specified in the file rule
  780. // - Last piece of the path in the section heading
  781. // - Filename
  782. DWORD ccFinalDest = _tcslen(ptsDest);
  783. if (ccFinalDest > MAX_PATH)
  784. {
  785. Win32PrintfResource(LogFile, IDS_FILE_COPYERROR, ptsName);
  786. if (Verbose)
  787. Win32Printf(STDERR, "Skipping Too Long Destination Filename: %s\r\n",
  788. ptsDest);
  789. continue;
  790. }
  791. _tcscpy(tsFinalDest, ptsDest);
  792. if (tsFinalDest[ccFinalDest] != TEXT('\\') && ccFinalDest < MAX_PATH)
  793. {
  794. tsFinalDest[ccFinalDest++] = TEXT('\\');
  795. }
  796. ptsTopDir = _tcsrchr( ptsSection, TEXT('\\'));
  797. if (ptsTopDir != NULL)
  798. {
  799. ptsTopDir++; // move past the '\'
  800. }
  801. // Skip this if we're going to create a filename that is too long
  802. ccPredictedLength = ccFinalDest + _tcslen(ptsName);
  803. if (ptsTopDir != NULL)
  804. {
  805. ccPredictedLength += _tcslen(ptsTopDir) + 1;
  806. }
  807. if ( ccPredictedLength > MAX_PATH )
  808. {
  809. Win32PrintfResource(LogFile,
  810. IDS_FILE_COPYERROR,
  811. ptsName);
  812. if (Verbose)
  813. {
  814. tsFinalDest[ccFinalDest] = 0; // Null terminate for printing
  815. if (ptsTopDir == NULL)
  816. Win32Printf(STDERR,
  817. "Skipping Too Long Destination Filename: %s%s\r\n",
  818. tsFinalDest,
  819. ptsName);
  820. else
  821. Win32Printf(STDERR,
  822. "Skipping Too Long Destination Filename: %s%s\\%s\r\n",
  823. tsFinalDest,
  824. ptsTopDir,
  825. ptsName);
  826. }
  827. if (dwReturnUp == ERROR_SUCCESS)
  828. {
  829. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  830. }
  831. continue;
  832. }
  833. if (ptsTopDir != NULL)
  834. {
  835. _tcscpy(tsFinalDest + ccFinalDest, ptsTopDir);
  836. ccFinalDest += _tcslen(ptsTopDir);
  837. if (tsFinalDest[ccFinalDest] != TEXT('\\') )
  838. {
  839. tsFinalDest[ccFinalDest++] = TEXT('\\');
  840. }
  841. }
  842. _tcscpy(tsFinalDest + ccFinalDest, ptsName);
  843. ptsDestFinal = tsFinalDest;
  844. }
  845. else
  846. {
  847. if ( ccDest + _tcslen(ptsName) > MAX_PATH )
  848. {
  849. Win32PrintfResource(LogFile,
  850. IDS_FILE_COPYERROR,
  851. ptsName);
  852. if (Verbose)
  853. {
  854. tsFinalDest[ccDest] = 0; // Null terminate for printing
  855. Win32Printf(STDERR,
  856. "Skipping Too Long Destination Filename: %s%s\r\n",
  857. tsFinalDest,
  858. ptsName);
  859. }
  860. if (dwReturnUp == ERROR_SUCCESS)
  861. {
  862. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  863. }
  864. continue;
  865. }
  866. //Use section destination
  867. _tcscpy(tsSectionDest + ccDest, ptsName);
  868. ptsDestFinal = tsSectionDest;
  869. }
  870. DWORD_PTR ccDestDir;
  871. // If the directory is more than 248 characters, then CreateDirectory will fail
  872. // There is no system define for 248, unfortunately.. It's only mentioned in the
  873. // documentation. How odd.
  874. ptsJustFile = _tcsrchr(ptsDestFinal, '\\');
  875. if ( ptsJustFile == NULL )
  876. {
  877. ccDestDir = _tcslen(ptsDestFinal);
  878. }
  879. else
  880. {
  881. ccDestDir = ptsJustFile - ptsDestFinal;
  882. ptsJustFile++; // Move past the '\'
  883. }
  884. if ( ccDestDir > CREATE_DIRECTORY_MAX_PATH )
  885. {
  886. Win32PrintfResource(LogFile,
  887. IDS_FILE_COPYERROR,
  888. ptsName);
  889. if (Verbose)
  890. {
  891. ptsDestFinal[ccDestDir] = 0; // Null terminate for printing
  892. Win32Printf(STDERR,
  893. "Skipping Too Long Destination Directory: %s for %s\r\n",
  894. ptsDestFinal,
  895. ptsJustFile ? ptsJustFile : TEXT("file list") );
  896. }
  897. if (dwReturnUp == ERROR_SUCCESS)
  898. {
  899. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  900. }
  901. continue;
  902. }
  903. // Windows appears to enforce that an existing file cannot exceed MAX_PATH,
  904. // but we'll check just to make sure.
  905. if ( (ccSection + _tcslen(ptsName)) > MAX_PATH )
  906. {
  907. Win32PrintfResource(LogFile,
  908. IDS_FILE_COPYERROR,
  909. ptsName);
  910. if (Verbose)
  911. {
  912. tsFinalSource[ccSection] = 0; // Null terminate for printing
  913. Win32Printf(STDERR,
  914. "Skipping Too Long Source Filename: %s\\%s\r\n",
  915. tsFinalSource,
  916. ptsName);
  917. }
  918. if (dwReturnUp == ERROR_SUCCESS)
  919. {
  920. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  921. }
  922. continue;
  923. }
  924. _tcscpy(tsFinalSource + ccSection, ptsName);
  925. // Store the full destination in the file list
  926. pcs->SetDestination(ptsDestFinal, i);
  927. //Finally we have the filenames constructed, now try
  928. //the CopyFile operation
  929. BOOL fPath = FALSE;
  930. ULONG ulVersion = 1;
  931. TCHAR tsCollision[MAX_PATH + 1];
  932. INT_PTR ccExt;
  933. TCHAR *ptsDestOriginal = ptsDestFinal;
  934. if (DebugOutput)
  935. {
  936. Win32Printf(LogFile, "Copying %s to %s\r\n", tsFinalSource, ptsDestFinal);
  937. }
  938. while (!CopyFile(tsFinalSource,
  939. ptsDestFinal,
  940. TRUE))
  941. {
  942. dwErr = GetLastError();
  943. if (dwErr == ERROR_PATH_NOT_FOUND)
  944. {
  945. if (fPath)
  946. {
  947. //We already tried to create the path, so something
  948. //else must be wrong. Punt-arooney.
  949. break;
  950. }
  951. dwErr = ERROR_SUCCESS;
  952. TCHAR *ptsPos;
  953. DWORD dwPos;
  954. //Try to create all the necessary directories
  955. TCHAR ptsDirectory[MAX_PATH + 1];
  956. // ptsDestFinal was built inside this function and verified to
  957. // be less than MAX_PATH in length
  958. _tcscpy(ptsDirectory, ptsDestFinal);
  959. dwPos = 0;
  960. // Skip any leading drive specifier.
  961. if (ptsDirectory[0] == TEXT('\\'))
  962. dwPos = 1;
  963. else if (ptsDirectory[0] != 0 &&
  964. ptsDirectory[1] == TEXT(':'))
  965. if (ptsDirectory[2] == TEXT('\\'))
  966. dwPos = 3;
  967. else
  968. dwPos = 2;
  969. //Create every directory along this path
  970. while (ptsPos = _tcschr(ptsDirectory + dwPos, TEXT('\\')))
  971. {
  972. *ptsPos = 0;
  973. //Create the directory
  974. if (!CreateDirectory(ptsDirectory,
  975. NULL))
  976. {
  977. dwErr = GetLastError();
  978. if (dwErr != ERROR_ALREADY_EXISTS)
  979. {
  980. break;
  981. }
  982. dwErr = ERROR_SUCCESS;
  983. }
  984. //Put the backslash back in
  985. *ptsPos = TEXT('\\');
  986. //Update dwLen
  987. dwPos = ptsPos - ptsDirectory + 1;
  988. }
  989. if (dwErr)
  990. break;
  991. fPath = TRUE;
  992. }
  993. else if (dwErr == ERROR_FILE_EXISTS)
  994. {
  995. TCHAR tsSquigs[MAX_PATH];
  996. TCHAR *ptsDestSquig;
  997. INT_PTR ccSquig;
  998. //Add squiggles until we get an OK name.
  999. if (ptsDestFinal != tsCollision)
  1000. {
  1001. TCHAR *ptsDestExt;
  1002. //First time
  1003. ptsDestExt = _tcsrchr(ptsDestOriginal, TEXT('.'));
  1004. if (ptsDestExt == NULL)
  1005. {
  1006. //No extension, just tack onto the end.
  1007. ccExt = _tcslen(ptsDestOriginal);
  1008. }
  1009. else
  1010. {
  1011. ccExt = ptsDestExt - ptsDestOriginal;
  1012. }
  1013. // ptsDestOriginal was built inside this function and verified to
  1014. // be less than MAX_PATH in length
  1015. _tcscpy(tsCollision, ptsDestOriginal);
  1016. ptsDestFinal = tsCollision;
  1017. // temporarily terminate the original to find the squig.
  1018. if( ptsDestExt != NULL )
  1019. *ptsDestExt = TEXT('\0');
  1020. ptsDestSquig = _tcsrchr(ptsDestOriginal, TEXT('('));
  1021. if( ptsDestSquig == NULL )
  1022. {
  1023. ccSquig = ccExt;
  1024. }
  1025. else
  1026. {
  1027. ccSquig = ptsDestSquig - ptsDestOriginal;
  1028. }
  1029. // put the period back where we took it off.
  1030. if( ptsDestExt != NULL )
  1031. *ptsDestExt = TEXT('.');
  1032. }
  1033. wsprintf(tsSquigs,
  1034. TEXT("(%lu)"),
  1035. ulVersion++);
  1036. if (_tcslen(ptsDestOriginal) + _tcslen(tsSquigs) > MAX_PATH)
  1037. {
  1038. Win32PrintfResource(LogFile,
  1039. IDS_FILE_COPYERROR,
  1040. tsFinalSource);
  1041. if (Verbose)
  1042. {
  1043. Win32Printf(STDERR,
  1044. "Could Not Copy To Too Long Destination Filename %s\r\n",
  1045. ptsDestOriginal);
  1046. }
  1047. if (dwReturnUp == ERROR_SUCCESS)
  1048. {
  1049. dwReturnUp = ERROR_FILENAME_EXCED_RANGE;
  1050. }
  1051. continue;
  1052. }
  1053. wsprintf(tsCollision + ccSquig,
  1054. TEXT("%s%s"),
  1055. tsSquigs,
  1056. ptsDestOriginal + ccExt);
  1057. //Go back around and try again.
  1058. }
  1059. else
  1060. {
  1061. Win32PrintfResource(LogFile,
  1062. IDS_FILE_COPYERROR,
  1063. tsFinalSource);
  1064. if (Verbose)
  1065. {
  1066. Win32Printf(STDERR,
  1067. "Error %lu trying to copy %s to %s\r\n",
  1068. dwErr,
  1069. tsFinalSource,
  1070. ptsDestFinal);
  1071. }
  1072. dwReturnUp = dwErr;
  1073. break;
  1074. }
  1075. }
  1076. if (ptsDestFinal == tsCollision)
  1077. {
  1078. dwErr = pcs->SetDestination(tsCollision, i);
  1079. Win32Printf(LogFile,
  1080. "Filename collision on %s, file renamed to %s\r\n",
  1081. ptsDestOriginal,
  1082. ptsDestFinal);
  1083. }
  1084. //Check if the file has a .lnk extension.
  1085. TCHAR *ptsLastDot;
  1086. ptsLastDot = _tcsrchr(ptsDestFinal, TEXT('.'));
  1087. if (ptsLastDot != NULL)
  1088. {
  1089. if (_tcsicmp(ptsLastDot + 1, TEXT("lnk")) == 0)
  1090. {
  1091. //It's a link, try to fix it. Ignore errors.
  1092. FixShellShortcut(ptsDestFinal);
  1093. }
  1094. }
  1095. }
  1096. pcs = pcs->GetNextSection();
  1097. }
  1098. return dwReturnUp;
  1099. }
  1100. DWORD ParseInputFile(HINF hi)
  1101. {
  1102. DWORD dwErr;
  1103. CSection *pcs;
  1104. BOOL fMapping = FALSE;
  1105. INFCONTEXT ic;
  1106. INFCONTEXT icDestinationDirs;
  1107. INFCONTEXT icDirectoryMapping;
  1108. TCHAR tsFirstDestKey[MAX_PATH + 1];
  1109. TCHAR tsFirstMapping[10];
  1110. dwErr = ProcessSpecialDirs(hi);
  1111. if (dwErr)
  1112. return dwErr;
  1113. dwErr = ProcessRules(hi);
  1114. if (dwErr)
  1115. return dwErr;
  1116. if (!SetupFindFirstLine(hi,
  1117. COPYFILE_SECTION,
  1118. NULL,
  1119. &ic))
  1120. {
  1121. dwErr = GetLastError();
  1122. if (dwErr == ERROR_LINE_NOT_FOUND)
  1123. {
  1124. if (Verbose)
  1125. Win32Printf(LogFile,
  1126. "Warning: No [Copy These Files] section found.\r\n");
  1127. return ERROR_SUCCESS;
  1128. }
  1129. Win32PrintfResource(LogFile,
  1130. IDS_SECTION_NAME_NOT_FOUND,
  1131. COPYFILE_SECTION);
  1132. if (Verbose)
  1133. Win32Printf(STDERR,
  1134. "SetupFindFirstLine failed with %lu\r\n",
  1135. dwErr);
  1136. return dwErr;
  1137. }
  1138. if (!SetupFindFirstLine(hi,
  1139. DESTINATIONDIRS_SECTION,
  1140. NULL,
  1141. &icDestinationDirs))
  1142. {
  1143. dwErr = GetLastError();
  1144. Win32PrintfResource(LogFile,
  1145. IDS_SECTION_NAME_NOT_FOUND,
  1146. DESTINATIONDIRS_SECTION);
  1147. if (Verbose)
  1148. Win32Printf(STDERR,
  1149. "SetupFindFirstLine failed with %lu\r\n",
  1150. dwErr);
  1151. return dwErr;
  1152. }
  1153. //Get the key for the first line, we'll need it later.
  1154. if (!SetupGetStringField(&icDestinationDirs,
  1155. 0,
  1156. tsFirstDestKey,
  1157. MAX_PATH + 1,
  1158. NULL))
  1159. {
  1160. //Error
  1161. dwErr = GetLastError();
  1162. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1163. if (Verbose)
  1164. Win32Printf(STDERR,
  1165. "SetupGetStringField couldn't get "
  1166. "first line in %s\r\n",
  1167. DESTINATIONDIRS_SECTION);
  1168. return dwErr;
  1169. }
  1170. if (SetupFindFirstLine(hi,
  1171. DIRECTORYMAPPING_SECTION,
  1172. NULL,
  1173. &icDirectoryMapping))
  1174. {
  1175. fMapping = TRUE;
  1176. //Get the first key, we'll need it later.
  1177. if (!SetupGetStringField(&icDirectoryMapping,
  1178. 0,
  1179. tsFirstMapping,
  1180. 10,
  1181. NULL))
  1182. {
  1183. //Error
  1184. dwErr = GetLastError();
  1185. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1186. if (Verbose)
  1187. Win32Printf(STDERR,
  1188. "SetupGetStringField couldn't get "
  1189. "first line in %s, error %lX\r\n",
  1190. DIRECTORYMAPPING_SECTION,
  1191. dwErr);
  1192. return dwErr;
  1193. }
  1194. }
  1195. else
  1196. {
  1197. //Ignore errors here, this section is optional
  1198. }
  1199. do
  1200. {
  1201. DWORD cFields;
  1202. cFields = SetupGetFieldCount(&ic);
  1203. TCHAR buf[MAX_PATH + 1];
  1204. if (cFields != 1)
  1205. {
  1206. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1207. return ERROR_INVALID_PARAMETER;
  1208. }
  1209. if (!SetupGetStringField(&ic,
  1210. 0,
  1211. buf,
  1212. MAX_PATH + 1,
  1213. NULL))
  1214. {
  1215. dwErr = GetLastError();
  1216. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1217. if (Verbose)
  1218. Win32Printf(STDERR,
  1219. "SetupGetStringField failed with %lu\r\n",
  1220. dwErr);
  1221. return dwErr;
  1222. }
  1223. dwErr = AddLoadFileSection(hi, buf, &pcs);
  1224. if (dwErr)
  1225. return dwErr;
  1226. if (fMapping)
  1227. {
  1228. INFCONTEXT icMap;
  1229. TCHAR tsMapping[MAX_PATH + 1];
  1230. //Find the destination path for this directory.
  1231. //First we have to check the first line, because
  1232. // of SetupFindNextMatchLine
  1233. if (_tcscmp(tsFirstDestKey, pcs->GetSectionTitle()) == 0)
  1234. {
  1235. //It's the first line
  1236. icMap = icDestinationDirs;
  1237. }
  1238. else if (!SetupFindNextMatchLine(&icDestinationDirs,
  1239. pcs->GetSectionTitle(),
  1240. &icMap))
  1241. {
  1242. //This is an error - we should have output this line
  1243. //ourselves in scanstate.
  1244. dwErr = GetLastError();
  1245. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1246. if (Verbose)
  1247. Win32Printf(STDERR,
  1248. "SetupFindNextMatch couldn't find "
  1249. "destination dir for %s\r\n",
  1250. pcs->GetSectionTitle());
  1251. return dwErr;
  1252. }
  1253. if (!SetupGetStringField(&icMap,
  1254. 1,
  1255. tsMapping,
  1256. MAX_PATH + 1,
  1257. NULL))
  1258. {
  1259. //Error, malformed INF
  1260. dwErr = GetLastError();
  1261. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1262. if (Verbose)
  1263. Win32Printf(STDERR,
  1264. "SetupGetIntField couldn't get "
  1265. "destination dir for %s\r\n",
  1266. pcs->GetSectionTitle());
  1267. return dwErr;
  1268. }
  1269. //Now look this up in the DirectoryMapping section
  1270. if (_tcscmp(tsFirstMapping, tsMapping) == 0)
  1271. icMap = icDirectoryMapping;
  1272. if ((_tcscmp(tsFirstMapping, tsMapping) == 0) ||
  1273. (SetupFindNextMatchLine(&icDirectoryMapping,
  1274. tsMapping,
  1275. &icMap)))
  1276. {
  1277. TCHAR bufDest[MAX_PATH + 1];
  1278. if (!SetupGetStringField(&icMap,
  1279. 1,
  1280. bufDest,
  1281. MAX_PATH + 1,
  1282. NULL))
  1283. {
  1284. //Error
  1285. dwErr = GetLastError();
  1286. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  1287. if (Verbose)
  1288. Win32Printf(STDERR,
  1289. "SetupGetStringField couldn't get "
  1290. "directory mapping for %s\r\n",
  1291. tsMapping);
  1292. return dwErr;
  1293. }
  1294. dwErr = pcs->SetSectionDest(bufDest);
  1295. if (dwErr)
  1296. {
  1297. return dwErr;
  1298. }
  1299. }
  1300. else
  1301. {
  1302. //Fall through
  1303. }
  1304. }
  1305. if ((pcs->GetSectionDest())[0] == 0)
  1306. {
  1307. //Check for implicit relocation, for special directories
  1308. TCHAR bufMacro[MAX_PATH + 1];
  1309. TCHAR *ptsFinal;
  1310. const TCHAR *ptsSectionTitle = pcs->GetSectionTitle();
  1311. if (_tcslen(ptsSectionTitle) > MAX_PATH)
  1312. {
  1313. if (DebugOutput)
  1314. Win32Printf(LogFile, "Error: ptsSectionTitle too long %s\r\n", ptsSectionTitle);
  1315. return ERROR_FILENAME_EXCED_RANGE;
  1316. }
  1317. _tcscpy(buf, ptsSectionTitle);
  1318. dwErr = g_csdCurrent.ExpandMacro(buf, bufMacro, &ptsFinal, TRUE);
  1319. if (dwErr)
  1320. return dwErr;
  1321. //Compare to section path - if they're different, set the
  1322. //section destination to the new section
  1323. if (_tcsicmp(ptsFinal, pcs->GetSectionPath()) != 0)
  1324. {
  1325. dwErr = pcs->SetSectionDest(ptsFinal);
  1326. if (dwErr)
  1327. {
  1328. return dwErr;
  1329. }
  1330. }
  1331. }
  1332. if ((pcs->GetSectionDest())[0] == 0)
  1333. {
  1334. dwErr = pcs->SetSectionDest(pcs->GetSectionPath());
  1335. if (dwErr)
  1336. {
  1337. return dwErr;
  1338. }
  1339. }
  1340. }
  1341. while (SetupFindNextLine(&ic, &ic));
  1342. return ERROR_SUCCESS;
  1343. }
  1344. //---------------------------------------------------------------
  1345. DWORD LoadFiles()
  1346. {
  1347. DWORD dwErr = ERROR_SUCCESS;
  1348. if (UserPath == NULL)
  1349. {
  1350. UserPath = (TCHAR *) malloc(MAX_PATH + 1);
  1351. if (UserPath == NULL)
  1352. {
  1353. Win32PrintfResource(LogFile, IDS_NOT_ENOUGH_MEMORY);
  1354. dwErr = ERROR_OUTOFMEMORY;
  1355. return dwErr;
  1356. }
  1357. //We need this but it hasn't been set in LoadUser, so get the
  1358. //USERPROFILE variable for the current user and put it in there.
  1359. dwErr = GetEnvironmentVariable(TEXT("USERPROFILE"),
  1360. UserPath,
  1361. MAX_PATH + 1);
  1362. if (dwErr == 0)
  1363. {
  1364. //Fatal error.
  1365. Win32PrintfResource(LogFile, IDS_NOT_ENOUGH_MEMORY);
  1366. dwErr = ERROR_OUTOFMEMORY;
  1367. return dwErr;
  1368. }
  1369. }
  1370. dwErr = g_csdCurrent.InitForUser(CurrentUser);
  1371. if (dwErr)
  1372. return dwErr;
  1373. if (DebugOutput)
  1374. {
  1375. for (ULONG i = 0; i < g_csdCurrent.GetDirectoryCount(); i++)
  1376. {
  1377. if (g_csdCurrent.GetDirectoryPath(i) != NULL)
  1378. {
  1379. Win32Printf(LogFile,
  1380. "%s=%s\r\n",
  1381. g_csdCurrent.GetDirectoryName(i),
  1382. g_csdCurrent.GetDirectoryPath(i));
  1383. }
  1384. }
  1385. Win32Printf(LogFile, "\r\n");
  1386. }
  1387. dwErr = ParseInputFile(InputInf);
  1388. if (dwErr)
  1389. return dwErr;
  1390. //If CopyFiles is FALSE, do nothing
  1391. if (!CopyFiles)
  1392. return ERROR_SUCCESS;
  1393. dwErr = CopyAllFiles();
  1394. if (dwErr)
  1395. return dwErr;
  1396. return ERROR_SUCCESS;
  1397. }