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.

1187 lines
33 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998 - 1998.
  5. //
  6. // File: scanfiles.cxx
  7. //
  8. // Contents: User file migration code
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 28-Sep-99 PhilipLa Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "scanhead.cxx"
  18. #pragma hdrstop
  19. #include <common.hxx>
  20. #include <filelist.hxx>
  21. #include <section.hxx>
  22. #include <special.hxx>
  23. #include <scanstate.hxx>
  24. #include <bothchar.hxx>
  25. #include <fileutil.cxx>
  26. CSection *g_pcsSectionList = NULL;
  27. CRuleList g_crlExcludeWildcards;
  28. CRuleList g_crlIncludeWildcards;
  29. CSpecialDirectory g_csd;
  30. CSysFileList g_sfl;
  31. DWORD ProcessSysFiles(HINF hi, const TCHAR *ptsName);
  32. DWORD InitializeFiles()
  33. {
  34. DWORD dwErr;
  35. dwErr = g_csd.Init();
  36. if (dwErr)
  37. {
  38. return dwErr;
  39. }
  40. if (CopyFiles)
  41. {
  42. dwErr = ProcessSysFiles(InputInf, SYSFILES_LABEL);
  43. if (dwErr != 0)
  44. return dwErr;
  45. }
  46. return ERROR_SUCCESS;
  47. }
  48. void CleanupFiles(void)
  49. {
  50. FreeSectionList(g_pcsSectionList);
  51. g_pcsSectionList = NULL;
  52. }
  53. //---------------------------------------------------------------
  54. DWORD ComputeTemp()
  55. {
  56. return ERROR_SUCCESS;
  57. }
  58. //---------------------------------------------------------------
  59. void EraseTemp()
  60. {
  61. }
  62. //---------------------------------------------------------------
  63. DWORD PickUpThisFile( char *file, char * dest)
  64. {
  65. DWORD dwErr;
  66. DWORD dwIndex;
  67. if ((file == NULL) ||
  68. (file[0] == 0))
  69. {
  70. //Wacky NULL strings must not be added as rules.
  71. //Ignore them and return success.
  72. return ERROR_SUCCESS;
  73. }
  74. if (Verbose)
  75. Win32Printf(LogFile,
  76. "Copy %s to the destination machine.\r\n",
  77. file );
  78. TCHAR *ptsFile, *ptsDest;
  79. TCHAR tsFileName[MAX_PATH + 1];
  80. TCHAR tsTemp[MAX_PATH + 1];
  81. #ifdef _UNICODE
  82. TCHAR tsDest[MAX_PATH + 1];
  83. if (!(MultiByteToWideChar(AreFileAPIsAnsi() ? CP_ACP : CP_OEMCP,
  84. MB_ERR_INVALID_CHARS,
  85. file,
  86. -1,
  87. tsFileName
  88. MAX_PATH + 1)))
  89. {
  90. dwErr = GetLastError();
  91. Win32PrintfResource(LogFile, IDS_INVALID_PARAMETER);
  92. if (Verbose)
  93. Win32Printf(STDERR,
  94. "Couldn't convert output path %s to Unicode.\r\n",
  95. file);
  96. return dwErr;
  97. }
  98. if (dest &&
  99. (!(MultiByteToWideChar(AreFileAPIsAnsi() ? CP_ACP : CP_OEMCP,
  100. MB_ERR_INVALID_CHARS,
  101. dest,
  102. -1,
  103. tsDest,
  104. MAX_PATH + 1))))
  105. {
  106. dwErr = GetLastError();
  107. Win32PrintfResource(LogFile, IDS_INVALID_PARAMETER);
  108. if (Verbose)
  109. Win32Printf(STDERR,
  110. "Couldn't convert output path %s to Unicode.\r\n",
  111. dest);
  112. return dwErr;
  113. }
  114. ptsFile = tsFileName;
  115. ptsDest = tsDest;
  116. #else
  117. ptsFile = file;
  118. ptsDest = dest;
  119. #endif //_UNICODE
  120. if (_tcslen(ptsFile) > MAX_PATH)
  121. {
  122. if (DebugOutput)
  123. {
  124. Win32Printf(LogFile, "Error: ptsFile too long %s\r\n", ptsFile);
  125. }
  126. return ERROR_FILENAME_EXCED_RANGE;
  127. }
  128. _tcscpy(tsTemp, ptsFile);
  129. dwErr = g_csd.ExpandMacro(tsTemp, tsFileName, &ptsFile, TRUE);
  130. if (dwErr)
  131. return dwErr;
  132. CRuleList *prlDest;
  133. dwErr = g_crlIncludeWildcards.SetName(ptsFile, &prlDest);
  134. if (!dwErr && ptsDest)
  135. dwErr = prlDest->SetDestination(ptsDest);
  136. //Remove it from the system files list if it's in there.
  137. g_sfl.RemoveName(ptsFile);
  138. return dwErr;
  139. }
  140. DWORD CopyAFile(const TCHAR *ptsSourcePath, const TCHAR *ptsName)
  141. {
  142. BOOL fPath = FALSE;
  143. DWORD dwErr = ERROR_SUCCESS;
  144. DWORD dwLen;
  145. TCHAR ptsMigrationPath[MAX_PATH + 1];
  146. TCHAR ptsPath[MAX_PATH + 1];
  147. TCHAR ptsSourceFullPath[MAX_PATH + 1];
  148. // If the source filename is too long, skip it
  149. if ( (_tcslen(ptsName) + _tcslen(ptsSourcePath) + 1) > MAX_PATH )
  150. {
  151. Win32PrintfResource(LogFile,
  152. IDS_FILE_COPYERROR,
  153. ptsName);
  154. if (Verbose)
  155. Win32Printf(STDERR,
  156. "Could Not Copy Too Long Source Filename: %s\\%s\r\n",
  157. ptsSourcePath,
  158. ptsName);
  159. return ERROR_FILENAME_EXCED_RANGE;
  160. }
  161. _tcscpy(ptsSourceFullPath, ptsSourcePath);
  162. _tcscat(ptsSourceFullPath, TEXT("\\"));
  163. _tcscat(ptsSourceFullPath, ptsName);
  164. #ifdef _UNICODE
  165. if (!(dwLen = MultiByteToWideChar(AreFileAPIsAnsi() ? CP_ACP : CP_OEMCP,
  166. MB_ERR_INVALID_CHARS,
  167. MigrationPath,
  168. -1,
  169. ptsMigrationPath,
  170. MAX_PATH + 1)))
  171. {
  172. dwErr = GetLastError();
  173. Win32PrintfResource(LogFile, IDS_INVALID_PARAMETER);
  174. if (Verbose)
  175. Win32Printf(STDERR,
  176. "Couldn't convert output path %s to Unicode.\r\n",
  177. MigrationPath);
  178. return dwErr;
  179. }
  180. #else
  181. dwLen = _tcslen(MigrationPath);
  182. if (dwLen > MAX_PATH)
  183. {
  184. if (DebugOutput)
  185. {
  186. Win32Printf(LogFile, "Error: MigrationPath too long %s\r\n", MigrationPath);
  187. }
  188. return ERROR_FILENAME_EXCED_RANGE;
  189. }
  190. _tcscpy(ptsMigrationPath, MigrationPath);
  191. #endif
  192. // If the destination path is too long, skip this file
  193. if ( (dwLen + _tcslen(ptsSourcePath) + _tcslen(ptsName)+1) > MAX_PATH )
  194. {
  195. Win32PrintfResource(LogFile,
  196. IDS_FILE_COPYERROR,
  197. ptsName);
  198. if (Verbose)
  199. Win32Printf(STDERR,
  200. "Could Not Copy To Too Long Destination Filename: %s\\%c%s\\%s\r\n",
  201. ptsMigrationPath,
  202. ptsSourcePath[0],
  203. ptsSourcePath+2,
  204. ptsName);
  205. return ERROR_FILENAME_EXCED_RANGE;
  206. }
  207. _tcscpy(ptsPath, ptsMigrationPath);
  208. ptsPath[dwLen++] = TEXT('\\');
  209. //Copy drive letter
  210. ptsPath[dwLen++] = ptsSourcePath[0];
  211. //Skip the colon
  212. _tcscpy(ptsPath + dwLen, ptsSourcePath + 2);
  213. dwLen = dwLen + _tcslen(ptsSourcePath) - 2;
  214. ptsPath[dwLen++] = TEXT('\\');
  215. _tcscpy(ptsPath + dwLen, ptsName);
  216. if (ReallyCopyFiles)
  217. {
  218. while (!CopyFile(ptsSourceFullPath,
  219. ptsPath,
  220. TRUE))
  221. {
  222. dwErr = GetLastError();
  223. if (dwErr == ERROR_PATH_NOT_FOUND)
  224. {
  225. if (fPath)
  226. {
  227. //We already tried to create the path, so something
  228. //else must be wrong. Punt-arooney.
  229. break;
  230. }
  231. dwErr = ERROR_SUCCESS;
  232. TCHAR *ptsPos;
  233. DWORD dwPos;
  234. //Try to create all the necessary directories
  235. TCHAR ptsDirectory[MAX_PATH + 1];
  236. // ptsPath is built inside this function and guarenteed to be less than MAX_PATH
  237. _tcscpy(ptsDirectory, ptsPath);
  238. dwPos = _tcslen(ptsMigrationPath) + 1;
  239. //Create every directory along this path
  240. while (ptsPos = _tcschr(ptsDirectory + dwPos, TEXT('\\')))
  241. {
  242. *ptsPos = TEXT(0);
  243. //Create the directory
  244. if (!CreateDirectory(ptsDirectory,
  245. NULL))
  246. {
  247. dwErr = GetLastError();
  248. if (dwErr != ERROR_ALREADY_EXISTS)
  249. {
  250. if (Verbose)
  251. Win32Printf(STDERR,
  252. "Error %lu trying to create "
  253. "directory %s\r\n",
  254. dwErr,
  255. ptsDirectory);
  256. break;
  257. }
  258. dwErr = ERROR_SUCCESS;
  259. }
  260. //Put the backslash back in
  261. *ptsPos = TEXT('\\');
  262. //Update dwLen
  263. dwPos = ptsPos - ptsDirectory + 1;
  264. }
  265. if (dwErr)
  266. break;
  267. fPath = TRUE;
  268. }
  269. else if (dwErr == ERROR_ACCESS_DENIED)
  270. {
  271. // Ignore files that we don't have permission to copy anyway
  272. Win32PrintfResource(LogFile,
  273. IDS_ACCESS_DENIED,
  274. ptsSourceFullPath);
  275. dwErr = ERROR_SUCCESS;
  276. break;
  277. }
  278. else
  279. {
  280. break;
  281. }
  282. }
  283. }
  284. if (dwErr)
  285. {
  286. Win32PrintfResource(LogFile,
  287. IDS_FILE_COPYERROR,
  288. ptsSourceFullPath);
  289. if (Verbose)
  290. Win32Printf(STDERR,
  291. "Error %lu while copying from %s to %s\r\n",
  292. dwErr,
  293. ptsSourceFullPath,
  294. ptsPath);
  295. }
  296. return dwErr;
  297. }
  298. const TCHAR * GetSpecialDirectoryName(const TCHAR *ptsPath)
  299. {
  300. TCHAR buf[MAX_PATH + 1];
  301. if (_tcslen(ptsPath) > MAX_PATH)
  302. {
  303. if (DebugOutput)
  304. {
  305. Win32Printf(LogFile, "Error: ptsPath too long %s\r\n", ptsPath);
  306. }
  307. return NULL;
  308. }
  309. _tcscpy(buf, ptsPath);
  310. DEBUG_ASSERT(buf[_tcslen(ptsPath) - 1] == TEXT('\\'));
  311. buf[_tcslen(ptsPath) - 1] = 0;
  312. for (ULONG i = 0; i < g_csd.GetDirectoryCount(); i++)
  313. {
  314. if (g_csd.GetDirectoryPath(i) &&
  315. (_tcsicmp(buf, g_csd.GetDirectoryPath(i)) == 0))
  316. {
  317. return g_csd.GetDirectoryName(i);
  318. }
  319. }
  320. return NULL;
  321. }
  322. BOOL ExcludeFile(const TCHAR *ptsRoot,
  323. const TCHAR *ptsName,
  324. const WIN32_FIND_DATA *pwfd,
  325. CRuleList **pprlMatch,
  326. DWORD *pdwMatchFit)
  327. {
  328. BOOL f;
  329. TCHAR *ptsExt;
  330. // This used to exclude HIDDEN and SYSTEM files,
  331. // but it turns out we do want to migrate those
  332. // if we have a matching rule. Note that system
  333. // files will be excluded if they are listed in the
  334. // system files section of the INF files.
  335. if (pwfd->dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)
  336. {
  337. if (pprlMatch)
  338. *pprlMatch = NULL;
  339. //Infinite strength on this hit, we should never take these
  340. //files even if we have a good include rule.
  341. if (pdwMatchFit)
  342. *pdwMatchFit = MAX_WEIGHT;
  343. return TRUE;
  344. }
  345. f = g_crlExcludeWildcards.MatchAgainstRuleList(ptsRoot,
  346. ptsName,
  347. pprlMatch,
  348. pdwMatchFit);
  349. if (!f && !CopyFiles)
  350. {
  351. //User specified no file copy, so pretend there's a low
  352. //priority rule that returned a hit. Any explicit include
  353. //(which will only be coming from PickUpThisFile) will win.
  354. if (pprlMatch)
  355. *pprlMatch = NULL;
  356. if (pdwMatchFit)
  357. *pdwMatchFit = 1;
  358. return TRUE;
  359. }
  360. return f;
  361. }
  362. BOOL IncludeFile(const TCHAR *ptsRoot,
  363. const TCHAR *ptsName,
  364. const WIN32_FIND_DATA *pwfd,
  365. CRuleList **pprlMatch)
  366. {
  367. CRuleList *prlExclude = NULL;
  368. CRuleList *prlInclude = NULL;
  369. DWORD dwBestExcludeFit = 0;
  370. DWORD dwBestIncludeFit = 0;
  371. ExcludeFile(ptsRoot,
  372. ptsName,
  373. pwfd,
  374. &prlExclude,
  375. &dwBestExcludeFit);
  376. g_crlIncludeWildcards.MatchAgainstRuleList(ptsRoot,
  377. ptsName,
  378. &prlInclude,
  379. &dwBestIncludeFit);
  380. if (DebugOutput)
  381. Win32Printf(LogFile, "File %s%s rule weighting: \r\n Best exclude %lu = %s\r\n Best include %lu = %s\r\n",
  382. ptsRoot,
  383. (ptsName == NULL) ? TEXT("") : ptsName,
  384. dwBestExcludeFit,
  385. ((prlExclude == NULL) ?
  386. TEXT("NULL") :
  387. prlExclude->GetFullName()),
  388. dwBestIncludeFit,
  389. ((prlInclude == NULL) ?
  390. TEXT("NULL") :
  391. prlInclude->GetFullName()));
  392. // Include the file when Include rating is stronger than Exclude rating, OR
  393. // There is an Exclude and Include rule that both match this equally, OR
  394. // No rules match this and we include by default, OR
  395. // No rules match this and it's a directory
  396. if ( (dwBestIncludeFit > dwBestExcludeFit) ||
  397. ( (dwBestIncludeFit == dwBestExcludeFit) &&
  398. ( (ExcludeByDefault == FALSE) ||
  399. (dwBestIncludeFit > 0) ||
  400. (pwfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))))
  401. {
  402. if (ptsName && g_sfl.LookupName(ptsName))
  403. {
  404. // If this file is listed as a system file in our rules,
  405. // then always exclude it
  406. if (pprlMatch)
  407. *pprlMatch = NULL;
  408. return FALSE;
  409. }
  410. //Include the file
  411. if (pprlMatch)
  412. *pprlMatch = prlInclude;
  413. return TRUE;
  414. }
  415. else
  416. {
  417. if (pprlMatch)
  418. *pprlMatch = prlExclude;
  419. return FALSE;
  420. }
  421. }
  422. BOOL PathPrefix(const TCHAR *ptsPath, const TCHAR *ptsInclude)
  423. {
  424. TCHAR ptsIncludePath[MAX_PATH + 1];
  425. TCHAR ptsWildPath[MAX_PATH + 1];
  426. if (_tcslen(ptsPath) + 2 > MAX_PATH)
  427. {
  428. if (DebugOutput)
  429. {
  430. Win32Printf(LogFile, "Error: ptsPath too long %s\r\n", ptsPath);
  431. }
  432. return FALSE;
  433. }
  434. _tcscpy(ptsWildPath, ptsPath);
  435. _tcscat(ptsWildPath, TEXT("*\\"));
  436. DeconstructFilename(ptsInclude,
  437. ptsIncludePath,
  438. NULL,
  439. NULL);
  440. if (ptsIncludePath[0])
  441. {
  442. BOOL fRet = IsPatternMatchFull(ptsWildPath, ptsIncludePath, NULL) ||
  443. IsPatternMatchFull(ptsIncludePath, ptsPath, NULL);
  444. return fRet;
  445. }
  446. return FALSE;
  447. }
  448. BOOL IncludeDirectory(const TCHAR *ptsPath, const WIN32_FIND_DATA *pwfd)
  449. {
  450. CRuleList *prl = g_crlIncludeWildcards.GetNextRule();
  451. while (prl != NULL)
  452. {
  453. if (PathPrefix(ptsPath, prl->GetFullName()))
  454. {
  455. return TRUE;
  456. }
  457. prl = prl->GetNextRule();
  458. }
  459. return FALSE;
  460. }
  461. DWORD ProcessFileTree(TCHAR *ptsRoot,
  462. CSection *pcsSection,
  463. ULONG cRecursionLevel)
  464. {
  465. DWORD dwErr;
  466. HANDLE hNext;
  467. WIN32_FIND_DATA wfd;
  468. TCHAR ptsStart[MAX_PATH];
  469. const TCHAR *ptsSpecialName = GetSpecialDirectoryName(ptsRoot);
  470. if ((cRecursionLevel < 2) || (ptsSpecialName != NULL))
  471. {
  472. pcsSection = new CSection;
  473. if (pcsSection == NULL)
  474. {
  475. Win32PrintfResource(LogFile, IDS_NOT_ENOUGH_MEMORY);
  476. return ERROR_OUTOFMEMORY;
  477. }
  478. if (g_pcsSectionList == NULL)
  479. {
  480. g_pcsSectionList = pcsSection;
  481. }
  482. else
  483. {
  484. g_pcsSectionList->AddToList(pcsSection);
  485. }
  486. dwErr = pcsSection->SetSectionTitle((ptsSpecialName == NULL) ?
  487. ptsRoot :
  488. ptsSpecialName);
  489. if (dwErr)
  490. {
  491. return dwErr;
  492. }
  493. dwErr = pcsSection->SetSectionPath(ptsRoot);
  494. if (dwErr)
  495. {
  496. return dwErr;
  497. }
  498. }
  499. if (_tcslen(ptsRoot) + 3 >= MAX_PATH)
  500. {
  501. if (DebugOutput)
  502. {
  503. Win32Printf(LogFile, "Error: ptsRoot too long %s\r\n", ptsRoot);
  504. }
  505. return ERROR_FILENAME_EXCED_RANGE;
  506. }
  507. _tcscpy(ptsStart, ptsRoot);
  508. _tcscat(ptsStart, TEXT("*.*"));
  509. hNext = FindFirstFile(ptsStart, &wfd);
  510. if (hNext == INVALID_HANDLE_VALUE)
  511. {
  512. dwErr = GetLastError();
  513. Win32PrintfResource(LogFile, IDS_FILE_ENUMFAIL, ptsStart);
  514. return dwErr;
  515. }
  516. //Files first, then directories
  517. do
  518. {
  519. CRuleList *prl = NULL;
  520. DWORD dwIndex;
  521. TCHAR *ptsName = ((wfd.cFileName) ?
  522. wfd.cFileName :
  523. wfd.cAlternateFileName);
  524. if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  525. IncludeFile(ptsRoot, ptsName, &wfd, &prl))
  526. {
  527. ULONG i;
  528. TCHAR buf[MAX_PATH+1];
  529. TCHAR *ptsScratch;
  530. ptsScratch = ptsRoot + pcsSection->GetSectionPathLength() + 1;
  531. if (_tcslen(ptsScratch) + _tcslen(ptsName) > MAX_PATH)
  532. {
  533. if (DebugOutput)
  534. {
  535. Win32Printf(LogFile, "Error: buf too long %s%s\r\n", ptsScratch, ptsName);
  536. }
  537. return ERROR_FILENAME_EXCED_RANGE;
  538. }
  539. _tcscpy(buf, ptsScratch);
  540. _tcscat(buf, ptsName);
  541. // Win32Printf(STDOUT, "%s%s\r\n", ptsRoot, ptsName);
  542. dwErr = pcsSection->SetName(buf, &i, FALSE);
  543. if (dwErr)
  544. return dwErr;
  545. if ((prl != NULL) && (prl->GetDestination() != NULL))
  546. {
  547. dwErr = pcsSection->SetDestination(
  548. prl->GetDestination(),
  549. i);
  550. if (dwErr)
  551. return dwErr;
  552. }
  553. }
  554. }
  555. while (0 != FindNextFile(hNext, &wfd));
  556. hNext = FindFirstFile(ptsStart, &wfd);
  557. if (hNext == INVALID_HANDLE_VALUE)
  558. {
  559. dwErr = GetLastError();
  560. Win32PrintfResource(LogFile, IDS_FILE_ENUMFAIL, ptsStart);
  561. return dwErr;
  562. }
  563. do
  564. {
  565. TCHAR ptsPath[MAX_PATH + 1];
  566. TCHAR *ptsName = ((wfd.cFileName) ?
  567. wfd.cFileName :
  568. wfd.cAlternateFileName);
  569. if (_tcslen(ptsRoot) + _tcslen(ptsName) + 1 > MAX_PATH)
  570. {
  571. if (DebugOutput)
  572. {
  573. Win32Printf(LogFile, "Error: filename too long %s%s\\\r\n", ptsRoot, ptsName);
  574. }
  575. return ERROR_FILENAME_EXCED_RANGE;
  576. }
  577. _tcscpy(ptsPath, ptsRoot);
  578. _tcscat(ptsPath, ptsName);
  579. _tcscat(ptsPath, TEXT("\\"));
  580. if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  581. _tcscmp(ptsName, TEXT(".")) &&
  582. _tcscmp(ptsName, TEXT("..")))
  583. {
  584. if (IncludeFile(ptsPath, NULL, &wfd, NULL) ||
  585. IncludeDirectory(ptsPath, &wfd))
  586. {
  587. ProcessFileTree(ptsPath, pcsSection, cRecursionLevel + 1);
  588. }
  589. }
  590. }
  591. while (0 != FindNextFile(hNext, &wfd));
  592. return 0;
  593. }
  594. DWORD AddInfSectionToRuleList(INFCONTEXT *pic,
  595. CRuleList *pfl,
  596. BOOL fAllowRename)
  597. {
  598. TCHAR buf[MAX_PATH + 1];
  599. TCHAR bufMacro[MAX_PATH + 1];
  600. TCHAR *ptsFinalName;
  601. TCHAR bufTag[MAX_PATH + 1];
  602. DWORD dwErr;
  603. CRuleList *prl;
  604. do
  605. {
  606. DWORD dwIndex;
  607. DWORD cFields;
  608. BOOL fDirectoryTag = FALSE;
  609. cFields = SetupGetFieldCount(pic);
  610. if (((cFields != 1) && !fAllowRename) ||
  611. ((cFields > 2) && fAllowRename))
  612. {
  613. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  614. if (Verbose)
  615. Win32Printf(STDERR,
  616. "Line contains more than one file name\r\n");
  617. return ERROR_INVALID_PARAMETER;
  618. }
  619. if (!SetupGetStringField(pic,
  620. 1,
  621. buf,
  622. MAX_PATH + 1,
  623. NULL))
  624. {
  625. dwErr = GetLastError();
  626. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  627. if (Verbose)
  628. Win32Printf(STDERR,
  629. "SetupGetStringField returned %lu\r\n",
  630. dwErr);
  631. return dwErr;
  632. }
  633. if (SetupGetStringField(pic,
  634. 0,
  635. bufTag,
  636. MAX_PATH + 1,
  637. NULL))
  638. {
  639. if (_tcsicmp(bufTag, buf))
  640. {
  641. //Someone put a field identifier on there. The only
  642. //one we recognize is 'dir'
  643. if (_tcsicmp(bufTag, TEXT("dir")))
  644. {
  645. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  646. if (Verbose)
  647. Win32Printf(STDERR,
  648. "Unknown tag %s\r\n",
  649. bufTag);
  650. return ERROR_INVALID_PARAMETER;
  651. }
  652. fDirectoryTag = TRUE;
  653. }
  654. }
  655. dwErr = g_csd.ExpandMacro(buf, bufMacro, &ptsFinalName, TRUE);
  656. if (dwErr)
  657. return dwErr;
  658. DWORD ccFinalName = _tcslen(ptsFinalName);
  659. if ((fDirectoryTag) && (ptsFinalName[ccFinalName-1] != '\\'))
  660. {
  661. //Append a backslash if there isn't one already
  662. if (ccFinalName > MAX_PATH)
  663. {
  664. if (DebugOutput)
  665. {
  666. Win32Printf(LogFile, "Error: ptsFinalName too long: %s\\\r\n", ptsFinalName);
  667. }
  668. return ERROR_FILENAME_EXCED_RANGE;
  669. }
  670. else
  671. {
  672. _tcscat(ptsFinalName, TEXT("\\"));
  673. }
  674. }
  675. dwErr = pfl->SetName(ptsFinalName, &prl);
  676. if (dwErr)
  677. {
  678. return dwErr;
  679. }
  680. if (cFields == 2)
  681. {
  682. if (!SetupGetStringField(pic,
  683. 2,
  684. buf,
  685. MAX_PATH + 1,
  686. NULL))
  687. {
  688. dwErr = GetLastError();
  689. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  690. if (Verbose)
  691. Win32Printf(STDERR,
  692. "SetupGetStringField returned %lu\r\n",
  693. dwErr);
  694. return dwErr;
  695. }
  696. dwErr = prl->SetDestination(buf);
  697. if (dwErr)
  698. {
  699. return dwErr;
  700. }
  701. }
  702. }
  703. while (SetupFindNextLine(pic, pic));
  704. return ERROR_SUCCESS;
  705. }
  706. DWORD ProcessCopyFiles(HINF hi, const TCHAR *ptsName)
  707. {
  708. DWORD dwErr;
  709. INFCONTEXT ic;
  710. if (!SetupFindFirstLine(hi,
  711. ptsName,
  712. NULL,
  713. &ic))
  714. {
  715. dwErr = GetLastError();
  716. Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
  717. if (Verbose)
  718. Win32Printf(STDERR,
  719. "SetupFindFirstLine failed on section %s with %lu\r\n",
  720. ptsName,
  721. dwErr);
  722. return dwErr;
  723. }
  724. dwErr = AddInfSectionToRuleList(&ic, &g_crlIncludeWildcards, TRUE);
  725. return dwErr;
  726. }
  727. DWORD ProcessDelFiles(HINF hi, const TCHAR *ptsName)
  728. {
  729. DWORD dwErr;
  730. INFCONTEXT ic;
  731. if (!SetupFindFirstLine(hi,
  732. ptsName,
  733. NULL,
  734. &ic))
  735. {
  736. dwErr = GetLastError();
  737. Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
  738. if (Verbose)
  739. Win32Printf(STDERR,
  740. "SetupFindFirstLine failed on section %s with %lu\r\n",
  741. ptsName,
  742. dwErr);
  743. return dwErr;
  744. }
  745. dwErr = AddInfSectionToRuleList(&ic, &g_crlExcludeWildcards, FALSE);
  746. return dwErr;
  747. }
  748. DWORD ProcessSysFiles(HINF hi, const TCHAR *ptsName)
  749. {
  750. DWORD dwErr;
  751. INFCONTEXT ic;
  752. if (!SetupFindFirstLine(hi,
  753. ptsName,
  754. NULL,
  755. &ic))
  756. {
  757. dwErr = GetLastError();
  758. Win32PrintfResource(LogFile, IDS_SECTION_NAME_NOT_FOUND, ptsName);
  759. if (Verbose)
  760. Win32Printf(STDERR,
  761. "SetupFindFirstLine failed on section %s with %lu\r\n",
  762. ptsName,
  763. dwErr);
  764. return dwErr;
  765. }
  766. LONG cLines = SetupGetLineCount(hi,
  767. ptsName);
  768. if (cLines == -1)
  769. {
  770. //Error
  771. dwErr = GetLastError();
  772. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  773. if (Verbose)
  774. Win32Printf(STDERR,
  775. "Couldn't get line count for System Files section\r\n");
  776. return ERROR_INVALID_PARAMETER;
  777. }
  778. g_sfl.SetInitialSize(cLines);
  779. TCHAR buf[MAX_PATH + 1];
  780. TCHAR bufMacro[MAX_PATH + 1];
  781. TCHAR *ptsFinalName;
  782. do
  783. {
  784. DWORD cFields;
  785. cFields = SetupGetFieldCount(&ic);
  786. if (cFields != 1)
  787. {
  788. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  789. if (Verbose)
  790. Win32Printf(STDERR,
  791. "Sys file line contains multiple fields\r\n");
  792. return ERROR_INVALID_PARAMETER;
  793. }
  794. if (!SetupGetStringField(&ic,
  795. 1,
  796. buf,
  797. MAX_PATH + 1,
  798. NULL))
  799. {
  800. dwErr = GetLastError();
  801. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  802. if (Verbose)
  803. Win32Printf(STDERR,
  804. "SetupGetStringField returned %lu\r\n",
  805. dwErr);
  806. return dwErr;
  807. }
  808. dwErr = g_csd.ExpandMacro(buf, bufMacro, &ptsFinalName, TRUE);
  809. if (dwErr)
  810. return dwErr;
  811. //Add the name to the sys file list
  812. dwErr = g_sfl.AddName(ptsFinalName);
  813. if (dwErr)
  814. return dwErr;
  815. } while (SetupFindNextLine(&ic, &ic));
  816. return ERROR_SUCCESS;
  817. }
  818. DWORD ParseInputFile(HINF hi)
  819. {
  820. DWORD dwErr;
  821. INFCONTEXT ic;
  822. if (!SetupFindFirstLine(hi,
  823. EXTENSION_SECTION,
  824. NULL,
  825. &ic))
  826. {
  827. dwErr = GetLastError();
  828. Win32PrintfResource(LogFile,
  829. IDS_SECTION_NAME_NOT_FOUND,
  830. EXTENSION_SECTION);
  831. if (Verbose)
  832. Win32Printf(STDERR,
  833. "SetupFindFirstLine failed with %lu\r\n", dwErr);
  834. return dwErr;
  835. }
  836. do
  837. {
  838. DWORD cFields;
  839. cFields = SetupGetFieldCount(&ic);
  840. TCHAR buf[MAX_PATH + 1];
  841. if (!SetupGetStringField(&ic,
  842. 0,
  843. buf,
  844. MAX_PATH + 1,
  845. NULL))
  846. {
  847. dwErr = GetLastError();
  848. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  849. if (Verbose)
  850. Win32Printf(STDERR,
  851. "SetupGetStringField failed with %lu\r\n",
  852. dwErr);
  853. return dwErr;
  854. }
  855. if (_tcsicmp(buf, COPYFILES_LABEL) == 0)
  856. {
  857. //Add files in all sections to the include list
  858. for (DWORD j = 1; j < cFields + 1; j++)
  859. {
  860. if (!SetupGetStringField(&ic,
  861. j,
  862. buf,
  863. MAX_PATH + 1,
  864. NULL))
  865. {
  866. dwErr = GetLastError();
  867. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  868. if (Verbose)
  869. Win32Printf(STDERR,
  870. "SetupGetStringField failed with %lu\r\n",
  871. dwErr);
  872. return dwErr;
  873. }
  874. dwErr = ProcessCopyFiles(hi, buf);
  875. if (dwErr != 0)
  876. return dwErr;
  877. }
  878. }
  879. else if (_tcsicmp(buf, DELFILES_LABEL) == 0)
  880. {
  881. //Add files in all sections to the include list
  882. for (DWORD j = 1; j < cFields + 1; j++)
  883. {
  884. if (!SetupGetStringField(&ic,
  885. j,
  886. buf,
  887. MAX_PATH + 1,
  888. NULL))
  889. {
  890. dwErr = GetLastError();
  891. Win32PrintfResource(LogFile, IDS_INF_ERROR);
  892. if (Verbose)
  893. Win32Printf(STDERR,
  894. "SetupGetStringField failed with %lu\r\n",
  895. dwErr);
  896. return dwErr;
  897. }
  898. dwErr = ProcessDelFiles(hi, buf);
  899. if (dwErr != 0)
  900. return dwErr;
  901. }
  902. }
  903. }
  904. while (SetupFindNextLine(&ic, &ic));
  905. return ERROR_SUCCESS;
  906. }
  907. DWORD OutputSectionList(CSection *pcs)
  908. {
  909. DWORD dwErr = ERROR_SUCCESS;
  910. CSection *pcsTemp = pcs;
  911. Win32Printf(OutputFile, "[%s]\r\n", COPYFILE_SECTION);
  912. while (pcsTemp != NULL)
  913. {
  914. if (pcsTemp->GetNameCount() != 0)
  915. Win32Printf(OutputFile,"%s\r\n", pcsTemp->GetSectionTitle());
  916. pcsTemp = pcsTemp->GetNextSection();
  917. }
  918. Win32Printf(OutputFile, "\r\n");
  919. pcsTemp = pcs;
  920. while (pcsTemp != NULL)
  921. {
  922. if (pcsTemp->GetNameCount() != 0)
  923. {
  924. Win32Printf(OutputFile,"[%s]\r\n", pcsTemp->GetSectionTitle());
  925. for (ULONG i = 0; i < pcsTemp->GetNameCount(); i++)
  926. {
  927. Win32Printf(OutputFile,"\"%s\"", pcsTemp->GetFullFileName(i));
  928. if (pcsTemp->GetDestination(i) != NULL)
  929. {
  930. Win32Printf(OutputFile,",\"%s\"", pcsTemp->GetDestination(i));
  931. }
  932. Win32Printf(OutputFile, "\r\n");
  933. if ((dwErr = CopyAFile(pcsTemp->GetSectionPath(),
  934. pcsTemp->GetFullFileName(i))))
  935. {
  936. return dwErr;
  937. }
  938. }
  939. Win32Printf(OutputFile, "\r\n");
  940. }
  941. pcsTemp = pcsTemp->GetNextSection();
  942. }
  943. pcsTemp = pcs;
  944. DWORD dwSection = 10000;
  945. Win32Printf(OutputFile, "[%s]\r\n", DESTINATIONDIRS_SECTION);
  946. while (pcsTemp != NULL)
  947. {
  948. if (pcsTemp->GetNameCount() != 0)
  949. {
  950. Win32Printf(OutputFile,"%s=%lu\r\n",
  951. pcsTemp->GetSectionTitle(),
  952. dwSection++);
  953. }
  954. pcsTemp = pcsTemp->GetNextSection();
  955. }
  956. Win32Printf(OutputFile,"\r\n");
  957. return dwErr;
  958. }
  959. void OutputSpecialDirectoryList(CSpecialDirectory *psd)
  960. {
  961. Win32Printf(OutputFile, "[%s]\r\n", SPECIALDIRS_SECTION);
  962. for (ULONG i = 0; i < psd->GetDirectoryCount(); i++)
  963. {
  964. if (psd->GetDirectoryPath(i) != NULL)
  965. {
  966. Win32Printf(OutputFile,
  967. "%s=\"%s\"\r\n",
  968. psd->GetDirectoryName(i),
  969. psd->GetDirectoryPath(i));
  970. }
  971. }
  972. Win32Printf(OutputFile, "\r\n");
  973. }
  974. DWORD ScanFiles()
  975. {
  976. DWORD dwErr;
  977. DWORD dwDrives;
  978. TCHAR tcDriveName[5];
  979. //If we're copying files, grab all the rules from the input file
  980. //Otherwise, we'll only take things specified by PickUpThisFile
  981. if (CopyFiles)
  982. {
  983. dwErr = ParseInputFile(InputInf);
  984. if (dwErr)
  985. return dwErr;
  986. }
  987. dwDrives = GetLogicalDrives();
  988. for (int i = 0; i < 26; i++)
  989. {
  990. if (dwDrives & 1)
  991. {
  992. tcDriveName[0] = (TCHAR)'A' + i;
  993. tcDriveName[1] = (TCHAR)':';
  994. tcDriveName[2] = (TCHAR)'\\';
  995. tcDriveName[3] = 0;
  996. UINT uiDriveType = GetDriveType(tcDriveName);
  997. TCHAR *tcDriveTypeName;
  998. if (uiDriveType == DRIVE_FIXED)
  999. {
  1000. ProcessFileTree(tcDriveName, NULL, 0);
  1001. }
  1002. else if (uiDriveType == DRIVE_NO_ROOT_DIR)
  1003. {
  1004. if (Verbose)
  1005. Win32Printf(STDERR,
  1006. "Warning: GetDriveType returned "
  1007. "DRIVE_NO_ROOT_DIR for drive %s\r\n",
  1008. tcDriveName);
  1009. }
  1010. }
  1011. dwDrives = dwDrives >> 1;
  1012. }
  1013. dwErr = OutputSectionList(g_pcsSectionList);
  1014. if (dwErr)
  1015. return dwErr;
  1016. OutputSpecialDirectoryList(&g_csd);
  1017. return ERROR_SUCCESS;
  1018. }