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.

2278 lines
54 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. dll.c
  5. Abstract:
  6. Initialization/de-initialization of setupapi.dll
  7. Author:
  8. Lonny McMichael (lonnym) 10-May-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #ifdef ANSI_SETUPAPI
  14. #include <locale.h>
  15. #endif
  16. HANDLE MyDllModuleHandle;
  17. OSVERSIONINFOEX OSVersionInfo;
  18. //
  19. // TLS Data
  20. //
  21. DWORD TlsIndex = (DWORD)(-1); // no data
  22. PSETUP_TLS pLastTlsAlloc = NULL; // for cleanup
  23. //
  24. // Static strings we retreive once. Listed in order they are retrieved
  25. //
  26. PCTSTR OsLoaderRelativePath = NULL; // (can be NULL)
  27. PCTSTR OsSystemPartitionRoot = NULL; // eg: \\?\GLOBALROOT\Device\HarddiskVolume1
  28. PCTSTR ProcessFileName = NULL; // Filename of app calling setupapi
  29. PCTSTR WindowsDirectory = NULL; // %windir%, GetSystemWindowsDirectory()
  30. PCTSTR InfDirectory = NULL; // %windir%\INF
  31. PCTSTR System16Directory = NULL; // %windir%\SYSTEM
  32. PCTSTR LastGoodDirectory = NULL; // %windir%\LastGood
  33. PCTSTR SystemDirectory = NULL; // <sys>, %windir%\SYSTEM or %windir%\System32
  34. PCTSTR WindowsBackupDirectory = NULL; // <sys>\ReinstallBackups
  35. PCTSTR ConfigDirectory = NULL; // <sys>\CONFIG
  36. PCTSTR DriversDirectory = NULL; // <sys>\DRIVERS
  37. PCTSTR SystemSourcePath = NULL; // location system installed from
  38. PCTSTR ServicePackSourcePath = NULL; // location service pack installed from (can be NULL)
  39. PCTSTR DriverCacheSourcePath = NULL; // location of driver cache (can be NULL)
  40. BOOL GuiSetupInProgress = FALSE; // set if we determine we're in GUI setup
  41. PCTSTR InfSearchPaths = NULL; // Multi-sz list of fully-qualified directories where INFs are to be searched for.
  42. #ifndef _WIN64
  43. BOOL IsWow64 = FALSE; // set if we're running under WOW64
  44. #endif
  45. CRITICAL_SECTION InitMutex; // for one-time initializations
  46. CRITICAL_SECTION ImageHlpMutex; // for dealing with IMAGEHLP library
  47. CRITICAL_SECTION DelayedComponentMutex; // for any delayed initialization of certain components
  48. CRITICAL_SECTION PlatformPathOverrideCritSect;
  49. CRITICAL_SECTION LogUseCountCs;
  50. CRITICAL_SECTION MruCritSect;
  51. CRITICAL_SECTION NetConnectionListCritSect;
  52. BOOL InInitialization = FALSE;
  53. DWORD DoneInitialization = 0; // bitmask of items we've initialized
  54. DWORD DoneCleanup = 0; // bitmask of items we've cleaned up
  55. DWORD DoneComponentInitialize = 0; // bitmask of components we've done delayed initialization
  56. DWORD FailedComponentInitialize = 0; // bitmask of components we've failed initialization
  57. HANDLE GlobalNoDriverPromptsEventFlag = NULL; // event that acts as a flag during setup
  58. BOOL DoneCriticalSections = FALSE;
  59. #ifdef UNICODE
  60. DWORD Seed;
  61. #endif
  62. #define DONEINIT_TLS (0x0000001)
  63. #define DONEINIT_UTILS (0x0000002)
  64. #define DONEINIT_MEM (0x0000004)
  65. #define DONEINIT_CTRL (0x0000008)
  66. #define DONEINIT_FUSION (0x0000010)
  67. #define DONEINIT_STUBS (0x0000020)
  68. #define DONEINIT_COMMON (0x0000040)
  69. #define DONEINIT_DIAMOND (0x0000080)
  70. #define DONEINIT_LOGGING (0x0000100)
  71. #define DONEINIT_CFGMGR32 (0x0000200)
  72. #define DONEINIT_COMPLETE (0x8000000)
  73. //
  74. // various control flags
  75. //
  76. DWORD GlobalSetupFlags = 0;
  77. DWORD GlobalSetupFlagsOverride = PSPGF_MINIMAL_EMBEDDED | PSPGF_NO_SCE_EMBEDDED; // flags that cannot be modified
  78. //
  79. // Declare a (non-CONST) array of strings that specifies what lines to look for
  80. // in an INF's [ControlFlags] section when determining whether a particular device
  81. // ID should be excluded. These lines are of the form "ExcludeFromSelect[.<suffix>]",
  82. // where <suffix> is determined and filled in during process attach as an optimization.
  83. //
  84. // The max string length (including NULL) is 32, and there can be a maximum of 3
  85. // such strings. E.g.: ExcludeFromSelect, ExcludeFromSelect.NT, ExcludeFromSelect.NTAlpha
  86. //
  87. // WARNING!! Be very careful when mucking with the order/number of these entries. Check
  88. // the assumptions made in devdrv.c!pSetupShouldDevBeExcluded.
  89. //
  90. TCHAR pszExcludeFromSelectList[3][32] = { INFSTR_KEY_EXCLUDEFROMSELECT,
  91. INFSTR_KEY_EXCLUDEFROMSELECT,
  92. INFSTR_KEY_EXCLUDEFROMSELECT
  93. };
  94. DWORD ExcludeFromSelectListUb; // contains the number of strings in the above list (2 or 3).
  95. #ifndef _WIN64
  96. BOOL
  97. GetIsWow64 (
  98. VOID
  99. );
  100. #endif
  101. BOOL
  102. CommonProcessAttach(
  103. IN BOOL Attach
  104. );
  105. PCTSTR
  106. GetDriverCacheSourcePath(
  107. VOID
  108. );
  109. PCTSTR
  110. pSetupGetOsLoaderPath(
  111. VOID
  112. );
  113. PCTSTR
  114. pSetupGetSystemPartitionRoot(
  115. VOID
  116. );
  117. PCTSTR
  118. pSetupGetProcessPath(
  119. VOID
  120. );
  121. BOOL
  122. pGetGuiSetupInProgress(
  123. VOID
  124. );
  125. BOOL
  126. CfgmgrEntry(
  127. PVOID hModule,
  128. ULONG Reason,
  129. PCONTEXT pContext
  130. );
  131. BOOL
  132. ThreadTlsInitialize(
  133. IN BOOL Init
  134. );
  135. VOID
  136. ThreadTlsCleanup(
  137. );
  138. BOOL
  139. IsNoDriverPrompts(
  140. VOID
  141. );
  142. DWORD
  143. GetEmbeddedFlags(
  144. VOID
  145. );
  146. DWORD
  147. GetSeed(
  148. VOID
  149. );
  150. BOOL
  151. ProcessAttach(
  152. IN HANDLE DllHandle,
  153. IN DWORD Reason,
  154. IN LPVOID Reserved
  155. )
  156. /*++
  157. Routine Description:
  158. Handles DLL_PROCESS_ATTACH in a way that can be unwound
  159. Arguments:
  160. Reserved = 'Reserved' value passed into DllMain
  161. Return Value:
  162. TRUE if processed initialized
  163. FALSE if partially/not initialized
  164. --*/
  165. {
  166. BOOL b = FALSE;
  167. if(DoneCleanup) {
  168. //
  169. // if we get here, this means someone lied to us
  170. //
  171. MYASSERT(!DoneCleanup);
  172. DoneInitialization &= ~DoneCleanup;
  173. DoneCleanup = 0;
  174. }
  175. //
  176. // nothing should already be initialized
  177. //
  178. MYASSERT(!DoneInitialization);
  179. try {
  180. MyDllModuleHandle = DllHandle;
  181. //
  182. // initialize TLS before anything else - hence why we use LocalAlloc
  183. //
  184. TlsIndex = TlsAlloc();
  185. if (TlsIndex!=(DWORD)(-1)) {
  186. DoneInitialization |= DONEINIT_TLS;
  187. } else {
  188. leave;
  189. }
  190. #ifndef UNICODE
  191. //
  192. // Initialize the C runtime locale (ANSI version of setupapi.dll only)
  193. //
  194. setlocale(LC_ALL,"");
  195. #endif
  196. //
  197. // always do pSetupInitializeUtils and MemoryInitializeEx first
  198. // (pSetupInitializeUtils sets up memory functions)
  199. //
  200. if(pSetupInitializeUtils()) {
  201. DoneInitialization |= DONEINIT_UTILS;
  202. } else {
  203. leave;
  204. }
  205. if(MemoryInitializeEx(TRUE)) {
  206. DoneInitialization |= DONEINIT_MEM;
  207. } else {
  208. leave;
  209. }
  210. #ifdef FUSIONAWARE
  211. if(spFusionInitialize()) {
  212. DoneInitialization |= DONEINIT_FUSION;
  213. }
  214. #else
  215. InitCommonControls();
  216. DoneInitialization |= DONEINIT_CTRL;
  217. #endif
  218. //
  219. // Dynamically load proc addresses of NT-specific APIs
  220. // must be before CommonProcessAttach etc
  221. // however memory must be initialized
  222. //
  223. InitializeStubFnPtrs();
  224. DoneInitialization |= DONEINIT_STUBS;
  225. //
  226. // most of the remaining initialization
  227. //
  228. if(CommonProcessAttach(TRUE)) {
  229. DoneInitialization |= DONEINIT_COMMON;
  230. } else {
  231. leave;
  232. }
  233. if(DiamondProcessAttach(TRUE)) {
  234. DoneInitialization |= DONEINIT_DIAMOND;
  235. } else {
  236. leave;
  237. }
  238. if(InitializeContextLogging(TRUE)) {
  239. DoneInitialization |= DONEINIT_LOGGING;
  240. } else {
  241. leave;
  242. }
  243. #ifdef UNICODE
  244. //
  245. // Since we've incorporated cfgmgr32 into setupapi, we need
  246. // to make sure it gets initialized just like it did when it was
  247. // its own DLL. - must do AFTER everything else
  248. //
  249. if(CfgmgrEntry(DllHandle, Reason, Reserved)) {
  250. DoneInitialization |= DONEINIT_CFGMGR32;
  251. }
  252. #endif
  253. DoneInitialization |= DONEINIT_COMPLETE;
  254. b = TRUE;
  255. } except(EXCEPTION_EXECUTE_HANDLER) {
  256. }
  257. return b;
  258. }
  259. void
  260. DestroySetupTlsData(
  261. )
  262. /*++
  263. Routine Description:
  264. Destroy all TLS data from every thread
  265. calling any cleanup routines as required
  266. Arguments:
  267. NONE
  268. Return Value:
  269. NONE
  270. --*/
  271. {
  272. PSETUP_TLS pTLS;
  273. if(pLastTlsAlloc) {
  274. pLastTlsAlloc->Prev->Next = NULL;
  275. while(pLastTlsAlloc) {
  276. pTLS = pLastTlsAlloc;
  277. pLastTlsAlloc = pTLS->Next;
  278. TlsSetValue(TlsIndex,pTLS); // switch specific data into this thread
  279. ThreadTlsCleanup();
  280. LocalFree(pTLS);
  281. }
  282. }
  283. TlsSetValue(TlsIndex,NULL); // don't leave invalid pointer hanging around
  284. }
  285. void
  286. ProcessDetach(
  287. IN HANDLE DllHandle,
  288. IN DWORD Reason,
  289. IN LPVOID Reserved
  290. )
  291. /*++
  292. Routine Description:
  293. Handles DLL_PROCESS_DETACH
  294. Arguments:
  295. Reserved = 'Reserved' value passed into DllMain
  296. Which is actually TRUE for Process Exit, FALSE otherwise
  297. Return Value:
  298. None
  299. --*/
  300. {
  301. DWORD ToCleanup = DoneInitialization & ~ DoneCleanup;
  302. if(!ToCleanup) {
  303. //
  304. // nothing to cleanup
  305. //
  306. return;
  307. }
  308. try {
  309. if (ToCleanup & DONEINIT_COMPLETE) {
  310. DoneCleanup |= DONEINIT_COMPLETE;
  311. }
  312. if(DoneInitialization & DONEINIT_TLS) {
  313. //
  314. // cleanup all remaining Tls data
  315. //
  316. if(!Reserved) {
  317. //
  318. // only do this for FreeLibrary/ failed LoadLibrary
  319. //
  320. DestroySetupTlsData();
  321. }
  322. }
  323. if(ToCleanup & DONEINIT_TLS) {
  324. //
  325. // destroy our allocated TLS index
  326. // do this now so that we don't try allocating
  327. // TLS storage during this cleanup
  328. //
  329. TlsFree(TlsIndex);
  330. TlsIndex = (DWORD)(-1);
  331. DoneCleanup |= DONEINIT_TLS;
  332. }
  333. //
  334. // do things generally in reverse order of ProcessAttach
  335. //
  336. #ifdef UNICODE
  337. // Since we've incorporated cfgmgr32 into setupapi, we need
  338. // to make sure it gets uninitialized just like it did when it was
  339. // its own DLL. - must do BEFORE anything else
  340. //
  341. if(ToCleanup & DONEINIT_CFGMGR32) {
  342. CfgmgrEntry(DllHandle, Reason, Reserved);
  343. DoneCleanup |= DONEINIT_CFGMGR32;
  344. }
  345. #endif
  346. if(ToCleanup & DONEINIT_DIAMOND) {
  347. DiamondProcessAttach(FALSE);
  348. DoneCleanup |= DONEINIT_DIAMOND;
  349. }
  350. #if 0 // see ComponentCleanup at end of file
  351. ComponentCleanup(DoneComponentInitialize);
  352. #endif
  353. #ifdef FUSIONAWARE
  354. if(ToCleanup & DONEINIT_FUSION) {
  355. //
  356. // Fusion cleanup
  357. // only do full if this is FreeLibrary (or failed attach)
  358. //
  359. spFusionUninitialize((Reserved == NULL) ? TRUE : FALSE);
  360. DoneCleanup |= DONEINIT_FUSION;
  361. }
  362. #endif
  363. if(ToCleanup & DONEINIT_COMMON) {
  364. //
  365. // Most of remaining cleanup
  366. //
  367. CommonProcessAttach(FALSE);
  368. DoneCleanup |= DONEINIT_COMMON;
  369. }
  370. if(ToCleanup & DONEINIT_STUBS) {
  371. //
  372. // Clean up stub functions
  373. //
  374. CleanUpStubFns();
  375. DoneCleanup |= DONEINIT_STUBS;
  376. }
  377. if(ToCleanup & DONEINIT_LOGGING) {
  378. //
  379. // Clean up context logging
  380. //
  381. InitializeContextLogging(FALSE);
  382. DoneCleanup |= DONEINIT_LOGGING;
  383. }
  384. //
  385. // *THESE MUST ALWAYS BE* very last things, in this order
  386. //
  387. if(ToCleanup & DONEINIT_MEM) {
  388. //
  389. // Clean up context logging
  390. //
  391. MemoryInitializeEx(FALSE);
  392. DoneCleanup |= DONEINIT_MEM;
  393. }
  394. if(ToCleanup & DONEINIT_UTILS) {
  395. //
  396. // Clean up context logging
  397. //
  398. pSetupUninitializeUtils();
  399. DoneCleanup |= DONEINIT_UTILS;
  400. }
  401. } except(EXCEPTION_EXECUTE_HANDLER) {
  402. }
  403. }
  404. //
  405. // Called by CRT when _DllMainCRTStartup is the DLL entry point
  406. //
  407. BOOL
  408. WINAPI
  409. DllMain(
  410. IN HANDLE DllHandle,
  411. IN DWORD Reason,
  412. IN LPVOID Reserved
  413. )
  414. {
  415. BOOL b;
  416. InInitialization = TRUE;
  417. b = TRUE;
  418. switch(Reason) {
  419. case DLL_PROCESS_ATTACH:
  420. b = ProcessAttach(DllHandle,Reason,Reserved);
  421. if(!b) {
  422. ProcessDetach(DllHandle,DLL_THREAD_DETACH,NULL);
  423. }
  424. break;
  425. case DLL_THREAD_ATTACH:
  426. //
  427. // don't do anything here
  428. // any TLS must be done on demand
  429. // via SetupGetTlsData
  430. //
  431. break;
  432. case DLL_PROCESS_DETACH:
  433. //
  434. // any TLS cleanup must be done in ThreadTlsCleanup
  435. //
  436. ProcessDetach(DllHandle,Reason,Reserved);
  437. break;
  438. case DLL_THREAD_DETACH:
  439. ThreadTlsInitialize(FALSE);
  440. break;
  441. }
  442. InInitialization = FALSE;
  443. return(b);
  444. }
  445. PSETUP_TLS
  446. SetupGetTlsData(
  447. )
  448. /*++
  449. Routine Description:
  450. Called to obtain a pointer to TLS data
  451. Arguments:
  452. NONE
  453. Return Value:
  454. Pointer to TLS data, or NULL
  455. --*/
  456. {
  457. PSETUP_TLS pTLS;
  458. if (TlsIndex==(DWORD)(-1)) {
  459. return NULL;
  460. }
  461. pTLS = (PSETUP_TLS)TlsGetValue(TlsIndex);
  462. if (!pTLS) {
  463. ThreadTlsInitialize(TRUE);
  464. pTLS = (PSETUP_TLS)TlsGetValue(TlsIndex);
  465. }
  466. return pTLS;
  467. }
  468. VOID
  469. ThreadTlsCleanup(
  470. )
  471. /*++
  472. Routine Description:
  473. Called to uninitialize some pTLS data
  474. might be a different thread to initialize
  475. but SetupAPI TLS data will have been switched in
  476. Arguments:
  477. pTLS - data to cleanup
  478. Return Value:
  479. NONE.
  480. --*/
  481. {
  482. DiamondTlsInit(FALSE);
  483. ContextLoggingTlsInit(FALSE);
  484. }
  485. BOOL
  486. ThreadTlsUnlink(
  487. IN PSETUP_TLS pTLS
  488. )
  489. {
  490. BOOL b;
  491. try {
  492. EnterCriticalSection(&InitMutex);
  493. if(pTLS->Next == pTLS->Prev) {
  494. pLastTlsAlloc = NULL;
  495. } else {
  496. pTLS->Prev->Next = pTLS->Next;
  497. pTLS->Next->Prev = pTLS->Prev;
  498. pLastTlsAlloc = pTLS->Prev; // anything but pTLS
  499. }
  500. LeaveCriticalSection(&InitMutex);
  501. b = TRUE;
  502. } except(EXCEPTION_EXECUTE_HANDLER) {
  503. b = FALSE;
  504. }
  505. return b;
  506. }
  507. PSETUP_TLS
  508. ThreadTlsCreate(
  509. )
  510. /*++
  511. Routine Description:
  512. Called to create pTLS data for this thread
  513. Arguments:
  514. NONE
  515. Return Value:
  516. per-thread data, or NULL on failure
  517. --*/
  518. {
  519. BOOL b;
  520. PSETUP_TLS pTLS;
  521. if (TlsIndex==(DWORD)(-1)) {
  522. return NULL;
  523. }
  524. pTLS = (PSETUP_TLS)LocalAlloc(LMEM_ZEROINIT,sizeof(SETUP_TLS));
  525. if(!pTLS) {
  526. return NULL;
  527. }
  528. b = TlsSetValue(TlsIndex,pTLS);
  529. if(!b) {
  530. LocalFree(pTLS);
  531. return NULL;
  532. }
  533. try {
  534. EnterCriticalSection(&InitMutex);
  535. if(pLastTlsAlloc) {
  536. pTLS->Prev = pLastTlsAlloc;
  537. pTLS->Next = pTLS->Prev->Next;
  538. pTLS->Prev->Next = pTLS;
  539. pTLS->Next->Prev = pTLS;
  540. } else {
  541. pTLS->Next = pTLS;
  542. pTLS->Prev = pTLS;
  543. }
  544. pLastTlsAlloc = pTLS;
  545. LeaveCriticalSection(&InitMutex);
  546. b = TRUE;
  547. } except(EXCEPTION_EXECUTE_HANDLER) {
  548. b = FALSE;
  549. }
  550. if(!b) {
  551. LocalFree(pTLS);
  552. TlsSetValue(TlsIndex,NULL);
  553. return NULL;
  554. }
  555. //
  556. // TLS data initialized, now specific Init routines
  557. //
  558. b = DiamondTlsInit(TRUE);
  559. if(b) {
  560. b = ContextLoggingTlsInit(TRUE);
  561. if(b) {
  562. //
  563. // all done ok
  564. //
  565. return pTLS;
  566. }
  567. //
  568. // cleanup DiamondTlsInit
  569. //
  570. DiamondTlsInit(FALSE);
  571. }
  572. //
  573. // cleanup memory
  574. //
  575. TlsSetValue(TlsIndex,NULL);
  576. if(ThreadTlsUnlink(pTLS)) {
  577. LocalFree(pTLS);
  578. }
  579. return NULL;
  580. }
  581. BOOL
  582. ThreadTlsInitialize(
  583. IN BOOL Init
  584. )
  585. /*++
  586. Routine Description:
  587. Called with TRUE to initialize TLS, if FALSE, to uninitialize
  588. Arguments:
  589. Init - indicates if we are to initialize vs uninitialize
  590. Return Value:
  591. NONE.
  592. --*/
  593. {
  594. BOOL b = FALSE;
  595. PSETUP_TLS pTLS = NULL;
  596. if (TlsIndex!=(DWORD)(-1)) {
  597. if (Init) {
  598. pTLS = ThreadTlsCreate();
  599. b = pTLS ? TRUE : FALSE;
  600. } else {
  601. pTLS = (PSETUP_TLS)TlsGetValue(TlsIndex);
  602. if(pTLS) {
  603. ThreadTlsCleanup();
  604. TlsSetValue(TlsIndex,NULL);
  605. if(ThreadTlsUnlink(pTLS)) {
  606. LocalFree(pTLS);
  607. }
  608. }
  609. b = TRUE;
  610. }
  611. }
  612. return b;
  613. }
  614. BOOL
  615. IsInteractiveWindowStation(
  616. )
  617. /*++
  618. Routine Description:
  619. Determine if we are running on an interactive station vs non-interactive station (i.e., service)
  620. Arguments:
  621. none
  622. Return Value:
  623. True if interactive
  624. --*/
  625. {
  626. HWINSTA winsta;
  627. USEROBJECTFLAGS flags;
  628. BOOL interactive = TRUE; // true unless we determine otherwise
  629. DWORD lenNeeded;
  630. winsta = GetProcessWindowStation();
  631. if(!winsta) {
  632. return interactive;
  633. }
  634. if(GetUserObjectInformation(winsta,UOI_FLAGS,&flags,sizeof(flags),&lenNeeded)) {
  635. interactive = (flags.dwFlags & WSF_VISIBLE) ? TRUE : FALSE;
  636. }
  637. //
  638. // don't call CLoseWindowStation
  639. //
  640. return interactive;
  641. }
  642. BOOL
  643. CommonProcessAttach(
  644. IN BOOL Attach
  645. )
  646. {
  647. BOOL b;
  648. TCHAR Buffer[MAX_PATH+32];
  649. PTCHAR p;
  650. UINT u;
  651. b = !Attach;
  652. if(Attach) {
  653. //
  654. // remaining critical sections
  655. //
  656. try {
  657. InitializeCriticalSection(&InitMutex);
  658. InitializeCriticalSection(&ImageHlpMutex);
  659. InitializeCriticalSection(&DelayedComponentMutex);
  660. InitializeCriticalSection(&PlatformPathOverrideCritSect);
  661. InitializeCriticalSection(&LogUseCountCs);
  662. InitializeCriticalSection(&MruCritSect);
  663. InitializeCriticalSection(&NetConnectionListCritSect);
  664. DoneCriticalSections = TRUE;
  665. } except (EXCEPTION_EXECUTE_HANDLER) {
  666. //
  667. // DoneCriticalSections remains FALSE
  668. //
  669. }
  670. if(!DoneCriticalSections) {
  671. return FALSE;
  672. }
  673. try {
  674. #ifndef _WIN64
  675. IsWow64 = GetIsWow64();
  676. #endif
  677. //
  678. // flag indicating we're running in context of GUI setup
  679. //
  680. GuiSetupInProgress = pGetGuiSetupInProgress();
  681. //
  682. // determine if we're interactive or not
  683. //
  684. if(!IsInteractiveWindowStation()) {
  685. GlobalSetupFlagsOverride |= PSPGF_NONINTERACTIVE; // don't allow this to be changed
  686. GlobalSetupFlags |= PSPGF_NONINTERACTIVE; // actual value
  687. }
  688. if(IsNoDriverPrompts()) {
  689. GlobalSetupFlagsOverride |= PSPGF_UNATTENDED_SETUP; // don't allow this to be changed
  690. GlobalSetupFlags |= PSPGF_UNATTENDED_SETUP; // actual value
  691. }
  692. GlobalSetupFlags |= GetEmbeddedFlags();
  693. #ifdef UNICODE
  694. Seed = GetSeed();
  695. #endif
  696. pSetupInitNetConnectionList(TRUE);
  697. pSetupInitPlatformPathOverrideSupport(TRUE);
  698. OsLoaderRelativePath = pSetupGetOsLoaderPath(); // ok to fail
  699. OsSystemPartitionRoot = pSetupGetSystemPartitionRoot(); // ok to fail
  700. //
  701. // Fill in system and windows directories.
  702. //
  703. if ((ProcessFileName = pSetupGetProcessPath()) == NULL) {
  704. goto cleanAll;
  705. }
  706. //
  707. // determine %windir%
  708. //
  709. if(((u = GetSystemWindowsDirectory(Buffer,MAX_PATH)) == 0) || u>MAX_PATH) {
  710. goto cleanAll;
  711. }
  712. p = Buffer + u; // offset past directory to do all the sub-directories
  713. //
  714. // %windir% ==> WindowsDirectory
  715. //
  716. if((WindowsDirectory = DuplicateString(Buffer)) == NULL) {
  717. goto cleanAll;
  718. }
  719. //
  720. // %windir%\INF ==> InfDirectory
  721. //
  722. *p = 0;
  723. if(!pSetupConcatenatePaths(Buffer,TEXT("INF"),MAX_PATH,NULL)
  724. || ((InfDirectory = DuplicateString(Buffer)) == NULL)) {
  725. goto cleanAll;
  726. }
  727. //
  728. // %windir%\SYSTEM ==> System16Directory
  729. //
  730. *p = 0;
  731. if(!pSetupConcatenatePaths(Buffer,TEXT("SYSTEM"),MAX_PATH,NULL)
  732. || ((System16Directory = DuplicateString(Buffer))==NULL)) {
  733. goto cleanAll;
  734. }
  735. //
  736. // %windir%\LastGood ==> LastGoodDirectory
  737. //
  738. *p = 0;
  739. if(!pSetupConcatenatePaths(Buffer,SP_LASTGOOD_NAME,MAX_PATH,NULL)
  740. || ((LastGoodDirectory = DuplicateString(Buffer))==NULL)) {
  741. goto cleanAll;
  742. }
  743. //
  744. // determine system directory
  745. //
  746. if(((u = GetSystemDirectory(Buffer,MAX_PATH)) == 0) || u>MAX_PATH) {
  747. goto cleanAll;
  748. }
  749. p = Buffer + u; // offset past directory to do all the sub-directories
  750. //
  751. // <sys> ==> SystemDirectory (%windir%\System or %windir%\System32)
  752. //
  753. if((SystemDirectory = DuplicateString(Buffer)) == NULL) {
  754. goto cleanAll;
  755. }
  756. //
  757. // <sys>\ReinstallBackups ==> WindowsBackupDirectory
  758. //
  759. *p = 0;
  760. if(!pSetupConcatenatePaths(Buffer,TEXT("ReinstallBackups"),MAX_PATH,NULL)
  761. || ((WindowsBackupDirectory = DuplicateString(Buffer))==NULL)) {
  762. goto cleanAll;
  763. }
  764. //
  765. // <sys>\CONFIG ==> ConfigDirectory
  766. //
  767. *p = 0;
  768. if(!pSetupConcatenatePaths(Buffer,TEXT("CONFIG"),MAX_PATH,NULL)
  769. || ((ConfigDirectory = DuplicateString(Buffer))==NULL)) {
  770. goto cleanAll;
  771. }
  772. //
  773. // <sys>\DRIVERS ==> DriversDirectory
  774. //
  775. *p = 0;
  776. if(!pSetupConcatenatePaths(Buffer,TEXT("DRIVERS"),MAX_PATH,NULL)
  777. || ((DriversDirectory = DuplicateString(Buffer))==NULL)) {
  778. goto cleanAll;
  779. }
  780. //
  781. // location system installed from
  782. //
  783. if((SystemSourcePath = GetSystemSourcePath())==NULL) {
  784. goto cleanAll;
  785. }
  786. //
  787. // location service pack installed from (may be NULL)
  788. //
  789. ServicePackSourcePath = GetServicePackSourcePath();
  790. //
  791. // location of driver cache (may be NULL)
  792. //
  793. DriverCacheSourcePath = GetDriverCacheSourcePath();
  794. //
  795. // determine driver search path
  796. //
  797. if((InfSearchPaths = AllocAndReturnDriverSearchList(INFINFO_INF_PATH_LIST_SEARCH))==NULL) {
  798. goto cleanAll;
  799. }
  800. //
  801. // note that InitMiniIconList, InitDrvSearchInProgressList, and
  802. // InitDrvSignPolicyList need to be explicitly cleaned up on failure
  803. //
  804. //
  805. // initialize mini icons
  806. //
  807. if(!InitMiniIconList()) {
  808. goto cleanAll;
  809. }
  810. //
  811. // allows aborting of search
  812. //
  813. if(!InitDrvSearchInProgressList()) {
  814. DestroyMiniIconList();
  815. goto cleanAll;
  816. }
  817. //
  818. // global list of device setup classes subject to driver signing policy
  819. //
  820. if(!InitDrvSignPolicyList()) {
  821. DestroyMiniIconList();
  822. DestroyDrvSearchInProgressList();
  823. goto cleanAll;
  824. }
  825. //
  826. // common version initialization
  827. //
  828. ZeroMemory(&OSVersionInfo,sizeof(OSVersionInfo));
  829. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
  830. if(!GetVersionEx((LPOSVERSIONINFO)&OSVersionInfo)) {
  831. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  832. if(!GetVersionEx((LPOSVERSIONINFO)&OSVersionInfo)) {
  833. //
  834. // should never get here
  835. //
  836. MYASSERT(FALSE);
  837. DestroyMiniIconList();
  838. DestroyDrvSearchInProgressList();
  839. DestroyDrvSignPolicyList();
  840. goto cleanAll;
  841. }
  842. }
  843. //
  844. // Fill in our ExcludeFromSelect string list which
  845. // we pre-compute as an optimization.
  846. //
  847. if(OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  848. lstrcat(pszExcludeFromSelectList[1],
  849. pszNtSuffix
  850. );
  851. lstrcat(pszExcludeFromSelectList[2],
  852. pszNtPlatformSuffix
  853. );
  854. ExcludeFromSelectListUb = 3;
  855. } else {
  856. lstrcat(pszExcludeFromSelectList[1],
  857. pszWinSuffix
  858. );
  859. ExcludeFromSelectListUb = 2;
  860. }
  861. //
  862. // Now lower-case all the strings in this list, so that it
  863. // doesn't have to be done at each string table lookup.
  864. //
  865. for(u = 0; u < ExcludeFromSelectListUb; u++) {
  866. CharLower(pszExcludeFromSelectList[u]);
  867. }
  868. b = TRUE;
  869. cleanAll: ;
  870. } except (EXCEPTION_EXECUTE_HANDLER) {
  871. //
  872. // Unexpected exception occurred, drop into cleanup
  873. //
  874. }
  875. if(b) {
  876. //
  877. // succeeded
  878. //
  879. goto Done;
  880. }
  881. } else {
  882. //
  883. // Detach
  884. //
  885. DestroyMiniIconList();
  886. DestroyDrvSearchInProgressList();
  887. DestroyDrvSignPolicyList();
  888. if(DoneCriticalSections) {
  889. DeleteCriticalSection(&InitMutex);
  890. DeleteCriticalSection(&ImageHlpMutex);
  891. DeleteCriticalSection(&DelayedComponentMutex);
  892. DeleteCriticalSection(&PlatformPathOverrideCritSect);
  893. DeleteCriticalSection(&LogUseCountCs);
  894. DeleteCriticalSection(&MruCritSect);
  895. DeleteCriticalSection(&NetConnectionListCritSect);
  896. }
  897. if(GlobalNoDriverPromptsEventFlag) {
  898. CloseHandle(GlobalNoDriverPromptsEventFlag);
  899. }
  900. }
  901. if (InfSearchPaths) {
  902. MyFree(InfSearchPaths);
  903. InfSearchPaths = NULL;
  904. }
  905. if (DriverCacheSourcePath) {
  906. MyFree(DriverCacheSourcePath);
  907. DriverCacheSourcePath = NULL;
  908. }
  909. if (ServicePackSourcePath) {
  910. MyFree(ServicePackSourcePath);
  911. ServicePackSourcePath = NULL;
  912. }
  913. if (SystemSourcePath) {
  914. MyFree(SystemSourcePath);
  915. SystemSourcePath = NULL;
  916. }
  917. if (SystemDirectory) {
  918. MyFree(SystemDirectory);
  919. SystemDirectory = NULL;
  920. if (WindowsBackupDirectory) {
  921. MyFree(WindowsBackupDirectory);
  922. WindowsBackupDirectory = NULL;
  923. }
  924. if (ConfigDirectory) {
  925. MyFree(ConfigDirectory);
  926. ConfigDirectory = NULL;
  927. }
  928. if (DriversDirectory) {
  929. MyFree(DriversDirectory);
  930. DriversDirectory = NULL;
  931. }
  932. }
  933. if (WindowsDirectory) {
  934. MyFree(WindowsDirectory);
  935. WindowsDirectory = NULL;
  936. if (InfDirectory) {
  937. MyFree(InfDirectory);
  938. InfDirectory = NULL;
  939. }
  940. if (System16Directory) {
  941. MyFree(System16Directory);
  942. System16Directory = NULL;
  943. }
  944. if (LastGoodDirectory) {
  945. MyFree(LastGoodDirectory);
  946. } LastGoodDirectory = NULL;
  947. }
  948. if (ProcessFileName) {
  949. MyFree(ProcessFileName);
  950. ProcessFileName = NULL;
  951. }
  952. if (OsLoaderRelativePath) {
  953. MyFree(OsLoaderRelativePath);
  954. OsLoaderRelativePath = NULL;
  955. }
  956. if (OsSystemPartitionRoot) {
  957. MyFree(OsSystemPartitionRoot);
  958. OsSystemPartitionRoot = NULL;
  959. }
  960. pSetupInitNetConnectionList(FALSE);
  961. pSetupInitPlatformPathOverrideSupport(FALSE);
  962. Done:
  963. return(b);
  964. }
  965. #if MEM_DBG
  966. #undef GetSystemSourcePath // defined again below
  967. #endif
  968. PCTSTR
  969. GetSystemSourcePath(
  970. TRACK_ARG_DECLARE
  971. )
  972. /*++
  973. Routine Description:
  974. This routine returns a newly-allocated buffer containing the source path from
  975. which the system was installed, or "A:\" if that value cannot be determined.
  976. This value is retrieved from the following registry location:
  977. \HKLM\Software\Microsoft\Windows\CurrentVersion\Setup
  978. SourcePath : REG_SZ : "\\ntalpha1\1300fre.wks" // for example.
  979. Arguments:
  980. None.
  981. Return Value:
  982. If the function succeeds, the return value is a pointer to the path string.
  983. This memory must be freed via MyFree().
  984. If the function fails due to out-of-memory, the return value is NULL.
  985. --*/
  986. {
  987. HKEY hKey;
  988. TCHAR CharBuffer[CSTRLEN(REGSTR_PATH_SETUP) + SIZECHARS(REGSTR_KEY_SETUP)];
  989. DWORD Err, DataType, DataSize;
  990. PTSTR Value;
  991. PCTSTR ReturnVal;
  992. TRACK_PUSH
  993. CopyMemory(CharBuffer,
  994. pszPathSetup,
  995. sizeof(pszPathSetup) - sizeof(TCHAR)
  996. );
  997. CopyMemory((PBYTE)CharBuffer + (sizeof(pszPathSetup) - sizeof(TCHAR)),
  998. pszKeySetup,
  999. sizeof(pszKeySetup)
  1000. );
  1001. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1002. CharBuffer,
  1003. 0,
  1004. KEY_READ,
  1005. &hKey)) == ERROR_SUCCESS) {
  1006. //
  1007. // Attempt to read the the "SourcePath" value.
  1008. //
  1009. Err = QueryRegistryValue(hKey, pszSourcePath, &Value, &DataType, &DataSize);
  1010. RegCloseKey(hKey);
  1011. }
  1012. ReturnVal = NULL;
  1013. if(Err == NO_ERROR) {
  1014. ReturnVal = Value;
  1015. }
  1016. if(!ReturnVal && Err != ERROR_NOT_ENOUGH_MEMORY) {
  1017. //
  1018. // We failed to retrieve the SourcePath value, and it wasn't due to an out-of-memory
  1019. // condition. Fall back to our default of "A:\".
  1020. //
  1021. ReturnVal = DuplicateString(pszOemInfDefaultPath);
  1022. }
  1023. TRACK_POP
  1024. return ReturnVal;
  1025. }
  1026. #if MEM_DBG
  1027. #define GetSystemSourcePath() GetSystemSourcePath(TRACK_ARG_CALL)
  1028. #endif
  1029. #if MEM_DBG
  1030. #undef GetServicePackSourcePath // defined again below
  1031. #endif
  1032. PCTSTR
  1033. GetServicePackSourcePath(
  1034. TRACK_ARG_DECLARE
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. This routine returns a newly-allocated buffer containing the service pack source path
  1039. where we should look for service pack source files, or "CDM" if that value cannot be determined.
  1040. This value is retrieved from the following registry location:
  1041. \HKLM\Software\Microsoft\Windows\CurrentVersion\Setup
  1042. ServicePackSourcePath : REG_SZ : "\\ntalpha1\1300fre.wks" // for example.
  1043. Arguments:
  1044. None.
  1045. Return Value:
  1046. If the function succeeds, the return value is a pointer to the path string.
  1047. This memory must be freed via MyFree().
  1048. If the function fails due to out-of-memory, the return value is NULL.
  1049. --*/
  1050. {
  1051. HKEY hKey;
  1052. TCHAR CharBuffer[CSTRLEN(REGSTR_PATH_SETUP) + SIZECHARS(REGSTR_KEY_SETUP)];
  1053. DWORD Err, DataType, DataSize;
  1054. PTSTR Value;
  1055. PCTSTR ReturnStr = NULL;
  1056. TRACK_PUSH
  1057. CopyMemory(CharBuffer,
  1058. pszPathSetup,
  1059. sizeof(pszPathSetup) - sizeof(TCHAR)
  1060. );
  1061. CopyMemory((PBYTE)CharBuffer + (sizeof(pszPathSetup) - sizeof(TCHAR)),
  1062. pszKeySetup,
  1063. sizeof(pszKeySetup)
  1064. );
  1065. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1066. CharBuffer,
  1067. 0,
  1068. KEY_READ,
  1069. &hKey)) == ERROR_SUCCESS) {
  1070. //
  1071. // Attempt to read the the "ServicePackSourcePath" value.
  1072. //
  1073. Err = QueryRegistryValue(hKey, pszSvcPackPath, &Value, &DataType, &DataSize);
  1074. RegCloseKey(hKey);
  1075. }
  1076. if(Err == NO_ERROR) {
  1077. ReturnStr = Value;
  1078. }
  1079. if(!ReturnStr && Err != ERROR_NOT_ENOUGH_MEMORY) {
  1080. //
  1081. // We failed to retrieve the ServicePackSourcePath value, and it wasn't due to an out-of-memory
  1082. // condition. Fall back to the SourcePath value in the registry
  1083. //
  1084. ReturnStr = GetSystemSourcePath();
  1085. }
  1086. TRACK_POP
  1087. return ReturnStr;
  1088. }
  1089. #if MEM_DBG
  1090. #define GetServicePackSourcePath() GetServicePackSourcePath(TRACK_ARG_CALL)
  1091. #endif
  1092. PCTSTR
  1093. GetDriverCacheSourcePath(
  1094. VOID
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. This routine returns a newly-allocated buffer containing the source path to the local driver cache
  1099. cab-file.
  1100. This value is retrieved from the following registry location:
  1101. \HKLM\Software\Microsoft\Windows\CurrentVersion\Setup
  1102. DriverCachePath : REG_SZ : "\\ntalpha1\1300fre.wks" // for example.
  1103. Arguments:
  1104. None.
  1105. Return Value:
  1106. If the function succeeds, the return value is a pointer to the path string.
  1107. This memory must be freed via MyFree().
  1108. If the function fails due to out-of-memory, the return value is NULL.
  1109. --*/
  1110. {
  1111. HKEY hKey;
  1112. TCHAR CharBuffer[CSTRLEN(REGSTR_PATH_SETUP) + SIZECHARS(REGSTR_KEY_SETUP)];
  1113. DWORD Err, DataType, DataSize;
  1114. PTSTR Value;
  1115. TCHAR Path[MAX_PATH];
  1116. CopyMemory(CharBuffer,
  1117. pszPathSetup,
  1118. sizeof(pszPathSetup) - sizeof(TCHAR)
  1119. );
  1120. CopyMemory((PBYTE)CharBuffer + (sizeof(pszPathSetup) - sizeof(TCHAR)),
  1121. pszKeySetup,
  1122. sizeof(pszKeySetup)
  1123. );
  1124. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1125. CharBuffer,
  1126. 0,
  1127. KEY_READ,
  1128. &hKey)) == ERROR_SUCCESS) {
  1129. //
  1130. // Attempt to read the the "DriverCachePath" value.
  1131. //
  1132. Err = QueryRegistryValue(hKey, pszDriverCachePath, &Value, &DataType, &DataSize);
  1133. RegCloseKey(hKey);
  1134. }
  1135. if(Err == NO_ERROR) {
  1136. if(Value) {
  1137. ExpandEnvironmentStrings(Value,Path,MAX_PATH);
  1138. MyFree(Value);
  1139. Value = NULL;
  1140. if (*Path) {
  1141. Value = DuplicateString( Path );
  1142. }
  1143. return (PCTSTR)Value;
  1144. }
  1145. } else if(Err == ERROR_NOT_ENOUGH_MEMORY) {
  1146. return NULL;
  1147. }
  1148. return NULL;
  1149. }
  1150. BOOL
  1151. pSetupSetSystemSourcePath(
  1152. IN PCTSTR NewSourcePath,
  1153. IN PCTSTR NewSvcPackSourcePath
  1154. )
  1155. /*++
  1156. Routine Description:
  1157. This routine is used to override the system source path used by setupapi (as
  1158. retrieved by GetSystemSourcePath during DLL initialization). This is used by
  1159. syssetup.dll to set the system source path appropriately during GUI-mode setup,
  1160. so that the device installer APIs will copy files from the correct source location.
  1161. We do the same thing for the service pack source path
  1162. NOTE: This routine IS NOT thread safe!
  1163. Arguments:
  1164. NewSourcePath - supplies the new source path to be used.
  1165. NewSvcPackSourcePath - supplies the new svcpack source path to be used.
  1166. Return Value:
  1167. If the function succeeds, the return value is TRUE.
  1168. If the function fails (due to out-of-memory), the return value is FALSE.
  1169. --*/
  1170. {
  1171. PCTSTR p,q;
  1172. p = (PCTSTR)DuplicateString(NewSourcePath);
  1173. q = (PCTSTR)DuplicateString(NewSvcPackSourcePath);
  1174. if(p) {
  1175. MyFree(SystemSourcePath);
  1176. SystemSourcePath = p;
  1177. }
  1178. if (q) {
  1179. MyFree(ServicePackSourcePath);
  1180. ServicePackSourcePath = q;
  1181. }
  1182. if (!p || !q) {
  1183. //
  1184. // failed due to out of memory!
  1185. //
  1186. return(FALSE);
  1187. }
  1188. return TRUE;
  1189. }
  1190. PCTSTR
  1191. pSetupGetOsLoaderPath(
  1192. VOID
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This routine returns a newly-allocated buffer containing the path to the OsLoader
  1197. (relative to the system partition drive). This value is retrieved from the
  1198. following registry location:
  1199. HKLM\System\Setup
  1200. OsLoaderPath : REG_SZ : <path> // e.g., "\os\winnt40"
  1201. Arguments:
  1202. None.
  1203. Return Value:
  1204. If the registry entry is found, the return value is a pointer to the string containing
  1205. the path. The caller must free this buffer via MyFree().
  1206. If the registry entry is not found, or memory cannot be allocated for the buffer, the
  1207. return value is NULL.
  1208. --*/
  1209. {
  1210. HKEY hKey;
  1211. PTSTR Value;
  1212. DWORD Err, DataType, DataSize;
  1213. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1214. TEXT("SYSTEM\\Setup"),
  1215. 0,
  1216. KEY_READ,
  1217. &hKey) == ERROR_SUCCESS) {
  1218. Err = QueryRegistryValue(hKey, TEXT("OsLoaderPath"), &Value, &DataType, &DataSize);
  1219. RegCloseKey(hKey);
  1220. return (Err == NO_ERROR) ? (PCTSTR)Value : NULL;
  1221. }
  1222. return NULL;
  1223. }
  1224. PCTSTR
  1225. pSetupGetSystemPartitionRoot(
  1226. VOID
  1227. )
  1228. /*++
  1229. Routine Description:
  1230. This routine returns a newly-allocated buffer containing the path to the OsLoader
  1231. (relative to the system partition drive). This value is retrieved from the
  1232. following registry location:
  1233. HKLM\System\Setup
  1234. SystemPartition : REG_SZ : <path> // e.g., "\Device\HarddiskVolume1"
  1235. Arguments:
  1236. None.
  1237. Return Value:
  1238. If the registry entry is found, the return value is a pointer to the string containing
  1239. the path. The caller must free this buffer via MyFree().
  1240. If the registry entry is not found, or memory cannot be allocated for the buffer, the
  1241. return value is NULL.
  1242. --*/
  1243. {
  1244. #ifdef UNICODE
  1245. HKEY hKey;
  1246. PTSTR Value;
  1247. DWORD Err, DataType, DataSize;
  1248. TCHAR Path[MAX_PATH];
  1249. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1250. TEXT("SYSTEM\\Setup"),
  1251. 0,
  1252. KEY_READ,
  1253. &hKey) == ERROR_SUCCESS) {
  1254. Err = QueryRegistryValue(hKey, TEXT("SystemPartition"), &Value, &DataType, &DataSize);
  1255. RegCloseKey(hKey);
  1256. if(Err == NO_ERROR) {
  1257. //
  1258. // prepend \\?\GLOBALROOT\
  1259. //
  1260. lstrcpy(Path,TEXT("\\\\?\\GLOBALROOT\\"));
  1261. if(pSetupConcatenatePaths(Path,Value,MAX_PATH,NULL)) {
  1262. MyFree(Value);
  1263. Value = DuplicateString(Path);
  1264. if(!Value) {
  1265. Err = ERROR_NOT_ENOUGH_MEMORY;
  1266. }
  1267. } else {
  1268. Err = GetLastError();
  1269. MyFree(Value);
  1270. }
  1271. }
  1272. return (Err == NO_ERROR) ? (PCTSTR)Value : NULL;
  1273. }
  1274. #endif
  1275. return NULL;
  1276. }
  1277. PCTSTR
  1278. pSetupGetProcessPath(
  1279. VOID
  1280. )
  1281. /*++
  1282. Routine Description:
  1283. Get the name of the EXE that we're running in.
  1284. Arguments:
  1285. NONE.
  1286. Return Value:
  1287. Pointer to a dynamically allocated string containing the name.
  1288. --*/
  1289. {
  1290. LPTSTR modname;
  1291. modname = MyMalloc(MAX_PATH * sizeof(TCHAR));
  1292. if(modname != NULL) {
  1293. if(GetModuleFileName(NULL, modname, MAX_PATH) > 0) {
  1294. LPTSTR modname2;
  1295. modname2 = MyRealloc(modname, (lstrlen(modname)+1)*sizeof(TCHAR));
  1296. if(modname2) {
  1297. modname = modname2;
  1298. }
  1299. return modname;
  1300. } else {
  1301. #ifdef PRERELEASE
  1302. OutputDebugStringA("GetModuleFileName returned 0\r\n");
  1303. DebugBreak();
  1304. #endif
  1305. MyFree(modname);
  1306. }
  1307. }
  1308. return NULL;
  1309. }
  1310. #ifdef UNICODE
  1311. BOOL
  1312. pGetGuiSetupInProgress(
  1313. VOID
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. This routine determines if we're doing a gui-mode setup.
  1318. This value is retrieved from the following registry location:
  1319. \HKLM\System\Setup\
  1320. SystemSetupInProgress : REG_DWORD : 0x00 (where nonzero means we're doing a gui-setup)
  1321. Arguments:
  1322. None.
  1323. Return Value:
  1324. If the function succeeds, the return value is a pointer to the path string.
  1325. This memory must be freed via MyFree().
  1326. If the function fails due to out-of-memory, the return value is NULL.
  1327. --*/
  1328. {
  1329. HKEY hKey;
  1330. TCHAR CharBuffer[CSTRLEN(REGSTR_PATH_SETUP) + SIZECHARS(REGSTR_KEY_SETUP)];
  1331. DWORD Err, DataType, DataSize = sizeof(DWORD);
  1332. DWORD Value;
  1333. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1334. TEXT("System\\Setup"),
  1335. 0,
  1336. KEY_READ,
  1337. &hKey)) == ERROR_SUCCESS) {
  1338. //
  1339. // Attempt to read the the "DriverCachePath" value.
  1340. //
  1341. Err = RegQueryValueEx(
  1342. hKey,
  1343. TEXT("SystemSetupInProgress"),
  1344. NULL,
  1345. &DataType,
  1346. (LPBYTE)&Value,
  1347. &DataSize);
  1348. RegCloseKey(hKey);
  1349. }
  1350. if(Err == NO_ERROR) {
  1351. if(Value) {
  1352. return(TRUE);
  1353. }
  1354. }
  1355. return(FALSE);
  1356. }
  1357. #else
  1358. BOOL
  1359. pGetGuiSetupInProgress(
  1360. VOID
  1361. )
  1362. {
  1363. return FALSE;
  1364. }
  1365. #endif
  1366. VOID pSetupSetGlobalFlags(
  1367. IN DWORD Value
  1368. )
  1369. /*++
  1370. exported as a private function
  1371. Routine Description:
  1372. Sets global flags to change certain setupapi features,
  1373. such as "should we call runonce after installing every device" (set if we will manually call it)
  1374. or "should we backup every file"
  1375. Used to initialize value
  1376. Arguments:
  1377. Value: combination of:
  1378. PSPGF_NO_RUNONCE - set to inhibit runonce calls (e.g., during GUI-
  1379. mode setup)
  1380. PSPGF_NO_BACKUP - set to inhibit automatic backup (e.g., during
  1381. GUI-mode setup)
  1382. PSPGF_NONINTERACTIVE - set to inhibit _all_ UI (e.g., for server-side
  1383. device installation)
  1384. PSPGF_SERVER_SIDE_RUNONCE - batch RunOnce entries for server-side
  1385. processing (for use only by umpnpmgr)
  1386. PSPGF_NO_VERIFY_INF - set to inhibit verification (digital signature) of
  1387. INF files until after the cyrpto DLLs have been registered.
  1388. PSPGF_UNATTENDED_SETUP - similar to NONINTERACTIVE - but specific to unattended setup
  1389. PSPGF_AUTOFAIL_VERIFIES - automatically fail all calls to crypto
  1390. Return Value:
  1391. none
  1392. --*/
  1393. {
  1394. pSetupModifyGlobalFlags((DWORD)(-1),Value);
  1395. }
  1396. VOID
  1397. pSetupModifyGlobalFlags(
  1398. IN DWORD Flags,
  1399. IN DWORD Value
  1400. )
  1401. /*++
  1402. exported as a private function
  1403. Routine Description:
  1404. Modifies global setup flags
  1405. such as "should we call runonce after installing every device" (set if we will manually call it)
  1406. or "should we backup every file"
  1407. only modifies specified flags to given value
  1408. Arguments:
  1409. Flags: what actual flags to modify, combination of:
  1410. PSPGF_NO_RUNONCE - set to inhibit runonce calls (e.g., during GUI-
  1411. mode setup)
  1412. PSPGF_NO_BACKUP - set to inhibit automatic backup (e.g., during
  1413. GUI-mode setup)
  1414. PSPGF_NONINTERACTIVE - set to inhibit _all_ UI (e.g., for server-side
  1415. device installation)
  1416. PSPGF_SERVER_SIDE_RUNONCE - batch RunOnce entries for server-side
  1417. processing (for use only by umpnpmgr)
  1418. PSPGF_NO_VERIFY_INF - set to inhibit verification (digital signature) of
  1419. INF files until after the cyrpto DLLs have been registered.
  1420. PSPGF_UNATTENDED_SETUP - similar to PSPGF_NONINTERACTIVE, but specific to setup
  1421. PSPGF_AUTOFAIL_VERIFIES - automatically fail all calls to crypto
  1422. Value: new value of bits specified in Flags
  1423. Return Value:
  1424. none
  1425. --*/
  1426. {
  1427. Flags &= ~GlobalSetupFlagsOverride; // exclusion
  1428. #ifdef UNICODE
  1429. if((Flags & PSPGF_NO_VERIFY_INF) && !(Value & PSPGF_NO_VERIFY_INF) && (GlobalSetupFlags & PSPGF_NO_VERIFY_INF)) {
  1430. Seed = GetSeed();
  1431. }
  1432. #endif
  1433. GlobalSetupFlags = (Value & Flags) | (GlobalSetupFlags & ~Flags);
  1434. }
  1435. DWORD pSetupGetGlobalFlags(
  1436. VOID
  1437. )
  1438. /*++
  1439. exported as a private function, also called internally
  1440. Routine Description:
  1441. Return flags previously set
  1442. Arguments:
  1443. none
  1444. Return value:
  1445. Flags (combination of values described above for pSetupSetGlobalFlags)
  1446. --*/
  1447. {
  1448. return GlobalSetupFlags;
  1449. }
  1450. BOOL
  1451. WINAPI
  1452. SetupSetNonInteractiveMode(
  1453. IN BOOL NonInteractiveFlag
  1454. )
  1455. /*++
  1456. Global access to the flag PSPGF_NONINTERACTIVE
  1457. Routine Description:
  1458. Set/Reset the NonInteractiveMode flag, and return previous flag value
  1459. (can't clear override)
  1460. Arguments:
  1461. New flag value
  1462. Return value:
  1463. Old flag value
  1464. --*/
  1465. {
  1466. BOOL f = (GlobalSetupFlags & PSPGF_NONINTERACTIVE) ? TRUE : FALSE;
  1467. if (NonInteractiveFlag) {
  1468. pSetupModifyGlobalFlags(PSPGF_NONINTERACTIVE,PSPGF_NONINTERACTIVE);
  1469. } else {
  1470. pSetupModifyGlobalFlags(PSPGF_NONINTERACTIVE,0);
  1471. }
  1472. return f;
  1473. }
  1474. BOOL
  1475. WINAPI
  1476. SetupGetNonInteractiveMode(
  1477. VOID
  1478. )
  1479. /*++
  1480. Global access to the flag PSPGF_NONINTERACTIVE
  1481. Routine Description:
  1482. Get current flag value
  1483. Arguments:
  1484. none
  1485. Return value:
  1486. Current flag value
  1487. --*/
  1488. {
  1489. return (GlobalSetupFlags & PSPGF_NONINTERACTIVE) ? TRUE : FALSE;
  1490. }
  1491. #ifndef _WIN64
  1492. BOOL
  1493. GetIsWow64 (
  1494. VOID
  1495. )
  1496. /*++
  1497. Routine Description:
  1498. Determine if we're running on WOW64 or not (not supported on ANSI builds)
  1499. Arguments:
  1500. none
  1501. Return value:
  1502. TRUE if running under WOW64 (and special Wow64 features available)
  1503. --*/
  1504. {
  1505. #ifdef UNICODE
  1506. ULONG_PTR ul = 0;
  1507. NTSTATUS st;
  1508. //
  1509. // If this call succeeds and sets ul non-zero
  1510. // it's a 32-bit process running on Win64
  1511. //
  1512. st = NtQueryInformationProcess(NtCurrentProcess(),
  1513. ProcessWow64Information,
  1514. &ul,
  1515. sizeof(ul),
  1516. NULL);
  1517. if (NT_SUCCESS(st) && (0 != ul)) {
  1518. // 32-bit code running on Win64
  1519. return TRUE;
  1520. }
  1521. #endif
  1522. return FALSE;
  1523. }
  1524. #endif // _WIN64
  1525. #if 0 // deleted code
  1526. //
  1527. // this will be useful at somepoint, but not used right now
  1528. //
  1529. BOOL
  1530. InitComponents(
  1531. DWORD Components
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. Called at a point we want certain components initialized
  1536. Arguments:
  1537. bitmask of components to initialize
  1538. Return value:
  1539. TRUE if all initialized ok
  1540. --*/
  1541. {
  1542. BOOL success = FALSE;
  1543. PSETUP_TLS pPerThread = SetupGetTlsData();
  1544. BOOL locked = FALSE;
  1545. if(!pPerThread) {
  1546. MYASSERT(pPerThread);
  1547. return FALSE;
  1548. }
  1549. try {
  1550. EnterCriticalSection(&DelayedComponentMutex);
  1551. locked = TRUE;
  1552. Components &= ~ DoneComponentInitialize;
  1553. Components &= ~ pPerThread->PerThreadDoneComponent;
  1554. if (!Components) {
  1555. //
  1556. // already done
  1557. //
  1558. success = TRUE;
  1559. leave;
  1560. }
  1561. if (Components & FailedComponentInitialize) {
  1562. //
  1563. // previously failed
  1564. //
  1565. leave;
  1566. }
  1567. if (Components & pPerThread->PerThreadFailedComponent) {
  1568. //
  1569. // previously failed
  1570. //
  1571. leave;
  1572. }
  1573. MYASSERT(((DoneComponentInitialize | pPerThread->PerThreadDoneComponent) & Components) == Components);
  1574. MYASSERT(((FailedComponentInitialize | pPerThread->PerThreadFailedComponent) & Components) == 0);
  1575. success = TRUE;
  1576. } except (EXCEPTION_EXECUTE_HANDLER) {
  1577. MYASSERT(FALSE);
  1578. }
  1579. if(locked) {
  1580. LeaveCriticalSection(&DelayedComponentMutex);
  1581. }
  1582. return success;
  1583. }
  1584. VOID
  1585. ComponentCleanup(
  1586. DWORD Components
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. Called to cleanup components
  1591. Arguments:
  1592. bitmask of components to uninitialize
  1593. Return value:
  1594. none
  1595. --*/
  1596. {
  1597. PSETUP_TLS pPerThread = SetupGetTlsData();
  1598. BOOL locked = FALSE;
  1599. try {
  1600. EnterCriticalSection(&DelayedComponentMutex);
  1601. locked = TRUE;
  1602. Components &= (DoneComponentInitialize | (pPerThread? pPerThread->PerThreadDoneComponent : 0));
  1603. if (!Components) {
  1604. //
  1605. // already done
  1606. //
  1607. leave;
  1608. }
  1609. } except (EXCEPTION_EXECUTE_HANDLER) {
  1610. MYASSERT(FALSE);
  1611. }
  1612. MYASSERT(((DoneComponentInitialize | (pPerThread ? pPerThread->PerThreadDoneComponent : 0)) & Components) == 0);
  1613. if(locked) {
  1614. LeaveCriticalSection(&DelayedComponentMutex);
  1615. }
  1616. }
  1617. #endif // deleted code
  1618. #ifdef UNICODE
  1619. BOOL
  1620. pSetupSetNoDriverPrompts(
  1621. BOOL Flag
  1622. )
  1623. /*++
  1624. exported as a private function
  1625. Routine Description:
  1626. Sets system into headless/non-headless mode
  1627. Arguments:
  1628. Flag - indicating mode
  1629. --*/
  1630. {
  1631. //
  1632. //
  1633. if(!GuiSetupInProgress) {
  1634. return FALSE;
  1635. }
  1636. if(GlobalNoDriverPromptsEventFlag == NULL) {
  1637. GlobalNoDriverPromptsEventFlag = CreateEvent(NULL,TRUE,Flag,SETUP_NODRIVERPROMPTS_MODE);
  1638. if(GlobalNoDriverPromptsEventFlag == NULL) {
  1639. return FALSE;
  1640. }
  1641. }
  1642. if(Flag) {
  1643. //
  1644. // force this process's setupapi to be non-interative, and any future setupapi's
  1645. //
  1646. GlobalSetupFlagsOverride |= PSPGF_UNATTENDED_SETUP; // don't allow this to be changed
  1647. GlobalSetupFlags |= PSPGF_UNATTENDED_SETUP; // actual value
  1648. SetEvent(GlobalNoDriverPromptsEventFlag);
  1649. } else {
  1650. //
  1651. // can't reset flag for this/existing processes, but can reset it for all future processes
  1652. //
  1653. ResetEvent(GlobalNoDriverPromptsEventFlag);
  1654. }
  1655. return TRUE;
  1656. }
  1657. #endif
  1658. BOOL
  1659. IsNoDriverPrompts(
  1660. VOID
  1661. )
  1662. /*++
  1663. internal
  1664. Routine Description:
  1665. Obtains headless state
  1666. Arguments:
  1667. Flag - indicating mode
  1668. --*/
  1669. {
  1670. #ifdef UNICODE
  1671. if(!GuiSetupInProgress) {
  1672. return FALSE;
  1673. }
  1674. if(GlobalNoDriverPromptsEventFlag == NULL) {
  1675. GlobalNoDriverPromptsEventFlag = OpenEvent(SYNCHRONIZE,FALSE,SETUP_NODRIVERPROMPTS_MODE);
  1676. if(GlobalNoDriverPromptsEventFlag == NULL) {
  1677. return FALSE;
  1678. }
  1679. }
  1680. //
  1681. // poll event, returning TRUE if it's signalled
  1682. //
  1683. return WaitForSingleObject(GlobalNoDriverPromptsEventFlag,0) == WAIT_OBJECT_0;
  1684. #else
  1685. return FALSE;
  1686. #endif
  1687. }
  1688. DWORD
  1689. GetEmbeddedFlags(
  1690. VOID
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. This routine determines whether or not we are running on an embedded
  1695. product, and if so, whether:
  1696. * The "minimize setupapi footprint" option is enabled. This causes us to
  1697. modify our default behaviors as follows:
  1698. 1. Never call any crypto APIs, and just assume everything is signed
  1699. 2. Never generate PNFs.
  1700. * The "disable SCE" option is enabled. This causes us to avoid all use of
  1701. the Security Configuration Editor (SCE) routines (as the corresponding
  1702. DLLs won't be available on that embedded configuration).
  1703. Arguments:
  1704. none
  1705. Return value:
  1706. Combination of the following flags:
  1707. PSPGF_MINIMAL_EMBEDDED if we're running in "minimize footprint" mode
  1708. PSPGF_NO_SCE_EMBEDDED if we're running in "disable SCE" mode
  1709. --*/
  1710. {
  1711. OSVERSIONINFOEX osvix;
  1712. DWORDLONG dwlConditionMask = 0;
  1713. HKEY hKey;
  1714. TCHAR CharBuffer[CSTRLEN(REGSTR_PATH_SETUP) + SIZECHARS(REGSTR_KEY_SETUP)];
  1715. DWORD RegDataType, Data, DataSize;
  1716. DWORD Flags;
  1717. //
  1718. // Are we on the embedded product suite?
  1719. //
  1720. ZeroMemory(&osvix, sizeof(OSVERSIONINFOEX));
  1721. osvix.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1722. osvix.wSuiteMask = VER_SUITE_EMBEDDEDNT;
  1723. VER_SET_CONDITION(dwlConditionMask, VER_SUITENAME, VER_OR);
  1724. if(!VerifyVersionInfo(&osvix,
  1725. VER_SUITENAME,
  1726. dwlConditionMask)) {
  1727. return 0;
  1728. }
  1729. Flags = 0;
  1730. //
  1731. // OK, we running on embedded. Now we need to find out whether or not we
  1732. // should run in "minimal footprint" mode. This is stored in a REG_DWORD
  1733. // value entry called "MinimizeFootprint" under
  1734. // HKLM\Software\Microsoft\Windows\CurrentVersion\Setup.
  1735. //
  1736. CopyMemory(CharBuffer,
  1737. pszPathSetup,
  1738. sizeof(pszPathSetup) - sizeof(TCHAR)
  1739. );
  1740. CopyMemory((PBYTE)CharBuffer + (sizeof(pszPathSetup) - sizeof(TCHAR)),
  1741. pszKeySetup,
  1742. sizeof(pszKeySetup)
  1743. );
  1744. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1745. CharBuffer,
  1746. 0,
  1747. KEY_READ,
  1748. &hKey)) {
  1749. DataSize = sizeof(Data);
  1750. if((ERROR_SUCCESS == RegQueryValueEx(hKey,
  1751. pszMinimizeFootprint,
  1752. NULL,
  1753. &RegDataType,
  1754. (LPBYTE)&Data,
  1755. &DataSize))
  1756. && (RegDataType == REG_DWORD) && (DataSize == sizeof(Data))) {
  1757. Flags |= PSPGF_MINIMAL_EMBEDDED;
  1758. }
  1759. RegCloseKey(hKey);
  1760. }
  1761. //
  1762. // Now look under HKLM\Software\Microsoft\EmbeddedNT\Security for a
  1763. // DisableSCE REG_DWORD value entry, indicating we shouldn't call SCE.
  1764. //
  1765. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1766. pszEmbeddedNTSecurity,
  1767. 0,
  1768. KEY_READ,
  1769. &hKey)) {
  1770. DataSize = sizeof(Data);
  1771. if((ERROR_SUCCESS == RegQueryValueEx(hKey,
  1772. pszDisableSCE,
  1773. NULL,
  1774. &RegDataType,
  1775. (LPBYTE)&Data,
  1776. &DataSize))
  1777. && (RegDataType == REG_DWORD) && (DataSize == sizeof(Data))) {
  1778. Flags |= PSPGF_NO_SCE_EMBEDDED;
  1779. }
  1780. RegCloseKey(hKey);
  1781. }
  1782. return Flags;
  1783. }
  1784. #ifdef UNICODE
  1785. DWORD
  1786. GetSeed(
  1787. VOID
  1788. )
  1789. {
  1790. HKEY hKey;
  1791. DWORD val = 0;
  1792. DWORD valsize, valdatatype;
  1793. if(GlobalSetupFlags & PSPGF_MINIMAL_EMBEDDED) {
  1794. return val;
  1795. }
  1796. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1797. L"System\\WPA\\PnP",
  1798. 0,
  1799. KEY_READ,
  1800. &hKey)) {
  1801. valsize = sizeof(val);
  1802. if((ERROR_SUCCESS != RegQueryValueEx(hKey,
  1803. L"seed",
  1804. NULL,
  1805. &valdatatype,
  1806. (PBYTE)&val,
  1807. &valsize))
  1808. || (valdatatype != REG_DWORD) || (valsize != sizeof(val))) {
  1809. val = 0;
  1810. }
  1811. RegCloseKey(hKey);
  1812. }
  1813. return val;
  1814. }
  1815. #endif