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.

849 lines
18 KiB

  1. //
  2. // Need to include below 3 files for "IsNEC_98", even if DEBUGPERFTRACE does not defined.
  3. //
  4. #include <nt.h>
  5. #include <ntrtl.h>
  6. #include <nturtl.h>
  7. #include <windows.h>
  8. #include <prsht.h>
  9. #include <commctrl.h>
  10. #ifdef PRERELEASE
  11. #ifdef DBG
  12. #include <objbase.h>
  13. #endif
  14. #endif
  15. #include <setupapi.h>
  16. #include <spapip.h>
  17. #include <ocmanage.h>
  18. #include <ocmgrlib.h>
  19. #include <tchar.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <assert.h>
  23. #include <winnls.h>
  24. #ifdef UNICODE
  25. #include <sfcapip.h>
  26. #endif
  27. #include "msg.h"
  28. #include "res.h"
  29. #if DBG
  30. #define MYASSERT( exp ) \
  31. if (!(exp)) \
  32. RtlAssert( #exp, __FILE__, __LINE__, NULL )
  33. #else
  34. #define MYASSERT( exp )
  35. #endif // DBG
  36. //
  37. // Names of wizard page types.
  38. //
  39. extern LPCTSTR WizardPagesTypeNames[WizPagesTypeMax];
  40. //
  41. // Window handle of wizard dialog. Set when the OC Manager client
  42. // calls OcRememberWizardDialogHandle.
  43. //
  44. extern HWND WizardDialogHandle;
  45. //
  46. // Name of sections and keys in infs.
  47. //
  48. extern LPCTSTR szComponents;
  49. extern LPCTSTR szOptionalComponents;
  50. extern LPCTSTR szExtraSetupFiles;
  51. extern LPCTSTR szNeeds;
  52. extern LPCTSTR szParent;
  53. extern LPCTSTR szIconIndex;
  54. extern LPCTSTR szTip;
  55. extern LPCTSTR szOptionDesc;
  56. extern LPCTSTR szInstalledFlag;
  57. //
  58. // Key in registry where private component data is kept.
  59. // We form a unique name within this key for the OC Manager
  60. // instantiation.
  61. //
  62. extern LPCTSTR szPrivateDataRoot;
  63. extern LPCTSTR szMasterInfs;
  64. extern LPCTSTR szSubcompList;
  65. //
  66. // Other string constants.
  67. //
  68. extern LPCTSTR szSetupDir;
  69. extern LPCTSTR szOcManagerErrors;
  70. //
  71. // DLL module handle.
  72. //
  73. extern HMODULE MyModuleHandle;
  74. //
  75. // for debugging
  76. //
  77. extern DWORD gDebugLevel;
  78. //
  79. // Define structure describing an optional component.
  80. //
  81. typedef struct _OPTIONAL_COMPONENT {
  82. //
  83. // String id of name of inf file in the OC Manager's
  84. // InfListStringTable string table. If -1, then
  85. // the subcomponent does not appear on the OC page.
  86. //
  87. LONG InfStringId;
  88. //
  89. // Backpointer to top level component
  90. //
  91. LONG TopLevelStringId;
  92. //
  93. // String id of parent component, -1 if none.
  94. //
  95. LONG ParentStringId;
  96. //
  97. // String id of first child, -1 if none.
  98. //
  99. LONG FirstChildStringId;
  100. //
  101. // Count of children.
  102. //
  103. UINT ChildrenCount;
  104. //
  105. // String id of next sibling, -1 if none.
  106. //
  107. LONG NextSiblingStringId;
  108. //
  109. // String ids of needs and needed by.
  110. //
  111. PLONG NeedsStringIds;
  112. UINT NeedsCount;
  113. PLONG NeededByStringIds;
  114. UINT NeededByCount;
  115. // String ids of exclude and excluded by
  116. PLONG ExcludeStringIds;
  117. UINT ExcludeCount;
  118. PLONG ExcludedByStringIds;
  119. UINT ExcludedByCount;
  120. //
  121. // Misc flags.
  122. //
  123. UINT InternalFlags;
  124. //
  125. // Approximation of required disk space.
  126. //
  127. LONGLONG SizeApproximation;
  128. //
  129. // Icon index of the component.
  130. // -1 means we're supposed to get it from the component itself.
  131. // -2 means we're supposed to use IconDll and IconResource
  132. //
  133. UINT IconIndex;
  134. TCHAR IconDll[MAX_PATH];
  135. TCHAR IconResource[50];
  136. //
  137. // Selection state (SELSTATE_xxx constants).
  138. //
  139. UINT SelectionState;
  140. UINT OriginalSelectionState;
  141. // Installation Flag as obtained from the inf
  142. UINT InstalledState;
  143. //
  144. // Mode bits.
  145. //
  146. UINT ModeBits;
  147. //
  148. // Human-readable stuff describing the component.
  149. //
  150. TCHAR Description[MAXOCDESC];
  151. TCHAR Tip[MAXOCTIP];
  152. //
  153. // From here down, stuff is meaningful only for top-level components.
  154. //
  155. //
  156. // Stuff describing the OC's installation DLL and how to call it.
  157. //
  158. TCHAR InstallationDllName[MAX_PATH];
  159. CHAR InterfaceFunctionName[MAX_PATH];
  160. HMODULE InstallationDll;
  161. POCSETUPPROC InstallationRoutine;
  162. //
  163. // Version of the OC Manager to which this component was written.
  164. //
  165. UINT ExpectedVersion;
  166. // this flag indicates whether the subcomponent was intialialized
  167. BOOL Exists;
  168. // points to the helper context for this component
  169. struct _HELPER_CONTEXT *HelperContext;
  170. //
  171. // Flags: ANSI/Unicode, etc.
  172. //
  173. UINT Flags;
  174. } OPTIONAL_COMPONENT, *POPTIONAL_COMPONENT;
  175. //
  176. // locale info
  177. //
  178. typedef struct _LOCALE {
  179. LCID lcid;
  180. TCHAR DecimalSeparator[4];
  181. } LOCALE, *PLOCALE;
  182. extern LOCALE locale;
  183. //
  184. // Indices for installation states.
  185. //
  186. #define INSTSTATE_NO 0
  187. #define INSTSTATE_UNKNOWN 1
  188. #define INSTSTATE_YES 2
  189. //
  190. // Flags for InternalFlags member of OPTIONAL_COMPONENT structure.
  191. //
  192. #define OCFLAG_PROCESSED 0x00000001
  193. #define OCFLAG_ANYORIGINALLYON 0x00000002
  194. #define OCFLAG_ANYORIGINALLYOFF 0x00000004
  195. #define OCFLAG_HIDE 0x00000008
  196. #define OCFLAG_STATECHANGE 0x00000010
  197. #define OCFLAG_TOPLEVELITEM 0x00000020
  198. #define OCFLAG_NEWITEM 0x00000040
  199. #define OCFLAG_NOWIZARDPAGES 0x00000080
  200. #define OCFLAG_APPROXSPACE 0x00000100
  201. #define OCFLAG_NOQUERYSKIPPAGES 0x00000200
  202. #define OCFLAG_NOEXTRAROUTINES 0x00000400
  203. // indicates an exception when calling a component
  204. #define ERROR_CALL_COMPONENT -666
  205. //
  206. // values to sync copies with the OS
  207. //
  208. #define OC_ALLOWRENAME TEXT("AllowProtectedRenames")
  209. //
  210. // Define structure describing a per-component inf.
  211. //
  212. typedef struct _OC_INF {
  213. //
  214. // Handle to open inf file.
  215. //
  216. HINF Handle;
  217. } OC_INF, *POC_INF;
  218. //
  219. // Define structure corresponding to an instance of the OC Manager.
  220. // This is actually somewhat broken, in that this actually closely corresponds
  221. // to a master OC INF, and we might want to consider breaking out the string
  222. // tables into another structure, so we can more easily achieve a unified
  223. // namespace if we have multiple master OC INFs at play simultaneously.
  224. //
  225. typedef struct _OC_MANAGER {
  226. //
  227. // Callbacks into OC Manaer client.
  228. //
  229. OCM_CLIENT_CALLBACKS Callbacks;
  230. //
  231. // Handle of Master OC INF.
  232. //
  233. HINF MasterOcInf;
  234. //
  235. // unattended inf handle
  236. //
  237. HINF UnattendedInf;
  238. //
  239. // Master OC Inf file, and unattended file
  240. //
  241. TCHAR MasterOcInfPath[MAX_PATH];
  242. TCHAR UnattendedInfPath[MAX_PATH];
  243. // we run from whatever directory the master inf is in
  244. TCHAR SourceDir[MAX_PATH];
  245. //
  246. // Name of "suite" -- in other words, a shortname that
  247. // is unique to the master OC inf that this structure represents.
  248. // We base it on the name of the master OC inf itself.
  249. //
  250. TCHAR SuiteName[MAX_PATH];
  251. //
  252. // page titles
  253. //
  254. TCHAR SetupPageTitle[MAX_PATH];
  255. // window title
  256. TCHAR WindowTitle[MAX_PATH];
  257. //
  258. // List of per-component OC INFs currently loaded.
  259. // Each inf's name is in the string table and the extra data
  260. // for each is an OC_INF structure.
  261. //
  262. PVOID InfListStringTable;
  263. //
  264. // String table for names of all components and subcomponents.
  265. // Extra data for each is an OPTIONAL_COMPONENT structure.
  266. //
  267. PVOID ComponentStringTable;
  268. //
  269. // pointer to OcSetupPage structure so we can free this data
  270. // if the user cancels before we get to the wizard page.
  271. //
  272. PVOID OcSetupPage;
  273. //
  274. // Setup mode (custom, typical, etc)
  275. //
  276. UINT SetupMode;
  277. //
  278. // List of top-level optional component string IDs.
  279. // This is necessary because we need to preserve ordering
  280. // from the master OC Inf.
  281. //
  282. UINT TopLevelOcCount;
  283. PLONG TopLevelOcStringIds;
  284. UINT TopLevelParentOcCount;
  285. PLONG TopLevelParentOcStringIds;
  286. //
  287. // Are there subcomponents on the details page?
  288. //
  289. BOOL SubComponentsPresent;
  290. //
  291. // Each element in this array points to an array that
  292. // gives ordering for querying wizard pages from the optional components.
  293. //
  294. PLONG WizardPagesOrder[WizPagesTypeMax];
  295. //
  296. // Subkey relative to szPrivateDataRoot where private
  297. // data for components plugged into the OC will live.
  298. // 2 8-char DWORD representations plus a separator and nul.
  299. //
  300. TCHAR PrivateDataSubkey[18];
  301. HKEY hKeyPrivateData;
  302. HKEY hKeyPrivateDataRoot;
  303. //
  304. // If we are completing installation, this item is the window handle
  305. // of the progress text control.
  306. //
  307. HWND ProgressTextWindow;
  308. //
  309. // String id of component currently processing an interface routine.
  310. // -1 means the OC manager is not currently processing one.
  311. //
  312. LONG CurrentComponentStringId;
  313. // Component Ids of aborted components
  314. PLONG AbortedComponentIds;
  315. UINT AbortedCount;
  316. //
  317. // Various flags
  318. //
  319. UINT InternalFlags;
  320. //
  321. // setup data
  322. //
  323. SETUP_DATA SetupData;
  324. } OC_MANAGER, *POC_MANAGER;
  325. //
  326. // Flags for InternalFlags member of OC_MANAGER structure
  327. //
  328. #define OCMFLAG_ANYORIGINALLYON 0x00000001
  329. #define OCMFLAG_ANYORIGINALLYOFF 0x00000002
  330. #define OCMFLAG_ANYDELAYEDMOVES 0x00000004
  331. #define OCMFLAG_NEWINF 0x00000008
  332. #define OCMFLAG_USERCANCELED 0x00000010
  333. #define OCMFLAG_FILEABORT 0x00000020
  334. #define OCMFLAG_NOPREOCPAGES 0x00000040
  335. #define OCMFLAG_KILLSUBCOMPS 0x00000080
  336. #define OCMFLAG_ANYINSTALLED 0x00000100
  337. #define OCMFLAG_ANYUNINSTALLED 0x00000200
  338. #define OCMFLAG_RUNQUIET 0x00000400
  339. #define OCMFLAG_LANGUAGEAWARE 0x00000800
  340. //
  341. // Define structure we use to get back to a particular component
  342. // when a component calls a helper routine asynchronously (for routines
  343. // such as get and set private data).
  344. //
  345. // As each component is initialized it gets one of these structures.
  346. //
  347. typedef struct _HELPER_CONTEXT {
  348. POC_MANAGER OcManager;
  349. LONG ComponentStringId;
  350. } HELPER_CONTEXT, *PHELPER_CONTEXT;
  351. //
  352. // Macros for callbacks. Assumes there is a local variable called OcManager
  353. // that is of type POC_MANAGER.
  354. //
  355. #define OcFillInSetupDataA(p) OcManager->Callbacks.FillInSetupDataA(p)
  356. #ifdef UNICODE
  357. #define OcFillInSetupDataW(p) OcManager->Callbacks.FillInSetupDataW(p)
  358. #endif
  359. #define OcLogError OcManager->Callbacks.LogError
  360. //
  361. // Global table of helper routines.
  362. //
  363. extern OCMANAGER_ROUTINESA HelperRoutinesA;
  364. #ifdef UNICODE
  365. extern OCMANAGER_ROUTINESW HelperRoutinesW;
  366. #endif
  367. extern EXTRA_ROUTINESA ExtraRoutinesA;
  368. #ifdef UNICODE
  369. extern EXTRA_ROUTINESW ExtraRoutinesW;
  370. #endif
  371. // ocm phase ids for reporting errors with
  372. typedef enum {
  373. pidCallComponent = 0,
  374. pidLoadComponent,
  375. pidPreInit,
  376. pidInitComponent,
  377. pidRequestPages,
  378. pidCalcDiskSpace,
  379. pidQueueFileOps,
  380. pidQueryStepCount,
  381. pidCompleteInstallation,
  382. pidExtraRoutines
  383. } pid;
  384. //
  385. // Misc routines.
  386. //
  387. VOID
  388. pOcGetApproximateDiskSpace(
  389. IN POC_MANAGER OcManager
  390. );
  391. LONG
  392. pOcGetTopLevelComponent(
  393. IN POC_MANAGER OcManager,
  394. IN LONG StringId
  395. );
  396. VOID
  397. pOcTickSetupGauge(
  398. IN OUT POC_MANAGER OcManager
  399. );
  400. UINT
  401. _LogError(
  402. IN POC_MANAGER OcManager,
  403. IN OcErrorLevel ErrorLevel,
  404. IN UINT MessageId,
  405. ...
  406. );
  407. UINT
  408. pOcCreateComponentSpecificMiniIcon(
  409. IN POC_MANAGER OcManager,
  410. IN LONG ComponentId,
  411. IN LPCTSTR Subcomponent,
  412. IN UINT Width,
  413. IN UINT Height,
  414. IN LPCTSTR DllName, OPTIONAL
  415. IN LPCTSTR ResourceId OPTIONAL
  416. );
  417. VOID
  418. pOcUpdateParentSelectionStates(
  419. IN POC_MANAGER OcManager,
  420. IN HWND ListBox, OPTIONAL
  421. IN LONG SubcomponentStringId
  422. );
  423. VOID
  424. pOcFormSuitePath(
  425. IN LPCTSTR SuiteName,
  426. IN LPCTSTR FileName, OPTIONAL
  427. OUT LPTSTR FullPath
  428. );
  429. BOOL
  430. OcHelperConfirmCancel(
  431. IN HWND ParentWindow
  432. );
  433. BOOL
  434. pOcDoesAnyoneWantToSkipPage(
  435. IN OUT POC_MANAGER OcManager,
  436. IN OcManagerPage WhichPage
  437. );
  438. VOID
  439. pOcExternalProgressIndicator(
  440. IN PHELPER_CONTEXT OcManagerContext,
  441. IN BOOL ExternalIndicator
  442. );
  443. BOOL
  444. pConvertStringToLongLong(
  445. IN PCTSTR String,
  446. OUT PLONGLONG Value
  447. );
  448. VOID
  449. pOcFreeOcSetupPage(
  450. IN PVOID SetupPageData
  451. );
  452. HRESULT
  453. FTestForOutstandingCoInits(
  454. VOID
  455. );
  456. //
  457. // wrapper for calling components
  458. //
  459. DWORD
  460. CallComponent(
  461. IN POC_MANAGER OcManager,
  462. IN POPTIONAL_COMPONENT Oc,
  463. IN LPCVOID ComponentId,
  464. IN LPCVOID SubcomponentId,
  465. IN UINT Function,
  466. IN UINT_PTR Param1,
  467. IN OUT PVOID Param2
  468. );
  469. //
  470. // Interfacing routines.
  471. //
  472. UINT
  473. OcInterfacePreinitialize(
  474. IN OUT POC_MANAGER OcManager,
  475. IN LONG ComponentId
  476. );
  477. UINT
  478. OcInterfaceInitComponent(
  479. IN OUT POC_MANAGER OcManager,
  480. IN LONG ComponentId
  481. );
  482. UINT
  483. OcInterfaceExtraRoutines(
  484. IN OUT POC_MANAGER OcManager,
  485. IN LONG ComponentId
  486. );
  487. SubComponentState
  488. OcInterfaceQueryState(
  489. IN OUT POC_MANAGER OcManager,
  490. IN LONG ComponentId,
  491. IN LPCTSTR Subcomponent,
  492. IN UINT WhichState
  493. );
  494. BOOL
  495. OcInterfaceSetLanguage(
  496. IN OUT POC_MANAGER OcManager,
  497. IN LONG ComponentId,
  498. IN WORD LanguageId
  499. );
  500. HBITMAP
  501. OcInterfaceQueryImage(
  502. IN OUT POC_MANAGER OcManager,
  503. IN LONG ComponentId,
  504. IN LPCTSTR Subcomponent,
  505. IN SubComponentInfo WhichImage,
  506. IN UINT DesiredWidth,
  507. IN UINT DesiredHeight
  508. );
  509. HBITMAP
  510. OcInterfaceQueryImageEx(
  511. IN OUT POC_MANAGER OcManager,
  512. IN LONG ComponentId,
  513. IN LPCTSTR Subcomponent,
  514. IN SubComponentInfo WhichImage,
  515. IN UINT DesiredWidth,
  516. IN UINT DesiredHeight
  517. );
  518. VOID
  519. OcInterfaceWizardCreated(
  520. IN OUT POC_MANAGER OcManager,
  521. IN LONG ComponentId,
  522. IN HWND DialogHandle
  523. );
  524. UINT
  525. OcInterfaceRequestPages(
  526. IN OUT POC_MANAGER OcManager,
  527. IN LONG ComponentId,
  528. IN WizardPagesType WhichPages,
  529. OUT PSETUP_REQUEST_PAGES *RequestPages
  530. );
  531. BOOL
  532. OcInterfaceQuerySkipPage(
  533. IN OUT POC_MANAGER OcManager,
  534. IN LONG ComponentId,
  535. IN OcManagerPage WhichPage
  536. );
  537. BOOL
  538. OcInterfaceNeedMedia(
  539. IN OUT POC_MANAGER OcManager,
  540. IN LONG ComponentId,
  541. IN PSOURCE_MEDIA SourceMedia,
  542. OUT LPTSTR NewPath
  543. );
  544. BOOL
  545. OcInterfaceFileBusy(
  546. IN OUT POC_MANAGER OcManager,
  547. IN LONG ComponentId,
  548. IN PFILEPATHS FIlePaths,
  549. OUT LPTSTR NewPath
  550. );
  551. BOOL
  552. OcInterfaceQueryChangeSelState(
  553. IN OUT POC_MANAGER OcManager,
  554. IN LONG ComponentId,
  555. IN LPCTSTR Subcomponent,
  556. IN BOOL Selected,
  557. IN UINT Flags
  558. );
  559. UINT
  560. OcInterfaceCalcDiskSpace(
  561. IN OUT POC_MANAGER OcManager,
  562. IN LONG ComponentId,
  563. IN LPCTSTR Subcomponent,
  564. IN HDSKSPC DiskSpaceList,
  565. IN BOOL AddingToList
  566. );
  567. UINT
  568. OcInterfaceQueueFileOps(
  569. IN OUT POC_MANAGER OcManager,
  570. IN LONG ComponentId,
  571. IN LPCTSTR Subcomponent,
  572. IN HSPFILEQ FileQueue
  573. );
  574. UINT
  575. OcInterfaceQueryStepCount(
  576. IN OUT POC_MANAGER OcManager,
  577. IN LONG ComponentId,
  578. IN LPCTSTR Subcomponent,
  579. OUT PUINT StepCount
  580. );
  581. UINT
  582. OcInterfaceCompleteInstallation(
  583. IN OUT POC_MANAGER OcManager,
  584. IN LONG ComponentId,
  585. IN LPCTSTR Subcomponent,
  586. IN BOOL PreQueueCommit
  587. );
  588. VOID
  589. OcInterfaceCleanup(
  590. IN OUT POC_MANAGER OcManager,
  591. IN LONG ComponentId
  592. );
  593. DWORD
  594. StandAloneSetupAppInterfaceRoutine(
  595. IN LPCVOID ComponentId,
  596. IN LPCVOID SubcomponentId,
  597. IN UINT Function,
  598. IN UINT_PTR Param1,
  599. IN OUT PVOID Param2
  600. );
  601. //
  602. // Persistent state fetch/store
  603. //
  604. BOOL
  605. pOcFetchInstallStates(
  606. IN POC_MANAGER OcManager
  607. );
  608. BOOL
  609. pOcRememberInstallStates(
  610. IN POC_MANAGER OcManager
  611. );
  612. BOOL
  613. pOcSetOneInstallState(
  614. IN POC_MANAGER OcManager,
  615. IN LONG StringId
  616. );
  617. BOOL
  618. pOcRemoveComponent(
  619. IN POC_MANAGER OcManager,
  620. IN LONG ComponentId,
  621. IN DWORD PhaseId
  622. );
  623. BOOL
  624. pOcComponentWasRemoved(
  625. IN POC_MANAGER OcManager,
  626. IN LONG ComponentId
  627. );
  628. BOOL
  629. pOcHelperReportExternalError(
  630. IN POC_MANAGER OcManager,
  631. IN LONG ComponentId,
  632. IN LONG SubcomponentId, OPTIONAL
  633. IN DWORD_PTR MessageId,
  634. IN DWORD Flags,
  635. ...
  636. );
  637. //
  638. // Use this flag to call OcHelperReportExternalError and use
  639. // a Message ID defined in the OCManage.dll
  640. //
  641. #define ERRFLG_OCM_MESSAGE 0x80000000
  642. BOOL
  643. OcHelperClearExternalError (
  644. IN POC_MANAGER OcManager,
  645. IN LONG ComponentId,
  646. IN LONG SubcomponentId OPTIONAL
  647. );
  648. //
  649. // Debuging stuff
  650. //
  651. #if DBG
  652. #define _OC_DBG
  653. #endif
  654. //
  655. // should not be defined for retail release!!!
  656. //
  657. #if PRERELEASE
  658. #define _OC_DBG
  659. #endif
  660. VOID
  661. _ErrOut(
  662. IN LPCTSTR Format,
  663. ...
  664. );
  665. VOID
  666. _WrnOut(
  667. IN LPCTSTR Format,
  668. ...
  669. );
  670. VOID
  671. _TrcOut(
  672. IN LPCTSTR Format,
  673. ...
  674. );
  675. #define ERR(x) _ErrOut x
  676. //
  677. // these guys are switched out in a free build.
  678. //
  679. #ifdef _OC_DBG
  680. #define TRACE(x) _TrcOut x
  681. #define WRN(x) _WrnOut x
  682. #define DBGOUT(x) \
  683. if (gDebugLevel >= 100) _TrcOut x
  684. #else
  685. #define TRACE(x)
  686. #define WRN(x)
  687. #define DBGOUT(x)
  688. #endif
  689. // Normally a call to tmbox is for debug tracing and all such calls
  690. // should be removed before checking in. However, if called through
  691. // the mbox() macro, this indicates the call is meant to ship.
  692. DWORD
  693. tmbox(
  694. LPCTSTR fmt,
  695. ...
  696. );
  697. #define mbox tmbox