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.

3221 lines
103 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. fileq2.c
  5. Abstract:
  6. Setup file queue routines for enqueing copy operations.
  7. Author:
  8. Ted Miller (tedm) 15-Feb-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define STR_DRIVERCACHEINF TEXT("drvindex.inf")
  14. //
  15. // Structure used with _SetupQueueCopy
  16. //
  17. typedef struct _SP_FILE_COPY_PARAMS_AEX {
  18. DWORD cbSize;
  19. HSPFILEQ QueueHandle;
  20. PCSTR SourceRootPath; OPTIONAL
  21. PCSTR SourcePath; OPTIONAL
  22. PCSTR SourceFilename;
  23. PCSTR SourceDescription; OPTIONAL
  24. PCSTR SourceTagfile; OPTIONAL
  25. PCSTR TargetDirectory;
  26. PCSTR TargetFilename; OPTIONAL
  27. DWORD CopyStyle;
  28. HINF LayoutInf; OPTIONAL
  29. PCSTR SecurityDescriptor; OPTIONAL
  30. DWORD SourceFlags; OPTIONAL
  31. BOOL SourceFlagsSet; OPTIONAL // we need this flag since SourceFlags may be zero
  32. PCSTR CacheName;
  33. } SP_FILE_COPY_PARAMS_AEX, *PSP_FILE_COPY_PARAMS_AEX;
  34. typedef struct _SP_FILE_COPY_PARAMS_WEX {
  35. DWORD cbSize;
  36. HSPFILEQ QueueHandle;
  37. PCWSTR SourceRootPath; OPTIONAL
  38. PCWSTR SourcePath; OPTIONAL
  39. PCWSTR SourceFilename;
  40. PCWSTR SourceDescription; OPTIONAL
  41. PCWSTR SourceTagfile; OPTIONAL
  42. PCWSTR TargetDirectory;
  43. PCWSTR TargetFilename; OPTIONAL
  44. DWORD CopyStyle;
  45. HINF LayoutInf; OPTIONAL
  46. PCWSTR SecurityDescriptor; OPTIONAL
  47. DWORD SourceFlags; OPTIONAL
  48. BOOL SourceFlagsSet; OPTIONAL // we need this flag since SourceFlags may be zero
  49. PCWSTR CacheName;
  50. } SP_FILE_COPY_PARAMS_WEX, *PSP_FILE_COPY_PARAMS_WEX;
  51. #ifdef UNICODE
  52. typedef SP_FILE_COPY_PARAMS_WEX SP_FILE_COPY_PARAMSEX;
  53. typedef PSP_FILE_COPY_PARAMS_WEX PSP_FILE_COPY_PARAMSEX;
  54. #else
  55. typedef SP_FILE_COPY_PARAMS_AEX SP_FILE_COPY_PARAMSEX;
  56. typedef PSP_FILE_COPY_PARAMS_AEX PSP_FILE_COPY_PARAMSEX;
  57. #endif
  58. BOOL
  59. _SetupQueueCopy(
  60. IN PSP_FILE_COPY_PARAMSEX CopyParams,
  61. IN PINFCONTEXT LayoutLineContext, OPTIONAL
  62. IN HINF AdditionalInfs OPTIONAL
  63. );
  64. PSOURCE_MEDIA_INFO
  65. pSetupQueueSourceMedia(
  66. IN OUT PSP_FILE_QUEUE Queue,
  67. IN OUT PSP_FILE_QUEUE_NODE QueueNode,
  68. IN LONG SourceRootStringId,
  69. IN PCTSTR SourceDescription, OPTIONAL
  70. IN PCTSTR SourceTagfile, OPTIONAL
  71. IN PCTSTR SourceCabfile, OPTIONAL
  72. IN DWORD MediaFlags
  73. );
  74. BOOL
  75. pSetupQueueSingleCopy(
  76. IN HSPFILEQ QueueHandle,
  77. IN HINF InfHandle,
  78. IN HINF ListInfHandle, OPTIONAL
  79. IN PCTSTR SectionName, OPTIONAL
  80. IN PCTSTR SourceRootPath,
  81. IN PCTSTR SourceFilename,
  82. IN PCTSTR TargetFilename,
  83. IN DWORD CopyStyle,
  84. IN PCTSTR SecurityDescriptor,
  85. IN PCTSTR CacheName
  86. );
  87. BOOL
  88. pSetupGetSourceAllInfo(
  89. IN HINF InfHandle,
  90. IN PINFCONTEXT LayoutLineContext, OPTIONAL
  91. IN UINT SourceId,
  92. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, OPTIONAL
  93. OUT PCTSTR *Description,
  94. OUT PCTSTR *Tagfile,
  95. OUT PCTSTR *RelativePath,
  96. OUT PUINT SourceFlags
  97. );
  98. BOOL
  99. pIsDriverCachePresent(
  100. IN PCTSTR DriverName,
  101. IN PCTSTR SubDirectory,
  102. OUT PTSTR DriverBuffer
  103. );
  104. BOOL
  105. pIsFileInDriverCache(
  106. IN HINF CabInf,
  107. IN PCTSTR TargetFilename,
  108. IN PCTSTR SubDirectory,
  109. OUT PCTSTR *CacheName
  110. );
  111. //
  112. // HACK ALERT!!! HACK HACK HACK!!!!
  113. //
  114. // There might be an override platform specified. If this is so,
  115. // we will look for \i386, \mips, etc as the final component of the
  116. // specified path when queuing files, and replace it with the
  117. // override path. This is a TOTAL HACK.
  118. //
  119. PCTSTR PlatformPathOverride;
  120. VOID
  121. pSetupInitPlatformPathOverrideSupport(
  122. IN BOOL Init
  123. )
  124. {
  125. if(Init) {
  126. PlatformPathOverride = NULL;
  127. } else {
  128. if( PlatformPathOverride ) {
  129. MyFree(PlatformPathOverride);
  130. PlatformPathOverride = NULL;
  131. }
  132. }
  133. }
  134. #ifdef UNICODE
  135. //
  136. // ANSI version
  137. //
  138. BOOL
  139. SetupSetPlatformPathOverrideA(
  140. IN PCSTR Override OPTIONAL
  141. )
  142. {
  143. BOOL b;
  144. DWORD rc;
  145. PCWSTR p;
  146. if(Override) {
  147. rc = pSetupCaptureAndConvertAnsiArg(Override,&p);
  148. } else {
  149. p = NULL;
  150. rc = NO_ERROR;
  151. }
  152. if(rc == NO_ERROR) {
  153. b = SetupSetPlatformPathOverrideW(p);
  154. rc = GetLastError();
  155. } else {
  156. b = FALSE;
  157. }
  158. if(p) {
  159. MyFree(p);
  160. }
  161. SetLastError(rc);
  162. return(b);
  163. }
  164. #else
  165. //
  166. // Unicode stub
  167. //
  168. BOOL
  169. SetupSetPlatformPathOverrideW(
  170. IN PCWSTR Override OPTIONAL
  171. )
  172. {
  173. UNREFERENCED_PARAMETER(Override);
  174. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  175. return(FALSE);
  176. }
  177. #endif
  178. BOOL
  179. SetupSetPlatformPathOverride(
  180. IN PCTSTR Override OPTIONAL
  181. )
  182. {
  183. BOOL b = FALSE;
  184. DWORD rc = ERROR_NOT_ENOUGH_MEMORY;
  185. BOOL locked = FALSE;
  186. try {
  187. EnterCriticalSection(&PlatformPathOverrideCritSect);
  188. locked = TRUE;
  189. rc = ERROR_INVALID_DATA;
  190. if(Override) {
  191. if(PlatformPathOverride) {
  192. MyFree(PlatformPathOverride);
  193. PlatformPathOverride = NULL;
  194. }
  195. try {
  196. b = ((PlatformPathOverride = DuplicateString(Override)) != NULL);
  197. if(!b) {
  198. rc = ERROR_NOT_ENOUGH_MEMORY;
  199. }
  200. } except(EXCEPTION_EXECUTE_HANDLER) {
  201. b = FALSE;
  202. rc = ERROR_INVALID_PARAMETER;
  203. }
  204. } else {
  205. if(PlatformPathOverride) {
  206. MyFree(PlatformPathOverride);
  207. PlatformPathOverride = NULL;
  208. }
  209. b = TRUE;
  210. }
  211. } except(EXCEPTION_EXECUTE_HANDLER) {
  212. }
  213. if(locked) {
  214. LeaveCriticalSection(&PlatformPathOverrideCritSect);
  215. } else {
  216. b = FALSE;
  217. rc = ERROR_NOT_ENOUGH_MEMORY;
  218. }
  219. if(!b) {
  220. SetLastError(rc);
  221. }
  222. return(b);
  223. }
  224. #ifdef UNICODE
  225. //
  226. // ANSI version
  227. //
  228. BOOL
  229. SetupQueueCopyA(
  230. IN HSPFILEQ QueueHandle,
  231. IN PCSTR SourceRootPath, OPTIONAL
  232. IN PCSTR SourcePath, OPTIONAL
  233. IN PCSTR SourceFilename,
  234. IN PCSTR SourceDescription, OPTIONAL
  235. IN PCSTR SourceTagfile, OPTIONAL
  236. IN PCSTR TargetDirectory,
  237. IN PCSTR TargetFilename, OPTIONAL
  238. IN DWORD CopyStyle
  239. )
  240. {
  241. PCWSTR sourceRootPath;
  242. PCWSTR sourcePath;
  243. PCWSTR sourceFilename;
  244. PCWSTR sourceDescription;
  245. PCWSTR sourceTagfile;
  246. PCWSTR targetDirectory;
  247. PCWSTR targetFilename;
  248. BOOL b;
  249. DWORD rc;
  250. SP_FILE_COPY_PARAMS_WEX CopyParams = {0};
  251. sourceRootPath = NULL;
  252. sourcePath = NULL;
  253. sourceFilename = NULL;
  254. sourceDescription = NULL;
  255. sourceTagfile = NULL;
  256. targetDirectory = NULL;
  257. targetFilename = NULL;
  258. rc = NO_ERROR;
  259. b = FALSE;
  260. if(SourceRootPath) {
  261. rc = pSetupCaptureAndConvertAnsiArg(SourceRootPath,&sourceRootPath);
  262. }
  263. if((rc == NO_ERROR) && SourcePath) {
  264. rc = pSetupCaptureAndConvertAnsiArg(SourcePath,&sourcePath);
  265. }
  266. if((rc == NO_ERROR) && SourceFilename) {
  267. rc = pSetupCaptureAndConvertAnsiArg(SourceFilename,&sourceFilename);
  268. }
  269. if((rc == NO_ERROR) && SourceDescription) {
  270. rc = pSetupCaptureAndConvertAnsiArg(SourceDescription,&sourceDescription);
  271. }
  272. if((rc == NO_ERROR) && SourceTagfile) {
  273. rc = pSetupCaptureAndConvertAnsiArg(SourceTagfile,&sourceTagfile);
  274. }
  275. if((rc == NO_ERROR) && TargetDirectory) {
  276. rc = pSetupCaptureAndConvertAnsiArg(TargetDirectory,&targetDirectory);
  277. }
  278. if((rc == NO_ERROR) && TargetFilename) {
  279. rc = pSetupCaptureAndConvertAnsiArg(TargetFilename,&targetFilename);
  280. }
  281. if(rc == NO_ERROR) {
  282. CopyParams.cbSize = sizeof(SP_FILE_COPY_PARAMS_WEX);
  283. CopyParams.QueueHandle = QueueHandle;
  284. CopyParams.SourceRootPath = sourceRootPath;
  285. CopyParams.SourcePath = sourcePath;
  286. CopyParams.SourceFilename = sourceFilename;
  287. CopyParams.SourceDescription = sourceDescription;
  288. CopyParams.SourceTagfile = sourceTagfile;
  289. CopyParams.TargetDirectory = targetDirectory;
  290. CopyParams.TargetFilename = targetFilename;
  291. CopyParams.CopyStyle = CopyStyle;
  292. CopyParams.LayoutInf = NULL;
  293. CopyParams.SecurityDescriptor= NULL;
  294. b = _SetupQueueCopy(&CopyParams, NULL, NULL);
  295. rc = GetLastError();
  296. }
  297. if(sourceRootPath) {
  298. MyFree(sourceRootPath);
  299. }
  300. if(sourcePath) {
  301. MyFree(sourcePath);
  302. }
  303. if(sourceFilename) {
  304. MyFree(sourceFilename);
  305. }
  306. if(sourceDescription) {
  307. MyFree(sourceDescription);
  308. }
  309. if(sourceTagfile) {
  310. MyFree(sourceTagfile);
  311. }
  312. if(targetDirectory) {
  313. MyFree(targetDirectory);
  314. }
  315. if(targetFilename) {
  316. MyFree(targetFilename);
  317. }
  318. SetLastError(rc);
  319. return(b);
  320. }
  321. #else
  322. //
  323. // Unicode stub
  324. //
  325. BOOL
  326. SetupQueueCopyW(
  327. IN HSPFILEQ QueueHandle,
  328. IN PCWSTR SourceRootPath, OPTIONAL
  329. IN PCWSTR SourcePath, OPTIONAL
  330. IN PCWSTR SourceFilename,
  331. IN PCWSTR SourceDescription, OPTIONAL
  332. IN PCWSTR SourceTagfile, OPTIONAL
  333. IN PCWSTR TargetDirectory,
  334. IN PCWSTR TargetFilename, OPTIONAL
  335. IN DWORD CopyStyle
  336. )
  337. {
  338. UNREFERENCED_PARAMETER(QueueHandle);
  339. UNREFERENCED_PARAMETER(SourceRootPath);
  340. UNREFERENCED_PARAMETER(SourcePath);
  341. UNREFERENCED_PARAMETER(SourceFilename);
  342. UNREFERENCED_PARAMETER(SourceDescription);
  343. UNREFERENCED_PARAMETER(SourceTagfile);
  344. UNREFERENCED_PARAMETER(TargetDirectory);
  345. UNREFERENCED_PARAMETER(TargetFilename);
  346. UNREFERENCED_PARAMETER(CopyStyle);
  347. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  348. return(FALSE);
  349. }
  350. #endif
  351. BOOL
  352. SetupQueueCopy(
  353. IN HSPFILEQ QueueHandle,
  354. IN PCTSTR SourceRootPath, OPTIONAL
  355. IN PCTSTR SourcePath, OPTIONAL
  356. IN PCTSTR SourceFilename,
  357. IN PCTSTR SourceDescription, OPTIONAL
  358. IN PCTSTR SourceTagfile, OPTIONAL
  359. IN PCTSTR TargetDirectory,
  360. IN PCTSTR TargetFilename, OPTIONAL
  361. IN DWORD CopyStyle
  362. )
  363. /*++
  364. Routine Description:
  365. Place a copy operation on a setup file queue.
  366. Arguments:
  367. QueueHandle - supplies a handle to a setup file queue, as returned
  368. by SetupOpenFileQueue.
  369. SourceRootPath - Supplies the root of the source for this copy,
  370. such as A:\ or \\FOO\BAR\BAZ. If this parameter isn't supplied, then
  371. this queue node will be added to a media descriptor's queue that
  372. matches on SourceDescription and SourceTagfile. (This merge will take
  373. place regardless of whether or not the media descriptor entry was
  374. already in the queue prior to calling SetupQueueCopy.)
  375. If there is no matching media descriptor that contains SourceRootPath
  376. information, the path will be set to the directory where the system was
  377. installed from.
  378. SourcePath - if specified, supplies the path relative to SourceRootPath
  379. where the file can be found.
  380. SourceFilename - supplies the filename part of the file to be copied.
  381. SourceDescription - if specified, supplies a description of the source
  382. media, to be used during disk prompts.
  383. SourceTagfile - if specified, supplies a tag file whose presence at
  384. SourceRootPath indicates the presence of the source media.
  385. If not specified, the file itself will be used as the tag file
  386. if required (tagfiles are used only for removable media).
  387. TargetDirectory - supplies the directory where the file is to be copied.
  388. TargetFilename - if specified, supplies the name of the target file.
  389. If not specified, the target file will have the same name as the source.
  390. CopyStyle - supplies flags that control the behavior of the copy operation
  391. for this file.
  392. Return Value:
  393. Boolean value indicating outcome. If FALSE, GetLastError() returns
  394. extended error information.
  395. --*/
  396. {
  397. SP_FILE_COPY_PARAMSEX CopyParams = {0};
  398. //
  399. // Work is done by common worker routine
  400. //
  401. CopyParams.cbSize = sizeof(SP_FILE_COPY_PARAMSEX);
  402. CopyParams.QueueHandle = QueueHandle;
  403. CopyParams.SourceRootPath = SourceRootPath;
  404. CopyParams.SourcePath = SourcePath;
  405. CopyParams.SourceFilename = SourceFilename;
  406. CopyParams.SourceDescription = SourceDescription;
  407. CopyParams.SourceTagfile = SourceTagfile;
  408. CopyParams.TargetDirectory = TargetDirectory;
  409. CopyParams.TargetFilename = TargetFilename;
  410. CopyParams.CopyStyle = CopyStyle;
  411. CopyParams.LayoutInf = NULL;
  412. CopyParams.SecurityDescriptor= NULL;
  413. CopyParams.CacheName = NULL;
  414. return(_SetupQueueCopy(&CopyParams, NULL, NULL));
  415. }
  416. BOOL
  417. _SetupQueueCopy(
  418. IN PSP_FILE_COPY_PARAMSEX CopyParams,
  419. IN PINFCONTEXT LayoutLineContext, OPTIONAL
  420. IN HINF AdditionalInfs OPTIONAL
  421. )
  422. /*++
  423. Routine Description:
  424. Worker routine for SetupQueueCopy and friends.
  425. Arguments:
  426. CopyParams - supplies a structure with information about the file
  427. to be queued. Fields are used as follows.
  428. cbSize - must be sizeof(SP_FILE_COPY_PARAMS). The caller should
  429. have verified this before calling this routine.
  430. QueueHandle - supplies a handle to a setup file queue, as returned
  431. by SetupOpenFileQueue.
  432. SourceRootPath - Supplies the root of the source for this copy,
  433. such as A:\ or \\FOO\BAR\BAZ. If this field is NULL, then this
  434. queue node will be added to a media descriptor's queue that matches
  435. on SourceDescription and SourceTagfile. (This merge will take
  436. place regardless of whether or not the media descriptor entry was
  437. already in the queue prior to calling SetupQueueCopy.)
  438. If there is no matching media descriptor that contains
  439. SourceRootPath information, the path will be set to the directory
  440. where the system was installed from.
  441. SourcePath - if specified, supplies the path relative to SourceRootPath
  442. where the file can be found.
  443. SourceFilename - supplies the filename part of the file to be copied.
  444. SourceDescription - if specified, supplies a description of the source
  445. media, to be used during disk prompts.
  446. SourceTagfile - if specified, supplies a tag file whose presence at
  447. SourceRootPath indicates the presence of the source media.
  448. If not specified, the file itself will be used as the tag file
  449. if required (tagfiles are used only for removable media).
  450. TargetDirectory - supplies the directory where the file is to be copied.
  451. TargetFilename - if specified, supplies the name of the target file. If
  452. not specified, the target file will have the same name as the source.
  453. CopyStyle - supplies flags that control the behavior of the copy
  454. operation for this file.
  455. LayoutInf - supplies the handle to the inf which contains the source
  456. layout info for this file, if any.
  457. LayoutLineContext - if specified, this argument provides the INF context
  458. for the [SourceDisksFiles] entry pertaining to the file to be copied.
  459. If not specified, the relevant [SourceDisksFiles] entry will be searched
  460. for in the LayoutInf handle specified in the CopyParams structure. This
  461. context must be contained within either the CopyParams->LayoutInf or
  462. AdditionalInfs loaded INF handles (because those are the two INFs we're
  463. gonna lock). The argument is used to prevent us from having to search
  464. for the file to be copied in a [SourceDisksFiles] section. The caller
  465. has already done that, and is either handing us the context to that INF
  466. entry, or has passed -1 to indicate that there is no [SourceDisksFiles]
  467. entry.
  468. AdditionalInfs - if specified, supplies an additional HINF (potentially
  469. containing multiple append-loaded INFs) that need to be added to our
  470. SPQ_CATALOG_INFO list for later validation. Do not supply this parameter
  471. if it is identical to the value of the LayoutInf field in the CopyParams
  472. structure.
  473. Return Value:
  474. Boolean value indicating outcome. If FALSE, GetLastError() returns
  475. extended error information.
  476. --*/
  477. {
  478. PSP_FILE_QUEUE Queue;
  479. PSP_FILE_QUEUE_NODE QueueNode, TempNode, PrevQueueNode;
  480. PSOURCE_MEDIA_INFO Source;
  481. TCHAR TempBuffer[MAX_PATH];
  482. TCHAR TempSubDir[MAX_PATH];
  483. TCHAR SourceCabfileBuffer[MAX_PATH];
  484. TCHAR SourceTagfile2Buffer[MAX_PATH];
  485. TCHAR DriverCache[MAX_PATH] = {0};
  486. PCTSTR LastPathPart;
  487. PCTSTR p;
  488. int Size;
  489. DWORD d;
  490. HINF LayoutInfHandle;
  491. INFCONTEXT LineContext;
  492. BOOL b;
  493. PSPQ_CATALOG_INFO CatalogNode, PrevCatalogNode, LastOldCatalogNode;
  494. LONG l1,l2, l3, l4;
  495. PLOADED_INF pLoadedInfs[2];
  496. DWORD LoadedInfCount, i;
  497. PLOADED_INF pCurLoadedInf;
  498. DWORD MediaFlags;
  499. PCTSTR SourcePath, SourceRootPath;
  500. PCTSTR SourceTagfile = NULL;
  501. PCTSTR SourceCabfile = NULL;
  502. #if defined(_X86_)
  503. BOOL ForcePlatform = FALSE;
  504. #endif
  505. UINT SourceFlags = 0;
  506. PINFCONTEXT pContext = LayoutLineContext;
  507. INFCONTEXT tmpContext,tmpContext2;
  508. UINT SourceId = 0;
  509. BOOL locked = FALSE;
  510. d = NO_ERROR;
  511. LoadedInfCount = 0;
  512. MediaFlags = 0;
  513. try {
  514. MYASSERT(CopyParams->cbSize == sizeof(SP_FILE_COPY_PARAMSEX));
  515. Queue = (PSP_FILE_QUEUE)CopyParams->QueueHandle;
  516. if (Queue->Signature != SP_FILE_QUEUE_SIG) {
  517. d = ERROR_INVALID_PARAMETER;
  518. }
  519. LayoutInfHandle = CopyParams->LayoutInf;
  520. //
  521. // Maintain local pointers to the SourceRootPath and SourcePath strings,
  522. // since we may be modifying them, and we don't want to muck with the
  523. // caller-supplied buffer.
  524. //
  525. SourcePath = CopyParams->SourcePath;
  526. if(CopyParams->SourceRootPath) {
  527. SourceRootPath = CopyParams->SourceRootPath;
  528. } else {
  529. SourceRootPath = SystemSourcePath;
  530. MediaFlags |= SMI_FLAG_NO_SOURCE_ROOT_PATH;
  531. }
  532. } except(EXCEPTION_EXECUTE_HANDLER) {
  533. d = ERROR_INVALID_PARAMETER;
  534. }
  535. if(d != NO_ERROR) {
  536. goto clean0;
  537. }
  538. //
  539. // Make sure that we weren't passed the same HINF in both CopyParams->LayoutInf
  540. // and AdditionalInfs (just adds redundant work to process the same
  541. // LOADED_INF list twice).
  542. //
  543. MYASSERT(!LayoutInfHandle || (LayoutInfHandle != AdditionalInfs));
  544. //
  545. // Lock inf(s). We do a whole bunch of operations on the inf later,
  546. // and we don't want anything changing out from under us.
  547. //
  548. if(LayoutInfHandle) {
  549. if(LockInf((PLOADED_INF)LayoutInfHandle)) {
  550. pLoadedInfs[LoadedInfCount++] = (PLOADED_INF)LayoutInfHandle;
  551. } else {
  552. d = ERROR_INVALID_HANDLE;
  553. goto clean0;
  554. }
  555. }
  556. if(AdditionalInfs) {
  557. if(LockInf((PLOADED_INF)AdditionalInfs)) {
  558. pLoadedInfs[LoadedInfCount++] = (PLOADED_INF)AdditionalInfs;
  559. } else {
  560. d = ERROR_INVALID_HANDLE;
  561. goto clean0;
  562. }
  563. }
  564. if(!(Queue->Flags & FQF_DEVICE_INSTALL)) {
  565. //
  566. // Look through all the INFs to see if any of them are device INFs.
  567. //
  568. for(i = 0; i < LoadedInfCount; i++) {
  569. if(IsInfForDeviceInstall(Queue->LogContext,
  570. NULL,
  571. pLoadedInfs[i],
  572. NULL,
  573. NULL,
  574. NULL,
  575. NULL)) {
  576. //
  577. // There be device INFs here! Mark the queue accordingly.
  578. //
  579. d = MarkQueueForDeviceInstall(CopyParams->QueueHandle,
  580. (HINF)(pLoadedInfs[i]),
  581. NULL
  582. );
  583. if(d == NO_ERROR) {
  584. break;
  585. } else {
  586. goto clean0;
  587. }
  588. }
  589. }
  590. }
  591. //
  592. // check if we already have a line context for the file we're adding
  593. // and if we don't, then try to fetch it
  594. //
  595. if (!LayoutLineContext || LayoutLineContext == (PINFCONTEXT) -1) {
  596. if ((LayoutInfHandle == (PINFCONTEXT) -1) || (LayoutInfHandle == NULL)) {
  597. pContext = NULL;
  598. } else {
  599. //
  600. // find the sourcerootpaths section
  601. //
  602. b = _SetupGetSourceFileLocation(
  603. LayoutInfHandle,
  604. NULL,
  605. CopyParams->SourceFilename,
  606. (Queue->Flags & FQF_USE_ALT_PLATFORM)
  607. ? &(Queue->AltPlatformInfo)
  608. : NULL,
  609. NULL,
  610. NULL,
  611. 0,
  612. NULL,
  613. &tmpContext // location in SourceDisksFiles
  614. );
  615. pContext = b ? &tmpContext : NULL;
  616. }
  617. }
  618. if(pContext) {
  619. //
  620. // now obtain the source id (file,*disk*,...)
  621. //
  622. SetupGetIntField(pContext,1,&SourceId);
  623. }
  624. //
  625. // if we have a NULL source path, then we should check 2 things:
  626. // 1) source flag information, which indicates if we have a service
  627. // pack or CDM source location.
  628. // 2) if the relative source path is null, we'll go looking for
  629. // a relative path in the inf file, just in case the caller didn't
  630. // supply it
  631. //
  632. // note that we use the SourceFlagsSet item in the COPY_FILE structure
  633. // to optimize this path -- the first item contains the source flags,
  634. // and the second item indicates that we shouldn't bother looking for
  635. // any information, we've already done a search
  636. //
  637. if (CopyParams->SourceFlagsSet) {
  638. SourceFlags = CopyParams->SourceFlags;
  639. } else if (pContext && LayoutInfHandle) {
  640. TCHAR data[32];
  641. if(pSetupGetSourceInfo(LayoutInfHandle,
  642. pContext,
  643. SourceId,
  644. (Queue->Flags & FQF_USE_ALT_PLATFORM)
  645. ? &(Queue->AltPlatformInfo)
  646. : NULL,
  647. SRCINFO_FLAGS,
  648. data,
  649. SIZECHARS(data),
  650. NULL)) {
  651. pAToI(data,&SourceFlags);
  652. }
  653. }
  654. if (MediaFlags & SMI_FLAG_NO_SOURCE_ROOT_PATH) {
  655. if(pContext
  656. && LayoutInfHandle
  657. && !CopyParams->SourceFlagsSet
  658. && !SourcePath
  659. && pSetupGetSourceInfo(LayoutInfHandle,
  660. pContext,
  661. SourceId,
  662. (Queue->Flags & FQF_USE_ALT_PLATFORM)
  663. ? &(Queue->AltPlatformInfo)
  664. : NULL,
  665. SRCINFO_PATH,
  666. TempSubDir,
  667. SIZECHARS(TempSubDir),
  668. NULL)) {
  669. SourcePath = TempSubDir;
  670. }
  671. //
  672. // override the system source path with the servicepack source path
  673. // if the flags are set
  674. //
  675. if (SourceFlags & SRC_FLAGS_SVCPACK_SOURCE) {
  676. MediaFlags |= SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH;
  677. SourceRootPath = ServicePackSourcePath;
  678. }
  679. }
  680. //
  681. // now determine tag file vs cab file
  682. //
  683. SourceTagfile = CopyParams->SourceTagfile;
  684. if (LayoutInfHandle && pContext && (SourceFlags & SRC_FLAGS_CABFILE)) {
  685. //
  686. // the given tagfile is really a cabfile, we may have optionally a real tagfile
  687. //
  688. SourceCabfile = CopyParams->SourceTagfile;
  689. if(SourceCabfile == NULL || SourceCabfile[0]==TEXT('\0')) {
  690. //
  691. // cab name hasn't been determined yet
  692. //
  693. if(pSetupGetSourceInfo(LayoutInfHandle,
  694. pContext,
  695. SourceId,
  696. (Queue->Flags & FQF_USE_ALT_PLATFORM)
  697. ? &(Queue->AltPlatformInfo)
  698. : NULL,
  699. SRCINFO_TAGFILE,
  700. SourceCabfileBuffer,
  701. SIZECHARS(SourceCabfileBuffer),
  702. NULL
  703. )) {
  704. SourceCabfile = SourceCabfileBuffer;
  705. }
  706. }
  707. if(SourceCabfile == NULL || SourceCabfile[0]==TEXT('\0')) {
  708. //
  709. // cabfilename is erroneous
  710. //
  711. SourceCabfile = SourceTagfile = NULL;
  712. } else if(pSetupGetSourceInfo(LayoutInfHandle,
  713. pContext,
  714. SourceId,
  715. (Queue->Flags & FQF_USE_ALT_PLATFORM)
  716. ? &(Queue->AltPlatformInfo)
  717. : NULL,
  718. SRCINFO_TAGFILE2,
  719. SourceTagfile2Buffer,
  720. SIZECHARS(SourceTagfile2Buffer),
  721. NULL
  722. )) {
  723. SourceTagfile = SourceTagfile2Buffer;
  724. }
  725. }
  726. //
  727. // Allocate a queue structure.
  728. //
  729. QueueNode = MyMalloc(sizeof(SP_FILE_QUEUE_NODE));
  730. if(!QueueNode) {
  731. d = ERROR_NOT_ENOUGH_MEMORY;
  732. goto clean0;
  733. }
  734. //
  735. // Operation is copy.
  736. //
  737. QueueNode->Operation = FILEOP_COPY;
  738. QueueNode->InternalFlags = 0;
  739. //
  740. // HACK ALERT!!! HACK HACK HACK!!!!
  741. //
  742. // There might be an override platform specified. If this is so,
  743. // we will look for \i386, \mips, etc as the final component of the
  744. // specified path, and replace it with the override path.
  745. // This is a TOTAL HACK.
  746. //
  747. try {
  748. EnterCriticalSection(&PlatformPathOverrideCritSect);
  749. locked = TRUE;
  750. if(PlatformPathOverride) {
  751. p = SourcePath ? SourcePath : SourceRootPath;
  752. if(LastPathPart = _tcsrchr(p,L'\\')) {
  753. LastPathPart++;
  754. } else {
  755. LastPathPart = p;
  756. }
  757. #if defined(_AXP64_)
  758. if(!lstrcmpi(LastPathPart,TEXT("axp64"))) {
  759. #elif defined(_ALPHA_)
  760. if(!lstrcmpi(LastPathPart,TEXT("alpha"))) {
  761. #elif defined(_AMD64_)
  762. if(!lstrcmpi(LastPathPart,TEXT("amd64"))) {
  763. #elif defined(_X86_)
  764. //
  765. // NEC98
  766. //
  767. // During GUI setup, source path on local disk must be "nec98",
  768. // so we don't override "i386".
  769. //
  770. if (IsNEC98()) {
  771. HKEY hKey;
  772. DWORD DataType, DataSize;
  773. PTSTR ForceOverride;
  774. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\Setup"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  775. if (QueryRegistryValue(hKey, TEXT("ForcePlatform"), &ForceOverride, &DataType, &DataSize)
  776. == NO_ERROR) {
  777. ForcePlatform = TRUE;
  778. MyFree(ForceOverride);
  779. }
  780. RegCloseKey(hKey);
  781. }
  782. // If use driver cache, There is not i386 driver cache on NEC98.
  783. if ((CopyParams->CopyStyle & PSP_COPY_USE_DRIVERCACHE) && !lstrcmpi(PlatformPathOverride,TEXT("i386"))) {
  784. ForcePlatform = TRUE;
  785. }
  786. }
  787. if((!IsNEC98() && (!lstrcmpi(LastPathPart,TEXT("x86")) || !lstrcmpi(LastPathPart,TEXT("i386"))))
  788. || (IsNEC98() && (!lstrcmpi(LastPathPart,TEXT("nec98")) && !ForcePlatform))) {
  789. #elif defined(_IA64_)
  790. if(!lstrcmpi(LastPathPart,TEXT("ia64"))) {
  791. #endif
  792. Size = (int)(LastPathPart - p);
  793. Size = min(Size,MAX_PATH);
  794. Size *= sizeof(TCHAR);
  795. CopyMemory(TempBuffer,p,Size);
  796. TempBuffer[Size/sizeof(TCHAR)] = 0;
  797. //
  798. // If the path was something like "mips" then TempBuffer
  799. // will be empty and we don't want to introduce any extra
  800. // backslashes.
  801. //
  802. if(*TempBuffer) {
  803. pSetupConcatenatePaths(TempBuffer,PlatformPathOverride,MAX_PATH,NULL);
  804. } else {
  805. lstrcpyn(TempBuffer,PlatformPathOverride,MAX_PATH);
  806. }
  807. if(SourcePath) {
  808. SourcePath = TempBuffer;
  809. } else {
  810. SourceRootPath = TempBuffer;
  811. }
  812. }
  813. }
  814. } except(EXCEPTION_EXECUTE_HANDLER) {
  815. d = ERROR_INVALID_PARAMETER;
  816. }
  817. if(locked) {
  818. LeaveCriticalSection(&PlatformPathOverrideCritSect);
  819. } else {
  820. //
  821. // if lock not grabbed, this is the cause
  822. //
  823. d = ERROR_NOT_ENOUGH_MEMORY;
  824. }
  825. if(d != NO_ERROR) {
  826. goto clean1;
  827. }
  828. //
  829. // check here if the cab-file is present on the disk.
  830. // if it isn't, then we fall back on the current
  831. // sourcerootpath
  832. //
  833. if (CopyParams->CopyStyle & PSP_COPY_USE_DRIVERCACHE) {
  834. if (pIsDriverCachePresent(CopyParams->CacheName,
  835. SourcePath,
  836. DriverCache)) {
  837. SourceRootPath = DriverCache;
  838. MediaFlags |= SMI_FLAG_USE_LOCAL_SOURCE_CAB;
  839. }
  840. SourceTagfile = CopyParams->CacheName;
  841. SourceCabfile = NULL;
  842. }
  843. //
  844. // NOTE: When adding the following strings to the string table, we cast away
  845. // their CONST-ness to avoid a compiler warning. Since we are adding them
  846. // case-sensitively, we are guaranteed they will not be modified.
  847. //
  848. try {
  849. //
  850. // Set up the source root path.
  851. //
  852. QueueNode->SourceRootPath = pSetupStringTableAddString(
  853. Queue->StringTable,
  854. (PTSTR)SourceRootPath,
  855. STRTAB_CASE_SENSITIVE
  856. );
  857. if(QueueNode->SourceRootPath == -1) {
  858. d = ERROR_NOT_ENOUGH_MEMORY;
  859. }
  860. //
  861. // Set up the source path.
  862. //
  863. if(d == NO_ERROR) {
  864. if(SourcePath) {
  865. QueueNode->SourcePath = pSetupStringTableAddString(
  866. Queue->StringTable,
  867. (PTSTR)SourcePath,
  868. STRTAB_CASE_SENSITIVE
  869. );
  870. if(QueueNode->SourcePath == -1) {
  871. d = ERROR_NOT_ENOUGH_MEMORY;
  872. }
  873. } else {
  874. QueueNode->SourcePath = -1;
  875. }
  876. }
  877. //
  878. // Set up the source filename.
  879. //
  880. if(d == NO_ERROR) {
  881. QueueNode->SourceFilename = pSetupStringTableAddString(
  882. Queue->StringTable,
  883. (PTSTR)CopyParams->SourceFilename,
  884. STRTAB_CASE_SENSITIVE
  885. );
  886. if(QueueNode->SourceFilename == -1) {
  887. d = ERROR_NOT_ENOUGH_MEMORY;
  888. }
  889. }
  890. //
  891. // Set up the target directory.
  892. //
  893. if(d == NO_ERROR) {
  894. QueueNode->TargetDirectory = pSetupStringTableAddString(
  895. Queue->StringTable,
  896. (PTSTR)CopyParams->TargetDirectory,
  897. STRTAB_CASE_SENSITIVE
  898. );
  899. if(QueueNode->TargetDirectory == -1) {
  900. d = ERROR_NOT_ENOUGH_MEMORY;
  901. }
  902. }
  903. //
  904. // Set up the target filename.
  905. //
  906. if(d == NO_ERROR) {
  907. QueueNode->TargetFilename = pSetupStringTableAddString(
  908. Queue->StringTable,
  909. (PTSTR)(CopyParams->TargetFilename ? CopyParams->TargetFilename
  910. : CopyParams->SourceFilename),
  911. STRTAB_CASE_SENSITIVE
  912. );
  913. if(QueueNode->TargetFilename == -1) {
  914. d = ERROR_NOT_ENOUGH_MEMORY;
  915. }
  916. }
  917. //
  918. // Set up the Security Descriptor
  919. //
  920. if(d == NO_ERROR) {
  921. if( CopyParams->SecurityDescriptor){
  922. QueueNode->SecurityDesc = pSetupStringTableAddString(
  923. Queue->StringTable,
  924. (PTSTR)(CopyParams->SecurityDescriptor),
  925. STRTAB_CASE_SENSITIVE
  926. );
  927. if(QueueNode->SecurityDesc == -1) {
  928. d = ERROR_NOT_ENOUGH_MEMORY;
  929. }
  930. } else {
  931. QueueNode->SecurityDesc = -1;
  932. }
  933. }
  934. } except(EXCEPTION_EXECUTE_HANDLER) {
  935. d = ERROR_INVALID_PARAMETER;
  936. }
  937. if(d != NO_ERROR) {
  938. goto clean1;
  939. }
  940. //
  941. // Initialize a pointer to the end of the queue's current catalog info list.
  942. // We do this so that later, we can easily back-out our changes by truncating
  943. // the list after this node, and freeing all subsequent elements.
  944. //
  945. LastOldCatalogNode = Queue->CatalogList;
  946. if(LastOldCatalogNode) {
  947. while(LastOldCatalogNode->Next) {
  948. LastOldCatalogNode = LastOldCatalogNode->Next;
  949. }
  950. }
  951. //
  952. // Now process all members of our pLoadedInfs lists, adding each one to the
  953. // SPQ_CATALOG_INFO list (avoiding duplicates entries, of course).
  954. //
  955. for(i = 0; i < LoadedInfCount; i++) {
  956. for(pCurLoadedInf = pLoadedInfs[i]; pCurLoadedInf; pCurLoadedInf = pCurLoadedInf->Next) {
  957. //
  958. // First, get the (native) CatalogFile= entry from the version block
  959. // of this INF member.
  960. //
  961. if(pSetupGetCatalogFileValue(&(pCurLoadedInf->VersionBlock),
  962. TempBuffer,
  963. SIZECHARS(TempBuffer),
  964. NULL)) {
  965. l1 = pSetupStringTableAddString(Queue->StringTable,
  966. TempBuffer,
  967. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  968. );
  969. if(l1 == -1) {
  970. d = ERROR_NOT_ENOUGH_MEMORY;
  971. goto clean2;
  972. }
  973. } else {
  974. //
  975. // This INF doesn't have a CatalogFile= entry.
  976. //
  977. l1 = -1;
  978. }
  979. //
  980. // If this file queue is currently setup for a platform override,
  981. // then retrieve that CatalogFile= entry as well.
  982. //
  983. if(Queue->Flags & FQF_USE_ALT_PLATFORM) {
  984. if(pSetupGetCatalogFileValue(&(pCurLoadedInf->VersionBlock),
  985. TempBuffer,
  986. SIZECHARS(TempBuffer),
  987. &(Queue->AltPlatformInfo))) {
  988. l3 = pSetupStringTableAddString(Queue->StringTable,
  989. TempBuffer,
  990. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  991. );
  992. if(l3 == -1) {
  993. d = ERROR_NOT_ENOUGH_MEMORY;
  994. goto clean2;
  995. }
  996. } else {
  997. //
  998. // This INF doesn't have a CatalogFile= entry.
  999. //
  1000. l3 = -1;
  1001. }
  1002. } else {
  1003. //
  1004. // We're not in a platform override scenario.
  1005. //
  1006. l3 = -1;
  1007. }
  1008. //
  1009. // Now, get the INF's full path.
  1010. //
  1011. lstrcpyn(TempBuffer, pCurLoadedInf->VersionBlock.Filename, SIZECHARS(TempBuffer));
  1012. l2 = pSetupStringTableAddString(Queue->StringTable,
  1013. TempBuffer,
  1014. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  1015. );
  1016. if(l2 == -1) {
  1017. d = ERROR_NOT_ENOUGH_MEMORY;
  1018. goto clean2;
  1019. }
  1020. //
  1021. // Finally, retrieve the INF's original name, if different than the
  1022. // current name.
  1023. //
  1024. if(pCurLoadedInf->OriginalInfName) {
  1025. lstrcpyn(TempBuffer, pCurLoadedInf->OriginalInfName, SIZECHARS(TempBuffer));
  1026. l4 = pSetupStringTableAddString(Queue->StringTable,
  1027. TempBuffer,
  1028. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  1029. );
  1030. if(l4 == -1) {
  1031. d = ERROR_NOT_ENOUGH_MEMORY;
  1032. goto clean2;
  1033. }
  1034. } else {
  1035. //
  1036. // The INF's original name is the same as its current name.
  1037. //
  1038. l4 = -1;
  1039. }
  1040. b = TRUE;
  1041. for(PrevCatalogNode=NULL, CatalogNode=Queue->CatalogList;
  1042. CatalogNode;
  1043. CatalogNode=CatalogNode->Next) {
  1044. if(CatalogNode->InfFullPath == l2) {
  1045. //
  1046. // Already in there. No need to create a new node.
  1047. // Break out here, with CatalogNode pointing at the
  1048. // proper node for this catalog file.
  1049. //
  1050. // In this case, PrevCatalogNode should not be used later,
  1051. // but it shouldn't need to be used, since we won't be
  1052. // adding anything new onto the list of catalog nodes.
  1053. //
  1054. MYASSERT(CatalogNode->CatalogFileFromInf == l1);
  1055. MYASSERT(CatalogNode->InfOriginalName == l4);
  1056. b = FALSE;
  1057. break;
  1058. }
  1059. //
  1060. // PrevCatalogNode will end up pointing to the final node
  1061. // currently in the linked list, in the case where we need
  1062. // to allocate a new node. This is useful so we don't have to
  1063. // traverse the list again later when we add the new catalog
  1064. // node to the list for this queue.
  1065. //
  1066. PrevCatalogNode = CatalogNode;
  1067. }
  1068. if(b) {
  1069. //
  1070. // Need to create a new catalog node.
  1071. //
  1072. CatalogNode = MyMalloc(sizeof(SPQ_CATALOG_INFO));
  1073. if(!CatalogNode) {
  1074. d = ERROR_NOT_ENOUGH_MEMORY;
  1075. goto clean2;
  1076. }
  1077. ZeroMemory(CatalogNode, sizeof(SPQ_CATALOG_INFO));
  1078. CatalogNode->CatalogFileFromInf = l1;
  1079. CatalogNode->InfFullPath = l2;
  1080. CatalogNode->AltCatalogFileFromInf = l3;
  1081. CatalogNode->InfOriginalName = l4;
  1082. CatalogNode->AltCatalogFileFromInfPending = -1;
  1083. CatalogNode->InfFinalPath = -1;
  1084. //
  1085. // Go ahead and link the new node into the list. If we
  1086. // encounter a failure later, we can easily back out of this by
  1087. // truncating the list, since we know we always append, and we
  1088. // remembered the original list tail.
  1089. //
  1090. if(Queue->CatalogList) {
  1091. PrevCatalogNode->Next = CatalogNode;
  1092. } else {
  1093. Queue->CatalogList = CatalogNode;
  1094. }
  1095. //
  1096. // We've successfully added a new, as yet unvalidated, catalog
  1097. // node. We must therefore reset the "catalog verifications
  1098. // done" flags so that we'll redo them later.
  1099. //
  1100. Queue->Flags &= ~(FQF_DID_CATALOGS_OK | FQF_DID_CATALOGS_FAILED);
  1101. }
  1102. }
  1103. }
  1104. //
  1105. // At this point, all the INFs involved in this installation (i.e., all INFs
  1106. // in the HINFs we were passed in) have been added to our catalog info list,
  1107. // if they weren't already present. Now we need to figure out which one of
  1108. // them should be associated with the file to be copied.
  1109. //
  1110. // Note that we want to get the CatalogFile= line from the actual inf
  1111. // that contains source layout information for the file being queued.
  1112. // If the layout inf handle references multiple append-loaded infs,
  1113. // the simple mechanism of just looking up CatalogFile= in the [Version]
  1114. // section using the given handle might give us the value from the
  1115. // wrong inf.
  1116. //
  1117. // To deal with this, we attempt to locate the file in a [SourceDisksFiles]
  1118. // section using the given inf handle, which gives us back a line context.
  1119. // From the line context we can easily get at the [Version] section of the
  1120. // actual inf where the file's layout info is contained.
  1121. //
  1122. // This handles all cases properly. For example, a file that is shipped by
  1123. // a vendor that replaces one of our files. If the OEM's inf has a
  1124. // SourceDisksFiles section with the file in it, it will be found first
  1125. // when we look the file up using the given inf handle because of the way
  1126. // inf append-loading works.
  1127. //
  1128. // If we cannot find the file in a [SourceDisksFiles] section (such as
  1129. // if there is no such section), then we can't associate the file to be
  1130. // copied with any INF/CAT. If we do find a [SourceDisksFiles] entry, but
  1131. // the containing INF doesn't specify a CatalogFile= entry, then we'll go
  1132. // ahead and associate that with a SPQ_CATALOG_INFO node for that INF, but
  1133. // that catalog info node will have a CatalogFileFromInf field of -1.
  1134. // That's OK for system-provided INFs, but it will fail validation if it's
  1135. // an OEM INF (this check is done later in _SetupVerifyQueuedCatalogs).
  1136. //
  1137. if(LayoutInfHandle || LayoutLineContext) {
  1138. //
  1139. // If we already have a valid layout line context, we don't need to go
  1140. // looking for the file in [SourceDisksFiles] again (the caller is
  1141. // assumed to have done that already). The caller might also have told
  1142. // us that he *knows* that there is no [SourceDisksFiles] by passing us
  1143. // a LayoutLineContext of -1.
  1144. //
  1145. if(LayoutLineContext == (PINFCONTEXT)(-1)) {
  1146. //
  1147. // For driver signing purposes, this may be an invalid file copy,
  1148. // because it's being copied by an INF that contains no source
  1149. // media information, nor does it use a layout file to supply such
  1150. // information.
  1151. //
  1152. // Since we don't have a LayoutLineContext, we don't know exactly
  1153. // which INF contained the CopyFile directive that initiated this
  1154. // copy. However, since the context is -1, that means that it was
  1155. // INF based (i.e., as opposed to being manually queued up via
  1156. // SetupQueueCopy). Therefore, we scan all the INFs passed into
  1157. // this routine (i.e., all the INFs in the pLoadedInfs lists), and
  1158. // check to see if they're all located in %windir%\Inf. If any of
  1159. // them aren't, then we mark this copynode such that later it will
  1160. // result in a signature verification failure of
  1161. // ERROR_NO_CATALOG_FOR_OEM_INF.
  1162. //
  1163. for(i = 0; i < LoadedInfCount; i++) {
  1164. for(pCurLoadedInf = pLoadedInfs[i]; pCurLoadedInf; pCurLoadedInf = pCurLoadedInf->Next) {
  1165. if(pSetupInfIsFromOemLocation(pCurLoadedInf->VersionBlock.Filename,
  1166. TRUE)) {
  1167. //
  1168. // INF doesn't exist in %windir%\Inf--mark the copynode
  1169. // for codesigning verification failure.
  1170. //
  1171. QueueNode->InternalFlags |= IQF_FROM_BAD_OEM_INF;
  1172. break;
  1173. }
  1174. //
  1175. // Even if the INF does exist in %windir%\Inf, it might have
  1176. // originally been an OEM INF that was installed here--check
  1177. // its original filename to be sure...
  1178. //
  1179. if(pCurLoadedInf->OriginalInfName &&
  1180. pSetupInfIsFromOemLocation(pCurLoadedInf->OriginalInfName, TRUE)) {
  1181. //
  1182. // INF was an OEM INF--in this case, too, we need to
  1183. // mark the copynode for codesigning verification failure.
  1184. //
  1185. QueueNode->InternalFlags |= IQF_FROM_BAD_OEM_INF;
  1186. break;
  1187. }
  1188. }
  1189. if(QueueNode->InternalFlags & IQF_FROM_BAD_OEM_INF) {
  1190. //
  1191. // We found an OEM INF--no need to look any further.
  1192. //
  1193. break;
  1194. }
  1195. }
  1196. LayoutLineContext = NULL;
  1197. } else {
  1198. if(!LayoutLineContext) {
  1199. b = _SetupGetSourceFileLocation(
  1200. LayoutInfHandle,
  1201. NULL,
  1202. CopyParams->SourceFilename,
  1203. (Queue->Flags & FQF_USE_ALT_PLATFORM)
  1204. ? &(Queue->AltPlatformInfo)
  1205. : NULL,
  1206. NULL,
  1207. NULL,
  1208. 0,
  1209. NULL,
  1210. &LineContext
  1211. );
  1212. LayoutLineContext = b ? &LineContext : NULL;
  1213. }
  1214. }
  1215. }
  1216. //
  1217. // At this point, a non-NULL LayoutLineContext indicates that we found an
  1218. // INF to associate with the file to be copied (via a [SourceDisksFiles]
  1219. // entry).
  1220. //
  1221. if(LayoutLineContext) {
  1222. pSetupGetPhysicalInfFilepath(LayoutLineContext,
  1223. TempBuffer,
  1224. SIZECHARS(TempBuffer)
  1225. );
  1226. l2 = pSetupStringTableAddString(Queue->StringTable,
  1227. TempBuffer,
  1228. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  1229. );
  1230. //
  1231. // This INF path should already be in the string table, and since we're
  1232. // supplying a writeable buffer, there's no need for memory allocation.
  1233. // Thus the addition of this string can't fail.
  1234. //
  1235. MYASSERT(l2 != -1);
  1236. for(CatalogNode=Queue->CatalogList; CatalogNode; CatalogNode=CatalogNode->Next) {
  1237. if(CatalogNode->InfFullPath == l2) {
  1238. break;
  1239. }
  1240. }
  1241. //
  1242. // This node had better already be in the list!
  1243. //
  1244. MYASSERT(CatalogNode);
  1245. QueueNode->CatalogInfo = CatalogNode;
  1246. } else {
  1247. //
  1248. // There really is no catalog info.
  1249. //
  1250. QueueNode->CatalogInfo = NULL;
  1251. }
  1252. //
  1253. // Unlock the INF(s) here, since the code below potentially returns without
  1254. // hitting the final clean-up code at the bottom of the routine.
  1255. //
  1256. for(i = 0; i < LoadedInfCount; i++) {
  1257. UnlockInf(pLoadedInfs[i]);
  1258. }
  1259. LoadedInfCount = 0;
  1260. //
  1261. // Set up the copy style flags
  1262. //
  1263. QueueNode->StyleFlags = CopyParams->CopyStyle;
  1264. QueueNode->Next = NULL;
  1265. //
  1266. // Set up the source media.
  1267. //
  1268. try {
  1269. Source = pSetupQueueSourceMedia(
  1270. Queue,
  1271. QueueNode,
  1272. QueueNode->SourceRootPath,
  1273. CopyParams->SourceDescription,
  1274. SourceTagfile,
  1275. SourceCabfile,
  1276. MediaFlags
  1277. );
  1278. if(!Source) {
  1279. d = ERROR_NOT_ENOUGH_MEMORY;
  1280. }
  1281. } except(EXCEPTION_EXECUTE_HANDLER) {
  1282. d = ERROR_INVALID_PARAMETER;
  1283. }
  1284. if(d != NO_ERROR) {
  1285. goto clean2;
  1286. }
  1287. //
  1288. // Link the node onto the end of the copy queue for this source media.
  1289. //
  1290. if(Source->CopyQueue) {
  1291. //
  1292. // Check to see if this same copy operation has already been enqueued
  1293. // for this source media, and if so, get rid of the new one, to avoid
  1294. // duplicates. NOTE: We don't check the "InternalFlags" field, since
  1295. // if the node already exists in the queue (based on all the other
  1296. // fields comparing successfully), then any internal flags that were set
  1297. // on the previously-existing node should be preserved. (I.e., our new
  1298. // node always is created with InternalFlags set to zero, except for
  1299. // possibly IQF_FROM_BAD_OEM_INF, which we'll OR into the original
  1300. // queue node's InternalFlags, if necessary.)
  1301. //
  1302. for(TempNode=Source->CopyQueue, PrevQueueNode = NULL;
  1303. TempNode;
  1304. PrevQueueNode = TempNode, TempNode=TempNode->Next) {
  1305. if((TempNode->SourceRootPath == QueueNode->SourceRootPath) &&
  1306. (TempNode->SourcePath == QueueNode->SourcePath) &&
  1307. (TempNode->SourceFilename == QueueNode->SourceFilename) &&
  1308. (TempNode->TargetDirectory == QueueNode->TargetDirectory) &&
  1309. (TempNode->TargetFilename == QueueNode->TargetFilename) &&
  1310. (TempNode->StyleFlags == QueueNode->StyleFlags) &&
  1311. (TempNode->CatalogInfo == QueueNode->CatalogInfo)) {
  1312. //
  1313. // We have a duplicate. OR in the IQF_FROM_BAD_OEM_INF flag
  1314. // from our present queue node, if necessary, into the existing
  1315. // queue node's InternalFlags.
  1316. //
  1317. if(QueueNode->InternalFlags & IQF_FROM_BAD_OEM_INF) {
  1318. TempNode->InternalFlags |= IQF_FROM_BAD_OEM_INF;
  1319. }
  1320. //
  1321. // Now kill the newly-created queue node and return success.
  1322. //
  1323. MyFree(QueueNode);
  1324. return TRUE;
  1325. }
  1326. }
  1327. MYASSERT(PrevQueueNode);
  1328. PrevQueueNode->Next = QueueNode;
  1329. } else {
  1330. Source->CopyQueue = QueueNode;
  1331. }
  1332. Queue->CopyNodeCount++;
  1333. Source->CopyNodeCount++;
  1334. return TRUE;
  1335. clean2:
  1336. //
  1337. // Truncate the catalog info node list at its original tail, and free all
  1338. // subsequent (newly-added) nodes.
  1339. //
  1340. if(LastOldCatalogNode) {
  1341. while(LastOldCatalogNode->Next) {
  1342. CatalogNode = LastOldCatalogNode->Next;
  1343. LastOldCatalogNode->Next = CatalogNode->Next;
  1344. MyFree(CatalogNode);
  1345. }
  1346. }
  1347. clean1:
  1348. MyFree(QueueNode);
  1349. clean0:
  1350. for(i = 0; i < LoadedInfCount; i++) {
  1351. UnlockInf(pLoadedInfs[i]);
  1352. }
  1353. SetLastError(d);
  1354. return FALSE;
  1355. }
  1356. #ifdef UNICODE
  1357. //
  1358. // ANSI version
  1359. //
  1360. BOOL
  1361. SetupQueueCopyIndirectA(
  1362. IN PSP_FILE_COPY_PARAMS_A CopyParams
  1363. )
  1364. {
  1365. SP_FILE_COPY_PARAMS_WEX copyParams;
  1366. DWORD rc;
  1367. BOOL b;
  1368. ZeroMemory(&copyParams,sizeof(SP_FILE_COPY_PARAMS_W));
  1369. rc = NO_ERROR;
  1370. b = FALSE;
  1371. try {
  1372. if(CopyParams->cbSize == sizeof(SP_FILE_COPY_PARAMS_W)) {
  1373. copyParams.QueueHandle = CopyParams->QueueHandle;
  1374. copyParams.CopyStyle = CopyParams->CopyStyle;
  1375. copyParams.LayoutInf = CopyParams->LayoutInf;
  1376. copyParams.SecurityDescriptor = NULL;
  1377. } else {
  1378. rc = ERROR_INVALID_PARAMETER;
  1379. }
  1380. if((rc == NO_ERROR) && CopyParams->SourceRootPath) {
  1381. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->SourceRootPath,&copyParams.SourceRootPath);
  1382. }
  1383. if((rc == NO_ERROR) && CopyParams->SourcePath) {
  1384. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->SourcePath,&copyParams.SourcePath);
  1385. }
  1386. if((rc == NO_ERROR) && CopyParams->SourceFilename) {
  1387. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->SourceFilename,&copyParams.SourceFilename);
  1388. }
  1389. if((rc == NO_ERROR) && CopyParams->SourceDescription) {
  1390. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->SourceDescription,&copyParams.SourceDescription);
  1391. }
  1392. if((rc == NO_ERROR) && CopyParams->SourceTagfile) {
  1393. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->SourceTagfile,&copyParams.SourceTagfile);
  1394. }
  1395. if((rc == NO_ERROR) && CopyParams->TargetDirectory) {
  1396. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->TargetDirectory,&copyParams.TargetDirectory);
  1397. }
  1398. if((rc == NO_ERROR) && CopyParams->TargetFilename) {
  1399. rc = pSetupCaptureAndConvertAnsiArg(CopyParams->TargetFilename,&copyParams.TargetFilename);
  1400. }
  1401. } except(EXCEPTION_EXECUTE_HANDLER) {
  1402. //
  1403. // This is to catch the case where the CopyParams pointer goes bad.
  1404. //
  1405. rc = ERROR_INVALID_PARAMETER;
  1406. }
  1407. if(rc == NO_ERROR) {
  1408. copyParams.cbSize = sizeof(SP_FILE_COPY_PARAMS_WEX);
  1409. b = _SetupQueueCopy(&copyParams, NULL, NULL);
  1410. rc = GetLastError();
  1411. }
  1412. if(copyParams.SourceRootPath) {
  1413. MyFree(copyParams.SourceRootPath);
  1414. }
  1415. if(copyParams.SourcePath) {
  1416. MyFree(copyParams.SourcePath);
  1417. }
  1418. if(copyParams.SourceFilename) {
  1419. MyFree(copyParams.SourceFilename);
  1420. }
  1421. if(copyParams.SourceDescription) {
  1422. MyFree(copyParams.SourceDescription);
  1423. }
  1424. if(copyParams.SourceTagfile) {
  1425. MyFree(copyParams.SourceTagfile);
  1426. }
  1427. if(copyParams.TargetDirectory) {
  1428. MyFree(copyParams.TargetDirectory);
  1429. }
  1430. if(copyParams.TargetFilename) {
  1431. MyFree(copyParams.TargetFilename);
  1432. }
  1433. SetLastError(rc);
  1434. return(b);
  1435. }
  1436. #else
  1437. //
  1438. // Unicode stub
  1439. //
  1440. BOOL
  1441. SetupQueueCopyIndirectW(
  1442. IN PSP_FILE_COPY_PARAMS_W CopyParams
  1443. )
  1444. {
  1445. UNREFERENCED_PARAMETER(CopyParams);
  1446. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1447. return(FALSE);
  1448. }
  1449. #endif
  1450. BOOL
  1451. SetupQueueCopyIndirect(
  1452. IN PSP_FILE_COPY_PARAMS CopyParams
  1453. )
  1454. {
  1455. BOOL b;
  1456. SP_FILE_COPY_PARAMSEX copyParamsEx = {0};
  1457. //
  1458. // All work is done by an internal subroutine.
  1459. // The only thing we need to do here is validate the size
  1460. // of the structure we've been given by the caller.
  1461. //
  1462. try {
  1463. b = (CopyParams->cbSize == sizeof(SP_FILE_COPY_PARAMS));
  1464. if (b) {
  1465. CopyMemory(&copyParamsEx,CopyParams,sizeof(SP_FILE_COPY_PARAMS));
  1466. copyParamsEx.cbSize = sizeof(SP_FILE_COPY_PARAMSEX);
  1467. }
  1468. } except(EXCEPTION_EXECUTE_HANDLER) {
  1469. b = FALSE;
  1470. }
  1471. if(b) {
  1472. b = _SetupQueueCopy(&copyParamsEx, NULL, NULL);
  1473. } else {
  1474. SetLastError(ERROR_INVALID_PARAMETER);
  1475. }
  1476. return(b);
  1477. }
  1478. #ifdef UNICODE
  1479. //
  1480. // ANSI version
  1481. //
  1482. BOOL
  1483. SetupQueueCopySectionA(
  1484. IN HSPFILEQ QueueHandle,
  1485. IN PCSTR SourceRootPath,
  1486. IN HINF InfHandle,
  1487. IN HINF ListInfHandle, OPTIONAL
  1488. IN PCSTR Section,
  1489. IN DWORD CopyStyle
  1490. )
  1491. {
  1492. PWSTR sourcerootpath;
  1493. PWSTR section;
  1494. DWORD rc;
  1495. BOOL b;
  1496. rc = pSetupCaptureAndConvertAnsiArg(SourceRootPath,&sourcerootpath);
  1497. if(rc != NO_ERROR) {
  1498. SetLastError(rc);
  1499. return(FALSE);
  1500. }
  1501. rc = pSetupCaptureAndConvertAnsiArg(Section,&section);
  1502. if(rc != NO_ERROR) {
  1503. MyFree(sourcerootpath);
  1504. SetLastError(rc);
  1505. return(FALSE);
  1506. }
  1507. b = SetupQueueCopySectionW(
  1508. QueueHandle,
  1509. sourcerootpath,
  1510. InfHandle,
  1511. ListInfHandle,
  1512. section,
  1513. CopyStyle
  1514. );
  1515. rc = GetLastError();
  1516. MyFree(sourcerootpath);
  1517. MyFree(section);
  1518. SetLastError(rc);
  1519. return(b);
  1520. }
  1521. #else
  1522. //
  1523. // Unicode stub
  1524. //
  1525. BOOL
  1526. SetupQueueCopySectionW(
  1527. IN HSPFILEQ QueueHandle,
  1528. IN PCWSTR SourceRootPath,
  1529. IN HINF InfHandle,
  1530. IN HINF ListInfHandle, OPTIONAL
  1531. IN PCWSTR Section,
  1532. IN DWORD CopyStyle
  1533. )
  1534. {
  1535. UNREFERENCED_PARAMETER(QueueHandle);
  1536. UNREFERENCED_PARAMETER(SourceRootPath);
  1537. UNREFERENCED_PARAMETER(InfHandle);
  1538. UNREFERENCED_PARAMETER(ListInfHandle);
  1539. UNREFERENCED_PARAMETER(Section);
  1540. UNREFERENCED_PARAMETER(CopyStyle);
  1541. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1542. return(FALSE);
  1543. }
  1544. #endif
  1545. BOOL
  1546. SetupQueueCopySection(
  1547. IN HSPFILEQ QueueHandle,
  1548. IN PCTSTR SourceRootPath,
  1549. IN HINF InfHandle,
  1550. IN HINF ListInfHandle, OPTIONAL
  1551. IN PCTSTR Section,
  1552. IN DWORD CopyStyle
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. Queue an entire section in an inf file for copy. The section must be
  1557. in copy-section format and the inf file must contain [SourceDisksFiles]
  1558. and [SourceDisksNames] sections.
  1559. Arguments:
  1560. QueueHandle - supplies a handle to a setup file queue, as returned
  1561. by SetupOpenFileQueue.
  1562. SourceRootPath - supplies the root directory for the intended source.
  1563. This should be a sharepoint or a device root such as a:\ or g:\.
  1564. InfHandle - supplies a handle to an open inf file, that contains the
  1565. [SourceDisksFiles] and [SourceDisksNames] sections, and, if
  1566. ListInfHandle is not specified, contains the section names by Section.
  1567. This handle must be for a win95-style inf.
  1568. ListInfHandle - if specified, supplies a handle to an open inf file
  1569. containing the section to be queued for copy. Otherwise InfHandle
  1570. is assumed to contain the section.
  1571. Section - supplies the name of the section to be queued for copy.
  1572. CopyStyle - supplies flags that control the behavior of the copy operation
  1573. for this file.
  1574. Return Value:
  1575. Boolean value indicating outcome. If FALSE, GetLastError() returns
  1576. extended error information. Some of the files may have been queued.
  1577. --*/
  1578. {
  1579. BOOL b;
  1580. INFCONTEXT LineContext;
  1581. PCTSTR SourceFilename;
  1582. PCTSTR TargetFilename;
  1583. PCTSTR SecurityDescriptor = NULL;
  1584. PCTSTR CacheName = NULL;
  1585. UINT Flags;
  1586. DWORD CopyStyleLocal;
  1587. LONG LineCount;
  1588. HINF CabInf = INVALID_HANDLE_VALUE;
  1589. DWORD rc;
  1590. //
  1591. // Note that there are no potential faults here so no try/excepts
  1592. // are necessary. pSetupQueueSingleCopy does all validation.
  1593. //
  1594. if(!ListInfHandle || (ListInfHandle == INVALID_HANDLE_VALUE)) {
  1595. ListInfHandle = InfHandle;
  1596. }
  1597. //
  1598. // Check for missing section
  1599. //
  1600. LineCount = SetupGetLineCount (ListInfHandle, Section);
  1601. if(LineCount == -1) {
  1602. rc = GetLastError();
  1603. pSetupLogSectionError(ListInfHandle,NULL,NULL,QueueHandle,Section,MSG_LOG_NOSECTION_COPY,rc,NULL);
  1604. SetLastError(ERROR_SECTION_NOT_FOUND); // maintain existing error code, log contains correct error code
  1605. return(FALSE);
  1606. }
  1607. //
  1608. // if section is empty, do nothing.
  1609. //
  1610. if(LineCount == 0) {
  1611. return(TRUE);
  1612. }
  1613. //
  1614. // The section has to exist and there has to be at least one line in it.
  1615. //
  1616. b = SetupFindFirstLine(ListInfHandle,Section,NULL,&LineContext);
  1617. if(!b) {
  1618. rc = GetLastError();
  1619. pSetupLogSectionError(ListInfHandle,NULL,NULL,QueueHandle,Section,MSG_LOG_NOSECTION_COPY,rc,NULL);
  1620. SetLastError(ERROR_SECTION_NOT_FOUND); // maintain existing error code, log contains correct error code
  1621. return(FALSE);
  1622. }
  1623. //
  1624. //Get the Security descriptor
  1625. //
  1626. if( !pSetupGetSecurityInfo( ListInfHandle, Section, &SecurityDescriptor ) )
  1627. SecurityDescriptor = NULL;
  1628. //
  1629. // load driver cache inf
  1630. //
  1631. CabInf = SetupOpenInfFile( STR_DRIVERCACHEINF , NULL, INF_STYLE_WIN4, NULL );
  1632. if (CabInf != INVALID_HANDLE_VALUE) {
  1633. CopyStyle |= PSP_COPY_USE_DRIVERCACHE;
  1634. }
  1635. //
  1636. // Iterate every line in the section.
  1637. //
  1638. do {
  1639. CopyStyleLocal = CopyStyle;
  1640. //
  1641. // Get the target filename out of the line.
  1642. // Field 1 is the target so there must be one for the line to be valid.
  1643. //
  1644. TargetFilename = pSetupFilenameFromLine(&LineContext,FALSE);
  1645. if(!TargetFilename) {
  1646. if (CabInf != INVALID_HANDLE_VALUE) {
  1647. SetupCloseInfFile(CabInf);
  1648. }
  1649. try {
  1650. if (QueueHandle != NULL
  1651. && QueueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE
  1652. && ((PSP_FILE_QUEUE)QueueHandle)->Signature == SP_FILE_QUEUE_SIG) {
  1653. WriteLogEntry(
  1654. ((PSP_FILE_QUEUE)QueueHandle)->LogContext,
  1655. SETUP_LOG_ERROR,
  1656. MSG_LOG_COPY_TARGET,
  1657. NULL,
  1658. Section);
  1659. }
  1660. } except(EXCEPTION_EXECUTE_HANDLER) {
  1661. }
  1662. SetLastError(ERROR_INVALID_DATA);
  1663. return(FALSE);
  1664. }
  1665. //
  1666. // Get source filename out of the line. If there is none, use
  1667. // the target name as the source name.
  1668. //
  1669. SourceFilename = pSetupFilenameFromLine(&LineContext,TRUE);
  1670. if(!SourceFilename || (*SourceFilename == 0)) {
  1671. SourceFilename = TargetFilename;
  1672. }
  1673. //
  1674. // if we were asked to use the driver cache, then check if the file
  1675. // is in the associated INF for the cab.
  1676. //
  1677. if (CabInf != INVALID_HANDLE_VALUE) {
  1678. if (!pIsFileInDriverCache(CabInf, SourceFilename, NULL, &CacheName)) {
  1679. CopyStyleLocal &= ~PSP_COPY_USE_DRIVERCACHE;
  1680. }
  1681. }
  1682. //
  1683. // If present, flags are field 3.
  1684. //
  1685. if(SetupGetIntField(&LineContext,4,(PINT)&Flags)) {
  1686. if(Flags & COPYFLG_WARN_IF_SKIP) {
  1687. CopyStyleLocal |= SP_COPY_WARNIFSKIP;
  1688. }
  1689. if(Flags & COPYFLG_NOSKIP) {
  1690. CopyStyleLocal |= SP_COPY_NOSKIP;
  1691. }
  1692. if(Flags & COPYFLG_NOVERSIONCHECK) {
  1693. CopyStyleLocal &= ~SP_COPY_NEWER;
  1694. }
  1695. if(Flags & COPYFLG_FORCE_FILE_IN_USE) {
  1696. CopyStyleLocal |= SP_COPY_FORCE_IN_USE;
  1697. CopyStyleLocal |= SP_COPY_IN_USE_NEEDS_REBOOT;
  1698. }
  1699. if(Flags & COPYFLG_NO_OVERWRITE) {
  1700. CopyStyleLocal |= SP_COPY_FORCE_NOOVERWRITE;
  1701. }
  1702. if(Flags & COPYFLG_NO_VERSION_DIALOG) {
  1703. CopyStyleLocal |= SP_COPY_FORCE_NEWER;
  1704. }
  1705. if(Flags & COPYFLG_OVERWRITE_OLDER_ONLY) {
  1706. CopyStyleLocal |= SP_COPY_NEWER_ONLY;
  1707. }
  1708. if(Flags & COPYFLG_REPLACEONLY) {
  1709. CopyStyleLocal |= SP_COPY_REPLACEONLY;
  1710. }
  1711. if(Flags & COPYFLG_NODECOMP) {
  1712. CopyStyleLocal |= SP_COPY_NODECOMP;
  1713. }
  1714. if(Flags & COPYFLG_REPLACE_BOOT_FILE) {
  1715. CopyStyleLocal |= SP_COPY_REPLACE_BOOT_FILE;
  1716. }
  1717. if(Flags & COPYFLG_NOPRUNE) {
  1718. CopyStyleLocal |= SP_COPY_NOPRUNE;
  1719. }
  1720. }
  1721. b = pSetupQueueSingleCopy(
  1722. QueueHandle,
  1723. InfHandle,
  1724. ListInfHandle,
  1725. Section,
  1726. SourceRootPath,
  1727. SourceFilename,
  1728. TargetFilename,
  1729. CopyStyleLocal,
  1730. SecurityDescriptor,
  1731. CacheName
  1732. );
  1733. if (CacheName) {
  1734. MyFree( CacheName );
  1735. CacheName = NULL;
  1736. }
  1737. if(!b) {
  1738. DWORD LastError = GetLastError();
  1739. if (CabInf != INVALID_HANDLE_VALUE) {
  1740. SetupCloseInfFile(CabInf);
  1741. }
  1742. SetLastError( LastError );
  1743. return(FALSE);
  1744. }
  1745. } while(SetupFindNextLine(&LineContext,&LineContext));
  1746. if (CabInf != INVALID_HANDLE_VALUE) {
  1747. SetupCloseInfFile(CabInf);
  1748. }
  1749. return(TRUE);
  1750. }
  1751. BOOL
  1752. pSetupQueueSingleCopy(
  1753. IN HSPFILEQ QueueHandle,
  1754. IN HINF InfHandle,
  1755. IN HINF ListInfHandle, OPTIONAL
  1756. IN PCTSTR SectionName, OPTIONAL
  1757. IN PCTSTR SourceRootPath,
  1758. IN PCTSTR SourceFilename,
  1759. IN PCTSTR TargetFilename,
  1760. IN DWORD CopyStyle,
  1761. IN PCTSTR SecurityDescriptor,
  1762. IN PCTSTR CacheName
  1763. )
  1764. /*++
  1765. Routine Description:
  1766. Add a single file to the copy queue, using the default source media
  1767. and destination as specified in an inf file.
  1768. Arguments:
  1769. QueueHandle - supplies a handle to a setup file queue, as returned
  1770. by SetupOpenFileQueue.
  1771. InfHandle - supplies a handle to an open inf file, that contains the
  1772. [SourceDisksFiles] and [SourceDisksNames] sections.
  1773. This handle must be for a win95-style inf.
  1774. ListInfHandle - if specified, supplies handle to the inf in which
  1775. the file being copied appears (such as in a file copy list section).
  1776. If not specified, this is assumed to be the same inf as InfHandle.
  1777. SourceRootPath - supplies the root directory for the intended source.
  1778. This should be a sharepoint or a device root such as a:\ or g:\.
  1779. SourceFilename - supplies the filename of the source file. Filename part
  1780. only.
  1781. TargetFilename - supplies the filename of the target file. Filename part
  1782. only.
  1783. CopyStyle - supplies flags that control the behavior of the copy operation
  1784. for this file.
  1785. SecurityDescriptor - describes the permissions for the target file
  1786. CacheName - if supplied this is the name of the driver cache we should
  1787. use to copy the file out of instead of the specified source path
  1788. Return Value:
  1789. Boolean value indicating outcome. If FALSE, GetLastError() returns
  1790. extended error information.
  1791. --*/
  1792. {
  1793. BOOL b;
  1794. UINT SourceId;
  1795. DWORD SizeRequired;
  1796. PTSTR TargetDirectory;
  1797. PCTSTR SourceDescription,SourceTagfile,SourceRelativePath;
  1798. PCTSTR TmpCacheName = CacheName;
  1799. UINT SourceFlags;
  1800. DWORD rc;
  1801. TCHAR FileSubdir[MAX_PATH];
  1802. TCHAR RelativePath[MAX_PATH];
  1803. INFCONTEXT LineContext;
  1804. PINFCONTEXT pLineContext;
  1805. SP_FILE_COPY_PARAMSEX CopyParams;
  1806. HINF CabInf = INVALID_HANDLE_VALUE;
  1807. PSETUP_LOG_CONTEXT lc = NULL;
  1808. BOOL AlreadyLoggedError = FALSE;
  1809. if(!ListInfHandle || (ListInfHandle == INVALID_HANDLE_VALUE)) {
  1810. ListInfHandle = InfHandle;
  1811. }
  1812. //
  1813. // Determine the source disk id and subdir where the file is located.
  1814. //
  1815. try {
  1816. if((QueueHandle != NULL) &&
  1817. (QueueHandle != INVALID_HANDLE_VALUE) &&
  1818. (((PSP_FILE_QUEUE)QueueHandle)->Signature == SP_FILE_QUEUE_SIG)) {
  1819. lc = ((PSP_FILE_QUEUE)QueueHandle)->LogContext;
  1820. b = _SetupGetSourceFileLocation(
  1821. InfHandle,
  1822. NULL,
  1823. SourceFilename,
  1824. (((PSP_FILE_QUEUE)QueueHandle)->Flags & FQF_USE_ALT_PLATFORM)
  1825. ? &(((PSP_FILE_QUEUE)QueueHandle)->AltPlatformInfo)
  1826. : NULL,
  1827. &SourceId,
  1828. FileSubdir,
  1829. MAX_PATH,
  1830. &rc,
  1831. &LineContext
  1832. );
  1833. if(!b) {
  1834. rc = GetLastError();
  1835. }
  1836. } else {
  1837. b = FALSE;
  1838. rc = ERROR_INVALID_HANDLE;
  1839. }
  1840. } except(EXCEPTION_EXECUTE_HANDLER) {
  1841. b = FALSE;
  1842. rc = ERROR_INVALID_HANDLE;
  1843. lc = NULL;
  1844. }
  1845. if(!b) {
  1846. if((rc == ERROR_INVALID_PARAMETER) || (rc == ERROR_INVALID_HANDLE)) {
  1847. //
  1848. // if we failed due to a bad parameter, bail now
  1849. //
  1850. goto clean1;
  1851. }
  1852. //
  1853. // Try to fetch just the id and assume there is no subdir.
  1854. //
  1855. try {
  1856. b = _SetupGetSourceFileLocation(
  1857. InfHandle,
  1858. NULL,
  1859. SourceFilename,
  1860. (((PSP_FILE_QUEUE)QueueHandle)->Flags & FQF_USE_ALT_PLATFORM)
  1861. ? &(((PSP_FILE_QUEUE)QueueHandle)->AltPlatformInfo)
  1862. : NULL,
  1863. &SourceId,
  1864. NULL,
  1865. 0,
  1866. NULL,
  1867. &LineContext
  1868. );
  1869. } except(EXCEPTION_EXECUTE_HANDLER) {
  1870. b = FALSE;
  1871. }
  1872. if(b) {
  1873. FileSubdir[0] = 0;
  1874. }
  1875. }
  1876. if(b) {
  1877. //
  1878. // Get information about the source. Need the tag file,
  1879. // description, and relative source path.
  1880. //
  1881. try {
  1882. b = pSetupGetSourceAllInfo(
  1883. InfHandle,
  1884. &LineContext,
  1885. SourceId,
  1886. (((PSP_FILE_QUEUE)QueueHandle)->Flags & FQF_USE_ALT_PLATFORM)
  1887. ? &(((PSP_FILE_QUEUE)QueueHandle)->AltPlatformInfo)
  1888. : NULL,
  1889. &SourceDescription,
  1890. &SourceTagfile,
  1891. &SourceRelativePath,
  1892. &SourceFlags
  1893. );
  1894. if(!b) {
  1895. rc = GetLastError();
  1896. if((rc == ERROR_LINE_NOT_FOUND) || (rc == ERROR_SECTION_NOT_FOUND)) {
  1897. WriteLogEntry(
  1898. lc,
  1899. SETUP_LOG_ERROR,
  1900. MSG_LOG_NO_SOURCE,
  1901. NULL,
  1902. SourceId
  1903. );
  1904. AlreadyLoggedError = TRUE;
  1905. }
  1906. }
  1907. } except(EXCEPTION_EXECUTE_HANDLER) {
  1908. b = FALSE;
  1909. rc = ERROR_INVALID_PARAMETER;
  1910. }
  1911. if(!b) {
  1912. goto clean1;
  1913. }
  1914. //
  1915. // Set a value that causes _SetupQueueCopy to skip looking for the
  1916. // [SourceDisksFiles] section -- we just found it, so we just pass
  1917. // the info along!
  1918. //
  1919. pLineContext = &LineContext;
  1920. } else {
  1921. //
  1922. // Assume there is no SourceDisksFiles section and fake it as best we can.
  1923. // Assume the media has a description of "Unknown," set the source path to
  1924. // the source root if there is one, and assume no tag file.
  1925. //
  1926. // We also set a special value that tells _SetupQueueCopy not to bother trying
  1927. // to look for the [SourceDisksFiles] section itself, since there isn't one.
  1928. //
  1929. FileSubdir[0] = 0;
  1930. SourceDescription = NULL;
  1931. SourceTagfile = NULL;
  1932. SourceRelativePath = NULL;
  1933. pLineContext = (PINFCONTEXT)(-1);
  1934. }
  1935. if ( CopyStyle & PSP_COPY_CHK_DRIVERCACHE) {
  1936. CabInf = SetupOpenInfFile( STR_DRIVERCACHEINF, NULL, INF_STYLE_WIN4, NULL );
  1937. if (CabInf != INVALID_HANDLE_VALUE) {
  1938. if (pIsFileInDriverCache(CabInf, SourceFilename, SourceRelativePath, &TmpCacheName)) {
  1939. CopyStyle |= PSP_COPY_USE_DRIVERCACHE;
  1940. CopyStyle &= ~PSP_COPY_CHK_DRIVERCACHE;
  1941. }
  1942. SetupCloseInfFile(CabInf);
  1943. }
  1944. }
  1945. if (CopyStyle & PSP_COPY_USE_DRIVERCACHE) {
  1946. //
  1947. // check if the inf we want to copy from is an OEM inf
  1948. //
  1949. if (!pLineContext || pLineContext==(PINFCONTEXT)-1) {
  1950. CopyStyle &= ~PSP_COPY_USE_DRIVERCACHE;
  1951. } else if (pSetupInfIsFromOemLocation( ((PLOADED_INF)pLineContext->CurrentInf)->VersionBlock.Filename,TRUE )) {
  1952. CopyStyle &= ~PSP_COPY_USE_DRIVERCACHE;
  1953. } else if ( ((PLOADED_INF)pLineContext->CurrentInf)->OriginalInfName
  1954. && pSetupInfIsFromOemLocation( ((PLOADED_INF)pLineContext->CurrentInf)->OriginalInfName, TRUE) ) {
  1955. CopyStyle &= ~PSP_COPY_USE_DRIVERCACHE;
  1956. }
  1957. }
  1958. //
  1959. // Determine the target path for the file.
  1960. //
  1961. if(b = SetupGetTargetPath(ListInfHandle,NULL,SectionName,NULL,0,&SizeRequired)) {
  1962. if(TargetDirectory = MyMalloc(SizeRequired*sizeof(TCHAR))) {
  1963. if(b = SetupGetTargetPath(ListInfHandle,NULL,SectionName,TargetDirectory,SizeRequired,NULL)) {
  1964. try {
  1965. WriteLogEntry(
  1966. lc,
  1967. SETUP_LOG_VVERBOSE,
  1968. SectionName ? MSG_LOG_COPY_QUEUE : MSG_LOG_DEFCOPY_QUEUE,
  1969. NULL,
  1970. SectionName ? SectionName : TEXT(""),
  1971. ((PLOADED_INF)ListInfHandle)->VersionBlock.Filename,
  1972. TargetFilename ? TargetFilename : TEXT(""),
  1973. SourceFilename ? SourceFilename : TEXT(""),
  1974. CopyStyle,
  1975. TargetDirectory ? TargetDirectory : TEXT(""));
  1976. if (pLineContext && (pLineContext != (PINFCONTEXT)(-1))) {
  1977. LPCTSTR SrcSecName = NULL;
  1978. LPCTSTR SrcInfName = NULL;
  1979. PLOADED_INF pInf = (PLOADED_INF)(pLineContext->CurrentInf);
  1980. MYASSERT(pInf);
  1981. SrcSecName = pStringTableStringFromId(
  1982. pInf->StringTable,
  1983. pInf->SectionBlock[pLineContext->Section].SectionName);
  1984. SrcInfName = pInf->VersionBlock.Filename;
  1985. WriteLogEntry(
  1986. lc,
  1987. SETUP_LOG_VVERBOSE,
  1988. (CopyStyle & PSP_COPY_USE_DRIVERCACHE) ? MSG_LOG_COPY_QUEUE_DRIVERCACHE : MSG_LOG_COPY_QUEUE_SOURCE,
  1989. NULL,
  1990. SrcSecName ? SrcSecName : TEXT(""),
  1991. SrcInfName ? SrcInfName : TEXT(""),
  1992. SourceId ? SourceId : TEXT('\0'),
  1993. SourceDescription ? SourceDescription : TEXT(""),
  1994. SourceTagfile ? SourceTagfile : TEXT(""),
  1995. SourceRelativePath ? SourceRelativePath : TEXT(""));
  1996. } else {
  1997. WriteLogEntry(
  1998. lc,
  1999. SETUP_LOG_VVERBOSE,
  2000. MSG_LOG_COPY_QUEUE_DEFAULT,
  2001. NULL);
  2002. }
  2003. } except(EXCEPTION_EXECUTE_HANDLER) {
  2004. }
  2005. //
  2006. // Append the source relative path and the file subdir.
  2007. //
  2008. if(SourceRelativePath) {
  2009. lstrcpyn(RelativePath,SourceRelativePath,MAX_PATH);
  2010. if(FileSubdir[0]) {
  2011. pSetupConcatenatePaths(RelativePath,FileSubdir,MAX_PATH,NULL);
  2012. }
  2013. } else {
  2014. RelativePath[0] = 0;
  2015. }
  2016. //
  2017. // Add to queue.
  2018. //
  2019. CopyParams.cbSize = sizeof(SP_FILE_COPY_PARAMSEX);
  2020. CopyParams.QueueHandle = QueueHandle;
  2021. CopyParams.SourceRootPath = SourceRootPath;
  2022. CopyParams.SourcePath = RelativePath[0] ? RelativePath : NULL ;
  2023. CopyParams.SourceFilename = SourceFilename;
  2024. CopyParams.SourceDescription = SourceDescription;
  2025. CopyParams.SourceTagfile = SourceTagfile;
  2026. CopyParams.TargetDirectory = TargetDirectory;
  2027. CopyParams.TargetFilename = TargetFilename;
  2028. CopyParams.CopyStyle = CopyStyle;
  2029. CopyParams.LayoutInf = InfHandle;
  2030. CopyParams.SecurityDescriptor= SecurityDescriptor;
  2031. CopyParams.CacheName = TmpCacheName;
  2032. //
  2033. // first item indicates source flag information
  2034. // second item indicates that we've already retrieved
  2035. // this information, so even if the SourceFlags are zero,
  2036. // we won't go looking for it again
  2037. //
  2038. CopyParams.SourceFlags = SourceFlags;
  2039. CopyParams.SourceFlagsSet = TRUE;
  2040. b = _SetupQueueCopy(&CopyParams,
  2041. pLineContext,
  2042. ((InfHandle == ListInfHandle) ? NULL : ListInfHandle)
  2043. );
  2044. rc = GetLastError();
  2045. }
  2046. MyFree(TargetDirectory);
  2047. } else {
  2048. rc = ERROR_NOT_ENOUGH_MEMORY;
  2049. }
  2050. } else {
  2051. rc = GetLastError();
  2052. }
  2053. if(SourceDescription) {
  2054. MyFree(SourceDescription);
  2055. }
  2056. if(SourceTagfile) {
  2057. MyFree(SourceTagfile);
  2058. }
  2059. if(SourceRelativePath) {
  2060. MyFree(SourceRelativePath);
  2061. }
  2062. if(TmpCacheName && TmpCacheName != CacheName) {
  2063. MyFree(TmpCacheName);
  2064. }
  2065. clean1:
  2066. if(!b) {
  2067. BOOL FreeLC = FALSE;
  2068. if(!lc) {
  2069. if(CreateLogContext(NULL, TRUE, &lc) == NO_ERROR) {
  2070. //
  2071. // success
  2072. //
  2073. FreeLC = TRUE;
  2074. } else {
  2075. lc = NULL;
  2076. }
  2077. }
  2078. //
  2079. // If we couldn't create a log context (i.e., due to out-of-memory),
  2080. // don't bother calling WriteLogEntry, because it's not going to have
  2081. // any better luck...
  2082. //
  2083. if(lc) {
  2084. if(!AlreadyLoggedError) {
  2085. try {
  2086. WriteLogEntry(
  2087. lc,
  2088. SETUP_LOG_ERROR|SETUP_LOG_BUFFER,
  2089. MSG_LOG_COPY_QUEUE_ERROR,
  2090. NULL,
  2091. SectionName ? SectionName : TEXT(""),
  2092. ((PLOADED_INF)ListInfHandle)->VersionBlock.Filename,
  2093. TargetFilename ? TargetFilename : TEXT(""),
  2094. SourceFilename ? SourceFilename : TEXT(""));
  2095. WriteLogError(
  2096. lc,
  2097. SETUP_LOG_ERROR,
  2098. rc
  2099. );
  2100. } except(EXCEPTION_EXECUTE_HANDLER) {
  2101. }
  2102. }
  2103. if(FreeLC) {
  2104. DeleteLogContext(lc);
  2105. }
  2106. }
  2107. SetLastError(rc);
  2108. }
  2109. return(b);
  2110. }
  2111. #ifdef UNICODE
  2112. //
  2113. // ANSI version
  2114. //
  2115. BOOL
  2116. SetupQueueDefaultCopyA(
  2117. IN HSPFILEQ QueueHandle,
  2118. IN HINF InfHandle,
  2119. IN PCSTR SourceRootPath,
  2120. IN PCSTR SourceFilename,
  2121. IN PCSTR TargetFilename,
  2122. IN DWORD CopyStyle
  2123. )
  2124. {
  2125. PWSTR sourcerootpath;
  2126. PWSTR sourcefilename;
  2127. PWSTR targetfilename;
  2128. DWORD rc;
  2129. BOOL b;
  2130. b = FALSE;
  2131. rc = pSetupCaptureAndConvertAnsiArg(SourceRootPath,&sourcerootpath);
  2132. if(rc == NO_ERROR) {
  2133. rc = pSetupCaptureAndConvertAnsiArg(SourceFilename,&sourcefilename);
  2134. if(rc == NO_ERROR) {
  2135. rc = pSetupCaptureAndConvertAnsiArg(TargetFilename,&targetfilename);
  2136. if(rc == NO_ERROR) {
  2137. b = SetupQueueDefaultCopyW(
  2138. QueueHandle,
  2139. InfHandle,
  2140. sourcerootpath,
  2141. sourcefilename,
  2142. targetfilename,
  2143. CopyStyle
  2144. );
  2145. rc = GetLastError();
  2146. MyFree(targetfilename);
  2147. }
  2148. MyFree(sourcefilename);
  2149. }
  2150. MyFree(sourcerootpath);
  2151. }
  2152. SetLastError(rc);
  2153. return(b);
  2154. }
  2155. #else
  2156. //
  2157. // Unicode stub
  2158. //
  2159. BOOL
  2160. SetupQueueDefaultCopyW(
  2161. IN HSPFILEQ QueueHandle,
  2162. IN HINF InfHandle,
  2163. IN PCWSTR SourceRootPath,
  2164. IN PCWSTR SourceFilename,
  2165. IN PCWSTR TargetFilename,
  2166. IN DWORD CopyStyle
  2167. )
  2168. {
  2169. UNREFERENCED_PARAMETER(QueueHandle);
  2170. UNREFERENCED_PARAMETER(InfHandle);
  2171. UNREFERENCED_PARAMETER(SourceRootPath);
  2172. UNREFERENCED_PARAMETER(SourceFilename);
  2173. UNREFERENCED_PARAMETER(TargetFilename);
  2174. UNREFERENCED_PARAMETER(CopyStyle);
  2175. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2176. return(FALSE);
  2177. }
  2178. #endif
  2179. BOOL
  2180. SetupQueueDefaultCopy(
  2181. IN HSPFILEQ QueueHandle,
  2182. IN HINF InfHandle,
  2183. IN PCTSTR SourceRootPath,
  2184. IN PCTSTR SourceFilename,
  2185. IN PCTSTR TargetFilename,
  2186. IN DWORD CopyStyle
  2187. )
  2188. /*++
  2189. Routine Description:
  2190. Add a single file to the copy queue, using the default source media
  2191. and destination as specified in an inf file.
  2192. Arguments:
  2193. QueueHandle - supplies a handle to a setup file queue, as returned
  2194. by SetupOpenFileQueue.
  2195. InfHandle - supplies a handle to an open inf file, that contains the
  2196. [SourceDisksFiles] and [SourceDisksNames] sections.
  2197. This handle must be for a win95-style inf.
  2198. SourceRootPath - supplies the root directory for the intended source.
  2199. This should be a sharepoint or a device root such as a:\ or g:\.
  2200. SourceFilename - supplies the filename of the source file. Filename part
  2201. only.
  2202. TargetFilename - supplies the filename of the target file. Filename part
  2203. only.
  2204. CopyStyle - supplies flags that control the behavior of the copy operation
  2205. for this file.
  2206. Return Value:
  2207. Boolean value indicating outcome. If FALSE, GetLastError() returns
  2208. extended error information.
  2209. --*/
  2210. {
  2211. BOOL b;
  2212. b = pSetupQueueSingleCopy(
  2213. QueueHandle,
  2214. InfHandle,
  2215. NULL,
  2216. NULL,
  2217. SourceRootPath,
  2218. SourceFilename,
  2219. TargetFilename,
  2220. CopyStyle | PSP_COPY_CHK_DRIVERCACHE,
  2221. NULL,
  2222. NULL
  2223. );
  2224. return(b);
  2225. }
  2226. PSOURCE_MEDIA_INFO
  2227. pSetupQueueSourceMedia(
  2228. IN OUT PSP_FILE_QUEUE Queue,
  2229. IN OUT PSP_FILE_QUEUE_NODE QueueNode,
  2230. IN LONG SourceRootStringId,
  2231. IN PCTSTR SourceDescription, OPTIONAL
  2232. IN PCTSTR SourceTagfile, OPTIONAL
  2233. IN PCTSTR SourceCabfile, OPTIONAL
  2234. IN DWORD MediaFlags
  2235. )
  2236. /*++
  2237. Routine Description:
  2238. Set up a file queue node's source media descriptor pointer, creating a new
  2239. source media descriptor if necessary.
  2240. Arguments:
  2241. Queue - supplies pointer to file queue with which the queue node
  2242. is associated.
  2243. QueueNode - supplies file queue node whose source media descriptor pointer
  2244. is to be set.
  2245. SourceRootStringId - supplies string id of root to source (something like a:\).
  2246. SourceDescription - if specified, supplies a description for the media.
  2247. SourceTagfile - if specified, supplies a tag file for the media.
  2248. SourceCabfile - if specified, supplies a cabfile for the media different to the tagfile.
  2249. MediaFlags - specifies additional information used in searching for an
  2250. existing source media descriptor in the specified queue, and in adding
  2251. new source media descriptors to that queue. May be a combination of
  2252. the following values:
  2253. SMI_FLAG_NO_SOURCE_ROOT_PATH : The caller didn't supply a SourceRootPath
  2254. for this copy action, so we're using a default path. This flag
  2255. causes us to not include the SourceRootStringId as part of our
  2256. match criteria when searching to see if the specified source media
  2257. information is already present in an existing media descriptor. If
  2258. we don't find a match (i.e., we have to create a new descriptor),
  2259. we'll store this flag away in the SOURCE_MEDIA_INFO.Flags field so
  2260. that if we come along later to add source media descriptors where
  2261. the caller did specify SourceRootPath, then we'll re-use this
  2262. descriptor and overwrite the existing (default) source root path
  2263. with the caller-specified one.
  2264. SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH : The caller didn't supply a SourceRootPath
  2265. for this copy action, and it's a tagged source media, so we're using a
  2266. service pack path. This flag causes us to not include the SourceRootStringId
  2267. as part of our match criteria when searching to see if the specified source media
  2268. information is already present in an existing media descriptor. If
  2269. we don't find a match (i.e., we have to create a new descriptor),
  2270. we'll store this flag away in the SOURCE_MEDIA_INFO.Flags field so
  2271. that if we come along later to add source media descriptors where
  2272. the caller did specify SourceRootPath, then we'll re-use this
  2273. descriptor and overwrite the existing (default) source root path
  2274. with the caller-specified one.
  2275. SMI_FLAG_USE_LOCAL_SOURCE_CAB : The caller wants to use the local source cab containing
  2276. driver files, etc. In this case, we supply the source description and tagfile,
  2277. ignoring what the caller passes in. At this point we know the media is present, as
  2278. the caller provided this check. If it wasnt't, we default to the OS Source path location.
  2279. Return Value:
  2280. Pointer to source media info structure, or NULL if out of memory.
  2281. --*/
  2282. {
  2283. LONG DescriptionStringId;
  2284. LONG TagfileStringId;
  2285. LONG CabfileStringId;
  2286. PSOURCE_MEDIA_INFO Source,LastSource, TempSource;
  2287. BOOL b1,b2,b3;
  2288. TCHAR TempTagfileString[MAX_PATH];
  2289. TCHAR TempCabfileString[MAX_PATH];
  2290. TCHAR TempSrcDescString[LINE_LEN];
  2291. if (MediaFlags & SMI_FLAG_USE_LOCAL_SOURCE_CAB) {
  2292. LoadString( MyDllModuleHandle, IDS_DRIVERCACHE_DESC, TempSrcDescString, sizeof(TempSrcDescString)/sizeof(TCHAR) );
  2293. SourceDescription = TempSrcDescString;
  2294. } else {
  2295. //
  2296. // For the optional SourceDescription and SourceTagfile parameters, treat
  2297. // empty strings as if the parameter had not been specified.
  2298. //
  2299. if(SourceDescription && !(*SourceDescription)) {
  2300. SourceDescription = NULL;
  2301. }
  2302. if(SourceTagfile && !(*SourceTagfile)) {
  2303. SourceTagfile = NULL;
  2304. }
  2305. //
  2306. // If no description is specified, force the tagfile to none.
  2307. //
  2308. if(!SourceDescription) {
  2309. SourceTagfile = NULL;
  2310. }
  2311. }
  2312. if(SourceDescription) {
  2313. //
  2314. // Description specified. See if it's in the table. If not,
  2315. // no need to search the list of media descriptors because we know
  2316. // we can't find a match.
  2317. //
  2318. // (We must first copy this string to a writeable buffer, to speed up the
  2319. // case-insensitive lookup.
  2320. //
  2321. lstrcpyn(TempSrcDescString, SourceDescription, SIZECHARS(TempSrcDescString));
  2322. DescriptionStringId = pSetupStringTableLookUpString(Queue->StringTable,
  2323. TempSrcDescString,
  2324. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  2325. );
  2326. b1 = (DescriptionStringId != -1);
  2327. } else {
  2328. //
  2329. // No description specified, look for a source media with -1 as the
  2330. // description string id
  2331. //
  2332. DescriptionStringId = -1;
  2333. b1 = TRUE;
  2334. }
  2335. if(SourceTagfile) {
  2336. //
  2337. // Tagfile specified. See if it's in the table. If not,
  2338. // no need to search the list of media descriptors because we know
  2339. // we can't find a match.
  2340. //
  2341. // (Again, we must first copy the string to a writeable buffer.
  2342. //
  2343. lstrcpyn(TempTagfileString, SourceTagfile, SIZECHARS(TempTagfileString));
  2344. TagfileStringId = pSetupStringTableLookUpString(Queue->StringTable,
  2345. TempTagfileString,
  2346. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  2347. );
  2348. b2 = (TagfileStringId != -1);
  2349. } else {
  2350. //
  2351. // No tagfile specified, look for a source media with -1 as the
  2352. // tagfile string id
  2353. //
  2354. TagfileStringId = -1;
  2355. b2 = TRUE;
  2356. }
  2357. if(SourceCabfile) {
  2358. //
  2359. // Cabfile specified. See if it's in the table. If not,
  2360. // no need to search the list of media descriptors because we know
  2361. // we can't find a match.
  2362. //
  2363. // (Again, we must first copy the string to a writeable buffer.
  2364. //
  2365. lstrcpyn(TempCabfileString, SourceCabfile, SIZECHARS(TempCabfileString));
  2366. CabfileStringId = pSetupStringTableLookUpString(Queue->StringTable,
  2367. TempCabfileString,
  2368. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  2369. );
  2370. b3 = (CabfileStringId != -1);
  2371. } else {
  2372. //
  2373. // No cabfile specified, merge Cabfile&Tagfile together
  2374. // since b2==b3, then we have the identities b2|b3 == b2 and b2&b3 == b2
  2375. // ie, old behavior
  2376. //
  2377. CabfileStringId = TagfileStringId;
  2378. b3 = b2;
  2379. }
  2380. //
  2381. // If we think there's a possibility of finding an existing source that
  2382. // matches the caller's parameters, scan the source media list looking
  2383. // for a match.
  2384. //
  2385. if(b1 && b2 && b3) {
  2386. for(Source=Queue->SourceMediaList; Source; Source=Source->Next) {
  2387. if((Source->Description == DescriptionStringId)
  2388. && (Source->Tagfile == TagfileStringId)
  2389. && (Source->Cabfile == CabfileStringId)) {
  2390. //
  2391. // We only consider the SourceRootPath when both existing
  2392. // media descriptor and new media descriptor have actual
  2393. // caller-supplied paths (as opposed to something we made up).
  2394. //
  2395. if((Source->Flags & SMI_FLAG_NO_SOURCE_ROOT_PATH) ||
  2396. (MediaFlags & SMI_FLAG_NO_SOURCE_ROOT_PATH) ||
  2397. (Source->SourceRootPath == SourceRootStringId)) {
  2398. //
  2399. // Got a match. Point the queue node at this source and return.
  2400. //
  2401. QueueNode->SourceMediaInfo = Source;
  2402. //
  2403. // If the existing media descriptor had a made-up source
  2404. // root path, but the new media information had an actual
  2405. // caller-supplied one, then replace the made-up one with
  2406. // the real one and clear the no-source-root-path flag.
  2407. //
  2408. if((Source->Flags & SMI_FLAG_NO_SOURCE_ROOT_PATH) &&
  2409. !(MediaFlags & SMI_FLAG_NO_SOURCE_ROOT_PATH)) {
  2410. Source->SourceRootPath = SourceRootStringId;
  2411. Source->Flags &= ~SMI_FLAG_NO_SOURCE_ROOT_PATH;
  2412. }
  2413. return(Source);
  2414. }
  2415. }
  2416. }
  2417. }
  2418. //
  2419. // Need to add a new source media descriptor.
  2420. // Allocate the structure and fill it in.
  2421. //
  2422. Source = MyMalloc(sizeof(SOURCE_MEDIA_INFO));
  2423. if(!Source) {
  2424. return(NULL);
  2425. }
  2426. Source->Next = NULL;
  2427. Source->CopyQueue = NULL;
  2428. Source->CopyNodeCount = 0;
  2429. Source->Flags = MediaFlags;
  2430. if(SourceDescription) {
  2431. //
  2432. // Since we already passed this in for a case-insensitive lookup with a writeable
  2433. // buffer, we can add it case-sensitively, because it's already lower-cased.
  2434. //
  2435. Source->Description = pSetupStringTableAddString(Queue->StringTable,
  2436. TempSrcDescString,
  2437. STRTAB_CASE_SENSITIVE | STRTAB_ALREADY_LOWERCASE
  2438. );
  2439. //
  2440. // We also must add the description in its original case, since this is a displayable string.
  2441. // (We're safe in casting away the CONST-ness of this string, since it won't be modified.)
  2442. //
  2443. Source->DescriptionDisplayName = pSetupStringTableAddString(Queue->StringTable,
  2444. (PTSTR)SourceDescription,
  2445. STRTAB_CASE_SENSITIVE
  2446. );
  2447. if((Source->Description == -1) || (Source->DescriptionDisplayName == -1)) {
  2448. MyFree(Source);
  2449. return(NULL);
  2450. }
  2451. } else {
  2452. Source->Description = Source->DescriptionDisplayName = -1;
  2453. }
  2454. if(SourceTagfile) {
  2455. //
  2456. // Again, we already lower-cased this in a writeable buffer above.
  2457. //
  2458. Source->Tagfile = pSetupStringTableAddString(Queue->StringTable,
  2459. TempTagfileString,
  2460. STRTAB_CASE_SENSITIVE | STRTAB_ALREADY_LOWERCASE
  2461. );
  2462. if(Source->Tagfile == -1) {
  2463. MyFree(Source);
  2464. return(NULL);
  2465. }
  2466. } else {
  2467. Source->Tagfile = -1;
  2468. }
  2469. if(SourceCabfile) {
  2470. //
  2471. // Again, we already lower-cased this in a writeable buffer above.
  2472. //
  2473. Source->Cabfile = pSetupStringTableAddString(Queue->StringTable,
  2474. TempCabfileString,
  2475. STRTAB_CASE_SENSITIVE | STRTAB_ALREADY_LOWERCASE
  2476. );
  2477. if(Source->Cabfile == -1) {
  2478. MyFree(Source);
  2479. return(NULL);
  2480. }
  2481. } else {
  2482. Source->Cabfile = Source->Tagfile;
  2483. }
  2484. Source->SourceRootPath = SourceRootStringId;
  2485. //
  2486. // insert our media descriptor into the list of descriptors
  2487. // Note: if the new descriptor has the "service pack" or
  2488. // "local cab driver cache" tag set, then we insert it into
  2489. // the head of the list, otherwise we put it into the end
  2490. // of the list. This ensures that if the user get's a
  2491. // need media complaint for os binaries, and overrides
  2492. // the source path, then the user will first be prompted for service
  2493. // pack media, then the os media. This saves us from adding lots of
  2494. // code to handle need media overrides in this case, since we would
  2495. // potentially have the os source files first in the media list, which
  2496. // would cause us to install the os media files instead of the service
  2497. // pack media files
  2498. //
  2499. // another potential service pack issue is if we get Tag==Cab entries mixed with Tag!=Cab
  2500. // for exactly the same cab
  2501. // nothing much we can do here, other than ensure that any change where Tag!=Cab
  2502. // is done across the board
  2503. //
  2504. LastSource = NULL;
  2505. for(TempSource=Queue->SourceMediaList; TempSource; LastSource=TempSource,TempSource=LastSource->Next) {
  2506. if ((Source->Flags ^ TempSource->Flags) & (SMI_FLAG_USE_LOCAL_SOURCE_CAB | SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH)) {
  2507. //
  2508. // one is either normal, local source cab, or source root path, and the other is different
  2509. //
  2510. // SMI_FLAG_USE_LOCAL_SOURCE_CAB inserted before anything else
  2511. //
  2512. if(TempSource->Flags & SMI_FLAG_USE_LOCAL_SOURCE_CAB) {
  2513. //
  2514. // ISSUE-2002/04/19-JamieHun Source->Flags can have this bit set
  2515. // ordering needs to be performed with this in mind
  2516. //
  2517. //MYASSERT(!(Source->Flags & SMI_FLAG_USE_LOCAL_SOURCE_CAB));
  2518. continue;
  2519. }
  2520. if(Source->Flags & SMI_FLAG_USE_LOCAL_SOURCE_CAB) {
  2521. break;
  2522. }
  2523. //
  2524. // SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH comes next
  2525. //
  2526. if(TempSource->Flags & SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH) {
  2527. //
  2528. // ISSUE-2002/04/19-JamieHun Source->Flags can have this bit set
  2529. // ordering needs to be performed with this in mind
  2530. //
  2531. //MYASSERT(!(Source->Flags & SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH));
  2532. continue;
  2533. }
  2534. if(Source->Flags & SMI_FLAG_USE_SVCPACK_SOURCE_ROOT_PATH) {
  2535. break;
  2536. }
  2537. }
  2538. //
  2539. // group same tagfiles together (needed because of tag+cab combinations)
  2540. //
  2541. if( LastSource && (Source->Tagfile == LastSource->Tagfile)
  2542. && (Source->Tagfile != TempSource->Tagfile)) {
  2543. break;
  2544. }
  2545. }
  2546. if (LastSource) {
  2547. //
  2548. // insert after this one
  2549. //
  2550. Source->Next = LastSource->Next;
  2551. LastSource->Next = Source;
  2552. } else {
  2553. //
  2554. // TempSource will either be NULL (no media) or first media (insert before first)
  2555. //
  2556. Source->Next = TempSource;
  2557. Queue->SourceMediaList = Source;
  2558. }
  2559. Queue->SourceMediaCount++;
  2560. QueueNode->SourceMediaInfo = Source;
  2561. return(Source);
  2562. }
  2563. BOOL
  2564. pSetupGetSourceAllInfo(
  2565. IN HINF InfHandle,
  2566. IN PINFCONTEXT LayoutLineContext, OPTIONAL
  2567. IN UINT SourceId,
  2568. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, OPTIONAL
  2569. OUT PCTSTR *Description,
  2570. OUT PCTSTR *Tagfile,
  2571. OUT PCTSTR *RelativePath,
  2572. OUT PUINT SourceFlags
  2573. )
  2574. {
  2575. BOOL b;
  2576. DWORD RequiredSize;
  2577. PTSTR p;
  2578. DWORD ec;
  2579. TCHAR Buffer[MAX_PATH];
  2580. //
  2581. // Get path relative to the source.
  2582. //
  2583. b = pSetupGetSourceInfo(InfHandle,
  2584. LayoutLineContext,
  2585. SourceId,
  2586. AltPlatformInfo,
  2587. SRCINFO_PATH,
  2588. NULL,
  2589. 0,
  2590. &RequiredSize
  2591. );
  2592. if(!b) {
  2593. ec = GetLastError();
  2594. goto clean0;
  2595. }
  2596. p = MyMalloc(RequiredSize*sizeof(TCHAR));
  2597. if(!p) {
  2598. ec = ERROR_NOT_ENOUGH_MEMORY;
  2599. goto clean0;
  2600. }
  2601. pSetupGetSourceInfo(InfHandle,
  2602. LayoutLineContext,
  2603. SourceId,
  2604. AltPlatformInfo,
  2605. SRCINFO_PATH,
  2606. p,
  2607. RequiredSize,
  2608. NULL
  2609. );
  2610. *RelativePath = p;
  2611. //
  2612. // Get description.
  2613. //
  2614. b = pSetupGetSourceInfo(InfHandle,
  2615. LayoutLineContext,
  2616. SourceId,
  2617. AltPlatformInfo,
  2618. SRCINFO_DESCRIPTION,
  2619. NULL,
  2620. 0,
  2621. &RequiredSize
  2622. );
  2623. if(!b) {
  2624. ec = GetLastError();
  2625. goto clean1;
  2626. }
  2627. p = MyMalloc(RequiredSize*sizeof(TCHAR));
  2628. if(!p) {
  2629. ec = ERROR_NOT_ENOUGH_MEMORY;
  2630. goto clean1;
  2631. }
  2632. pSetupGetSourceInfo(InfHandle,
  2633. LayoutLineContext,
  2634. SourceId,
  2635. AltPlatformInfo,
  2636. SRCINFO_DESCRIPTION,
  2637. p,
  2638. RequiredSize,
  2639. NULL
  2640. );
  2641. *Description = p;
  2642. //
  2643. // Get tagfile, if any.
  2644. //
  2645. b = pSetupGetSourceInfo(InfHandle,
  2646. LayoutLineContext,
  2647. SourceId,
  2648. AltPlatformInfo,
  2649. SRCINFO_TAGFILE,
  2650. NULL,
  2651. 0,
  2652. &RequiredSize
  2653. );
  2654. if(!b) {
  2655. ec = GetLastError();
  2656. goto clean2;
  2657. }
  2658. p = MyMalloc(RequiredSize*sizeof(TCHAR));
  2659. if(!p) {
  2660. ec = ERROR_NOT_ENOUGH_MEMORY;
  2661. goto clean2;
  2662. }
  2663. pSetupGetSourceInfo(InfHandle,
  2664. LayoutLineContext,
  2665. SourceId,
  2666. AltPlatformInfo,
  2667. SRCINFO_TAGFILE,
  2668. p,
  2669. RequiredSize,
  2670. NULL
  2671. );
  2672. if(*p) {
  2673. *Tagfile = p;
  2674. } else {
  2675. MyFree(p);
  2676. *Tagfile = NULL;
  2677. }
  2678. //
  2679. // Get flags, if any.
  2680. //
  2681. b = pSetupGetSourceInfo(InfHandle,
  2682. LayoutLineContext,
  2683. SourceId,
  2684. AltPlatformInfo,
  2685. SRCINFO_FLAGS,
  2686. Buffer,
  2687. SIZECHARS(Buffer),
  2688. NULL
  2689. );
  2690. if(!b) {
  2691. ec = GetLastError();
  2692. goto clean3;
  2693. }
  2694. pAToI( Buffer, SourceFlags );
  2695. return(TRUE);
  2696. clean3:
  2697. MyFree(*Tagfile);
  2698. clean2:
  2699. MyFree(*Description);
  2700. clean1:
  2701. MyFree(*RelativePath);
  2702. clean0:
  2703. SetLastError(ec);
  2704. return(FALSE);
  2705. }
  2706. BOOL
  2707. pIsFileInDriverCache(
  2708. IN HINF CabInf,
  2709. IN PCTSTR TargetFilename,
  2710. IN PCTSTR SubDirectory,
  2711. OUT PCTSTR *CacheName
  2712. )
  2713. {
  2714. INFCONTEXT Context,SectionContext;
  2715. PCTSTR SectionName,CabName;
  2716. TCHAR TempBuffer[MAX_PATH];
  2717. UINT Field, FieldCount;
  2718. MYASSERT(CabInf != INVALID_HANDLE_VALUE);
  2719. MYASSERT(TargetFilename);
  2720. MYASSERT(CacheName);
  2721. if (!SetupFindFirstLine(CabInf, TEXT("Version"), TEXT("CabFiles"), &SectionContext)) {
  2722. return(FALSE);
  2723. }
  2724. do {
  2725. FieldCount = SetupGetFieldCount(&SectionContext);
  2726. for(Field=1; Field<=FieldCount; Field++) {
  2727. SectionName = pSetupGetField(&SectionContext,Field);
  2728. if (SetupFindFirstLine(CabInf,SectionName,TargetFilename,&Context)) {
  2729. //
  2730. // we found a match
  2731. //
  2732. if (SetupFindFirstLine(CabInf,TEXT("Cabs"),SectionName,&Context)) {
  2733. CabName= pSetupGetField(&Context,1);
  2734. //if (pIsDriverCachePresent(CabName,SubDirectory,TempBuffer)) {
  2735. *CacheName = DuplicateString( CabName );
  2736. if (*CacheName) {
  2737. return(TRUE);
  2738. }
  2739. //}
  2740. }
  2741. }
  2742. } // end for
  2743. } while (SetupFindNextMatchLine(&SectionContext,TEXT("CabFiles"),&SectionContext));
  2744. return(FALSE);
  2745. }
  2746. BOOL
  2747. pIsDriverCachePresent(
  2748. IN PCTSTR DriverName,
  2749. IN PCTSTR Subdirectory,
  2750. IN OUT PTSTR DriverBuffer
  2751. )
  2752. /*++
  2753. Routine Description:
  2754. Looks at the proper location for the driver cache cab-file, and if it's
  2755. present, return TRUE. If present, it returns the partial path to the
  2756. cab file
  2757. Arguments:
  2758. DriveName - the cab file we're looking for
  2759. Subdirectory - if specified, use this as the subdirectory from the root of the driver
  2760. cache, otherwise use the specified architecture's subdirectory
  2761. DriverBuffer - if the cab file is present, return the source root to the cab file
  2762. Return Value:
  2763. TRUE if the cab file is present
  2764. --*/
  2765. {
  2766. TCHAR TempBuffer[MAX_PATH];
  2767. if (!DriverCacheSourcePath || !DriverName) {
  2768. return FALSE;
  2769. }
  2770. if (!Subdirectory) {
  2771. Subdirectory =
  2772. #if defined(_AXP64_)
  2773. TEXT("axp64");
  2774. #elif defined(_ALPHA_)
  2775. TEXT("alpha");
  2776. #elif defined(_X86_)
  2777. IsNEC98() ? TEXT("nec98") : TEXT("i386");
  2778. #elif defined(_IA64_)
  2779. TEXT("ia64");
  2780. #elif defined(_AMD64_)
  2781. TEXT("amd64");
  2782. #endif
  2783. }
  2784. lstrcpy(TempBuffer, DriverCacheSourcePath);
  2785. pSetupConcatenatePaths(TempBuffer, Subdirectory , MAX_PATH, NULL);
  2786. pSetupConcatenatePaths(TempBuffer, DriverName, MAX_PATH, NULL);
  2787. if (FileExists(TempBuffer,NULL)) {
  2788. lstrcpy(DriverBuffer,DriverCacheSourcePath);
  2789. return(TRUE);
  2790. }
  2791. return(FALSE);
  2792. }