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.

1942 lines
49 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ocinterf.c
  5. Abstract:
  6. Routines to interface with optional components via the OC Manager
  7. interface routine exported from the component's installation DLL.
  8. Author:
  9. Ted Miller (tedm) 16-Sep-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #ifdef DEBUGPERFTRACE
  15. #define RES_BUFFER 512
  16. #define MAX_LOGLINE 1024
  17. #define EOL_LENGTH 3
  18. #define BUFFER_SIZE 64*1024
  19. VOID
  20. DebugLogPerf(
  21. VOID
  22. )
  23. {
  24. LPTSTR lpProcessName;
  25. NTSTATUS Status;
  26. ULONG Offset1;
  27. PUCHAR CurrentBuffer;
  28. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  29. LPTSTR lpTemp;//[RES_BUFFER];
  30. HMODULE hNtDll;
  31. LONG_PTR (*NtQSI)(); // Ptr to NtQuerySystemInformation
  32. HANDLE hProcessName;
  33. TCHAR szLogLine[MAX_LOGLINE+EOL_LENGTH];
  34. LPCTSTR szResBuf = TEXT("%7i%20ws->%10u%10u%10u%10u%10u%10u%10u\r\n");
  35. if ((hNtDll = LoadLibrary(TEXT("NTDLL.DLL"))) == NULL)
  36. {
  37. return;
  38. }
  39. NtQSI = GetProcAddress(hNtDll, "NtQuerySystemInformation" );
  40. if( NtQSI == NULL )
  41. {
  42. FreeLibrary(hNtDll);
  43. return;
  44. }
  45. //header for mem area
  46. TRACE (( TEXT("Proc ID Proc.Name Wrkng.Set PagedPool NonPgdPl Pagefile Commit Handles Threads\n") ));
  47. /* grab all process information */
  48. /* log line format, all comma delimited,CR delimited:
  49. pid,name,WorkingSetSize,QuotaPagedPoolUsage,QuotaNonPagedPoolUsage,PagefileUsage,CommitCharge<CR>
  50. log all process information */
  51. /* from pmon */
  52. Offset1 = 0;
  53. if ((CurrentBuffer = VirtualAlloc (NULL,
  54. BUFFER_SIZE,
  55. MEM_COMMIT,
  56. PAGE_READWRITE)) != NULL)
  57. {
  58. /* from memsnap */
  59. /* get commit charge */
  60. /* get all of the status information */
  61. Status = (NTSTATUS)(*NtQSI)(
  62. SystemProcessInformation,
  63. CurrentBuffer,
  64. BUFFER_SIZE,
  65. NULL );
  66. if (NT_SUCCESS(Status)){
  67. for (;;)
  68. {
  69. /* get process info from buffer */
  70. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&CurrentBuffer[Offset1];
  71. Offset1 += ProcessInfo->NextEntryOffset;
  72. if (ProcessInfo->ImageName.Buffer) {
  73. if (!lstrcmpi(ProcessInfo->ImageName.Buffer, TEXT("sysocmgr.exe")) ||
  74. !lstrcmpi(ProcessInfo->ImageName.Buffer, TEXT("setup.exe")) ) {
  75. wsprintf(szLogLine,
  76. szResBuf,
  77. ProcessInfo->UniqueProcessId,
  78. ProcessInfo->ImageName.Buffer,
  79. ProcessInfo->WorkingSetSize / 1024,
  80. ProcessInfo->QuotaPagedPoolUsage / 1024,
  81. ProcessInfo->QuotaNonPagedPoolUsage / 1024,
  82. ProcessInfo->PagefileUsage / 1024,
  83. ProcessInfo->PrivatePageCount / 1024,
  84. ProcessInfo->HandleCount,
  85. ProcessInfo->NumberOfThreads );
  86. TRACE(( szLogLine ));
  87. }
  88. }
  89. #if 0
  90. // if buffer is null then it's idle process or unknown
  91. if (!ProcessInfo->ImageName.Buffer)
  92. {
  93. if (ProcessInfo->UniqueProcessId == (HANDLE)0)
  94. lpTemp = TEXT("Idle");
  95. else
  96. lpTemp = TEXT("Unknown");
  97. wsprintf(szLogLine,
  98. szResBuf,
  99. ProcessInfo->UniqueProcessId,
  100. lpTemp,
  101. ProcessInfo->WorkingSetSize / 1024,
  102. ProcessInfo->QuotaPagedPoolUsage / 1024,
  103. ProcessInfo->QuotaNonPagedPoolUsage / 1024,
  104. ProcessInfo->PagefileUsage / 1024,
  105. ProcessInfo->PrivatePageCount / 1024,
  106. ProcessInfo->HandleCount,
  107. ProcessInfo->NumberOfThreads );
  108. }
  109. else
  110. {
  111. wsprintf(szLogLine,
  112. szResBuf,
  113. ProcessInfo->UniqueProcessId,
  114. ProcessInfo->ImageName.Buffer,
  115. ProcessInfo->WorkingSetSize / 1024,
  116. ProcessInfo->QuotaPagedPoolUsage / 1024,
  117. ProcessInfo->QuotaNonPagedPoolUsage / 1024,
  118. ProcessInfo->PagefileUsage / 1024,
  119. ProcessInfo->PrivatePageCount / 1024,
  120. ProcessInfo->HandleCount,
  121. ProcessInfo->NumberOfThreads );
  122. }
  123. TRACE(( szLogLine ));
  124. #endif
  125. if (ProcessInfo->NextEntryOffset == 0)
  126. {
  127. break;
  128. }
  129. }
  130. //status failed
  131. }
  132. /* free mem */
  133. VirtualFree(CurrentBuffer,0,MEM_RELEASE);
  134. }
  135. //tail for mem area
  136. TRACE(( TEXT("\n") ));
  137. FreeLibrary(hNtDll);
  138. }
  139. #endif
  140. #ifdef UNICODE
  141. NTSYSAPI
  142. BOOLEAN
  143. NTAPI
  144. RtlValidateProcessHeaps (
  145. VOID
  146. );
  147. #define ASSERT_HEAP_IS_VALID(_x_) sapiAssert(RtlValidateProcessHeaps && _x_)
  148. #else
  149. #define ASSERT_HEAP_IS_VALID(_x_)
  150. #endif
  151. DWORD gecode;
  152. PVOID geaddr;
  153. DWORD
  154. efilter(
  155. LPEXCEPTION_POINTERS ep
  156. )
  157. /*++
  158. Routine Description:
  159. handles exception during calls to oc component routines
  160. Arguments:
  161. ep - exception information
  162. Return Value:
  163. always 1 - execute the handler
  164. --*/
  165. {
  166. gecode = ep->ExceptionRecord->ExceptionCode;
  167. geaddr = ep->ExceptionRecord->ExceptionAddress;
  168. RtlUnhandledExceptionFilter( ep);
  169. return EXCEPTION_EXECUTE_HANDLER;
  170. }
  171. BOOL
  172. pOcInterface(
  173. IN POC_MANAGER OcManager,
  174. OUT PUINT Result,
  175. IN LONG ComponentId,
  176. IN LPCTSTR Subcomponent, OPTIONAL
  177. IN UINT Function,
  178. IN UINT_PTR Param1,
  179. IN PVOID Param2
  180. )
  181. /*++
  182. Routine Description:
  183. Perform the actual call to the OC interface routine.
  184. Converts Unicode component/subcomponent names to ANSI if needed.
  185. Arguments:
  186. OcManager - supplies OC Manager context structure.
  187. Result -
  188. ComponentId -
  189. Remaining arguments specify parameters to be passed directly to
  190. the interface.
  191. Return Value:
  192. TRUE if the interface routine was successfully called and returned
  193. without faulting. LastError() is preserved in this case.
  194. FALSE otherwise.
  195. --*/
  196. {
  197. LONG OldComponentStringId;
  198. BOOL b;
  199. LPCTSTR Component;
  200. OPTIONAL_COMPONENT Oc;
  201. LPCVOID comp,subcomp;
  202. #ifdef UNICODE
  203. CHAR AnsiComp[500];
  204. CHAR AnsiSub[500];
  205. #endif
  206. //
  207. // Get the name of the component and the optional component data
  208. // from the string table.
  209. //
  210. // Though it would be strange, it is possible that this will fail,
  211. // so we do a little checking for robustness.
  212. //
  213. Component = pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId);
  214. b = pSetupStringTableGetExtraData(OcManager->ComponentStringTable,ComponentId,&Oc,sizeof(OPTIONAL_COMPONENT));
  215. if(!Component || !b || !Oc.InstallationRoutine) {
  216. return(FALSE);
  217. }
  218. OldComponentStringId = OcManager->CurrentComponentStringId;
  219. OcManager->CurrentComponentStringId = ComponentId;
  220. #ifdef UNICODE
  221. //
  222. // If necessary, convert component name and subcomponent name to ANSI.
  223. //
  224. if((Function != OC_PREINITIALIZE) && (Oc.Flags & OCFLAG_ANSI)) {
  225. WideCharToMultiByte(CP_ACP,0,Component,-1,AnsiComp,sizeof(AnsiComp),NULL,NULL);
  226. comp = AnsiComp;
  227. if(Subcomponent) {
  228. WideCharToMultiByte(CP_ACP,0,Subcomponent,-1,AnsiSub,sizeof(AnsiSub),NULL,NULL);
  229. subcomp = AnsiSub;
  230. } else {
  231. subcomp = NULL;
  232. }
  233. } else
  234. #endif
  235. {
  236. comp = Component;
  237. subcomp = Subcomponent;
  238. }
  239. *Result = CallComponent(OcManager, &Oc, comp, subcomp, Function, Param1, Param2);
  240. b = (*Result == ERROR_CALL_COMPONENT) ? FALSE : TRUE;
  241. OcManager->CurrentComponentStringId = OldComponentStringId;
  242. return b;
  243. }
  244. DWORD
  245. CallComponent(
  246. IN POC_MANAGER OcManager,
  247. IN POPTIONAL_COMPONENT Oc,
  248. IN LPCVOID ComponentId,
  249. IN LPCVOID SubcomponentId,
  250. IN UINT Function,
  251. IN UINT_PTR Param1,
  252. IN OUT PVOID Param2
  253. )
  254. /*++
  255. Routine Description:
  256. Calls a component's interface routine with a try-except block.
  257. Arguments:
  258. Oc - supplies a pointer to the component description structure
  259. ComponentId - string description of the component
  260. SubcomponentId - string description of the subcomponent
  261. Function - notification being sent to the component
  262. Param1 - differs with each function
  263. Param2 - differs with each function
  264. Return Value:
  265. Component return value. Meaning differs with each function.
  266. --*/
  267. {
  268. DWORD result;
  269. BOOL exception = FALSE;
  270. TCHAR *comp;
  271. LONG id;
  272. int i;
  273. #ifdef DEBUGPERFTRACE
  274. DWORD tick;
  275. #endif
  276. // don't call dead components
  277. id = OcManager->CurrentComponentStringId;
  278. sapiAssert(id > 0);
  279. if (pOcComponentWasRemoved(OcManager, id))
  280. return NO_ERROR;
  281. sapiAssert(Oc->InstallationRoutine);
  282. #ifdef PRERELEASE
  283. #ifdef DBG
  284. ASSERT_HEAP_IS_VALID("The process heap was corrupted before calling the component.");
  285. #if 0
  286. if (FTestForOutstandingCoInits() != S_OK) {
  287. sapiAssert( FALSE && "There is an unbalanced call to CoInitialize()");
  288. }
  289. #endif
  290. #endif
  291. #endif
  292. #ifdef DEBUGPERFTRACE
  293. TRACE(( TEXT("before calling component\n") ));
  294. DebugLogPerf();
  295. tick = GetTickCount();
  296. TRACE(( TEXT("calling component, %d:\n"), tick ));
  297. #endif
  298. try {
  299. result = Oc->InstallationRoutine(ComponentId, SubcomponentId, Function, Param1, Param2);
  300. } except(efilter(GetExceptionInformation())) {
  301. exception = TRUE;
  302. }
  303. #ifdef DEBUGPERFTRACE
  304. TRACE(( TEXT("after calling component, %d (time = %d)\n"),GetTickCount(), GetTickCount() - tick));
  305. DebugLogPerf();
  306. #endif
  307. #ifdef PRERELEASE
  308. #ifdef DBG
  309. ASSERT_HEAP_IS_VALID("The process heap was corrupted after calling the component. If you did not get an assertion before calling the component, this indicates an error in the component. Click yes and get a stack trace to detect the component.");
  310. #if 0
  311. if (FTestForOutstandingCoInits() != S_OK) {
  312. sapiAssert( FALSE && "There is an unbalanced call to CoInitialize()");
  313. }
  314. #endif
  315. #endif
  316. #endif
  317. if (exception) {
  318. #ifdef UNICODE
  319. if (Oc->Flags & OCFLAG_ANSI)
  320. comp = pSetupAnsiToUnicode(ComponentId);
  321. else
  322. #endif
  323. comp = (TCHAR *)ComponentId;
  324. _LogError(
  325. OcManager,
  326. OcErrLevError|MB_ICONEXCLAMATION|MB_OK,
  327. MSG_OC_EXCEPTION_IN_COMPONENT,
  328. comp,
  329. Oc->InstallationRoutine,
  330. Function,
  331. Param1,
  332. Param2,
  333. gecode,
  334. geaddr
  335. );
  336. #ifdef UNICODE
  337. if (Oc->Flags & OCFLAG_ANSI)
  338. pSetupFree(comp);
  339. #endif
  340. sapiAssert(0);
  341. pOcRemoveComponent(OcManager, id, pidCallComponent);
  342. result = ERROR_CALL_COMPONENT;
  343. }
  344. return result;
  345. }
  346. UINT
  347. OcInterfacePreinitialize(
  348. IN OUT POC_MANAGER OcManager,
  349. IN LONG ComponentId
  350. )
  351. /*++
  352. Routine Description:
  353. Sets up and calls the OC_PREINITIALIZE function for a
  354. given component.
  355. Arguments:
  356. OcManager - supplies a pointer to the context data structure
  357. for the OC Manager.
  358. ComponentId - supplies the string id of the component whose
  359. interface routine is to be called. This is for a string in
  360. the ComponentStringTable string table (a handle to which
  361. is in the OcManager structure).
  362. Return Value:
  363. Flags bitfield (OCFLAG_xxx) for the component. 0 means error.
  364. --*/
  365. {
  366. BOOL b;
  367. UINT FlagsIn;
  368. UINT FlagsOut;
  369. OPTIONAL_COMPONENT Oc;
  370. #ifdef UNICODE
  371. CHAR AnsiName[250];
  372. LPCWSTR UnicodeName;
  373. #endif
  374. TRACE((
  375. TEXT("OCM: OC_PREINITIALIZE Component %s..."),
  376. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  377. ));
  378. //
  379. // Set up input flags.
  380. //
  381. FlagsIn = OCFLAG_ANSI;
  382. #ifdef UNICODE
  383. FlagsIn |= OCFLAG_UNICODE;
  384. UnicodeName = pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId);
  385. if(!UnicodeName) {
  386. return(0);
  387. }
  388. WideCharToMultiByte(CP_ACP,0,UnicodeName,-1,AnsiName,sizeof(AnsiName),NULL,NULL);
  389. #endif
  390. b = pOcInterface(
  391. OcManager,
  392. &FlagsOut,
  393. ComponentId,
  394. #ifdef UNICODE
  395. (LPCTSTR)AnsiName,
  396. #else
  397. NULL,
  398. #endif
  399. OC_PREINITIALIZE,
  400. FlagsIn,
  401. 0
  402. );
  403. TRACE(( TEXT("...%x (retval %s)\n"), FlagsOut, b ? TEXT("TRUE") : TEXT("FALSE") ));
  404. if(!b) {
  405. goto error;
  406. }
  407. //
  408. // If neither flag is set, error.
  409. //
  410. if(!(FlagsOut & (OCFLAG_ANSI | OCFLAG_UNICODE))) {
  411. goto error;
  412. }
  413. #ifdef UNICODE
  414. //
  415. // Use Unicode if it is supported by the component.
  416. //
  417. if(FlagsOut & OCFLAG_UNICODE) {
  418. FlagsOut = OCFLAG_UNICODE;
  419. }
  420. #else
  421. //
  422. // If ANSI is not supported then we've got a problem.
  423. //
  424. if(FlagsOut & OCFLAG_ANSI) {
  425. FlagsOut = OCFLAG_ANSI;
  426. } else {
  427. goto error;
  428. }
  429. #endif
  430. goto eof;
  431. error:
  432. pOcRemoveComponent(OcManager, ComponentId, pidPreInit);
  433. FlagsOut = 0;
  434. eof:
  435. return(FlagsOut);
  436. }
  437. UINT
  438. OcInterfaceInitComponent(
  439. IN OUT POC_MANAGER OcManager,
  440. IN LONG ComponentId
  441. )
  442. /*++
  443. Routine Description:
  444. Sets up and calls the OC_INIT_COMPONENT interface function for a
  445. given component.
  446. Arguments:
  447. OcManager - supplies a pointer to the context data structure
  448. for the OC Manager.
  449. ComponentId - supplies the string id of the component whose
  450. interface routine is to be called. This is for a string in
  451. the ComponentStringTable string table (a handle to which
  452. is in the OcManager structure).
  453. Return Value:
  454. Win32 error indicating value returned by the component.
  455. --*/
  456. {
  457. OPTIONAL_COMPONENT Oc;
  458. OC_INF OcInf;
  459. BOOL b;
  460. SETUP_INIT_COMPONENTA InitDataA;
  461. #ifdef UNICODE
  462. SETUP_INIT_COMPONENTW InitDataW;
  463. #endif
  464. UINT u;
  465. PUINT pu;
  466. PHELPER_CONTEXT HelperContext;
  467. #ifdef UNICODE
  468. ZeroMemory( &InitDataW, sizeof( InitDataW ));
  469. #else
  470. ZeroMemory( &InitDataA, sizeof( InitDataA ));
  471. #endif
  472. TRACE((
  473. TEXT("OCM: OC_INIT_COMPONENT Component %s..."),
  474. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  475. ));
  476. HelperContext = pSetupMalloc(sizeof(HELPER_CONTEXT));
  477. if(!HelperContext) {
  478. return(ERROR_NOT_ENOUGH_MEMORY);
  479. }
  480. HelperContext->OcManager = OcManager;
  481. HelperContext->ComponentStringId = ComponentId;
  482. //
  483. // Fetch the optional component data.
  484. //
  485. b = pSetupStringTableGetExtraData(
  486. OcManager->ComponentStringTable,
  487. ComponentId,
  488. &Oc,
  489. sizeof(OPTIONAL_COMPONENT)
  490. );
  491. if(b) {
  492. if(Oc.InfStringId == -1) {
  493. OcInf.Handle = NULL;
  494. b = TRUE;
  495. } else {
  496. b = pSetupStringTableGetExtraData(
  497. OcManager->InfListStringTable,
  498. Oc.InfStringId,
  499. &OcInf,
  500. sizeof(OC_INF)
  501. );
  502. }
  503. }
  504. if(!b) {
  505. //
  506. // Strange case, should never get here.
  507. //
  508. pSetupFree(HelperContext);
  509. return(ERROR_INVALID_PARAMETER);
  510. }
  511. //
  512. // Set up the main part of the initialization structure
  513. // and the HelperRoutines table.
  514. //
  515. // Also set up the SetupData part of the initialization structure.
  516. // This is specific to the environment in which the OC Manager
  517. // common library is linked, so we call out to a routine that
  518. // lives elsewhere to do this part.
  519. //
  520. #ifdef UNICODE
  521. if(Oc.Flags & OCFLAG_UNICODE) {
  522. InitDataW.HelperRoutines = HelperRoutinesW;
  523. InitDataW.OCManagerVersion = OCMANAGER_VERSION;
  524. InitDataW.ComponentVersion = 0;
  525. InitDataW.OCInfHandle = OcManager->MasterOcInf;
  526. InitDataW.ComponentInfHandle = OcInf.Handle;
  527. InitDataW.HelperRoutines.OcManagerContext = HelperContext;
  528. OcFillInSetupDataW(&InitDataW.SetupData);
  529. pu = &InitDataW.ComponentVersion;
  530. b = pOcInterface(OcManager,&u,ComponentId,NULL,OC_INIT_COMPONENT,0,&InitDataW);
  531. } else
  532. #endif
  533. {
  534. InitDataA.HelperRoutines = HelperRoutinesA;
  535. InitDataA.OCManagerVersion = OCMANAGER_VERSION;
  536. InitDataA.ComponentVersion = 0;
  537. InitDataA.OCInfHandle = OcManager->MasterOcInf;
  538. InitDataA.ComponentInfHandle = OcInf.Handle;
  539. InitDataA.HelperRoutines.OcManagerContext = HelperContext;
  540. OcFillInSetupDataA(&InitDataA.SetupData);
  541. pu = &InitDataA.ComponentVersion;
  542. b = pOcInterface(OcManager,&u,ComponentId,NULL,OC_INIT_COMPONENT,0,&InitDataA);
  543. }
  544. TRACE(( TEXT("...returns %d, expect version %x\n"), u, *pu ));
  545. if(b) {
  546. if(u == NO_ERROR) {
  547. //
  548. // Remember the version of the OC Manager that the
  549. // component expects to be dealing with.
  550. //
  551. Oc.ExpectedVersion = *pu;
  552. Oc.HelperContext = HelperContext;
  553. pSetupStringTableSetExtraData(
  554. OcManager->ComponentStringTable,
  555. ComponentId,
  556. &Oc,
  557. sizeof(OPTIONAL_COMPONENT)
  558. );
  559. }
  560. } else {
  561. u = ERROR_INVALID_PARAMETER;
  562. }
  563. if(u != NO_ERROR) {
  564. pSetupFree(HelperContext);
  565. pOcRemoveComponent(OcManager, ComponentId, pidInitComponent);
  566. }
  567. return(u);
  568. }
  569. UINT
  570. OcInterfaceExtraRoutines(
  571. IN OUT POC_MANAGER OcManager,
  572. IN LONG ComponentId
  573. )
  574. /*++
  575. Routine Description:
  576. Sets up and calls the OC_EXTRA_ROUTINES interface function for a
  577. given component.
  578. Arguments:
  579. OcManager - supplies a pointer to the context data structure
  580. for the OC Manager.
  581. ComponentId - supplies the string id of the component whose
  582. interface routine is to be called. This is for a string in
  583. the ComponentStringTable string table (a handle to which
  584. is in the OcManager structure).
  585. Return Value:
  586. Win32 error indicating value returned by the component.
  587. --*/
  588. {
  589. BOOL b;
  590. UINT u;
  591. PVOID param2;
  592. OPTIONAL_COMPONENT Oc;
  593. TRACE((
  594. TEXT("OC: OC_EXTRA_ROUTINES Component %s\n"),
  595. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  596. ));
  597. //
  598. // Fetch the optional component data.
  599. //
  600. b = pSetupStringTableGetExtraData(
  601. OcManager->ComponentStringTable,
  602. ComponentId,
  603. &Oc,
  604. sizeof(OPTIONAL_COMPONENT)
  605. );
  606. if(!b) {
  607. //
  608. // Strange case, should never get here.
  609. //
  610. return ERROR_INVALID_PARAMETER;
  611. }
  612. #ifdef UNICODE
  613. if (Oc.Flags & OCFLAG_UNICODE)
  614. b = pOcInterface(OcManager, &u, ComponentId, NULL, OC_EXTRA_ROUTINES, 0, &ExtraRoutinesW);
  615. else
  616. #endif
  617. b = pOcInterface(OcManager, &u, ComponentId, NULL, OC_EXTRA_ROUTINES, 0, &ExtraRoutinesA);
  618. TRACE(( TEXT("...returns %d (retval %s)\n"),
  619. u,
  620. b ? TEXT("TRUE") : TEXT("FALSE") ));
  621. if (!b)
  622. u = ERROR_INVALID_PARAMETER;
  623. if(u != NO_ERROR)
  624. pOcRemoveComponent(OcManager, ComponentId, pidExtraRoutines);
  625. return u;
  626. }
  627. SubComponentState
  628. OcInterfaceQueryState(
  629. IN OUT POC_MANAGER OcManager,
  630. IN LONG ComponentId,
  631. IN LPCTSTR Subcomponent,
  632. IN UINT WhichState
  633. )
  634. /*++
  635. Routine Description:
  636. Sets up and calls OC_QUERY_STATE interface routine.
  637. Arguments:
  638. OcManager - supplies oc manager context
  639. ComponentId - supplies the string id for the top-level component
  640. whose subcomponent is being detected/queried
  641. Subcomponent - supplies the name of the subcomponent whose
  642. state is to be detected/queried.
  643. WhichState - one of OCSELSTATETYPE_ORIGINAL or OCSELSTATETYPE_CURRENT.
  644. Return Value:
  645. Member of the SubComponentState enum indicating what to do.
  646. If an error occurs, SubcompUseOcManagerDefault will be returned.
  647. There is no error return.
  648. --*/
  649. {
  650. SubComponentState s;
  651. TRACE((
  652. TEXT("OCM: OC_QUERY_STATE Comp(%s) Sub(%s)"),
  653. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  654. Subcomponent == NULL ? TEXT("NULL") : Subcomponent
  655. ));
  656. if(pOcInterface(OcManager,(PUINT)&s,ComponentId,Subcomponent,OC_QUERY_STATE,WhichState,0)) {
  657. TRACE(( TEXT("...returns TRUE (%d state)\n"), s ));
  658. if((s != SubcompOn) && (s != SubcompOff)) {
  659. s = SubcompUseOcManagerDefault;
  660. }
  661. } else {
  662. TRACE(( TEXT("...returns FALSE\n") ));
  663. s = SubcompUseOcManagerDefault;
  664. }
  665. return(s);
  666. }
  667. BOOL
  668. OcInterfaceSetLanguage(
  669. IN OUT POC_MANAGER OcManager,
  670. IN LONG ComponentId,
  671. IN WORD LanguageId
  672. )
  673. /*++
  674. Routine Description:
  675. Sets up and calls the OC_SET_LANGUAGE interface function for a
  676. given component.
  677. Arguments:
  678. OcManager - supplies a pointer to the context data structure
  679. for the OC Manager.
  680. ComponentId - supplies the string id of the component whose
  681. interface routine is to be called. This is for a string in
  682. the ComponentStringTable string table (a handle to which
  683. is in the OcManager structure).
  684. LanguageId - supplies the Win32 language id to pass to the component.
  685. Return Value:
  686. TRUE if the component indicated it could support the language.
  687. FALSE otherwise.
  688. --*/
  689. {
  690. LPCTSTR p;
  691. BOOL b;
  692. BOOL Result = FALSE;
  693. TRACE((
  694. TEXT("OCM: OC_SET_LANGUAGE Comp(%s)LanguageId %d..."),
  695. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  696. LanguageId
  697. ));
  698. b = pOcInterface(OcManager,&Result,ComponentId,NULL,OC_SET_LANGUAGE,LanguageId,NULL);
  699. TRACE(( TEXT("...returns %d (retval %s)\n"),
  700. Result ? TEXT("TRUE") : TEXT("FALSE"),
  701. b ? TEXT("TRUE") : TEXT("FALSE") ));
  702. if(!b) {
  703. Result = FALSE;
  704. }
  705. return(Result);
  706. }
  707. HBITMAP
  708. OcInterfaceQueryImage(
  709. IN OUT POC_MANAGER OcManager,
  710. IN LONG ComponentId,
  711. IN LPCTSTR Subcomponent,
  712. IN SubComponentInfo WhichImage,
  713. IN UINT DesiredWidth,
  714. IN UINT DesiredHeight
  715. )
  716. /*++
  717. Routine Description:
  718. Sets up and calls the OC_QUERY_IMAGE interface function for a
  719. given component.
  720. Arguments:
  721. OcManager - supplies a pointer to the context data structure
  722. for the OC Manager.
  723. ComponentId - supplies the string id of the component whose
  724. interface routine is to be called. This is for a string in
  725. the ComponentStringTable string table (a handle to which
  726. is in the OcManager structure).
  727. Subcomponent - supplies the name of the subcomponent for which
  728. to request the image.
  729. WhichImage - specifies which image is desired.
  730. DesiredWidth - specifies desired width, in pixels, of the bitmap.
  731. DesiredHeight - specifies desired height, in pixels, of the bitmap.
  732. Return Value:
  733. GDI handle to the bitmap as returned by the component,
  734. or NULL if an error occurred.
  735. --*/
  736. {
  737. LPCTSTR p;
  738. BOOL b;
  739. HBITMAP Bitmap = NULL;
  740. TRACE((
  741. TEXT("OCM: OC_QUERY_IMAGE Comp(%s) Sub(%s)..."),
  742. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  743. Subcomponent == NULL ? TEXT("NULL") : Subcomponent
  744. ));
  745. b = pOcInterface(
  746. OcManager,
  747. (PUINT)&Bitmap,
  748. ComponentId,
  749. Subcomponent,
  750. OC_QUERY_IMAGE,
  751. WhichImage,
  752. LongToPtr(MAKELONG(DesiredWidth,DesiredHeight))
  753. );
  754. TRACE(( TEXT("...returns %s, (retval 0x%08x)\n"),
  755. b ? TEXT("TRUE") : TEXT("FALSE"),
  756. (ULONG_PTR)Bitmap ));
  757. if(!b) {
  758. Bitmap = NULL;
  759. }
  760. return(Bitmap);
  761. }
  762. HBITMAP
  763. OcInterfaceQueryImageEx(
  764. IN OUT POC_MANAGER OcManager,
  765. IN LONG ComponentId,
  766. IN LPCTSTR Subcomponent,
  767. IN SubComponentInfo WhichImage,
  768. IN UINT DesiredWidth,
  769. IN UINT DesiredHeight
  770. )
  771. /*++
  772. Routine Description:
  773. Sets up and calls the OC_QUERY_IMAGE interface function for a
  774. given component.
  775. Arguments:
  776. OcManager - supplies a pointer to the context data structure
  777. for the OC Manager.
  778. ComponentId - supplies the string id of the component whose
  779. interface routine is to be called. This is for a string in
  780. the ComponentStringTable string table (a handle to which
  781. is in the OcManager structure).
  782. Subcomponent - supplies the name of the subcomponent for which
  783. to request the image.
  784. WhichImage - specifies which image is desired.
  785. DesiredWidth - specifies desired width, in pixels, of the bitmap.
  786. DesiredHeight - specifies desired height, in pixels, of the bitmap.
  787. Return Value:
  788. GDI handle to the bitmap as returned by the component,
  789. or NULL if an error occurred.
  790. --*/
  791. {
  792. LPCTSTR p;
  793. BOOL b;
  794. BOOL Result = FALSE;
  795. HBITMAP Bitmap = NULL;
  796. OC_QUERY_IMAGE_INFO QueryImageInfo;
  797. QueryImageInfo.SizeOfStruct = sizeof(QueryImageInfo);
  798. QueryImageInfo.ComponentInfo = WhichImage;
  799. QueryImageInfo.DesiredWidth = DesiredWidth;
  800. QueryImageInfo.DesiredHeight = DesiredHeight;
  801. TRACE((
  802. TEXT("OCM: OC_QUERY_IMAGE_EX Comp(%s) Sub(%s)..."),
  803. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  804. Subcomponent == NULL ? TEXT("NULL") : Subcomponent
  805. ));
  806. b = pOcInterface(
  807. OcManager,
  808. &Result,
  809. ComponentId,
  810. Subcomponent,
  811. OC_QUERY_IMAGE_EX,
  812. (UINT_PTR)&QueryImageInfo,
  813. &Bitmap
  814. );
  815. TRACE(( TEXT("...returns %s, (retval = %s)\n"),
  816. Result ? TEXT("TRUE") : TEXT("FALSE"),
  817. b ? TEXT("TRUE") : TEXT("FALSE") ));
  818. if(!b) {
  819. Bitmap = NULL;
  820. }
  821. return((Result == TRUE) ? Bitmap : NULL);
  822. }
  823. UINT
  824. OcInterfaceRequestPages(
  825. IN OUT POC_MANAGER OcManager,
  826. IN LONG ComponentId,
  827. IN WizardPagesType WhichPages,
  828. OUT PSETUP_REQUEST_PAGES *RequestPages
  829. )
  830. /*++
  831. Routine Description:
  832. Sets up and calls the OC_REQUEST_PAGES interface function for a
  833. given component.
  834. Note that this routine does not enforce any policy regarding whether
  835. the component is *supposed* to be asked for pages, ordering, etc.
  836. The caller is expected to do that.
  837. Arguments:
  838. OcManager - supplies a pointer to the context data structure
  839. for the OC Manager.
  840. ComponentId - supplies the string id of the component whose
  841. interface routine is to be called. This is for a string in
  842. the ComponentStringTable string table (a handle to which
  843. is in the OcManager structure).
  844. WhichPages - specifies which set of pages is to be requested.
  845. RequestPages - on successful return, receives a pointer to
  846. a SETUP_REQUEST_PAGES structure containing a count and handles
  847. for returned pages. The caller can free this structure with
  848. pSetupFree() when it is no longer needed.
  849. Return Value:
  850. Win32 error code indicating outcome.
  851. --*/
  852. {
  853. UINT PageCount;
  854. PSETUP_REQUEST_PAGES pages;
  855. PVOID p;
  856. BOOL b;
  857. UINT ec;
  858. //
  859. // Start with room for 10 pages.
  860. //
  861. #define INITIAL_PAGE_CAPACITY 10
  862. TRACE((
  863. TEXT("OCM: OC_REQUEST_PAGES Component %s..."),
  864. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  865. ));
  866. pages = pSetupMalloc(offsetof(SETUP_REQUEST_PAGES,Pages)
  867. + (INITIAL_PAGE_CAPACITY * sizeof(HPROPSHEETPAGE)));
  868. if(!pages) {
  869. return(ERROR_NOT_ENOUGH_MEMORY);
  870. }
  871. pages->MaxPages = INITIAL_PAGE_CAPACITY;
  872. b = pOcInterface(
  873. OcManager,
  874. &PageCount,
  875. ComponentId,
  876. NULL,
  877. OC_REQUEST_PAGES,
  878. WhichPages,
  879. pages
  880. );
  881. if(b && (PageCount != (UINT)(-1)) && (PageCount > INITIAL_PAGE_CAPACITY)) {
  882. p = pSetupRealloc(
  883. pages,
  884. offsetof(SETUP_REQUEST_PAGES,Pages) + (PageCount * sizeof(HPROPSHEETPAGE))
  885. );
  886. if(p) {
  887. pages = p;
  888. } else {
  889. pSetupFree(pages);
  890. return(ERROR_NOT_ENOUGH_MEMORY);
  891. }
  892. pages->MaxPages = PageCount;
  893. b = pOcInterface(
  894. OcManager,
  895. &PageCount,
  896. ComponentId,
  897. NULL,
  898. OC_REQUEST_PAGES,
  899. WhichPages,
  900. pages
  901. );
  902. }
  903. TRACE(( TEXT("...returns %d pages (retval %s)\n"),
  904. PageCount,
  905. b ? TEXT("TRUE") : TEXT("FALSE") ));
  906. if(!b) {
  907. pSetupFree(pages);
  908. return ERROR_CALL_COMPONENT;
  909. }
  910. if(PageCount == (UINT)(-1)) {
  911. ec = GetLastError();
  912. pSetupFree(pages);
  913. pOcRemoveComponent(OcManager, ComponentId, pidRequestPages);
  914. return(ec);
  915. }
  916. //
  917. // Success. Realloc the array down to its final size and return.
  918. //
  919. p = pSetupRealloc(
  920. pages,
  921. offsetof(SETUP_REQUEST_PAGES,Pages) + (PageCount * sizeof(HPROPSHEETPAGE))
  922. );
  923. if(p) {
  924. pages = p;
  925. pages->MaxPages = PageCount;
  926. *RequestPages = pages;
  927. return(NO_ERROR);
  928. }
  929. pSetupFree(pages);
  930. return(ERROR_NOT_ENOUGH_MEMORY);
  931. }
  932. BOOL
  933. OcInterfaceQuerySkipPage(
  934. IN OUT POC_MANAGER OcManager,
  935. IN LONG ComponentId,
  936. IN OcManagerPage WhichPage
  937. )
  938. /*++
  939. Routine Description:
  940. This routine asks a component dll (identified by a top-level
  941. component's string id) whether it wants to skip displaying
  942. a particular page that is owned by the oc manager.
  943. Arguments:
  944. OcManager - supplies OC Manager context
  945. ComponentId - supplies string id of a top-level component
  946. WhichPage - supplies a value indicating which page oc manager
  947. is asking the component about.
  948. Return Value:
  949. Boolean value indicating whether the component wants to skip
  950. the page.
  951. --*/
  952. {
  953. BOOL Result;
  954. BOOL b;
  955. TRACE((
  956. TEXT("OCM: OC_QUERY_SKIP_PAGE Component %s Page %d..."),
  957. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  958. WhichPage
  959. ));
  960. //
  961. // Send out the notification to the component DLL.
  962. //
  963. b = pOcInterface(
  964. OcManager,
  965. &Result,
  966. ComponentId,
  967. NULL,
  968. OC_QUERY_SKIP_PAGE,
  969. WhichPage,
  970. NULL
  971. );
  972. TRACE(( TEXT("...returns %x (retval %s)\n"),
  973. Result,
  974. b ? TEXT("TRUE") : TEXT("FALSE") ));
  975. if(b) {
  976. b = Result;
  977. } else {
  978. //
  979. // Error calling component, don't skip page.
  980. //
  981. b = FALSE;
  982. }
  983. return(b);
  984. }
  985. BOOL
  986. OcInterfaceNeedMedia(
  987. IN OUT POC_MANAGER OcManager,
  988. IN LONG ComponentId,
  989. IN PSOURCE_MEDIA SourceMedia,
  990. OUT LPTSTR NewPath
  991. )
  992. /*++
  993. Routine Description:
  994. This routine invokes the OC_NEED_MEDIA interface entry point
  995. for a (top-level) component.
  996. Arguments:
  997. OcManager - supplies OC Manager context
  998. ComponentId - supplies string id of top level component
  999. SourceMedia - supplies setupapi source media description
  1000. NewPath - receives path where files on media are to be found
  1001. Return Value:
  1002. Boolean value indicating outcome.
  1003. --*/
  1004. {
  1005. BOOL Result;
  1006. BOOL b;
  1007. TRACE((
  1008. TEXT("OCM: OC_NEED_MEDIA Component %s..."),
  1009. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  1010. ));
  1011. //
  1012. // Send out the notification to the component DLL.
  1013. //
  1014. b = pOcInterface(
  1015. OcManager,
  1016. &Result,
  1017. ComponentId,
  1018. NULL,
  1019. OC_NEED_MEDIA,
  1020. (UINT_PTR)SourceMedia,
  1021. NewPath
  1022. );
  1023. TRACE(( TEXT("...returns %x (retval %s, NewPath %s)\n"),
  1024. Result,
  1025. b ? TEXT("TRUE") : TEXT("FALSE"),
  1026. NewPath ? NewPath : TEXT("NULL")
  1027. ));
  1028. if(b) {
  1029. b = Result;
  1030. }
  1031. return(b);
  1032. }
  1033. BOOL
  1034. OcInterfaceFileBusy(
  1035. IN OUT POC_MANAGER OcManager,
  1036. IN LONG ComponentId,
  1037. IN PFILEPATHS FilePaths,
  1038. OUT LPTSTR NewPath
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This routine invokes the OC_FILE_BUSY interface entry point
  1043. for a (top-level) component.
  1044. Arguments:
  1045. OcManager - supplies OC Manager context
  1046. ComponentId - supplies string id of top level component
  1047. SourceMedia - supplies setupapi source media description
  1048. NewPath - receives path where files on media are to be found
  1049. Return Value:
  1050. Boolean value indicating outcome.
  1051. --*/
  1052. {
  1053. BOOL Result;
  1054. BOOL b;
  1055. TRACE((
  1056. TEXT("OCM: OC_FILE_BUSY Component %s..."),
  1057. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  1058. ));
  1059. //
  1060. // Send out the notification to the component DLL.
  1061. //
  1062. b = pOcInterface(
  1063. OcManager,
  1064. &Result,
  1065. ComponentId,
  1066. NULL,
  1067. OC_FILE_BUSY,
  1068. (UINT_PTR)FilePaths,
  1069. NewPath
  1070. );
  1071. TRACE(( TEXT("...returns %x (retval %s, newpath %s)\n"),
  1072. Result,
  1073. b ? TEXT("TRUE") : TEXT("FALSE"),
  1074. NewPath ? NewPath : TEXT("NULL") ));
  1075. if(b) {
  1076. b = Result;
  1077. }
  1078. return(b);
  1079. }
  1080. BOOL
  1081. OcInterfaceQueryChangeSelState(
  1082. IN OUT POC_MANAGER OcManager,
  1083. IN LONG ComponentId,
  1084. IN LPCTSTR Subcomponent,
  1085. IN BOOL Selected,
  1086. IN UINT Flags
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. Sets up and calls the OC_QUERY_CHANGE_SEL_STATE interface function
  1091. for a given component and subcomponent.
  1092. Arguments:
  1093. OcManager - supplies a pointer to the context data structure
  1094. for the OC Manager.
  1095. ComponentId - supplies the string id of the component whose
  1096. interface routine is to be called. This is for a string in
  1097. the ComponentStringTable string table (a handle to which
  1098. is in the OcManager structure).
  1099. Subcomponent - supplies the name of the subcomponent whose
  1100. selection state is potentially to be changed.
  1101. Selected - if TRUE then the proposed new selection state is
  1102. "selected." If FALSE then the proposed new selection state
  1103. is "unselected."
  1104. Flags - supplies misc flags to be passed to the interface routine
  1105. as param2.
  1106. Return Value:
  1107. TRUE if the new selection state should be accepted.
  1108. --*/
  1109. {
  1110. BOOL b;
  1111. UINT Result;
  1112. TRACE((
  1113. TEXT("OCM: OC_QUERY_CHANGE_SEL_STATE Comp(%s) Sub(%s) State %d..."),
  1114. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  1115. Subcomponent == NULL ? TEXT("NULL") : Subcomponent,
  1116. Selected
  1117. ));
  1118. b = pOcInterface(
  1119. OcManager,
  1120. &Result,
  1121. ComponentId,
  1122. Subcomponent,
  1123. OC_QUERY_CHANGE_SEL_STATE,
  1124. Selected,
  1125. UlongToPtr((Flags & (OCQ_ACTUAL_SELECTION | OCQ_DEPENDENT_SELECTION)))
  1126. );
  1127. TRACE(( TEXT("...returns %x (retval %s)\n"),
  1128. Result,
  1129. b ? TEXT("TRUE") : TEXT("FALSE") ));
  1130. if(!b) {
  1131. //
  1132. // If we can't call the component for some reason,
  1133. // allow the new state.
  1134. //
  1135. Result = TRUE;
  1136. }
  1137. return(Result);
  1138. }
  1139. VOID
  1140. OcInterfaceWizardCreated(
  1141. IN OUT POC_MANAGER OcManager,
  1142. IN LONG ComponentId,
  1143. IN HWND DialogHandle
  1144. )
  1145. /*++
  1146. Routine Description:
  1147. Sets up and calls the OC_WIZARD_CREATED interface function
  1148. for a given component.
  1149. Arguments:
  1150. OcManager - supplies a pointer to the context data structure
  1151. for the OC Manager.
  1152. ComponentId - supplies the string id of the component whose
  1153. interface routine is to be called. This is for a string in
  1154. the ComponentStringTable string table (a handle to which
  1155. is in the OcManager structure).
  1156. DialogHandle - Supplies wizard dialog handle.
  1157. Return Value:
  1158. None.
  1159. --*/
  1160. {
  1161. UINT Result;
  1162. BOOL b;
  1163. TRACE((
  1164. TEXT("OCM: OC_WIZARD_CREATED Component %s..."),
  1165. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  1166. ));
  1167. b = pOcInterface(
  1168. OcManager,
  1169. &Result,
  1170. ComponentId,
  1171. NULL,
  1172. OC_WIZARD_CREATED,
  1173. 0,
  1174. DialogHandle
  1175. );
  1176. TRACE(( TEXT("...returns %x (retval %s)\n"),
  1177. Result,
  1178. b ? TEXT("TRUE") : TEXT("FALSE") ));
  1179. }
  1180. UINT
  1181. OcInterfaceCalcDiskSpace(
  1182. IN OUT POC_MANAGER OcManager,
  1183. IN LONG ComponentId,
  1184. IN LPCTSTR Subcomponent,
  1185. IN HDSKSPC DiskSpaceList,
  1186. IN BOOL AddingToList
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. Sets up and calls the OC_CALC_DISK_SPACE interface function for a
  1191. given component and subcomponent.
  1192. Arguments:
  1193. OcManager - supplies a pointer to the context data structure
  1194. for the OC Manager.
  1195. ComponentId - supplies the string id of the component whose
  1196. interface routine is to be called. This is for a string in
  1197. the ComponentStringTable string table (a handle to which
  1198. is in the OcManager structure).
  1199. Subcomponent - supplies the name of the subcomponent whose files
  1200. are to be added or removed. This may be NULL, such as when
  1201. there is no per-component inf.
  1202. DiskSpaceList - supplies a SETUPAPI disk space list handle.
  1203. AddingToList - if TRUE, the component is being directed to add
  1204. files for the (sub)component. If FALSE, the component is
  1205. being directed to remove files.
  1206. Return Value:
  1207. Win32 error code indicating outcome.
  1208. --*/
  1209. {
  1210. BOOL b;
  1211. UINT Result;
  1212. TRACE((
  1213. TEXT("OCM: OC_CALC_DISK_SPACE Comp(%s) Sub(%s) AddtoList(%s)..."),
  1214. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  1215. Subcomponent == NULL ? TEXT("NULL") : Subcomponent,
  1216. AddingToList ? TEXT("Yes") : TEXT("No")
  1217. ));
  1218. b = pOcInterface(
  1219. OcManager,
  1220. &Result,
  1221. ComponentId,
  1222. Subcomponent,
  1223. OC_CALC_DISK_SPACE,
  1224. AddingToList,
  1225. DiskSpaceList
  1226. );
  1227. TRACE(( TEXT("...returns %x (retval %s)\n"),
  1228. Result,
  1229. b ? TEXT("TRUE") : TEXT("FALSE") ));
  1230. if(!b) {
  1231. pOcRemoveComponent(OcManager, ComponentId, pidCalcDiskSpace);
  1232. Result = ERROR_INVALID_PARAMETER;
  1233. }
  1234. return(Result);
  1235. }
  1236. UINT
  1237. OcInterfaceQueueFileOps(
  1238. IN OUT POC_MANAGER OcManager,
  1239. IN LONG ComponentId,
  1240. IN LPCTSTR Subcomponent,
  1241. IN HSPFILEQ FileQueue
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. Sets up and calls the OC_QUEUE_FILE_OPS interface function for a
  1246. given component and subcomponent.
  1247. Arguments:
  1248. OcManager - supplies a pointer to the context data structure
  1249. for the OC Manager.
  1250. ComponentId - supplies the string id of the component whose
  1251. interface routine is to be called. This is for a string in
  1252. the ComponentStringTable string table (a handle to which
  1253. is in the OcManager structure).
  1254. Subcomponent - supplies the name of the subcomponent whose file ops
  1255. are to be queued. This may be NULL, such as when there is no
  1256. per-component inf.
  1257. FileQueue - supplies a SETUPAPI file queue handle.
  1258. Return Value:
  1259. Win32 error code indicating outcome.
  1260. --*/
  1261. {
  1262. UINT Result;
  1263. TRACE((
  1264. TEXT("OCM: OC_QUEUE_FILE_OPS Comp(%s) Sub(%s)..."),
  1265. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  1266. Subcomponent == NULL ? TEXT("NULL") : Subcomponent
  1267. ));
  1268. if(!pOcInterface(OcManager,&Result,ComponentId,Subcomponent,OC_QUEUE_FILE_OPS,0,FileQueue)) {
  1269. pOcRemoveComponent(OcManager, ComponentId, pidQueueFileOps);
  1270. TRACE(( TEXT("...(returns %x initially) "), Result ));
  1271. Result = ERROR_INVALID_PARAMETER;
  1272. }
  1273. TRACE(( TEXT("...returns %x\n"), Result ));
  1274. return(Result);
  1275. }
  1276. UINT
  1277. OcInterfaceQueryStepCount(
  1278. IN OUT POC_MANAGER OcManager,
  1279. IN LONG ComponentId,
  1280. IN LPCTSTR Subcomponent,
  1281. OUT PUINT StepCount
  1282. )
  1283. /*++
  1284. Routine Description:
  1285. Sets up and calls the OC_QUERY_STEP_COUNT interface function for a
  1286. given component and subcomponent.
  1287. Arguments:
  1288. OcManager - supplies a pointer to the context data structure
  1289. for the OC Manager.
  1290. ComponentId - supplies the string id of the component whose
  1291. interface routine is to be called. This is for a string in
  1292. the ComponentStringTable string table (a handle to which
  1293. is in the OcManager structure).
  1294. Subcomponent - supplies the name of the subcomponent whose step count
  1295. is to be determined. This may be NULL, such as when there is no
  1296. per-component inf.
  1297. StepCount - if the routine returns NO_ERROR then StepCount receives
  1298. the number of steps as returned by the component's interface routine.
  1299. Return Value:
  1300. Win32 error code indicating outcome.
  1301. --*/
  1302. {
  1303. UINT Result;
  1304. TRACE((
  1305. TEXT("OCM: OC_QUERY_STEP_COUNT Comp(%s) Sub(%s)..."),
  1306. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  1307. Subcomponent == NULL ? TEXT("NULL") : Subcomponent
  1308. ));
  1309. if(pOcInterface(OcManager,StepCount,ComponentId,Subcomponent,OC_QUERY_STEP_COUNT,0,0)) {
  1310. if(*StepCount == (UINT)(-1)) {
  1311. Result = GetLastError();
  1312. } else {
  1313. Result = NO_ERROR;
  1314. }
  1315. } else {
  1316. Result = ERROR_INVALID_PARAMETER;
  1317. }
  1318. TRACE(( TEXT("...returns %s (%d steps)\n"),
  1319. Result ? TEXT("TRUE") : TEXT("FALSE"),
  1320. *StepCount ));
  1321. if (Result != NO_ERROR) {
  1322. pOcRemoveComponent(OcManager, ComponentId, pidQueryStepCount);
  1323. }
  1324. return(Result);
  1325. }
  1326. UINT
  1327. OcInterfaceCompleteInstallation(
  1328. IN OUT POC_MANAGER OcManager,
  1329. IN LONG ComponentId,
  1330. IN LPCTSTR Subcomponent,
  1331. IN BOOL PreQueueCommit
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. Sets up and calls the OC_ABOUT_TO_COMMIT_QUEUE or
  1336. OC_COMPLETE_INSTALLATION interface function for a given
  1337. component and subcomponent.
  1338. Arguments:
  1339. OcManager - supplies a pointer to the context data structure
  1340. for the OC Manager.
  1341. ComponentId - supplies the string id of the component whose
  1342. interface routine is to be called. This is for a string in
  1343. the ComponentStringTable string table (a handle to which
  1344. is in the OcManager structure).
  1345. Subcomponent - supplies the name of the subcomponent whose
  1346. installation is to be completed. This may be NULL,
  1347. such as when there is no per-component inf.
  1348. PreQueueCommit - if non-0, then OC_ABOUT_TO_COMMIT_QUEUE is sent.
  1349. If 0, then OC_COMPLETE_INSTALLATION is sent.
  1350. Return Value:
  1351. Win32 error code indicating outcome.
  1352. --*/
  1353. {
  1354. UINT Result;
  1355. BOOL b;
  1356. LPTSTR p;
  1357. TCHAR DisplayText[300],FormatString[200];
  1358. OPTIONAL_COMPONENT Oc;
  1359. HELPER_CONTEXT Helper;
  1360. TRACE((
  1361. TEXT("OCM:%s Comp(%s) Sub(%s)..."),
  1362. PreQueueCommit ? TEXT("OC_ABOUT_TO_COMMIT_QUEUE") : TEXT("OC_COMPLETE_INSTALLATION"),
  1363. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId),
  1364. Subcomponent == NULL ? TEXT("NULL") : Subcomponent
  1365. ));
  1366. //
  1367. // update the installation text for this component
  1368. //
  1369. __try {
  1370. if (pSetupStringTableGetExtraData(
  1371. OcManager->ComponentStringTable,
  1372. ComponentId,
  1373. &Oc,
  1374. sizeof(OPTIONAL_COMPONENT)
  1375. ) && (*Oc.Description != 0)) {
  1376. p = Oc.Description;
  1377. } else if ((p = pSetupStringTableStringFromId(OcManager->ComponentStringTable, ComponentId)) != NULL) {
  1378. } else {
  1379. p = TEXT("Component");
  1380. }
  1381. LoadString(
  1382. MyModuleHandle,
  1383. PreQueueCommit
  1384. ? IDS_CONFIGURE_FORMAT
  1385. : IDS_INSTALL_FORMAT,
  1386. FormatString,
  1387. sizeof(FormatString)/sizeof(TCHAR)
  1388. );
  1389. wsprintf(DisplayText,FormatString,p);
  1390. Helper.OcManager = OcManager;
  1391. Helper.ComponentStringId = ComponentId;
  1392. #ifdef UNICODE
  1393. HelperRoutinesW.SetProgressText(&Helper,DisplayText);
  1394. #else
  1395. HelperRoutinesA.SetProgressText(&Helper,DisplayText);
  1396. #endif
  1397. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1398. ERR(( TEXT("OCM: OcCompleteInstallation exception, ec = 0x%08x\n"), GetExceptionCode() ));
  1399. }
  1400. b = pOcInterface(
  1401. OcManager,
  1402. &Result,
  1403. ComponentId,
  1404. Subcomponent,
  1405. PreQueueCommit ? OC_ABOUT_TO_COMMIT_QUEUE : OC_COMPLETE_INSTALLATION,
  1406. 0,
  1407. 0
  1408. );
  1409. TRACE(( TEXT("...returns %x (retval %s)\n"),
  1410. Result,
  1411. b ? TEXT("TRUE") : TEXT("FALSE") ));
  1412. if(!b) {
  1413. Result = ERROR_INVALID_PARAMETER;
  1414. }
  1415. // Don't shutdown the component if it returns an error.
  1416. // Let them deal with it in OC_QUERY_STATE(SELSTATETYPE_FINAL)
  1417. return(Result);
  1418. }
  1419. VOID
  1420. OcInterfaceCleanup(
  1421. IN OUT POC_MANAGER OcManager,
  1422. IN LONG ComponentId
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. Sets up and calls the OC_CLEANUP interface function for a
  1427. given component, to inform the component that it is about to be unloaded.
  1428. Arguments:
  1429. OcManager - supplies a pointer to the context data structure
  1430. for the OC Manager.
  1431. ComponentId - supplies the string id of the component whose
  1432. interface routine is to be called. This is for a string in
  1433. the ComponentStringTable string table (a handle to which
  1434. is in the OcManager structure).
  1435. Return Value:
  1436. None.
  1437. --*/
  1438. {
  1439. UINT DontCare;
  1440. BOOL b;
  1441. TRACE((
  1442. TEXT("OCM: OC_CLEANUP Comp(%s)..."),
  1443. pSetupStringTableStringFromId(OcManager->ComponentStringTable,ComponentId)
  1444. ));
  1445. b = pOcInterface(OcManager,&DontCare,ComponentId,NULL,OC_CLEANUP,0,0);
  1446. TRACE(( TEXT("...returns %x (retval %s)\n"),
  1447. DontCare,
  1448. b ? TEXT("TRUE") : TEXT("FALSE") ));
  1449. }