Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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