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.

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