Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1203 lines
36 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. fileq1.c
  5. Abstract:
  6. Miscellaneous setup file queue routines.
  7. Author:
  8. Ted Miller (tedm) 15-Feb-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. HSPFILEQ
  14. WINAPI
  15. SetupOpenFileQueue(
  16. VOID
  17. )
  18. /*++
  19. Routine Description:
  20. Create a setup file queue.
  21. Arguments:
  22. None.
  23. Return Value:
  24. Handle to setup file queue. INVALID_HANDLE_VALUE if error occurs (GetLastError reports the error)
  25. --*/
  26. {
  27. PSP_FILE_QUEUE Queue = NULL;
  28. DWORD rc;
  29. DWORD status = ERROR_INVALID_DATA;
  30. try {
  31. //
  32. // Allocate a queue structure.
  33. //
  34. Queue = MyMalloc(sizeof(SP_FILE_QUEUE));
  35. if(!Queue) {
  36. status = ERROR_NOT_ENOUGH_MEMORY;
  37. leave;
  38. }
  39. ZeroMemory(Queue,sizeof(SP_FILE_QUEUE));
  40. //
  41. // Create a string table for this queue.
  42. //
  43. Queue->StringTable = pSetupStringTableInitialize();
  44. if(!Queue->StringTable) {
  45. status = ERROR_NOT_ENOUGH_MEMORY;
  46. leave;
  47. }
  48. Queue->TargetLookupTable = pSetupStringTableInitializeEx( sizeof(SP_TARGET_ENT), 0 );
  49. if(!Queue->TargetLookupTable) {
  50. status = ERROR_NOT_ENOUGH_MEMORY;
  51. leave;
  52. }
  53. Queue->BackupInfID = -1; // no Backup INF
  54. Queue->BackupInstanceID = -1; // no Backup INF
  55. Queue->RestorePathID = -1; // no Restore directory
  56. Queue->Flags = FQF_TRY_SIS_COPY;
  57. Queue->SisSourceDirectory = NULL;
  58. Queue->SisSourceHandle = INVALID_HANDLE_VALUE;
  59. Queue->Signature = SP_FILE_QUEUE_SIG;
  60. //
  61. // Retrieve the codesigning policy currently in effect (policy in
  62. // effect is for non-driver signing behavior until we are told
  63. // otherwise).
  64. //
  65. Queue->DriverSigningPolicy = pSetupGetCurrentDriverSigningPolicy(FALSE);
  66. //
  67. // Initialize the device description field to the null string id.
  68. //
  69. Queue->DeviceDescStringId = -1;
  70. //
  71. // Initialize the override catalog filename to the null string id.
  72. //
  73. Queue->AltCatalogFile = -1;
  74. //
  75. // Createa a generic log context
  76. //
  77. rc = CreateLogContext(NULL, TRUE, &Queue->LogContext);
  78. if (rc != NO_ERROR) {
  79. status = rc;
  80. leave;
  81. }
  82. status = NO_ERROR;
  83. } except (EXCEPTION_EXECUTE_HANDLER) {
  84. //
  85. // do nothing; this just allows us to catch errors
  86. //
  87. }
  88. if (status == NO_ERROR) {
  89. //
  90. // The address of the queue structure is the queue handle.
  91. //
  92. return(Queue);
  93. }
  94. //
  95. // failure cleanup
  96. //
  97. if (Queue != NULL) {
  98. if (Queue->StringTable) {
  99. pSetupStringTableDestroy(Queue->StringTable);
  100. }
  101. if (Queue->TargetLookupTable) {
  102. pSetupStringTableDestroy(Queue->TargetLookupTable);
  103. }
  104. if(Queue->LogContext) {
  105. DeleteLogContext(Queue->LogContext);
  106. }
  107. MyFree(Queue);
  108. }
  109. //
  110. // return with this on error
  111. //
  112. SetLastError(status);
  113. return (HSPFILEQ)INVALID_HANDLE_VALUE;
  114. }
  115. BOOL
  116. WINAPI
  117. SetupCloseFileQueue(
  118. IN HSPFILEQ QueueHandle
  119. )
  120. /*++
  121. Routine Description:
  122. Destroy a setup file queue. Enqueued operations are not performed.
  123. Arguments:
  124. QueueHandle - supplies handle to setup file queue to be destroyed.
  125. Return Value:
  126. If the function succeeds, the return value is TRUE.
  127. If the function fails, the return value is FALSE. To get extended error
  128. information, call GetLastError. Presently, the only error that can be
  129. encountered is ERROR_INVALID_HANDLE or ERROR_FILEQUEUE_LOCKED, which will occur if someone (typically,
  130. a device installation parameter block) is referencing this queue handle.
  131. --*/
  132. {
  133. PSP_FILE_QUEUE Queue;
  134. PSP_FILE_QUEUE_NODE Node,NextNode;
  135. PSP_DELAYMOVE_NODE DelayMoveNode,NextDelayMoveNode;
  136. PSP_UNWIND_NODE UnwindNode,NextUnwindNode;
  137. PSOURCE_MEDIA_INFO Media,NextMedia;
  138. BOOL b;
  139. PSPQ_CATALOG_INFO Catalog,NextCatalog;
  140. DWORD status = ERROR_INVALID_HANDLE;
  141. if (QueueHandle == NULL || QueueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE) {
  142. SetLastError(ERROR_INVALID_HANDLE);
  143. return FALSE;
  144. }
  145. Queue = (PSP_FILE_QUEUE)QueueHandle;
  146. //
  147. // Primitive queue validation.
  148. //
  149. b = TRUE;
  150. try {
  151. if(Queue->Signature != SP_FILE_QUEUE_SIG) {
  152. b = FALSE;
  153. }
  154. } except(EXCEPTION_EXECUTE_HANDLER) {
  155. b = FALSE;
  156. }
  157. if(!b) {
  158. SetLastError(ERROR_INVALID_HANDLE);
  159. return(FALSE);
  160. }
  161. try {
  162. //
  163. // Don't close the queue if someone is still referencing it.
  164. //
  165. if(Queue->LockRefCount) {
  166. WriteLogEntry(
  167. Queue->LogContext,
  168. SETUP_LOG_ERROR,
  169. MSG_LOG_FILEQUEUE_IN_USE,
  170. NULL); // text message
  171. status = ERROR_FILEQUEUE_LOCKED;
  172. leave;
  173. }
  174. //
  175. // we may have some unwinding to do, but assume we succeeded
  176. // ie, delete temp files and cleanup memory used
  177. //
  178. pSetupUnwindAll(Queue, TRUE);
  179. //
  180. // If the queue wasn't committed and we are backup aware and this is
  181. // a device install then we need to clean up any backup directories and
  182. // registry entries that we created since we have already unwound the
  183. // queue up above.
  184. //
  185. if (!(Queue->Flags & FQF_QUEUE_ALREADY_COMMITTED) &&
  186. (Queue->Flags & FQF_DEVICE_BACKUP)) {
  187. pSetupCleanupBackup(Queue);
  188. }
  189. Queue->Signature = 0;
  190. //
  191. // Free the DelayMove list
  192. //
  193. for(DelayMoveNode = Queue->DelayMoveQueue; DelayMoveNode; DelayMoveNode = NextDelayMoveNode) {
  194. NextDelayMoveNode = DelayMoveNode->NextNode;
  195. MyFree(DelayMoveNode);
  196. }
  197. //
  198. // Free the queue nodes.
  199. //
  200. for(Node=Queue->DeleteQueue; Node; Node=NextNode) {
  201. NextNode = Node->Next;
  202. MyFree(Node);
  203. }
  204. for(Node=Queue->RenameQueue; Node; Node=NextNode) {
  205. NextNode = Node->Next;
  206. MyFree(Node);
  207. }
  208. // Free the backup queue nodes
  209. for(Node=Queue->BackupQueue; Node; Node=NextNode) {
  210. NextNode = Node->Next;
  211. MyFree(Node);
  212. }
  213. // Free the unwind queue nodes
  214. for(UnwindNode=Queue->UnwindQueue; UnwindNode; UnwindNode=NextUnwindNode) {
  215. NextUnwindNode = UnwindNode->NextNode;
  216. MyFree(UnwindNode);
  217. }
  218. //
  219. // Free the media structures and associated copy queues.
  220. //
  221. for(Media=Queue->SourceMediaList; Media; Media=NextMedia) {
  222. for(Node=Media->CopyQueue; Node; Node=NextNode) {
  223. NextNode = Node->Next;
  224. MyFree(Node);
  225. }
  226. NextMedia = Media->Next;
  227. MyFree(Media);
  228. }
  229. //
  230. // Free the catalog nodes.
  231. //
  232. for(Catalog=Queue->CatalogList; Catalog; Catalog=NextCatalog) {
  233. NextCatalog = Catalog->Next;
  234. MyFree(Catalog);
  235. }
  236. //
  237. // Free the validation platform information (if any)
  238. //
  239. if(Queue->ValidationPlatform) {
  240. MyFree(Queue->ValidationPlatform);
  241. }
  242. //
  243. // Free the string table.
  244. //
  245. pSetupStringTableDestroy(Queue->StringTable);
  246. //
  247. // (jamiehun) Free the target lookup table.
  248. //
  249. pSetupStringTableDestroy(Queue->TargetLookupTable);
  250. //
  251. // Free SIS-related fields.
  252. //
  253. if (Queue->SisSourceHandle != INVALID_HANDLE_VALUE) {
  254. CloseHandle(Queue->SisSourceHandle);
  255. }
  256. if (Queue->SisSourceDirectory != NULL) {
  257. MyFree(Queue->SisSourceDirectory);
  258. }
  259. //
  260. // Unreference log context
  261. //
  262. DeleteLogContext(Queue->LogContext);
  263. //
  264. // Release the crypto context (if there is one)
  265. //
  266. if(Queue->hCatAdmin) {
  267. CryptCATAdminReleaseContext(Queue->hCatAdmin, 0);
  268. }
  269. //
  270. // Release the handle to the bad driver database (if there is one)
  271. //
  272. #ifdef UNICODE
  273. if(Queue->hSDBDrvMain) {
  274. SdbReleaseDatabase(Queue->hSDBDrvMain);
  275. }
  276. #else
  277. MYASSERT(!(Queue->hSDBDrvMain));
  278. #endif
  279. //
  280. // Free the queue structure itself.
  281. //
  282. MyFree(Queue);
  283. status = NO_ERROR;
  284. } except (EXCEPTION_EXECUTE_HANDLER) {
  285. //
  286. // do nothing; this just allows us to catch errors
  287. //
  288. }
  289. if (status != NO_ERROR) {
  290. SetLastError(status);
  291. return FALSE;
  292. }
  293. return TRUE;
  294. }
  295. #ifdef UNICODE
  296. //
  297. // ANSI version
  298. //
  299. BOOL
  300. WINAPI
  301. SetupSetFileQueueAlternatePlatformA(
  302. IN HSPFILEQ QueueHandle,
  303. IN PSP_ALTPLATFORM_INFO_V2 AlternatePlatformInfo, OPTIONAL
  304. IN PCSTR AlternateDefaultCatalogFile OPTIONAL
  305. )
  306. {
  307. PWSTR UAlternateDefaultCatalogFile;
  308. DWORD Err;
  309. if(AlternateDefaultCatalogFile) {
  310. Err = pSetupCaptureAndConvertAnsiArg(AlternateDefaultCatalogFile,
  311. &UAlternateDefaultCatalogFile
  312. );
  313. if(Err != NO_ERROR) {
  314. SetLastError(Err);
  315. return FALSE;
  316. }
  317. } else {
  318. UAlternateDefaultCatalogFile = NULL;
  319. }
  320. if(SetupSetFileQueueAlternatePlatformW(QueueHandle,
  321. AlternatePlatformInfo,
  322. UAlternateDefaultCatalogFile)) {
  323. Err = NO_ERROR;
  324. } else {
  325. Err = GetLastError();
  326. MYASSERT(Err != NO_ERROR);
  327. }
  328. if(UAlternateDefaultCatalogFile) {
  329. MyFree(UAlternateDefaultCatalogFile);
  330. }
  331. SetLastError(Err);
  332. return (Err == NO_ERROR);
  333. }
  334. #else
  335. //
  336. // Unicode stub
  337. //
  338. BOOL
  339. WINAPI
  340. SetupSetFileQueueAlternatePlatformW(
  341. IN HSPFILEQ QueueHandle,
  342. IN PSP_ALTPLATFORM_INFO_V2 AlternatePlatformInfo, OPTIONAL
  343. IN PCWSTR AlternateDefaultCatalogFile OPTIONAL
  344. )
  345. {
  346. UNREFERENCED_PARAMETER(QueueHandle);
  347. UNREFERENCED_PARAMETER(AlternatePlatformInfo);
  348. UNREFERENCED_PARAMETER(AlternateDefaultCatalogFile);
  349. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  350. return(FALSE);
  351. }
  352. #endif
  353. BOOL
  354. WINAPI
  355. SetupSetFileQueueAlternatePlatform(
  356. IN HSPFILEQ QueueHandle,
  357. IN PSP_ALTPLATFORM_INFO_V2 AlternatePlatformInfo, OPTIONAL
  358. IN PCTSTR AlternateDefaultCatalogFile OPTIONAL
  359. )
  360. /*++
  361. Routine Description:
  362. This API associates the specified file queue with an alternate platform in
  363. order to allow for non-native signature verification (e.g., verifying Win98
  364. files on Windows NT, verifying x86 Windows NT files on Alpha, etc.). The
  365. verification is done using the corresponding catalog files specified via
  366. platform-specific CatalogFile= entries in the source media descriptor INFs
  367. (i.e., INFs containing [SourceDisksNames] and [SourceDisksFiles] sections
  368. used when queueing files to be copied).
  369. The caller may also optionally specify a default catalog file, to be used
  370. for verification of files that have no associated catalog, thus would
  371. otherwise be globally validated (e.g., files queued up from the system
  372. layout.inf). A side-effect of this is that INFs with no CatalogFile= entry
  373. are considered valid, even if they exist outside of %windir%\Inf.
  374. If this file queue is subsequently committed, the nonnative catalogs will be
  375. installed into the system catalog database, just as native catalogs would.
  376. Arguments:
  377. QueueHandle - supplies a handle to the file queue with which the alternate
  378. platform is to be associated.
  379. AlternatePlatformInfo - optionally, supplies the address of a structure
  380. containing information regarding the alternate platform that is to be
  381. used for subsequent validation of files contained in the specified file
  382. queue. If this parameter is not supplied, then the queue's association
  383. with an alternate platform is reset, and is reverted back to the default
  384. (i.e., native) environment. This information is also used in
  385. determining the appropriate platform-specific CatalogFile= entry to be
  386. used when finding out which catalog file is applicable for a particular
  387. source media descriptor INF.
  388. (NOTE: caller may actually pass in a V1 struct instead--we detect this
  389. case and convert the V1 struct into a V2 one.)
  390. AlternateDefaultCatalogFile - optionally, supplies the full path to the
  391. catalog file to be used for verification of files contained in the
  392. specified file queue that are not associated with any particular catalog
  393. (hence would normally be globally validated).
  394. If this parameter is NULL, then the file queue will no longer be
  395. associated with any 'override' catalog, and all validation will take
  396. place normally (i.e., using the standard rules for digital signature
  397. verification via system-supplied and 3rd-party provided INFs/CATs).
  398. If this alternate default catalog is still associated with the file
  399. queue at commit time, it will be installed using its present name, and
  400. will overwrite any existing installed catalog file having that name.
  401. Return Value:
  402. If the function succeeds, the return value is TRUE.
  403. If the function fails, the return value is FALSE. To get extended error
  404. information, call GetLastError.
  405. --*/
  406. {
  407. PSP_FILE_QUEUE Queue;
  408. DWORD Err;
  409. TCHAR PathBuffer[MAX_PATH];
  410. DWORD RequiredSize;
  411. PTSTR TempCharPtr;
  412. LONG AltCatalogStringId;
  413. PSPQ_CATALOG_INFO CatalogNode;
  414. LPCTSTR InfFullPath;
  415. SP_ALTPLATFORM_INFO_V2 AltPlatformInfoV2;
  416. Err = NO_ERROR; // assume success
  417. try {
  418. Queue = (PSP_FILE_QUEUE)QueueHandle;
  419. //
  420. // Now validate the AlternatePlatformInfo parameter.
  421. //
  422. if(AlternatePlatformInfo) {
  423. if(AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO_V2)) {
  424. //
  425. // The caller may have passed us in a Version 1 struct, or they
  426. // may have passed us in bad data...
  427. //
  428. if(AlternatePlatformInfo->cbSize == sizeof(SP_ALTPLATFORM_INFO_V1)) {
  429. //
  430. // Flags/Reserved field is reserved in V1
  431. //
  432. if(AlternatePlatformInfo->Reserved) {
  433. Err = ERROR_INVALID_PARAMETER;
  434. goto clean0;
  435. }
  436. //
  437. // Convert the caller-supplied data into Version 2 format.
  438. //
  439. ZeroMemory(&AltPlatformInfoV2, sizeof(AltPlatformInfoV2));
  440. AltPlatformInfoV2.cbSize = sizeof(SP_ALTPLATFORM_INFO_V2);
  441. AltPlatformInfoV2.Platform = ((PSP_ALTPLATFORM_INFO_V1)AlternatePlatformInfo)->Platform;
  442. AltPlatformInfoV2.MajorVersion = ((PSP_ALTPLATFORM_INFO_V1)AlternatePlatformInfo)->MajorVersion;
  443. AltPlatformInfoV2.MinorVersion = ((PSP_ALTPLATFORM_INFO_V1)AlternatePlatformInfo)->MinorVersion;
  444. AltPlatformInfoV2.ProcessorArchitecture = ((PSP_ALTPLATFORM_INFO_V1)AlternatePlatformInfo)->ProcessorArchitecture;
  445. AltPlatformInfoV2.Flags = 0;
  446. AlternatePlatformInfo = &AltPlatformInfoV2;
  447. } else {
  448. Err = ERROR_INVALID_USER_BUFFER;
  449. goto clean0;
  450. }
  451. }
  452. //
  453. // Gotta be either Windows or Windows NT
  454. //
  455. if((AlternatePlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS) &&
  456. (AlternatePlatformInfo->Platform != VER_PLATFORM_WIN32_NT)) {
  457. Err = ERROR_INVALID_PARAMETER;
  458. goto clean0;
  459. }
  460. //
  461. // Processor had better be either i386, alpha, ia64, or amd64
  462. //
  463. if((AlternatePlatformInfo->ProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) &&
  464. (AlternatePlatformInfo->ProcessorArchitecture != PROCESSOR_ARCHITECTURE_ALPHA) &&
  465. (AlternatePlatformInfo->ProcessorArchitecture != PROCESSOR_ARCHITECTURE_IA64) &&
  466. (AlternatePlatformInfo->ProcessorArchitecture != PROCESSOR_ARCHITECTURE_ALPHA64) &&
  467. (AlternatePlatformInfo->ProcessorArchitecture != PROCESSOR_ARCHITECTURE_AMD64)) {
  468. Err = ERROR_INVALID_PARAMETER;
  469. goto clean0;
  470. }
  471. //
  472. // MajorVersion field must be non-zero (MinorVersion field can be
  473. // anything)
  474. //
  475. if(!AlternatePlatformInfo->MajorVersion) {
  476. Err = ERROR_INVALID_PARAMETER;
  477. goto clean0;
  478. }
  479. //
  480. // Validate structure parameter flags (bits indicating what
  481. // parts of the structure are valid).
  482. //
  483. if((AlternatePlatformInfo->Flags & ~ (SP_ALTPLATFORM_FLAGS_VERSION_RANGE)) != 0) {
  484. Err = ERROR_INVALID_PARAMETER;
  485. goto clean0;
  486. }
  487. //
  488. // fill in version validation range if none supplied by caller
  489. //
  490. if((AlternatePlatformInfo->Flags & SP_ALTPLATFORM_FLAGS_VERSION_RANGE) == 0) {
  491. //
  492. // If caller does not know about FirstValidate*Version,
  493. // version upper and lower bounds are equal.
  494. //
  495. AlternatePlatformInfo->FirstValidatedMajorVersion = AlternatePlatformInfo->MajorVersion;
  496. AlternatePlatformInfo->FirstValidatedMinorVersion = AlternatePlatformInfo->MinorVersion;
  497. AlternatePlatformInfo->Flags |= SP_ALTPLATFORM_FLAGS_VERSION_RANGE;
  498. }
  499. }
  500. //
  501. // OK, the platform info structure checks out. Now, associate the
  502. // default catalog (if supplied) with the file queue, otherwise reset
  503. // any existing association with a default catalog.
  504. //
  505. if(AlternateDefaultCatalogFile) {
  506. RequiredSize = GetFullPathName(AlternateDefaultCatalogFile,
  507. SIZECHARS(PathBuffer),
  508. PathBuffer,
  509. &TempCharPtr
  510. );
  511. if(!RequiredSize) {
  512. Err = GetLastError();
  513. goto clean0;
  514. } else if(RequiredSize >= SIZECHARS(PathBuffer)) {
  515. MYASSERT(0);
  516. Err = ERROR_BUFFER_OVERFLOW;
  517. goto clean0;
  518. }
  519. AltCatalogStringId = pSetupStringTableAddString(Queue->StringTable,
  520. PathBuffer,
  521. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  522. );
  523. if(AltCatalogStringId == -1) {
  524. Err = ERROR_NOT_ENOUGH_MEMORY;
  525. goto clean0;
  526. }
  527. } else {
  528. //
  529. // Caller has not supplied an alternate default catalog, so reset
  530. // any existing association.
  531. //
  532. AltCatalogStringId = -1;
  533. }
  534. //
  535. // If we've been passed an AltPlatformInfo structure, then we need to
  536. // process each existing catalog node in our file queue and retrieve the
  537. // appropriate platform-specific CatalogFile= entry.
  538. //
  539. if(AlternatePlatformInfo) {
  540. for(CatalogNode = Queue->CatalogList; CatalogNode; CatalogNode = CatalogNode->Next) {
  541. //
  542. // Get the INF name associated with this catalog node.
  543. //
  544. InfFullPath = pSetupStringTableStringFromId(Queue->StringTable,
  545. CatalogNode->InfFullPath
  546. );
  547. Err = pGetInfOriginalNameAndCatalogFile(NULL,
  548. InfFullPath,
  549. NULL,
  550. NULL,
  551. 0,
  552. PathBuffer,
  553. SIZECHARS(PathBuffer),
  554. AlternatePlatformInfo
  555. );
  556. if(Err != NO_ERROR) {
  557. goto clean0;
  558. }
  559. if(*PathBuffer) {
  560. //
  561. // We retrieved a CatalogFile= entry that's pertinent for
  562. // the specified platform from the INF.
  563. //
  564. CatalogNode->AltCatalogFileFromInfPending = pSetupStringTableAddString(
  565. Queue->StringTable,
  566. PathBuffer,
  567. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  568. );
  569. if(CatalogNode->AltCatalogFileFromInfPending == -1) {
  570. Err = ERROR_NOT_ENOUGH_MEMORY;
  571. goto clean0;
  572. }
  573. } else {
  574. //
  575. // The INF doesn't specify a CatalogFile= entry for this
  576. // platform.
  577. //
  578. CatalogNode->AltCatalogFileFromInfPending = -1;
  579. }
  580. }
  581. //
  582. // OK, if we get to this point, then we've added all the strings to
  583. // the string table we need to, and we're done opening INFs. We
  584. // should encounter no problems from this point forward, so it's
  585. // safe to commit our changes.
  586. //
  587. for(CatalogNode = Queue->CatalogList; CatalogNode; CatalogNode = CatalogNode->Next) {
  588. CatalogNode->AltCatalogFileFromInf = CatalogNode->AltCatalogFileFromInfPending;
  589. }
  590. }
  591. Queue->AltCatalogFile = AltCatalogStringId;
  592. //
  593. // Finally, update (or reset) the AltPlatformInfo structure in the queue
  594. // with the data the caller specified.
  595. //
  596. if(AlternatePlatformInfo) {
  597. CopyMemory(&(Queue->AltPlatformInfo),
  598. AlternatePlatformInfo,
  599. sizeof(SP_ALTPLATFORM_INFO_V2)
  600. );
  601. Queue->Flags |= FQF_USE_ALT_PLATFORM;
  602. } else {
  603. Queue->Flags &= ~FQF_USE_ALT_PLATFORM;
  604. }
  605. //
  606. // Clear the "catalog verifications done" flags in the queue, so that
  607. // we'll redo them the next time _SetupVerifyQueuedCatalogs is called.
  608. // Also, clear the FQF_DIGSIG_ERRORS_NOUI flag so that the next
  609. // verification error we encounter will relayed to the user (based on
  610. // policy).
  611. //
  612. Queue->Flags &= ~(FQF_DID_CATALOGS_OK | FQF_DID_CATALOGS_FAILED | FQF_DIGSIG_ERRORS_NOUI);
  613. clean0: ; // nothing to do.
  614. } except(EXCEPTION_EXECUTE_HANDLER) {
  615. Err = ERROR_INVALID_PARAMETER;
  616. }
  617. SetLastError(Err);
  618. return (Err == NO_ERROR);
  619. }
  620. BOOL
  621. pSetupSetQueueFlags(
  622. IN HSPFILEQ QueueHandle,
  623. IN DWORD flags
  624. )
  625. {
  626. PSP_FILE_QUEUE Queue;
  627. DWORD Err = NO_ERROR;
  628. try {
  629. Queue = (PSP_FILE_QUEUE)QueueHandle;
  630. Queue->Flags = flags;
  631. if (Queue->Flags & FQF_QUEUE_FORCE_BLOCK_POLICY) {
  632. Queue->DriverSigningPolicy = DRIVERSIGN_BLOCKING;
  633. }
  634. } except(EXCEPTION_EXECUTE_HANDLER) {
  635. Err = GetExceptionCode();
  636. }
  637. SetLastError(Err);
  638. return (Err == NO_ERROR);
  639. }
  640. DWORD
  641. pSetupGetQueueFlags(
  642. IN HSPFILEQ QueueHandle
  643. )
  644. {
  645. PSP_FILE_QUEUE Queue;
  646. try {
  647. Queue = (PSP_FILE_QUEUE)QueueHandle;
  648. return Queue->Flags;
  649. } except(EXCEPTION_EXECUTE_HANDLER) {
  650. }
  651. return 0;
  652. }
  653. WINSETUPAPI
  654. BOOL
  655. WINAPI
  656. SetupGetFileQueueCount(
  657. IN HSPFILEQ FileQueue,
  658. IN UINT SubQueueFileOp,
  659. OUT PUINT NumOperations
  660. )
  661. /*++
  662. Routine Description:
  663. This API obtains a count of a sub-queue in advance of submitting the queue
  664. Arguments:
  665. FileQueue - Queue to query
  666. SubQueueFileOp - operation
  667. FILEOP_COPY FILEOP_DELETE FILEOP_RENAME FILEOP_BACKUP
  668. NumOperations - ptr to hold the return value - number of files in that queue
  669. Return Value:
  670. If the function succeeds, the return value is TRUE.
  671. If the function fails, the return value is FALSE. To get extended error
  672. information, call GetLastError.
  673. --*/
  674. {
  675. PSP_FILE_QUEUE Queue;
  676. BOOL b;
  677. DWORD status = ERROR_INVALID_HANDLE;
  678. if (FileQueue == NULL || FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE) {
  679. SetLastError(ERROR_INVALID_HANDLE);
  680. return FALSE;
  681. }
  682. Queue = (PSP_FILE_QUEUE)FileQueue;
  683. b = TRUE;
  684. try {
  685. if(Queue->Signature != SP_FILE_QUEUE_SIG) {
  686. b = FALSE;
  687. }
  688. } except(EXCEPTION_EXECUTE_HANDLER) {
  689. b = FALSE;
  690. }
  691. if(!b) {
  692. SetLastError(ERROR_INVALID_HANDLE);
  693. return(FALSE);
  694. }
  695. try {
  696. //
  697. // Invalid/NULL NumOperations ptr will be caught by exception handling
  698. //
  699. switch (SubQueueFileOp) {
  700. case FILEOP_COPY:
  701. *NumOperations=Queue->CopyNodeCount;
  702. status = NO_ERROR;
  703. break;
  704. case FILEOP_RENAME:
  705. *NumOperations=Queue->RenameNodeCount;
  706. status = NO_ERROR;
  707. break;
  708. case FILEOP_DELETE:
  709. *NumOperations=Queue->DeleteNodeCount;
  710. status = NO_ERROR;
  711. break;
  712. case FILEOP_BACKUP:
  713. *NumOperations=Queue->BackupNodeCount;
  714. status = NO_ERROR;
  715. break;
  716. default:
  717. status = ERROR_INVALID_PARAMETER;
  718. }
  719. } except(EXCEPTION_EXECUTE_HANDLER) {
  720. status = ERROR_INVALID_DATA;
  721. }
  722. SetLastError(status);
  723. return (status==NO_ERROR);
  724. }
  725. WINSETUPAPI
  726. BOOL
  727. WINAPI
  728. SetupGetFileQueueFlags(
  729. IN HSPFILEQ FileQueue,
  730. OUT PDWORD Flags
  731. )
  732. /*++
  733. Routine Description:
  734. This API obtains public viewable flags for FileQueue
  735. Arguments:
  736. FileQueue - Queue to query
  737. Flags - ptr to hold the return value - flags, includes:
  738. SPQ_FLAG_BACKUP_AWARE
  739. SPQ_FLAG_ABORT_IF_UNSIGNED
  740. Return Value:
  741. If the function succeeds, the return value is TRUE.
  742. If the function fails, the return value is FALSE. To get extended error
  743. information, call GetLastError.
  744. --*/
  745. {
  746. PSP_FILE_QUEUE Queue;
  747. BOOL b;
  748. DWORD status = ERROR_INVALID_HANDLE;
  749. if (FileQueue == NULL || FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE) {
  750. SetLastError(ERROR_INVALID_HANDLE);
  751. return FALSE;
  752. }
  753. Queue = (PSP_FILE_QUEUE)FileQueue;
  754. b = TRUE;
  755. try {
  756. if(Queue->Signature != SP_FILE_QUEUE_SIG) {
  757. b = FALSE;
  758. }
  759. } except(EXCEPTION_EXECUTE_HANDLER) {
  760. b = FALSE;
  761. }
  762. if(!b) {
  763. SetLastError(ERROR_INVALID_HANDLE);
  764. return(FALSE);
  765. }
  766. try {
  767. //
  768. // Invalid/NULL Flags ptr will be caught by exception handling
  769. //
  770. *Flags = (((Queue->Flags & FQF_BACKUP_AWARE) ? SPQ_FLAG_BACKUP_AWARE : 0) |
  771. ((Queue->Flags & FQF_ABORT_IF_UNSIGNED) ? SPQ_FLAG_ABORT_IF_UNSIGNED : 0) |
  772. ((Queue->Flags & FQF_FILES_MODIFIED ) ? SPQ_FLAG_FILES_MODIFIED : 0));
  773. status = NO_ERROR;
  774. } except(EXCEPTION_EXECUTE_HANDLER) {
  775. status = ERROR_INVALID_DATA;
  776. }
  777. SetLastError(status);
  778. return (status==NO_ERROR);
  779. }
  780. VOID
  781. ResetQueueState(
  782. IN PSP_FILE_QUEUE Queue
  783. )
  784. /*++
  785. Routine Description:
  786. This routine resets an aborted filequeue so that it can be committed yet
  787. again. This is used when a client (e.g., newdev) requests that queue
  788. committal be aborted when unsigned files are encountered (i.e., so they can
  789. set a system restore point), then they want to re-commit the file queue
  790. once the restore point has been established.
  791. Arguments:
  792. Queue - supplies a pointer to the file queue to be reset.
  793. Return Value:
  794. none.
  795. --*/
  796. {
  797. PSP_DELAYMOVE_NODE DelayMoveNode, NextDelayMoveNode;
  798. PSP_UNWIND_NODE UnwindNode, NextUnwindNode;
  799. PSP_FILE_QUEUE_NODE QueueNode;
  800. PSOURCE_MEDIA_INFO Media;
  801. SP_TARGET_ENT TargetInfo;
  802. //
  803. // There should be no need to unwind the queue here, as that should've
  804. // already happened when we failed during _SetupCommitFileQueue.
  805. //
  806. //
  807. // Free the DelayMove list
  808. //
  809. for(DelayMoveNode = Queue->DelayMoveQueue; DelayMoveNode; DelayMoveNode = NextDelayMoveNode) {
  810. NextDelayMoveNode = DelayMoveNode->NextNode;
  811. MyFree(DelayMoveNode);
  812. }
  813. Queue->DelayMoveQueue = Queue->DelayMoveQueueTail = NULL;
  814. //
  815. // Free the unwind queue nodes
  816. //
  817. for(UnwindNode = Queue->UnwindQueue; UnwindNode; UnwindNode = NextUnwindNode) {
  818. NextUnwindNode = UnwindNode->NextNode;
  819. MyFree(UnwindNode);
  820. }
  821. Queue->UnwindQueue = NULL;
  822. //
  823. // Clear the "catalog verifications done" flags in the queue, so that we'll
  824. // redo them the next time _SetupVerifyQueuedCatalogs is called.
  825. //
  826. Queue->Flags &= ~(FQF_DID_CATALOGS_OK | FQF_DID_CATALOGS_FAILED);
  827. //
  828. // Clear the flag that indicates we've already committed the file queue.
  829. //
  830. Queue->Flags &= ~FQF_QUEUE_ALREADY_COMMITTED;
  831. //
  832. // Clear the flag that indicates we didn't successfully back-up all files.
  833. // Since we already unwound out of that queue committal, this flag is no
  834. // longer relevant (although we'll quite likely hit this problem again when
  835. // the client re-commits the file queue).
  836. //
  837. Queue->Flags &= ~FQF_BACKUP_INCOMPLETE;
  838. //
  839. // Clear certain internal flags on all the file queue nodes.
  840. //
  841. #define QUEUE_NODE_BITS_TO_RESET ( INUSE_IN_USE \
  842. | INUSE_INF_WANTS_REBOOT \
  843. | IQF_PROCESSED \
  844. | IQF_MATCH \
  845. | IQF_LAST_MATCH )
  846. //
  847. // Note: neither the IQF_ALLOW_UNSIGNED nor IQF_TARGET_PROTECTED flags
  848. // should be set for any queue nodes, because we should only do this if we
  849. // previously committed the queue with the SPQ_FLAG_ABORT_IF_UNSIGNED flag
  850. // was set. In this scenario, we never check to see if a file is protected,
  851. // nor do we request that an exception be granted).
  852. //
  853. for(QueueNode = Queue->BackupQueue; QueueNode; QueueNode = QueueNode->Next) {
  854. QueueNode->InternalFlags &= ~QUEUE_NODE_BITS_TO_RESET;
  855. MYASSERT(!(QueueNode->InternalFlags & (IQF_ALLOW_UNSIGNED | IQF_TARGET_PROTECTED)));
  856. }
  857. for(QueueNode = Queue->DeleteQueue; QueueNode; QueueNode = QueueNode->Next) {
  858. QueueNode->InternalFlags &= ~QUEUE_NODE_BITS_TO_RESET;
  859. MYASSERT(!(QueueNode->InternalFlags & (IQF_ALLOW_UNSIGNED | IQF_TARGET_PROTECTED)));
  860. }
  861. for(QueueNode = Queue->RenameQueue; QueueNode; QueueNode = QueueNode->Next) {
  862. QueueNode->InternalFlags &= ~QUEUE_NODE_BITS_TO_RESET;
  863. MYASSERT(!(QueueNode->InternalFlags & (IQF_ALLOW_UNSIGNED | IQF_TARGET_PROTECTED)));
  864. }
  865. for(Media = Queue->SourceMediaList; Media; Media = Media->Next) {
  866. for(QueueNode = Media->CopyQueue; QueueNode; QueueNode = QueueNode->Next) {
  867. QueueNode->InternalFlags &= ~QUEUE_NODE_BITS_TO_RESET;
  868. MYASSERT(!(QueueNode->InternalFlags & (IQF_ALLOW_UNSIGNED | IQF_TARGET_PROTECTED)));
  869. }
  870. }
  871. //
  872. // Iterate through all the entries in the TargetLookupTable string table,
  873. // and clear some flags in their associated SP_TARGET_ENT data.
  874. //
  875. pSetupStringTableEnum(Queue->TargetLookupTable,
  876. &TargetInfo,
  877. sizeof(TargetInfo),
  878. pSetupResetTarget,
  879. (LPARAM)0
  880. );
  881. }
  882. WINSETUPAPI
  883. BOOL
  884. WINAPI
  885. SetupSetFileQueueFlags(
  886. IN HSPFILEQ FileQueue,
  887. IN DWORD FlagMask,
  888. IN DWORD Flags
  889. )
  890. /*++
  891. Routine Description:
  892. This API modifies public settable flags for FileQueue
  893. Arguments:
  894. FileQueue - Queue in which flags are to be set.
  895. FlagMask - Flags to modify, must not be zero
  896. Flags - New value of flags, must be a subset of FlagMask
  897. FlagMask and Flags include:
  898. SPQ_FLAG_BACKUP_AWARE
  899. SPQ_FLAG_ABORT_IF_UNSIGNED
  900. Return Value:
  901. If the function succeeds, the return value is TRUE.
  902. If the function fails, the return value is FALSE. To get extended error
  903. information, call GetLastError.
  904. --*/
  905. {
  906. PSP_FILE_QUEUE Queue;
  907. BOOL b;
  908. DWORD status = ERROR_INVALID_HANDLE;
  909. DWORD RemapFlags = 0;
  910. DWORD RemapFlagMask = 0;
  911. if (FileQueue == NULL || FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE) {
  912. SetLastError(ERROR_INVALID_HANDLE);
  913. return FALSE;
  914. }
  915. Queue = (PSP_FILE_QUEUE)FileQueue;
  916. b = TRUE;
  917. try {
  918. if(Queue->Signature != SP_FILE_QUEUE_SIG) {
  919. b = FALSE;
  920. }
  921. } except(EXCEPTION_EXECUTE_HANDLER) {
  922. b = FALSE;
  923. }
  924. if(!b) {
  925. SetLastError(ERROR_INVALID_HANDLE);
  926. return(FALSE);
  927. }
  928. try {
  929. //
  930. // validate FlagMask and Flags
  931. //
  932. if (!FlagMask
  933. || (FlagMask & ~SPQ_FLAG_VALID)
  934. || (Flags & ~FlagMask)) {
  935. status = ERROR_INVALID_PARAMETER;
  936. leave;
  937. }
  938. //
  939. // remap SPQ_FLAG_BACKUP_AWARE to FQF_BACKUP_AWARE
  940. //
  941. if (FlagMask & SPQ_FLAG_BACKUP_AWARE) {
  942. RemapFlagMask |= FQF_BACKUP_AWARE;
  943. if (Flags & SPQ_FLAG_BACKUP_AWARE) {
  944. RemapFlags |= FQF_BACKUP_AWARE;
  945. }
  946. }
  947. //
  948. // remap SPQ_FLAG_ABORT_IF_UNSIGNED to FQF_ABORT_IF_UNSIGNED
  949. //
  950. if (FlagMask & SPQ_FLAG_ABORT_IF_UNSIGNED) {
  951. RemapFlagMask |= FQF_ABORT_IF_UNSIGNED;
  952. if (Flags & SPQ_FLAG_ABORT_IF_UNSIGNED) {
  953. RemapFlags |= FQF_ABORT_IF_UNSIGNED;
  954. } else {
  955. //
  956. // If we're clearing this flag, then we also need to go reset
  957. // the queue state so that it can be committed again, just like
  958. // it was the very first time (except that no driver signing UI
  959. // will happen in the subsequent queue committal).
  960. //
  961. if(Queue->Flags & FQF_ABORT_IF_UNSIGNED) {
  962. ResetQueueState(Queue);
  963. }
  964. }
  965. }
  966. //
  967. // remap SPQ_FLAG_FILES_MODIFIED to FQF_FILES_MODIFIED
  968. // allows explicit setting/resetting of this state
  969. // which is informational only
  970. //
  971. if (FlagMask & SPQ_FLAG_FILES_MODIFIED) {
  972. RemapFlagMask |= FQF_FILES_MODIFIED;
  973. if (Flags & SPQ_FLAG_FILES_MODIFIED) {
  974. RemapFlags |= FQF_FILES_MODIFIED;
  975. }
  976. }
  977. //
  978. // now modify real flags
  979. //
  980. Queue->Flags = (Queue->Flags & ~RemapFlagMask) | RemapFlags;
  981. status = NO_ERROR;
  982. } except(EXCEPTION_EXECUTE_HANDLER) {
  983. status = ERROR_INVALID_DATA;
  984. }
  985. SetLastError(status);
  986. return (status==NO_ERROR);
  987. }