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.

4693 lines
107 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. octest.c
  5. Abstract:
  6. The code for the component setup DLL. This includes ComponentSetupProc,
  7. the DLL's entry point that is called by the OC Manager, as well as some
  8. routines that test the private data calls and the private functions calls.
  9. Author:
  10. Bogdan Andreiu (bogdana) 10-Feb-1997 Created.
  11. Jason Allor (jasonall) 24-Feb-1998 Took over the project.
  12. Sean Edmison (SEdmison) 21-Feb-2000 Took over the project.
  13. Revision History:
  14. 10-Feb-1997 bogdana
  15. First draft.
  16. 20-Feb-1997 bogdana
  17. Added multistring testing for the private data
  18. 19-Mar-1997 bogdana
  19. Modified and added routines that test the private functions call
  20. 21-Feb-2000 SEdmison
  21. Initialized a bunch of variables.
  22. Added casts to avoid compiler warnings.
  23. Added a return TRUE to avoid compiler error.
  24. --*/
  25. #include "octest.h"
  26. const static PTCHAR g_atszStringValues[MAX_STRINGS_FOR_PRIVATE_DATA] =
  27. {
  28. TEXT("First value to set"),
  29. TEXT("Second value to set"),
  30. TEXT("The third and longest value to set"),
  31. TEXT(""),
  32. TEXT("A"),
  33. TEXT("AB"),
  34. TEXT("ABC"),
  35. TEXT("The final value : \\//\\//\\//\\")
  36. };
  37. const static PTCHAR g_atszMultiStringValues[MAX_MULTI_STRINGS_FOR_PRIVATE_DATA] =
  38. {
  39. TEXT("A\0B\0C\0D\0E\0\0"),
  40. TEXT("\0\0"),
  41. TEXT("One\0Two\0Three\0\0"),
  42. TEXT("String1\0\0"),
  43. TEXT("0\01\02\03\0\0"),
  44. TEXT("Multi\0String\0\\0\0\0")
  45. };
  46. /*++
  47. Routine Description: DllMain (1.24)
  48. main routine
  49. Arguments:
  50. standard DllMain arguments
  51. Return Value:
  52. BOOL
  53. --*/
  54. BOOL WINAPI DllMain(IN HINSTANCE hInstance,
  55. IN DWORD fdwReason,
  56. IN PVOID pvReserved)
  57. {
  58. USHORT i = 0;
  59. TCHAR tszModulePath[MAX_PATH], szMsg[MAX_MSG_LEN];
  60. PTCHAR tszLogPath = NULL;
  61. PTCHAR tszAux = NULL;
  62. static UINT uiThreadCount = 0;
  63. switch (fdwReason)
  64. {
  65. case DLL_PROCESS_ATTACH:
  66. InitializeMemoryManager();
  67. InitGlobals();
  68. ParseCommandLine();
  69. //
  70. // Randomize, save the module instance and in initialize the log
  71. //
  72. srand((unsigned) time(NULL));
  73. g_hDllInstance = hInstance;
  74. InitCommonControls();
  75. GetModuleFileName(g_hDllInstance, tszModulePath, MAX_PATH);
  76. break;
  77. case DLL_PROCESS_DETACH:
  78. CleanUpTest();
  79. ExitLog();
  80. CheckAllocs();
  81. break;
  82. case DLL_THREAD_DETACH:
  83. //
  84. // If we added a participant, we have to remoce it
  85. //
  86. break;
  87. case DLL_THREAD_ATTACH:
  88. //
  89. // Otherwise we won't be able to log on correctly
  90. //
  91. uiThreadCount++;
  92. break;
  93. default:
  94. break;
  95. }
  96. return TRUE;
  97. } // DllMain //
  98. //==========================================================================
  99. //
  100. // Functions to set up UI
  101. //
  102. //==========================================================================
  103. /*++
  104. Routine Description: ChooseVersionDlgProc (1.26)
  105. Dialog procedure that allows the user to choose a component version
  106. less, equal or greater then the one of the OC Manager's.
  107. Arguments:
  108. Standard dialog procedure parameters
  109. Return Value:
  110. Standard dialog procedure return value
  111. --*/
  112. BOOL CALLBACK ChooseVersionDlgProc(IN HWND hwnd,
  113. IN UINT uiMsg,
  114. IN WPARAM wParam,
  115. IN LPARAM lParam)
  116. {
  117. PTSTR tszComponentId = NULL;
  118. INT iVersion = 0;
  119. switch (uiMsg)
  120. {
  121. case WM_INITDIALOG:
  122. CheckRadioButton(hwnd, IDC_LESS, IDC_GREATER, IDC_EQUAL);
  123. tszComponentId = (PTSTR)lParam;
  124. SetDlgItemText(hwnd, IDC_COMPONENT1, tszComponentId);
  125. return TRUE;
  126. case WM_COMMAND:
  127. switch (LOWORD(wParam))
  128. {
  129. case IDOK:
  130. //
  131. // Retrieve the current selection
  132. //
  133. if (QueryButtonCheck(hwnd, IDC_LESS))
  134. {
  135. iVersion = -1;
  136. }
  137. if (QueryButtonCheck(hwnd, IDC_EQUAL))
  138. {
  139. iVersion = 0;
  140. }
  141. if (QueryButtonCheck(hwnd, IDC_GREATER))
  142. {
  143. iVersion = 1;
  144. }
  145. //
  146. // Send the version chosen back to ChooseVersionEx
  147. //
  148. EndDialog(hwnd, iVersion);
  149. return TRUE;
  150. case IDCANCEL:
  151. EndDialog(hwnd, 0);
  152. return TRUE;
  153. default:
  154. break;
  155. }
  156. default:
  157. break;
  158. }
  159. return FALSE;
  160. } // ChooseVersionDlgProc //
  161. /*++
  162. Routine Description: ChooseSubcomponentDlgProc (1.27)
  163. Dialog procedure that allows the user to select a different
  164. initial state for a component than the one found by the OC Manager
  165. Arguments:
  166. Standard dialog procedure parameters
  167. Return Value:
  168. Standard dialog procedure return value
  169. --*/
  170. BOOL CALLBACK ChooseSubcomponentDlgProc(IN HWND hwnd,
  171. IN UINT uiMsg,
  172. IN WPARAM wParam,
  173. IN LPARAM lParam)
  174. {
  175. PTSTR tszComponentId = NULL;
  176. SubComponentState scsInitialState;
  177. switch (uiMsg)
  178. {
  179. case WM_INITDIALOG:
  180. CheckRadioButton(hwnd, IDC_DEFAULT, IDC_OFF, IDC_DEFAULT);
  181. tszComponentId = (PTSTR)lParam;
  182. SetDlgItemText(hwnd, IDC_COMPONENT1, tszComponentId);
  183. return TRUE;
  184. case WM_COMMAND:
  185. switch (LOWORD(wParam))
  186. {
  187. case IDOK:
  188. //
  189. // Retrieve the current selection
  190. //
  191. if (QueryButtonCheck(hwnd, IDC_DEFAULT))
  192. {
  193. scsInitialState = SubcompUseOcManagerDefault;
  194. }
  195. if (QueryButtonCheck(hwnd, IDC_OFF))
  196. {
  197. scsInitialState = SubcompOff;
  198. }
  199. if (QueryButtonCheck(hwnd, IDC_ON))
  200. {
  201. scsInitialState = SubcompOn;
  202. }
  203. EndDialog(hwnd, 0);
  204. return TRUE;
  205. case IDCANCEL:
  206. EndDialog(hwnd, 0);
  207. return TRUE;
  208. default:
  209. break;
  210. }
  211. default:
  212. break;
  213. }
  214. return FALSE;
  215. } // ChooseSubcomponentDlgProc //
  216. /*++
  217. Routine Description: ChooseVersionEx (1.29)
  218. "Wrapper" routine for the dialog box procedure ChooseVersionDlgProc.
  219. Retrieves the value chosen by the user and sets the version field of
  220. pInitComponent accordingly.
  221. Arguments:
  222. lpcvComponentId: supplies the id for the component.
  223. pInitComponent: supplies the address of the initialization structure.
  224. After return the "Version" field of that structure will
  225. reflect the user's selection
  226. Return Value:
  227. void
  228. --*/
  229. VOID ChooseVersionEx(IN LPCVOID lpcvComponentId,
  230. IN OUT PSETUP_INIT_COMPONENT psicInitComponent)
  231. {
  232. INT iVersion = 0;
  233. //
  234. // We will display a dialog box so the user can choose the
  235. // version he/she wants
  236. //
  237. iVersion = DialogBoxParam(g_hDllInstance,
  238. MAKEINTRESOURCE(IDD_DIALOG2),
  239. NULL,
  240. ChooseVersionDlgProc,
  241. (LPARAM)lpcvComponentId);
  242. //
  243. // We set the version choosen in a structure that will be sent
  244. // back to the Oc Manager
  245. //
  246. psicInitComponent->ComponentVersion =
  247. psicInitComponent->OCManagerVersion + iVersion;
  248. return;
  249. } // ChooseVersionEx //
  250. //==========================================================================
  251. //
  252. // Test functions. The ocmanager will call these functions.
  253. //
  254. //==========================================================================
  255. /*++
  256. Routine Description: ComponentSetupProc (1.6)
  257. The DLL entry point. This function is called by the OC Manager whenever
  258. it wants to send/recieve setup information to/from the component.
  259. Note that the ComponentId and SubcomponentId are LPCVOID because we
  260. don't know in advance if they are ANSI or Unicode.
  261. Arguments:
  262. lpcvComponentId: supplies the id for the component.
  263. lpcvSubcomponentId: supplies the id for the subcomponent.
  264. uiFunction: one of OC_XXX.
  265. uiParam1: its meaning depends on the function.
  266. pvParam2: its meaning depends on the function.
  267. Return Value:
  268. Depends on the function (e.g. TRUE/FALSE for the language supported,
  269. the number of pages supplied by the component, etc.).
  270. --*/
  271. EXPORT DWORD ComponentSetupProc(IN LPCVOID lpcvComponentId,
  272. IN LPCVOID lpcvSubcomponentId,
  273. IN UINT uiFunction,
  274. IN UINT uiParam1,
  275. IN PVOID pvParam2)
  276. {
  277. double fn = 1.6;
  278. DWORD dwRetval = NO_ERROR;
  279. PTCHAR tszComponentId = (PTCHAR)lpcvComponentId;
  280. PTCHAR tszSubcomponentId = (PTCHAR)lpcvSubcomponentId;
  281. TCHAR tsz[MAX_MSG_LEN];
  282. PCOMPONENT_DATA pcdComponentData = NULL;
  283. TCHAR tszDlgMessage[256];
  284. PTCHAR tszDummy = NULL;
  285. ReturnOrAV raValue;
  286. static BOOL bFirstTime = TRUE;
  287. //
  288. // Log the details about the call
  289. //
  290. LogOCFunction(lpcvComponentId,
  291. lpcvSubcomponentId,
  292. uiFunction,
  293. uiParam1,
  294. pvParam2);
  295. //if (uiFunction == g_uiFunctionToAV && uiFunction != OC_PREINITIALIZE && uiFunction != OC_INIT_COMPONENT) {
  296. // testAV(TRUE);
  297. //}
  298. causeAVPerComponent(uiFunction, lpcvComponentId);
  299. #ifndef UNICODE
  300. //if (g_bAccessViolation && !g_uiFunctionToAV) {
  301. // causeAV(uiFunction);
  302. //}
  303. #endif
  304. //
  305. // Check to see if valid component and subcomponent IDs were received
  306. //
  307. if (uiFunction > OC_INIT_COMPONENT && uiFunction < OCP_TEST_PRIVATE_BASE)
  308. {
  309. if (!FindSubcomponentInformationNode((PTCHAR)lpcvComponentId,
  310. (PTCHAR)lpcvSubcomponentId))
  311. {
  312. Log(fn, SEV2, TEXT("ComponentSetupProc function received %s.%s. ")
  313. TEXT("This is not a valid component.subcomponent."),
  314. lpcvComponentId, lpcvSubcomponentId);
  315. }
  316. }
  317. //
  318. // Whenever the user hits the next or back button, check all
  319. // the needs dependencies, exclude dependencies,
  320. // and parent child dependencies
  321. //
  322. if (uiFunction == OC_QUERY_SKIP_PAGE ||
  323. uiFunction == OC_QUEUE_FILE_OPS ||
  324. uiFunction == OC_ABOUT_TO_COMMIT_QUEUE ||
  325. uiFunction == OC_COMPLETE_INSTALLATION)
  326. {
  327. //
  328. // Check selection status of components to make sure all
  329. // dependency relationships are being fulfilled.
  330. //
  331. CheckNeedsDependencies();
  332. CheckExcludeDependencies();
  333. CheckParentDependencies();
  334. }
  335. //
  336. // Enable the use of private functions
  337. //
  338. g_bUsePrivateFunctions = TRUE;
  339. if (g_bTestExtended || !bFirstTime){
  340. bFirstTime = FALSE;
  341. // Prepare to call TestReturnValueAndAV
  342. raValue.tszComponent = NULL;
  343. raValue.tszSubComponent = NULL;
  344. raValue.bOverride = FALSE;
  345. raValue.iReturnValue = 0;
  346. TestReturnValueAndAV(lpcvComponentId,
  347. lpcvSubcomponentId,
  348. uiFunction,
  349. uiParam1,
  350. pvParam2,
  351. &raValue);
  352. }
  353. switch (uiFunction)
  354. {
  355. case OC_PREINITIALIZE:
  356. //testAV(g_bAccessViolation);
  357. #ifdef UNICODE
  358. testAV(g_bCrashUnicode);
  359. #endif
  360. dwRetval = RunOcPreinitialize(lpcvComponentId,
  361. lpcvSubcomponentId,
  362. uiParam1);
  363. break;
  364. case OC_INIT_COMPONENT:
  365. __ASSERT(pvParam2 != NULL);
  366. //
  367. // Init the log, now that OC Manager knows whether we
  368. // are ANSI or Unicode
  369. //
  370. _stprintf(tsz, TEXT("%s.log"), (PTCHAR)lpcvComponentId);
  371. InitLog(tsz, TEXT("OCManager Test Log"), TRUE);
  372. dwRetval = RunOcInitComponent(lpcvComponentId,
  373. lpcvSubcomponentId,
  374. pvParam2);
  375. #ifdef UNICODE
  376. if (g_bCloseInf && hInfGlobal != NULL){
  377. SetupCloseInfFile(pcdComponentData->hinfMyInfHandle);
  378. }
  379. #endif
  380. // Let's read the INF file and decide the values of some global variables
  381. if ((pcdComponentData = LocateComponent(lpcvComponentId)) &&
  382. (pcdComponentData->hinfMyInfHandle != NULL) &&
  383. !(pcdComponentData->dwlFlags & SETUPOP_BATCH))
  384. {
  385. SetGlobalsFromINF(pcdComponentData->hinfMyInfHandle);
  386. }
  387. //if (g_bNoWizPage) {
  388. // Check is there is a default mode specified in [OCTest] section
  389. SetDefaultMode(pcdComponentData);
  390. //}
  391. break;
  392. case OC_QUERY_STATE:
  393. dwRetval = RunOcQueryState(lpcvComponentId,
  394. lpcvSubcomponentId);
  395. if (dwRetval == SubcompOn) {
  396. //MessageBox(NULL, TEXT("Let's turn it on"), TEXT("OC_QUERY_STATE"), MB_OK);
  397. }
  398. break;
  399. case OC_SET_LANGUAGE:
  400. dwRetval = RunOcSetLanguage(lpcvComponentId,
  401. lpcvSubcomponentId,
  402. uiParam1);
  403. if (g_bNoLangSupport) {
  404. //MessageBox(NULL, TEXT("No Language Support"), TEXT("OC_SET_LANGUAGE"), MB_OK);
  405. dwRetval = FALSE;
  406. }
  407. break;
  408. case OC_QUERY_IMAGE:
  409. if (g_bInvalidBitmap){
  410. dwRetval = 1000;
  411. }
  412. else{
  413. dwRetval = RunOcQueryImage(lpcvComponentId,
  414. lpcvSubcomponentId,
  415. pvParam2);
  416. }
  417. break;
  418. case OC_REQUEST_PAGES:
  419. if (g_bNoWizPage){
  420. dwRetval = 0;
  421. }
  422. else{
  423. dwRetval = RunOcRequestPages(lpcvComponentId,
  424. uiParam1,
  425. pvParam2);
  426. }
  427. break;
  428. case OC_QUERY_CHANGE_SEL_STATE:
  429. dwRetval = RunOcQueryChangeSelState(lpcvComponentId,
  430. lpcvSubcomponentId,
  431. uiParam1);
  432. break;
  433. case OC_CALC_DISK_SPACE:
  434. dwRetval = RunOcCalcDiskSpace(lpcvComponentId,
  435. lpcvSubcomponentId,
  436. uiParam1,
  437. pvParam2);
  438. break;
  439. case OC_QUEUE_FILE_OPS:
  440. dwRetval = RunOcQueueFileOps(lpcvComponentId,
  441. lpcvSubcomponentId,
  442. pvParam2);
  443. break;
  444. case OC_NEED_MEDIA:
  445. //if (!g_bNoNeedMedia){
  446. // dwRetval = RunOcNeedMedia(lpcvComponentId,
  447. // uiParam1,
  448. // pvParam2);
  449. //}
  450. //else{
  451. dwRetval = NO_ERROR;
  452. Log(fn, SEV2, TEXT("OC_NEED_MEDIA is passed in for %s.%s. ")
  453. TEXT("This should not happen according to the spec."),
  454. lpcvComponentId, lpcvSubcomponentId);
  455. //MessageBox(NULL, TEXT("OC_NEED_MEDIA is passed to the DLL."), TEXT("OC_NEED_MEDIA"), MB_OK);
  456. //}
  457. break;
  458. case OC_QUERY_STEP_COUNT:
  459. dwRetval = RunOcQueryStepCount(lpcvComponentId);
  460. break;
  461. case OC_COMPLETE_INSTALLATION:
  462. dwRetval = RunOcCompleteInstallation(lpcvComponentId,
  463. lpcvSubcomponentId);
  464. if (g_bReboot) {
  465. if ((pcdComponentData = LocateComponent(lpcvComponentId)) &&
  466. (pcdComponentData->hinfMyInfHandle != NULL) &&
  467. !(pcdComponentData->dwlFlags & SETUPOP_BATCH))
  468. {
  469. //MessageBox(NULL, TEXT("A reboot is queued"), TEXT("Reboot"), MB_OK);
  470. //OcHelperSetReboot(pcdComponentData->ocrHelperRoutines.OcManagerContext, NULL);
  471. pcdComponentData->ocrHelperRoutines.SetReboot(pcdComponentData->ocrHelperRoutines.OcManagerContext,TRUE);
  472. }
  473. }
  474. break;
  475. case OC_CLEANUP:
  476. dwRetval = RunOcCleanup(lpcvComponentId);
  477. break;
  478. case OCP_TEST_PRIVATE_BASE:
  479. dwRetval = RunTestOcPrivateBase(lpcvSubcomponentId,
  480. uiParam1,
  481. pvParam2);
  482. break;
  483. case OCP_CHECK_NEEDS:
  484. if (pcdComponentData = LocateComponent(lpcvComponentId))
  485. {
  486. dwRetval = CheckLocalNeedsDependencies(
  487. pcdComponentData->ocrHelperRoutines,
  488. (PSUBCOMP)uiParam1,
  489. ((PCHECK_NEEDS)pvParam2)->pclNeeds,
  490. ((PCHECK_NEEDS)pvParam2)->tszNodesVisited);
  491. ((PCHECK_NEEDS)pvParam2)->bResult = (BOOL)dwRetval;
  492. dwRetval = (DWORD)pvParam2;
  493. }
  494. else
  495. {
  496. Log(fn, SEV2, TEXT("Could not get component data of %s"),
  497. lpcvComponentId);
  498. }
  499. break;
  500. default:
  501. dwRetval = (DWORD)FALSE;
  502. }
  503. if ((g_bTestExtended || !bFirstTime) && BeginTest() && raValue.bOverride){
  504. return raValue.iReturnValue;
  505. }
  506. else {
  507. return dwRetval;
  508. }
  509. } // ComponentSetupProc //
  510. /*++
  511. Routine Description: RunOcPreinitialize (1.7)
  512. Code to run if OC_PREINITIALIZE is called.
  513. Arguments:
  514. lpcvComponentId: supplies the id for the component.
  515. lpcvSubcomponentId: supplies the id for the subcomponent.
  516. uiParam1: its meaning depends on the function.
  517. Return Value:
  518. DWORD: returns error status
  519. --*/
  520. DWORD RunOcPreinitialize(IN LPCVOID lpcvComponentId,
  521. IN LPCVOID lpcvSubcomponentId,
  522. IN UINT uiParam1)
  523. {
  524. DWORD dwComponentReturnValue = NO_ERROR;
  525. //
  526. // If the test is not extended, the return value
  527. // matches the native character width.
  528. //
  529. #ifdef UNICODE
  530. dwComponentReturnValue = OCFLAG_UNICODE;
  531. #else
  532. dwComponentReturnValue = OCFLAG_ANSI;
  533. #endif
  534. return dwComponentReturnValue;
  535. } // RunOcPreinitialize //
  536. /*++
  537. Routine Description: RunOcInitComponent (1.8)
  538. Code to run if OC_INIT_COMPONENT is called.
  539. Arguments:
  540. lpcvComponentId: supplies the id for the component.
  541. lpcvSubcomponentId: supplies the id for the subcomponent.
  542. pvParam2: its meaning depends on the function.
  543. Return Value:
  544. DWORD: returns error status
  545. --*/
  546. DWORD RunOcInitComponent(IN LPCVOID lpcvComponentId,
  547. IN LPCVOID lpcvSubcomponentId,
  548. IN PVOID pvParam2)
  549. {
  550. double fn = 1.8;
  551. PSETUP_INIT_COMPONENT psicInitComponent;
  552. PCOMPONENT_DATA pcdComponentData;
  553. DWORD dwComponentReturnValue = NO_ERROR;
  554. TCHAR tszFunctionName[256];
  555. BOOL bSuccess;
  556. INFCONTEXT infContext;
  557. int nRequiredBufferSize = 255;
  558. TCHAR tszMsg[256];
  559. psicInitComponent = (PSETUP_INIT_COMPONENT)pvParam2;
  560. hInfGlobal = psicInitComponent->OCInfHandle;
  561. if (pcdComponentData = AddNewComponent(lpcvComponentId))
  562. {
  563. //
  564. // Save the INF file handle
  565. //
  566. pcdComponentData->hinfMyInfHandle =
  567. (psicInitComponent->ComponentInfHandle == INVALID_HANDLE_VALUE)
  568. ? NULL : psicInitComponent->ComponentInfHandle;
  569. if (pcdComponentData->hinfMyInfHandle)
  570. {
  571. SetupOpenAppendInfFile(NULL,
  572. pcdComponentData->hinfMyInfHandle,
  573. NULL);
  574. }
  575. CreateSubcomponentInformationList(pcdComponentData->hinfMyInfHandle);
  576. _tcscpy(pcdComponentData->tszSourcePath,
  577. psicInitComponent->SetupData.SourcePath);
  578. _tcscpy(pcdComponentData->tszUnattendFile,
  579. psicInitComponent->SetupData.UnattendFile);
  580. pcdComponentData->ocrHelperRoutines =
  581. psicInitComponent->HelperRoutines;
  582. pcdComponentData->dwlFlags =
  583. psicInitComponent->SetupData.OperationFlags;
  584. dwComponentReturnValue = NO_ERROR;
  585. //
  586. // Initialize the "witness" file queue
  587. //
  588. if ((g_FileQueue = SetupOpenFileQueue()) == INVALID_HANDLE_VALUE)
  589. {
  590. Log(fn, SEV2, TEXT("Unable to create file queue"));
  591. }
  592. // Determine where to AV
  593. bSuccess = SetupFindFirstLine(pcdComponentData->hinfMyInfHandle, TEXT("OCTest"), TEXT("AccessViolation"), &infContext);
  594. if (bSuccess) {
  595. pcdComponentData->bAccessViolation = TRUE;
  596. bSuccess = SetupGetStringField(&infContext, 1, tszFunctionName, 255, &nRequiredBufferSize);
  597. if (bSuccess) {
  598. //_stprintf(tszMsg, TEXT("An access violation will be generated at %s of %s"), tszFunctionName, lpcvComponentId);
  599. //MessageBox(NULL, tszMsg, TEXT("Access Violation"), MB_OK);
  600. pcdComponentData->uiFunctionToAV = GetOCFunctionName(tszFunctionName);
  601. }
  602. }
  603. else{
  604. pcdComponentData->bAccessViolation = FALSE;
  605. }
  606. //
  607. // Test the helper routines
  608. //
  609. TestHelperRoutines(lpcvComponentId,
  610. pcdComponentData->ocrHelperRoutines);
  611. }
  612. else
  613. {
  614. dwComponentReturnValue = ERROR_NOT_ENOUGH_MEMORY;
  615. }
  616. if (g_bTestExtended && (dwComponentReturnValue == NO_ERROR))
  617. {
  618. //
  619. // Let the user decide if the component is
  620. // compatible with the OC Manager
  621. //
  622. ChooseVersionEx(lpcvComponentId, psicInitComponent);
  623. //ChooseAccessViolationEx();
  624. }
  625. else
  626. {
  627. //
  628. // We put the same component version to be sure that can go on
  629. //
  630. psicInitComponent->ComponentVersion =
  631. psicInitComponent->OCManagerVersion;
  632. }
  633. return dwComponentReturnValue;
  634. } // RunOcInitComponent //
  635. /*++
  636. Routine Description: RunOcQueryState (1.9)
  637. Code to run if OC_QUERY_STATE is called.
  638. Arguments:
  639. lpcvComponentId: supplies the id for the component.
  640. lpcvSubcomponentId: supplies the id for the subcomponent.
  641. Return Value:
  642. DWORD: returns error status
  643. --*/
  644. DWORD RunOcQueryState(IN LPCVOID lpcvComponentId,
  645. IN LPCVOID lpcvSubcomponentId)
  646. {
  647. PCOMPONENT_DATA pcdComponentData = NULL;
  648. DWORD dwComponentReturnValue = NO_ERROR;
  649. BOOL bSuccess;
  650. TCHAR tszKeyName[256];
  651. INFCONTEXT infContext;
  652. int nRequiredSize;
  653. TCHAR tszState[256];
  654. if (pcdComponentData = LocateComponent(lpcvComponentId))
  655. {
  656. if (!g_bTestExtended)
  657. {
  658. dwComponentReturnValue = SubcompUseOcManagerDefault;
  659. }
  660. else
  661. {
  662. dwComponentReturnValue =
  663. ChooseSubcomponentInitialState(lpcvComponentId,
  664. lpcvSubcomponentId);
  665. }
  666. _stprintf(tszKeyName, TEXT("%s.initState"),lpcvSubcomponentId);
  667. //MessageBox(NULL, TEXT("Going to look for the key"), tszKeyName, MB_OK);
  668. bSuccess = SetupFindFirstLine(pcdComponentData->hinfMyInfHandle,
  669. TEXT("OCTest"),
  670. tszKeyName,
  671. &infContext);
  672. if (bSuccess) {
  673. //MessageBox(NULL, TEXT("Key Found"), tszKeyName, MB_OK);
  674. bSuccess = SetupGetStringField(&infContext,
  675. 1,
  676. tszState,
  677. 255,
  678. &nRequiredSize);
  679. if (bSuccess) {
  680. //MessageBox(NULL, TEXT("String field fetched"), tszState, MB_OK);
  681. if (_tcscmp(tszState, TEXT("On")) == 0) {
  682. dwComponentReturnValue = SubcompOn;
  683. }
  684. else if (_tcscmp(tszState, TEXT("Off")) == 0) {
  685. dwComponentReturnValue = SubcompOff;
  686. }
  687. else{
  688. dwComponentReturnValue = SubcompUseOcManagerDefault;
  689. }
  690. }
  691. }
  692. //
  693. // Test the helper routines
  694. //
  695. TestHelperRoutines(lpcvComponentId,
  696. pcdComponentData->ocrHelperRoutines);
  697. }
  698. else
  699. {
  700. dwComponentReturnValue = SubcompUseOcManagerDefault;
  701. }
  702. return dwComponentReturnValue;
  703. } // RunOcQueryState //
  704. /*++
  705. Routine Description: RunOcSetLanguage (1.11)
  706. Code to run if OC_SET_LANGUAGE is called.
  707. Arguments:
  708. lpcvComponentId: supplies the id for the component.
  709. lpcvSubcomponentId: supplies the id for the subcomponent.
  710. uiParam1: its meaning depends on the function.
  711. Return Value:
  712. DWORD: returns error status
  713. --*/
  714. DWORD RunOcSetLanguage(IN LPCVOID lpcvComponentId,
  715. IN LPCVOID lpcvSubcomponentId,
  716. IN UINT uiParam1)
  717. {
  718. DWORD dwComponentReturnValue = NO_ERROR;
  719. PCOMPONENT_DATA pcdComponentData;
  720. if (pcdComponentData = LocateComponent(lpcvComponentId))
  721. {
  722. //
  723. // If we won't support the language, the OC Manager won't
  724. // continue, so we have to return TRUE
  725. //
  726. dwComponentReturnValue = (DWORD)TRUE;
  727. pcdComponentData->LanguageId = (LANGID)uiParam1;
  728. //
  729. // Test the helper routines
  730. //
  731. TestHelperRoutines(lpcvComponentId,
  732. pcdComponentData->ocrHelperRoutines);
  733. }
  734. else
  735. {
  736. dwComponentReturnValue = (DWORD)FALSE;
  737. }
  738. return dwComponentReturnValue;
  739. } // RunOcSetLanguage //
  740. /*++
  741. Routine Description: RunOcQueryImage (1.12)
  742. Code to run if OC_QUERY_IMAGE is called.
  743. Arguments:
  744. lpcvComponentId: supplies the id for the component.
  745. lpcvSubcomponentId: supplies the id for the subcomponent.
  746. pvParam2: its meaning depends on the function.
  747. Return Value:
  748. DWORD: returns error status
  749. --*/
  750. DWORD RunOcQueryImage(IN LPCVOID lpcvComponentId,
  751. IN LPCVOID lpcvSubcomponentId,
  752. IN PVOID pvParam2)
  753. {
  754. double fn = 1.12;
  755. DWORD dwComponentReturnValue = NO_ERROR;
  756. BOOL bAux;
  757. TCHAR tszMsg[MAX_MSG_LEN];
  758. TCHAR tszResourceName[MAX_PATH];
  759. INFCONTEXT infContext;
  760. PCOMPONENT_DATA pcdComponentData;
  761. #ifdef DEBUG
  762. Log(fn, INFO, TEXT("Height = %d, Width = %d"),
  763. HIWORD(pvParam2), LOWORD(pvParam2));
  764. #endif
  765. if ((pcdComponentData = LocateComponent(lpcvComponentId)) &&
  766. (pcdComponentData->hinfMyInfHandle))
  767. {
  768. __ASSERT(LOWORD(uiParam1) == SubCompInfoSmallIcon);
  769. _stprintf(tszMsg, TEXT("%s.%s"), lpcvComponentId, lpcvSubcomponentId);
  770. if (SetupFindFirstLine(pcdComponentData->hinfMyInfHandle, tszMsg,
  771. TEXT("Bitmap"), &infContext))
  772. {
  773. bAux = SetupGetStringField(&infContext, 1, tszResourceName,
  774. sizeof(tszResourceName) /
  775. sizeof(TCHAR), NULL);
  776. if (bAux)
  777. {
  778. //
  779. // Try to use Param1 and Param2 to resize the icon
  780. //
  781. dwComponentReturnValue = (DWORD)LoadBitmap(g_hDllInstance,
  782. tszResourceName);
  783. bAux = SetBitmapDimensionEx((HBITMAP)dwComponentReturnValue,
  784. LOWORD(pvParam2),
  785. HIWORD(pvParam2),
  786. NULL);
  787. #ifdef DEBUG
  788. if (bAux)
  789. {
  790. Log(fn, PASS, TEXT("Success"));
  791. }
  792. else
  793. {
  794. _stprintf(tszMsg, TEXT("Can't resize %d"),
  795. GetLastError());
  796. Log(fn, PASS, tszMsg);
  797. }
  798. #endif
  799. }
  800. }
  801. //
  802. // Test the helper routines
  803. //
  804. TestHelperRoutines(lpcvComponentId,
  805. pcdComponentData->ocrHelperRoutines);
  806. }
  807. return dwComponentReturnValue;
  808. } // RunOcQueryImage //
  809. /*++
  810. Routine Description: RunOcRequestPages (1.13)
  811. Code to run if OC_REQUEST_PAGES is called.
  812. Arguments:
  813. lpcvComponentId: supplies the id for the component.
  814. uiParam1: its meaning depends on the function.
  815. pvParam2: its meaning depends on the function.
  816. Return Value:
  817. DWORD: returns error status
  818. --*/
  819. DWORD RunOcRequestPages(IN LPCVOID lpcvComponentId,
  820. IN UINT uiParam1,
  821. IN PVOID pvParam2)
  822. {
  823. DWORD dwComponentReturnValue = NO_ERROR;
  824. PCOMPONENT_DATA pcdComponentData;
  825. TCHAR tsz[256];
  826. if (pcdComponentData = LocateComponent(lpcvComponentId))
  827. {
  828. dwComponentReturnValue = DoPageRequest(
  829. pcdComponentData->tszComponentId,
  830. uiParam1,
  831. (PSETUP_REQUEST_PAGES)pvParam2,
  832. pcdComponentData->ocrHelperRoutines);
  833. //
  834. // Test the helper routines
  835. //
  836. TestHelperRoutines(lpcvComponentId,
  837. pcdComponentData->ocrHelperRoutines);
  838. }
  839. else
  840. {
  841. //
  842. // Some kind of error, 0 pages
  843. //
  844. dwComponentReturnValue = -1;
  845. }
  846. return dwComponentReturnValue;
  847. } // RunOcRequestPages //
  848. /*++
  849. Routine Description: RunOcQueryChangeSelState (1.14)
  850. Code to run if OC_QUERY_CHANGE_SEL_STATE is called.
  851. Arguments:
  852. lpcvComponentId: supplies the id for the component.
  853. lpcvSubcomponentId: supplies the id for the subcomponent.
  854. uiParam1: its meaning depends on the function.
  855. Return Value:
  856. DWORD: returns error status
  857. --*/
  858. DWORD RunOcQueryChangeSelState(IN LPCVOID lpcvComponentId,
  859. IN LPCVOID lpcvSubcomponentId,
  860. IN UINT uiParam1)
  861. {
  862. DWORD dwComponentReturnValue = TRUE;
  863. TCHAR tszText[MAX_MSG_LEN];
  864. TCHAR tszSectionName[MAX_MSG_LEN];
  865. INFCONTEXT infContext;
  866. PCOMPONENT_DATA pcdComponentData;
  867. if ((pcdComponentData = LocateComponent(lpcvComponentId)) &&
  868. (pcdComponentData->hinfMyInfHandle != NULL) &&
  869. !(pcdComponentData->dwlFlags & SETUPOP_BATCH))
  870. {
  871. //
  872. // Check to see if this component should refuse to enable or
  873. // disable. The component should refuse if there is a field
  874. // called "RefuseSelect" or "RefuseDeselect" in the INF file.
  875. //
  876. if (lpcvSubcomponentId == NULL ||
  877. _tcscmp((PTCHAR)lpcvSubcomponentId, TEXT("(null)")) == 0 ||
  878. ((PTCHAR)lpcvSubcomponentId)[0] == TEXT('\0'))
  879. {
  880. _stprintf(tszSectionName, (PTCHAR)lpcvComponentId);
  881. }
  882. else
  883. {
  884. _stprintf(tszSectionName, (PTCHAR)lpcvSubcomponentId);
  885. }
  886. if (SetupFindFirstLine(
  887. pcdComponentData->hinfMyInfHandle,
  888. tszSectionName,
  889. uiParam1 ? TEXT("RefuseSelect") : TEXT("RefuseDeselect"),
  890. &infContext))
  891. {
  892. dwComponentReturnValue = FALSE;
  893. }
  894. //
  895. // Test the helper routines
  896. //
  897. TestHelperRoutines(lpcvComponentId,
  898. pcdComponentData->ocrHelperRoutines);
  899. }
  900. else
  901. {
  902. dwComponentReturnValue = FALSE;
  903. }
  904. return dwComponentReturnValue;
  905. } // RunOcQueryChangerSelState //
  906. /*++
  907. Routine Description: RunOcCalcDiskSpace (1.15)
  908. Code to run if OC_CALC_DISK_SPACE is called.
  909. Arguments:
  910. lpcvComponentId: supplies the id for the component.
  911. lpcvSubcomponentId: supplies the id for the subcomponent.
  912. uiParam1: its meaning depends on the function.
  913. pvParam2: its meaning depends on the function.
  914. Return Value:
  915. DWORD: returns error status
  916. --*/
  917. DWORD RunOcCalcDiskSpace(IN LPCVOID lpcvComponentId,
  918. IN LPCVOID lpcvSubcomponentId,
  919. IN UINT uiParam1,
  920. IN PVOID pvParam2)
  921. {
  922. DWORD dwComponentReturnValue = TRUE;
  923. BOOL bAux, bRetval;
  924. TCHAR tszSectionName[MAX_PATH];
  925. TCHAR tszMsg[MAX_MSG_LEN];
  926. PCOMPONENT_DATA pcdComponentData;
  927. INFCONTEXT infContext;
  928. if ((pcdComponentData = LocateComponent(lpcvComponentId)) &&
  929. (pcdComponentData->hinfMyInfHandle))
  930. {
  931. //
  932. // Check to see if the file to be copied in this section is called
  933. // "hugefile.txt" If it is, don't add the real size of this file.
  934. // Instead, add a gigantic file size so large that there won't
  935. // be enough disk space to complete the operation.
  936. //
  937. _stprintf(tszMsg, TEXT("%s.%s.copyfiles"),
  938. lpcvComponentId, lpcvSubcomponentId);
  939. bAux = SetupFindFirstLine(pcdComponentData->hinfMyInfHandle,
  940. tszSectionName,
  941. TEXT("hugefile.txt"),
  942. &infContext);
  943. bAux = bAux && g_bHugeSize;
  944. if (bAux)
  945. {
  946. //
  947. // hugefile.txt is present.
  948. //
  949. if (uiParam1)
  950. {
  951. //
  952. // Add gigantic file size
  953. //
  954. bRetval = SetupAddToDiskSpaceList((HDSKSPC)pvParam2,
  955. TEXT("c:\\file.big"),
  956. ONE_HUNDRED_GIG,
  957. FILEOP_COPY,
  958. 0, 0);
  959. }
  960. else
  961. {
  962. //
  963. // Remove a gigantic file size
  964. //
  965. bRetval = SetupAddToDiskSpaceList((HDSKSPC)pvParam2,
  966. TEXT("c:\\file.big"),
  967. ONE_HUNDRED_GIG,
  968. FILEOP_COPY,
  969. 0, 0);
  970. }
  971. }
  972. else
  973. {
  974. //
  975. // Get the section name
  976. //
  977. _stprintf(tszMsg, TEXT("%s.%s"), lpcvComponentId, lpcvSubcomponentId);
  978. if (uiParam1)
  979. {
  980. //
  981. // Adding
  982. //
  983. bRetval = SetupAddInstallSectionToDiskSpaceList(
  984. (HDSKSPC)pvParam2,
  985. pcdComponentData->hinfMyInfHandle,
  986. NULL, tszMsg, 0, 0);
  987. }
  988. else
  989. {
  990. //
  991. // Removing
  992. //
  993. bRetval = SetupRemoveInstallSectionFromDiskSpaceList(
  994. (HDSKSPC)pvParam2,
  995. pcdComponentData->hinfMyInfHandle,
  996. NULL, tszMsg, 0, 0);
  997. }
  998. }
  999. dwComponentReturnValue = bRetval ? NO_ERROR : GetLastError();
  1000. //
  1001. // Test the helper routines
  1002. //
  1003. TestHelperRoutines(lpcvComponentId,
  1004. pcdComponentData->ocrHelperRoutines);
  1005. }
  1006. else
  1007. {
  1008. dwComponentReturnValue = ERROR_NOT_ENOUGH_MEMORY;
  1009. }
  1010. return dwComponentReturnValue;
  1011. } // RunOcCalcDiskSpace //
  1012. /*++
  1013. Routine Description: RunOcQueueFileOps (1.16)
  1014. Code to run if OC_QUEUE_FILE_OPS is called.
  1015. Arguments:
  1016. lpcvComponentId: supplies the id for the component.
  1017. lpcvSubcomponentId: supplies the id for the subcomponent.
  1018. pvParam2: its meaning depends on the function.
  1019. Return Value:
  1020. DWORD: returns error status
  1021. --*/
  1022. DWORD RunOcQueueFileOps(IN LPCVOID lpcvComponentId,
  1023. IN LPCVOID lpcvSubcomponentId,
  1024. IN PVOID pvParam2)
  1025. {
  1026. double fn = 1.16;
  1027. DWORD dwComponentReturnValue = NO_ERROR;
  1028. BOOL bAux;
  1029. BOOL bCurrentState, bOriginalState;
  1030. TCHAR tszMsg[MAX_MSG_LEN];
  1031. TCHAR tszSectionName[MAX_PATH];
  1032. INFCONTEXT infContext;
  1033. PCOMPONENT_DATA pcdComponentData;
  1034. PSUBCOMP pscTemp;
  1035. //
  1036. // Check to make sure this subcomponent is allowed to do work.
  1037. // If the subcomponent is not a bottom leaf on the subcomponent
  1038. // tree, it is not allowed to do any work. So we will check to
  1039. // see if it has any children.
  1040. //
  1041. for (pscTemp = g_pscHead; pscTemp != NULL; pscTemp = pscTemp->Next)
  1042. {
  1043. if (lpcvSubcomponentId && _tcscmp(pscTemp->tszSubcomponentId,
  1044. (PTCHAR)lpcvSubcomponentId) == 0)
  1045. {
  1046. if (pscTemp->pclChildren)
  1047. {
  1048. //
  1049. // This subcomponent has children. OcManager should not be
  1050. // try to queue file ops for this subcomponent. This is
  1051. // a failure.
  1052. //
  1053. Log(fn, SEV2, TEXT("OC Manager is trying to queue file ops ")
  1054. TEXT("for subcomponent %s of component %s. ")
  1055. TEXT("This subcomponent has children and ")
  1056. TEXT("should not be allowed to do any work."),
  1057. lpcvSubcomponentId, lpcvComponentId);
  1058. return NO_ERROR;
  1059. }
  1060. }
  1061. }
  1062. if (lpcvSubcomponentId &&
  1063. (pcdComponentData = LocateComponent(lpcvComponentId)))
  1064. {
  1065. //
  1066. // Get original and current state. If the state didn't change,
  1067. // nothing to do.
  1068. //
  1069. bOriginalState =
  1070. pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  1071. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  1072. lpcvSubcomponentId,
  1073. OCSELSTATETYPE_ORIGINAL);
  1074. bCurrentState =
  1075. pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  1076. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  1077. lpcvSubcomponentId,
  1078. OCSELSTATETYPE_CURRENT);
  1079. _stprintf(tszSectionName, TEXT("%s.%s"),
  1080. lpcvComponentId, lpcvSubcomponentId);
  1081. bAux = TRUE;
  1082. if (!bCurrentState)
  1083. {
  1084. //
  1085. // Being uninstalled. Fetch uninstall section name.
  1086. //
  1087. bAux = SetupFindFirstLine(pcdComponentData->hinfMyInfHandle,
  1088. tszSectionName,
  1089. TEXT("Uninstall"),
  1090. &infContext);
  1091. if (bAux)
  1092. {
  1093. bAux = SetupGetStringField(&infContext, 1, tszSectionName,
  1094. sizeof(tszSectionName) /
  1095. sizeof(TCHAR), NULL);
  1096. }
  1097. }
  1098. if (bAux)
  1099. {
  1100. bAux = SetupInstallFilesFromInfSection(
  1101. pcdComponentData->hinfMyInfHandle,
  1102. NULL,
  1103. pvParam2,
  1104. tszSectionName,
  1105. pcdComponentData->tszSourcePath,
  1106. bCurrentState ? SP_COPY_NEWER : 0);
  1107. SetupInstallFilesFromInfSection(
  1108. pcdComponentData->hinfMyInfHandle,
  1109. NULL,
  1110. g_FileQueue,
  1111. tszSectionName,
  1112. pcdComponentData->tszSourcePath,
  1113. bCurrentState ? SP_COPY_NEWER : 0);
  1114. dwComponentReturnValue = bAux ? NO_ERROR : GetLastError();
  1115. }
  1116. //
  1117. // Test the helper routines
  1118. //
  1119. TestHelperRoutines(lpcvComponentId,
  1120. pcdComponentData->ocrHelperRoutines);
  1121. }
  1122. return dwComponentReturnValue;
  1123. } // RunOcQueueFileOps //
  1124. /*++
  1125. Routine Description: RunOcNeedMedia (1.17)
  1126. Code to run if OC_NEED_MEDIA is called.
  1127. Arguments:
  1128. lpcvComponentId: supplies the id for the component.
  1129. uiParam1: its meaning depends on the function.
  1130. pvParam2: its meaning depends on the function.
  1131. Return Value:
  1132. DWORD: returns error status
  1133. --*/
  1134. DWORD RunOcNeedMedia(IN LPCVOID lpcvComponentId,
  1135. IN UINT uiParam1,
  1136. IN PVOID pvParam2)
  1137. {
  1138. PVOID pvQueueContext;
  1139. DWORD dwComponentReturnValue;
  1140. //
  1141. // Nothing special to do if media is needed
  1142. // Call the default queue routine
  1143. //
  1144. pvQueueContext = SetupInitDefaultQueueCallback(NULL);
  1145. dwComponentReturnValue = SetupDefaultQueueCallback(pvQueueContext,
  1146. SPFILENOTIFY_NEEDMEDIA,
  1147. uiParam1,
  1148. (UINT)pvParam2);
  1149. SetupTermDefaultQueueCallback(pvQueueContext);
  1150. return dwComponentReturnValue;
  1151. } // RunOcNeedMedia //
  1152. /*++
  1153. Routine Description: RunOcQueryStepCount (1.18)
  1154. Code to run if OC_QUERY_STEP_COUNT is called.
  1155. Arguments:
  1156. lpcvComponentId: supplies the id for the component.
  1157. Return Value:
  1158. DWORD: returns error status
  1159. --*/
  1160. DWORD RunOcQueryStepCount(IN LPCVOID lpcvComponentId)
  1161. {
  1162. PCOMPONENT_DATA pcdComponentData;
  1163. if (pcdComponentData = LocateComponent(lpcvComponentId))
  1164. {
  1165. //
  1166. // Test the helper routines
  1167. //
  1168. TestHelperRoutines(lpcvComponentId,
  1169. pcdComponentData->ocrHelperRoutines);
  1170. }
  1171. return NO_STEPS_FINAL;
  1172. } // RunOcQueryStepCount //
  1173. /*++
  1174. Routine Description: RunOcCompleteInstallation (1.19)
  1175. Code to run if OC_COMPLETE_INSTALLATION is called.
  1176. Arguments:
  1177. lpcvComponentId: supplies the id for the component.
  1178. lpcvSubcomponentId: supplies the id for the subcomponent.
  1179. Return Value:
  1180. DWORD: returns error status
  1181. --*/
  1182. DWORD RunOcCompleteInstallation(IN LPCVOID lpcvComponentId,
  1183. IN LPCVOID lpcvSubcomponentId)
  1184. {
  1185. double fn = 1.19;
  1186. DWORD dwComponentReturnValue = NO_ERROR;
  1187. DWORD dwResult;
  1188. INT iCount;
  1189. BOOL bAux;
  1190. TCHAR tszMsg[MAX_MSG_LEN];
  1191. PVOID pvCallbackContext;
  1192. PCOMPONENT_DATA pcdComponentData;
  1193. //
  1194. // Output the name of the component that is currently working
  1195. //
  1196. _stprintf(tszMsg, TEXT("OC_COMPLETE_INSTALLATION: Copying files for %s\n"), lpcvSubcomponentId);
  1197. OutputDebugString(tszMsg);
  1198. if (pcdComponentData = LocateComponent(lpcvComponentId))
  1199. {
  1200. //
  1201. // We perform the check for the top-level component
  1202. // We will scan the witness queue
  1203. //
  1204. pvCallbackContext = SetupInitDefaultQueueCallback(NULL);
  1205. bAux = SetupScanFileQueue(g_FileQueue,
  1206. SPQ_SCAN_FILE_PRESENCE,
  1207. NULL,
  1208. SetupDefaultQueueCallback,
  1209. pvCallbackContext,
  1210. &dwResult);
  1211. SetupTermDefaultQueueCallback(pvCallbackContext);
  1212. if (!dwResult)
  1213. {
  1214. Log(fn, SEV2, TEXT("Not all the files are on the target!"));
  1215. }
  1216. //
  1217. // Check the helper routines
  1218. //
  1219. for (iCount = 0; iCount < nStepsFinal; iCount++)
  1220. {
  1221. //
  1222. // From time to time (every 3 "ticks") change the progress text
  1223. //
  1224. pcdComponentData->ocrHelperRoutines.TickGauge(
  1225. pcdComponentData->ocrHelperRoutines.OcManagerContext);
  1226. if (iCount % 3 == 1)
  1227. {
  1228. _stprintf(tszMsg, TEXT("%s Progress Text Changed Step %d "),
  1229. lpcvSubcomponentId, iCount);
  1230. pcdComponentData->ocrHelperRoutines.SetProgressText(
  1231. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  1232. tszMsg);
  1233. }
  1234. Sleep(10 * TICK_TIME);
  1235. }
  1236. //
  1237. // Test the helper routines
  1238. //
  1239. TestHelperRoutines(lpcvComponentId,
  1240. pcdComponentData->ocrHelperRoutines);
  1241. }
  1242. else
  1243. {
  1244. dwComponentReturnValue = ERROR_NOT_ENOUGH_MEMORY;
  1245. }
  1246. return dwComponentReturnValue;
  1247. } // RunOcCompleteInstallation //
  1248. /*++
  1249. Routine Description: RunOcCleanup (1.21)
  1250. Code to run if OC_CLEANUP is called.
  1251. Arguments:
  1252. lpcvComponentId: supplies the id for the component.
  1253. Return Value:
  1254. DWORD: returns error status
  1255. --*/
  1256. DWORD RunOcCleanup(IN LPCVOID lpcvComponentId)
  1257. {
  1258. UINT uiCount;
  1259. RemoveComponent(lpcvComponentId);
  1260. g_bFirstTime = TRUE;
  1261. //
  1262. // Close the witness file queue
  1263. //
  1264. SetupCloseFileQueue(g_FileQueue);
  1265. return NO_ERROR;
  1266. } // RunOcCleanup //
  1267. /*++
  1268. Routine Description: RunTestOcPrivateBase (1.22)
  1269. Code to run if OCP_TEST_PRIVATE_BASE is called.
  1270. Arguments:
  1271. lpcvSubcomponentId: supplies the id for the subcomponent.
  1272. uiParam1: its meaning depends on the function.
  1273. pvParam2: its meaning depends on the function.
  1274. Return Value:
  1275. DWORD: returns error status
  1276. --*/
  1277. DWORD RunTestOcPrivateBase(IN LPCVOID lpcvSubcomponentId,
  1278. IN UINT uiParam1,
  1279. IN PVOID pvParam2)
  1280. {
  1281. //
  1282. // Will send back the value in Param1.
  1283. // But first, assert that the subcomponent is NULL,
  1284. // as well as the Param2
  1285. //
  1286. __ASSERT((lpcvSubcomponentId == NULL) && (pvParam2 == NULL));
  1287. return uiParam1;
  1288. } // RunTestOcPrivateBase //
  1289. /*++
  1290. Routine Description: TestHelperRoutines (1.5)
  1291. Tests the helper routines, using the functions above.
  1292. Arguments:
  1293. OCManagerRoutines: the helper routines.
  1294. Return Value:
  1295. DWORD: error return
  1296. --*/
  1297. DWORD TestHelperRoutines(IN LPCVOID lpcvComponentId,
  1298. IN OCMANAGER_ROUTINES OCManagerRoutines)
  1299. {
  1300. double fn = 1.5;
  1301. DWORD dwPreviousMode, dwSetPreviousMode, dwSetupMode, dwRandomSetupMode;
  1302. DWORD dwComponentReturnValue;
  1303. DWORD dwError;
  1304. TCHAR tszMsg[MAX_MSG_LEN];
  1305. BOOL bQueryReturn;
  1306. //
  1307. // Test TickGauge - the call is ignored except when the component
  1308. // is allowed to perform its own (final) setup and informs the OC Manager
  1309. // about the number of steps this setup will require.
  1310. // For each such step, the OC Manager ticks the gauge once.
  1311. //
  1312. OCManagerRoutines.TickGauge(OCManagerRoutines.OcManagerContext);
  1313. //
  1314. // Test SetProgressText - the call is ignored except the final stage
  1315. // (the text above the tick gauge is set this way)
  1316. //
  1317. OCManagerRoutines.SetProgressText(OCManagerRoutines.OcManagerContext,
  1318. TEXT("Progress text"));
  1319. //
  1320. // Test Get/SetPrivateData
  1321. //
  1322. TestPrivateData(OCManagerRoutines);
  1323. //
  1324. // Test Get/SetSetupMode
  1325. //
  1326. //
  1327. // Get the original mode first
  1328. //
  1329. dwPreviousMode = OCManagerRoutines.GetSetupMode(
  1330. OCManagerRoutines.OcManagerContext);
  1331. dwRandomSetupMode = (DWORD)rand();
  1332. //
  1333. // The return value should be the previous mode
  1334. //
  1335. dwSetPreviousMode = OCManagerRoutines.SetSetupMode(
  1336. OCManagerRoutines.OcManagerContext,
  1337. dwRandomSetupMode);
  1338. if (dwPreviousMode != dwSetPreviousMode)
  1339. {
  1340. Log(fn, SEV2, TEXT("SetSetupMode failed. Return value is not equal ")
  1341. TEXT("to previous mode: Previous = %lu Return = %lu ")
  1342. TEXT("New Mode = %lu"),
  1343. dwPreviousMode, dwSetPreviousMode, dwRandomSetupMode);
  1344. }
  1345. else
  1346. {
  1347. //
  1348. // Set the mode again
  1349. // The first 24 bits are private data, the last 8 are the mode
  1350. //
  1351. dwSetupMode = ((DWORD)rand()) << 8;
  1352. //
  1353. // So, get the last 8 bits from PreviousMode
  1354. //
  1355. dwSetupMode |= (dwPreviousMode & 0xFF);
  1356. dwSetPreviousMode = OCManagerRoutines.SetSetupMode(
  1357. OCManagerRoutines.OcManagerContext,
  1358. dwSetupMode);
  1359. if (dwRandomSetupMode != dwSetPreviousMode)
  1360. {
  1361. Log(fn, SEV2, TEXT("SetSetupMode failed. Return value is not ")
  1362. TEXT("equal to previous mode: Previous = %lu ")
  1363. TEXT("Return = %lu New Mode = %lu"),
  1364. dwRandomSetupMode, dwSetPreviousMode, dwSetupMode);
  1365. }
  1366. }
  1367. //
  1368. // Leave the mode back at its original state
  1369. //
  1370. dwSetPreviousMode = OCManagerRoutines.SetSetupMode(
  1371. OCManagerRoutines.OcManagerContext,
  1372. dwPreviousMode);
  1373. //
  1374. // Test QuerySelectionState
  1375. //
  1376. //
  1377. // Perform negative testing first : use an inexistent component name
  1378. // Expect to get ERROR_INVALID_NAME
  1379. //
  1380. bQueryReturn = OCManagerRoutines.QuerySelectionState(
  1381. OCManagerRoutines.OcManagerContext,
  1382. TEXT("Phony component"),
  1383. OCSELSTATETYPE_ORIGINAL);
  1384. if ((bQueryReturn == FALSE) &&
  1385. ((dwError = GetLastError()) != ERROR_INVALID_NAME ))
  1386. {
  1387. Log(fn, SEV2, TEXT("QuerySelectionState returned error %lu ")
  1388. TEXT("when called with phony name"), dwError);
  1389. }
  1390. bQueryReturn = OCManagerRoutines.QuerySelectionState(
  1391. OCManagerRoutines.OcManagerContext,
  1392. TEXT("Phony component"),
  1393. OCSELSTATETYPE_CURRENT);
  1394. if ((bQueryReturn == FALSE) &&
  1395. ((dwError = GetLastError()) != ERROR_INVALID_NAME ))
  1396. {
  1397. Log(fn, SEV2, TEXT("QuerySelectionState returned error %lu ")
  1398. TEXT("when called with phony name"), dwError);
  1399. }
  1400. SetLastError(NO_ERROR);
  1401. //
  1402. // Tests the private function calls
  1403. // Save the return value first : this is done because another
  1404. // component is called and the return value is modified
  1405. //
  1406. dwComponentReturnValue = TestPrivateFunction(lpcvComponentId,
  1407. OCManagerRoutines);
  1408. return dwComponentReturnValue;
  1409. } // TestHelperRountines //
  1410. /*++
  1411. Routine Description: TestPrivateFunction (1.4)
  1412. Tests the private function calls
  1413. (these are used for inter-component communication)
  1414. Arguments:
  1415. OCManagerRoutines: the helper routines (CallPrivateFunction is a member
  1416. of this structure)
  1417. Return Value:
  1418. DWORD: error value
  1419. --*/
  1420. DWORD TestPrivateFunction(IN LPCVOID lpcvComponentId,
  1421. IN OCMANAGER_ROUTINES OCManagerRoutines)
  1422. {
  1423. double fn = 1.4;
  1424. DWORD dwComponentReturnValue = ERROR_SUCCESS;
  1425. UINT uiRemoteResult = 0;
  1426. UINT uiLocalResult = 0;
  1427. UINT uiRandomValue = 0;
  1428. BOOL bBlank = FALSE;
  1429. BOOL bOtherComponent = FALSE;
  1430. TCHAR tszComponent[MAX_PATH];
  1431. TCHAR tszOtherComponent[MAX_PATH];
  1432. TCHAR tszStandalone[MAX_PATH];
  1433. TCHAR tszMsg[MAX_MSG_LEN];
  1434. TCHAR tszSubComp[] = TEXT("");
  1435. PSUBCOMP pscTemp;
  1436. //
  1437. // Copy the current component
  1438. //
  1439. _tcscpy(tszComponent, (PTCHAR)lpcvComponentId);
  1440. //
  1441. // Find another component, if one exists
  1442. //
  1443. for (pscTemp = g_pscHead; pscTemp != NULL; pscTemp = pscTemp->Next)
  1444. {
  1445. if (_tcscmp(tszComponent, pscTemp->tszComponentId) != 0)
  1446. {
  1447. bOtherComponent = TRUE;
  1448. _tcscpy(tszOtherComponent, pscTemp->tszComponentId);
  1449. break;
  1450. }
  1451. }
  1452. //
  1453. // 1. Call the same component
  1454. //
  1455. uiLocalResult = OCManagerRoutines.CallPrivateFunction(
  1456. OCManagerRoutines.OcManagerContext,
  1457. tszComponent,
  1458. tszSubComp,
  1459. OCP_TEST_PRIVATE_BASE,
  1460. 0, 0, &uiRemoteResult);
  1461. if (uiLocalResult != ERROR_BAD_ENVIRONMENT)
  1462. {
  1463. Log(fn, SEV2, TEXT("CallPrivateFunction: expected ")
  1464. TEXT("ERROR_BAD_ENVIRONMENT, received %lu"),
  1465. uiLocalResult);
  1466. bBlank = TRUE;
  1467. }
  1468. //
  1469. // 2. Call a non-existing component
  1470. //
  1471. uiLocalResult = OCManagerRoutines.CallPrivateFunction(
  1472. OCManagerRoutines.OcManagerContext,
  1473. TEXT("No component"),
  1474. tszSubComp,
  1475. OCP_TEST_PRIVATE_BASE,
  1476. 0, 0, &uiRemoteResult);
  1477. if (uiLocalResult != ERROR_INVALID_FUNCTION)
  1478. {
  1479. Log(fn, SEV2, TEXT("CallPrivateFunction: expected ")
  1480. TEXT("ERROR_INVALID_FUNCTION, received %lu"),
  1481. uiLocalResult);
  1482. bBlank = TRUE;
  1483. }
  1484. //
  1485. // 3. Call the standalone component
  1486. //
  1487. uiLocalResult = OCManagerRoutines.CallPrivateFunction(
  1488. OCManagerRoutines.OcManagerContext,
  1489. tszStandalone,
  1490. tszSubComp,
  1491. OCP_TEST_PRIVATE_BASE,
  1492. 0, 0, &uiRemoteResult);
  1493. if (uiLocalResult != ERROR_INVALID_FUNCTION)
  1494. {
  1495. Log(fn, SEV2, TEXT("CallPrivateFunction: expected ")
  1496. TEXT("ERROR_INVALID_FUNCTION, received %lu"),
  1497. uiLocalResult);
  1498. bBlank = TRUE;
  1499. }
  1500. if (bOtherComponent)
  1501. {
  1502. //
  1503. // 4. Call the other component with OC_PRIVATE_BASE - 1
  1504. //
  1505. uiLocalResult = OCManagerRoutines.CallPrivateFunction(
  1506. OCManagerRoutines.OcManagerContext,
  1507. tszOtherComponent,
  1508. tszSubComp,
  1509. OC_PRIVATE_BASE - 1,
  1510. 0, 0, &uiRemoteResult);
  1511. if (uiLocalResult != ERROR_INVALID_FUNCTION)
  1512. {
  1513. Log(fn, SEV2, TEXT("CallPrivateFunction: expected ")
  1514. TEXT("ERROR_INVALID_FUNCTION, received %lu"),
  1515. uiLocalResult);
  1516. bBlank = TRUE;
  1517. }
  1518. //
  1519. // 5. A normal call : we will supply a random number and will expect
  1520. // to receive as a result the same value. This is true if the
  1521. // private calls are allowed
  1522. //
  1523. uiRandomValue = (UINT)(rand() + 1);
  1524. //
  1525. // To be sure the two values are not equal
  1526. //
  1527. uiRemoteResult = 0;
  1528. uiLocalResult = OCManagerRoutines.CallPrivateFunction(
  1529. OCManagerRoutines.OcManagerContext,
  1530. tszOtherComponent,
  1531. tszSubComp,
  1532. OCP_TEST_PRIVATE_BASE,
  1533. uiRandomValue,
  1534. 0,
  1535. &uiRemoteResult);
  1536. if (uiLocalResult != ERROR_ACCESS_DENIED)
  1537. {
  1538. if (g_bUsePrivateFunctions && (uiLocalResult != NO_ERROR))
  1539. {
  1540. Log(fn, SEV2, TEXT("CallPrivateFunction called on %s for ")
  1541. TEXT("OCP_TEST_PRIVATE_BASE returned %lu"),
  1542. tszOtherComponent, uiLocalResult);
  1543. bBlank = TRUE;
  1544. }
  1545. if (!g_bUsePrivateFunctions &&
  1546. (uiLocalResult != ERROR_BAD_ENVIRONMENT))
  1547. {
  1548. Log(fn, SEV2, TEXT("CallPrivateFunction: expected ")
  1549. TEXT("ERROR_BAD_ENVIRONMENT, received %lu"),
  1550. uiLocalResult);
  1551. bBlank = TRUE;
  1552. }
  1553. if (g_bUsePrivateFunctions && (uiRemoteResult != uiRandomValue))
  1554. {
  1555. Log(fn, SEV2, TEXT("CallPrivateFunction: received invalid data ")
  1556. TEXT("from routine. Expected %lu, received %lu"),
  1557. uiRandomValue, uiRemoteResult);
  1558. bBlank = TRUE;
  1559. }
  1560. }
  1561. }
  1562. if (bBlank) LogBlankLine();
  1563. return dwComponentReturnValue;
  1564. } // TestPrivateFunction //
  1565. /*++
  1566. Routine Description: TestPrivateData (1.3)
  1567. Checks all the OC Manager values against the local ones,
  1568. then it randomly changes one value.
  1569. Arguments:
  1570. OCManagerRoutines: the helper routines (Get/SetPrivateData are members
  1571. of this structure)
  1572. Return Value:
  1573. void
  1574. --*/
  1575. VOID TestPrivateData(IN OCMANAGER_ROUTINES OCManagerRoutines)
  1576. {
  1577. double fn = 1.3;
  1578. PVOID pvBuffer;
  1579. UINT uiCount, uiRandomValue;
  1580. BOOL bResult;
  1581. PRIVATE_DATA aPrivateDataTable[] =
  1582. {
  1583. {TEXT("Binary value"), REG_BINARY, 0, NULL, NULL},
  1584. {TEXT("Binary value 2"), REG_BINARY, 0, NULL, NULL},
  1585. {TEXT("String value"), REG_SZ, 0, NULL, NULL},
  1586. {TEXT("String value 2"), REG_SZ, 0, NULL, NULL},
  1587. {TEXT("Multi String value"), REG_MULTI_SZ, 0, NULL, NULL},
  1588. {TEXT("Multi String value 2"), REG_MULTI_SZ, 0, NULL, NULL},
  1589. {TEXT("DWORD value"), REG_DWORD, 0, NULL, NULL},
  1590. {TEXT("DWORD value 2"), REG_DWORD, 0, NULL, NULL}
  1591. };
  1592. //
  1593. // Set all the values
  1594. //
  1595. for (uiCount = 0; uiCount < MAX_PRIVATE_VALUES; uiCount++)
  1596. {
  1597. bResult = SetAValue(OCManagerRoutines, uiCount, aPrivateDataTable);
  1598. }
  1599. //
  1600. // Check all the values against the local table
  1601. //
  1602. CheckPrivateValues(OCManagerRoutines, aPrivateDataTable);
  1603. free(aPrivateDataTable[0].pvBuffer);
  1604. free(aPrivateDataTable[1].pvBuffer);
  1605. free(aPrivateDataTable[2].pvBuffer);
  1606. free(aPrivateDataTable[3].pvBuffer);
  1607. free(aPrivateDataTable[4].pbBuffer);
  1608. free(aPrivateDataTable[5].pbBuffer);
  1609. free(aPrivateDataTable[6].pvBuffer);
  1610. free(aPrivateDataTable[7].pvBuffer);
  1611. return;
  1612. } // TestPrivateData //
  1613. /*++
  1614. Routine Description: CheckPrivateValues (1.2)
  1615. Checks the values of the private data stored by the OC Manager against
  1616. those stored internally by the application.
  1617. Arguments:
  1618. OCManagerRoutines: the helper routines (GetPrivateData is a member of
  1619. this structure)
  1620. Return Value:
  1621. void
  1622. --*/
  1623. VOID CheckPrivateValues(IN OCMANAGER_ROUTINES OCManagerRoutines,
  1624. IN PRIVATE_DATA *aPrivateDataTable)
  1625. {
  1626. double fn = 1.2;
  1627. UINT uiCount, uiSize, uiType;
  1628. DWORD dwErrorCode;
  1629. PVOID pvBuffer = NULL;
  1630. PTCHAR tszBuffer;
  1631. TCHAR tszMsg[MAX_MSG_LEN];
  1632. TCHAR tszError[MAX_ERROR_LEN];
  1633. for (uiCount = 0; uiCount < MAX_PRIVATE_VALUES; uiCount++)
  1634. {
  1635. //
  1636. // First call is used only to get the size of the data
  1637. // Only the second one will actually retrieve it
  1638. //
  1639. dwErrorCode = OCManagerRoutines.GetPrivateData(
  1640. OCManagerRoutines.OcManagerContext,
  1641. NULL,
  1642. aPrivateDataTable[uiCount].tszName,
  1643. NULL,
  1644. &uiSize,
  1645. &uiType);
  1646. if (dwErrorCode != NO_ERROR)
  1647. {
  1648. Log(fn, SEV2, TEXT("GetPrivateData failed for %s: %s"),
  1649. aPrivateDataTable[uiCount].tszName,
  1650. ErrorMsg(dwErrorCode, tszError));
  1651. continue;
  1652. }
  1653. if (pvBuffer) __Free(&pvBuffer);
  1654. __Malloc(&pvBuffer, uiSize);
  1655. dwErrorCode = OCManagerRoutines.GetPrivateData(
  1656. OCManagerRoutines.OcManagerContext,
  1657. NULL,
  1658. aPrivateDataTable[uiCount].tszName,
  1659. pvBuffer,
  1660. &uiSize,
  1661. &uiType);
  1662. if (dwErrorCode != NO_ERROR)
  1663. {
  1664. Log(fn, SEV2, TEXT("GetPrivateData failed for %s: %s"),
  1665. aPrivateDataTable[uiCount].tszName,
  1666. ErrorMsg(dwErrorCode, tszError));
  1667. continue;
  1668. }
  1669. //
  1670. // Now perform the actual checking
  1671. // The type first
  1672. //
  1673. if (uiType != aPrivateDataTable[uiCount].uiType)
  1674. {
  1675. Log(fn, SEV2, TEXT("GetPrivateData: Retrieved type %d ")
  1676. TEXT("instead of %d"),
  1677. uiType, aPrivateDataTable[uiCount].uiType);
  1678. }
  1679. //
  1680. // Then the size
  1681. //
  1682. if (uiSize != aPrivateDataTable[uiCount].uiSize)
  1683. {
  1684. if (uiType == REG_SZ)
  1685. {
  1686. tszBuffer = (PTCHAR)pvBuffer;
  1687. _stprintf(tszMsg, TEXT("GetPrivateData: Size retrieved %d ")
  1688. TEXT("expected %d, ")
  1689. TEXT("pvBuffer = %s, known buffer = %s, ")
  1690. TEXT("Chars %u %u %u %u"),
  1691. uiSize,
  1692. aPrivateDataTable[uiCount].uiSize,
  1693. tszBuffer,
  1694. aPrivateDataTable[uiCount].pvBuffer,
  1695. tszBuffer[uiSize - 4],
  1696. tszBuffer[uiSize - 3],
  1697. tszBuffer[uiSize - 2],
  1698. tszBuffer[uiSize - 1]);
  1699. }
  1700. else
  1701. {
  1702. if (uiType == REG_MULTI_SZ)
  1703. {
  1704. TCHAR tszAux[MAX_MSG_LEN];
  1705. _stprintf(tszMsg, TEXT("MULTI_SZ Size retrieved %d, ")
  1706. TEXT("expected %d, pvBuffer = "),
  1707. uiSize, aPrivateDataTable[uiCount].uiSize);
  1708. tszBuffer = (PTCHAR)pvBuffer;
  1709. MultiStringToString(tszBuffer, tszAux);
  1710. _tcscat(tszMsg, tszAux);
  1711. _tcscat(tszMsg, TEXT(" and known buffer = "));
  1712. tszBuffer = (PTCHAR)aPrivateDataTable[uiCount].pvBuffer;
  1713. MultiStringToString(tszBuffer, tszAux);
  1714. _tcscat(tszMsg, tszAux);
  1715. }
  1716. else
  1717. {
  1718. _stprintf(tszMsg, TEXT("Size retrieved %d instead %d"),
  1719. uiSize, aPrivateDataTable[uiCount].uiSize);
  1720. }
  1721. }
  1722. Log(fn, SEV2, tszMsg);
  1723. }
  1724. if (uiType == REG_BINARY)
  1725. {
  1726. if (memcmp(pvBuffer,
  1727. aPrivateDataTable[uiCount].pbBuffer,
  1728. aPrivateDataTable[uiCount].uiSize))
  1729. {
  1730. Log(fn, SEV2, TEXT("Private data %s, Received %s expected %s"),
  1731. aPrivateDataTable[uiCount].tszName,
  1732. (PTSTR)pvBuffer,
  1733. (PTSTR)aPrivateDataTable[uiCount].pbBuffer);
  1734. }
  1735. }
  1736. else
  1737. {
  1738. if (memcmp(pvBuffer,
  1739. aPrivateDataTable[uiCount].pvBuffer,
  1740. aPrivateDataTable[uiCount].uiSize))
  1741. {
  1742. Log(fn, SEV2, TEXT("Private data %s, Received %s expected %s"),
  1743. aPrivateDataTable[uiCount].tszName,
  1744. (PTSTR)pvBuffer,
  1745. (PTSTR)aPrivateDataTable[uiCount].pvBuffer);
  1746. }
  1747. }
  1748. //
  1749. // Try to use a smaller buffer - should get an error code
  1750. //
  1751. uiSize--;
  1752. dwErrorCode = OCManagerRoutines.GetPrivateData(
  1753. OCManagerRoutines.OcManagerContext,
  1754. NULL,
  1755. aPrivateDataTable[uiCount].tszName,
  1756. pvBuffer,
  1757. &uiSize,
  1758. &uiType);
  1759. if (dwErrorCode != ERROR_INSUFFICIENT_BUFFER)
  1760. {
  1761. Log(fn, SEV2, TEXT("GetPrivateData returned %s when called ")
  1762. TEXT("with small buffer size for %s"),
  1763. ErrorMsg(dwErrorCode, tszError),
  1764. aPrivateDataTable[uiCount].tszName);
  1765. continue;
  1766. }
  1767. __Free(&pvBuffer);
  1768. }
  1769. if (pvBuffer) __Free(&pvBuffer);
  1770. } // CheckPrivateValues //
  1771. /*++
  1772. Routine Description: SetAValue (1.1)
  1773. Sets the value of a variable from the private data. The variable
  1774. that will be changed is randomly selected.
  1775. Arguments:
  1776. OCManagerRoutines: the helper routines (SetPrivateData is a member
  1777. of this structure)
  1778. uiIndex: the index of the variable to change
  1779. Return Value:
  1780. BOOL: TRUE if value is set, FALSE if not
  1781. --*/
  1782. BOOL SetAValue(IN OCMANAGER_ROUTINES OCManagerRoutines,
  1783. IN UINT uiIndex,
  1784. IN OUT PRIVATE_DATA *aPrivateDataTable)
  1785. {
  1786. double fn = 1.1;
  1787. UINT uiAuxIndex;
  1788. UINT uiOffset;
  1789. DWORD dwRandomValue;
  1790. PTCHAR tszBuffer;
  1791. TCHAR tszMsg[MAX_MSG_LEN];
  1792. switch (aPrivateDataTable[uiIndex].uiType)
  1793. {
  1794. case REG_DWORD:
  1795. aPrivateDataTable[uiIndex].uiSize = sizeof(DWORD);
  1796. aPrivateDataTable[uiIndex].pvBuffer =
  1797. (PVOID)malloc(aPrivateDataTable[uiIndex].uiSize);
  1798. //
  1799. // Fill in the buffer
  1800. //
  1801. dwRandomValue = (DWORD)rand();
  1802. memcpy(aPrivateDataTable[uiIndex].pvBuffer,
  1803. &dwRandomValue,
  1804. aPrivateDataTable[uiIndex].uiSize);
  1805. //
  1806. // Set the private data "with" the OC Manager
  1807. //
  1808. OCManagerRoutines.SetPrivateData(
  1809. OCManagerRoutines.OcManagerContext,
  1810. aPrivateDataTable[uiIndex].tszName,
  1811. aPrivateDataTable[uiIndex].pvBuffer,
  1812. aPrivateDataTable[uiIndex].uiSize,
  1813. aPrivateDataTable[uiIndex].uiType);
  1814. break;
  1815. case REG_BINARY:
  1816. aPrivateDataTable[uiIndex].uiSize =
  1817. (UINT)(rand() % MAX_PRIVATE_DATA_SIZE) + 1;
  1818. aPrivateDataTable[uiIndex].pbBuffer =
  1819. (PVOID)malloc(aPrivateDataTable[uiIndex].uiSize);
  1820. //
  1821. // Fill in the buffer
  1822. //
  1823. for (uiAuxIndex = 0;
  1824. uiAuxIndex < aPrivateDataTable[uiIndex].uiSize;
  1825. uiAuxIndex++)
  1826. {
  1827. aPrivateDataTable[uiIndex].pbBuffer[uiAuxIndex] = (BYTE)rand();
  1828. }
  1829. //
  1830. // Set the private data
  1831. //
  1832. OCManagerRoutines.SetPrivateData(
  1833. OCManagerRoutines.OcManagerContext,
  1834. aPrivateDataTable[uiIndex].tszName,
  1835. aPrivateDataTable[uiIndex].pbBuffer,
  1836. aPrivateDataTable[uiIndex].uiSize,
  1837. aPrivateDataTable[uiIndex].uiType);
  1838. break;
  1839. case REG_SZ:
  1840. uiAuxIndex = (UINT)(rand() % MAX_STRINGS_FOR_PRIVATE_DATA);
  1841. aPrivateDataTable[uiIndex].uiSize =
  1842. (_tcslen(g_atszStringValues[uiAuxIndex]) + 1) * sizeof(TCHAR);
  1843. aPrivateDataTable[uiIndex].pvBuffer =
  1844. (PVOID)malloc(aPrivateDataTable[uiIndex].uiSize);
  1845. //
  1846. // Fill in the buffer
  1847. //
  1848. _tcscpy((PTSTR)aPrivateDataTable[uiIndex].pvBuffer,
  1849. g_atszStringValues[uiAuxIndex]);
  1850. //
  1851. // Set the private data
  1852. //
  1853. OCManagerRoutines.SetPrivateData(
  1854. OCManagerRoutines.OcManagerContext,
  1855. aPrivateDataTable[uiIndex].tszName,
  1856. aPrivateDataTable[uiIndex].pvBuffer,
  1857. aPrivateDataTable[uiIndex].uiSize,
  1858. aPrivateDataTable[uiIndex].uiType);
  1859. break;
  1860. case REG_MULTI_SZ:
  1861. uiAuxIndex = (UINT)(rand() % MAX_MULTI_STRINGS_FOR_PRIVATE_DATA);
  1862. aPrivateDataTable[uiIndex].uiSize =
  1863. MultiStringSize(g_atszMultiStringValues[uiAuxIndex]);
  1864. aPrivateDataTable[uiIndex].pvBuffer =
  1865. (PVOID)malloc(aPrivateDataTable[uiIndex].uiSize);
  1866. //
  1867. // Fill in the buffer
  1868. //
  1869. CopyMultiString((PTSTR)aPrivateDataTable[uiIndex].pvBuffer,
  1870. g_atszMultiStringValues[uiAuxIndex]);
  1871. //
  1872. // Set the private data
  1873. //
  1874. OCManagerRoutines.SetPrivateData(
  1875. OCManagerRoutines.OcManagerContext,
  1876. aPrivateDataTable[uiIndex].tszName,
  1877. aPrivateDataTable[uiIndex].pvBuffer,
  1878. aPrivateDataTable[uiIndex].uiSize,
  1879. aPrivateDataTable[uiIndex].uiType);
  1880. break;
  1881. default:
  1882. break;
  1883. }
  1884. return TRUE;
  1885. } // SetAValue //
  1886. /*++
  1887. Routine Description: ChooseSubcomponentInitialState (1.31)
  1888. "Wrapper" routine for the dialog box procedure ChooseSuncomponentDlgProc.
  1889. Arguments:
  1890. lpcvComponentId: supplies the id for the component.
  1891. lpcvSubcomponentId: supplies the id for the subcomponent.
  1892. Return Value:
  1893. void
  1894. --*/
  1895. DWORD ChooseSubcomponentInitialState(IN LPCVOID lpcvComponentId,
  1896. IN LPCVOID lpcvSubcomponentId)
  1897. {
  1898. TCHAR tszDlgBoxMessage[MAX_MSG_LEN];
  1899. //
  1900. // We will display a dialog box so the user can choose the
  1901. // initial state he/she wants
  1902. //
  1903. _stprintf(tszDlgBoxMessage, TEXT("%s, %s"),
  1904. lpcvComponentId, lpcvSubcomponentId);
  1905. return DialogBoxParam(g_hDllInstance,
  1906. MAKEINTRESOURCE(IDD_DIALOG3),
  1907. NULL,
  1908. ChooseSubcomponentDlgProc,
  1909. (LPARAM)tszDlgBoxMessage);
  1910. } // ChooseSubcomponentInitialState //
  1911. /*++
  1912. Routine Description: AddNewComponent (1.32)
  1913. Add a new component to the list
  1914. Arguments:
  1915. tszComponentId: supplies id of component to be added to the list.
  1916. Return Value:
  1917. Pointer to new per-component data structure or NULL if no memory.
  1918. The structure will be zeroed out except for the ComponentId field.
  1919. --*/
  1920. PCOMPONENT_DATA AddNewComponent(IN LPCTSTR tszComponentId)
  1921. {
  1922. PCOMPONENT_DATA pcdAux;
  1923. if (__Malloc(&pcdAux, sizeof(COMPONENT_DATA)))
  1924. {
  1925. __Malloc(&(PTCHAR)(pcdAux->tszComponentId),
  1926. (_tcslen(tszComponentId) + 1) * sizeof(TCHAR));
  1927. if (pcdAux->tszComponentId)
  1928. {
  1929. _tcscpy((PTSTR)pcdAux->tszComponentId, tszComponentId);
  1930. //
  1931. // Prepend at the begining
  1932. //
  1933. pcdAux->Next = g_pcdComponents;
  1934. g_pcdComponents = pcdAux;
  1935. }
  1936. }
  1937. return pcdAux;
  1938. } // AddNewComponent //
  1939. /*++
  1940. Routine Description: LocateComponent (1.33)
  1941. Locate a component by name from the list of components
  1942. that this dll has been assigned to handle via
  1943. OC_INIT_COMPONENT.
  1944. Arguments:
  1945. tszComponentId: supplies the id for the component to look up.
  1946. Return Value:
  1947. Pointer to component data or NULL if not found.
  1948. --*/
  1949. PCOMPONENT_DATA LocateComponent(IN LPCTSTR tszComponentId)
  1950. {
  1951. PCOMPONENT_DATA pcdAux;
  1952. for (pcdAux = g_pcdComponents; pcdAux; pcdAux = pcdAux->Next)
  1953. {
  1954. if (!(_tcscmp(pcdAux->tszComponentId, tszComponentId)))
  1955. {
  1956. break;
  1957. }
  1958. }
  1959. return pcdAux;
  1960. } // LocateComponent //
  1961. /*++
  1962. Routine Description: RemoveComponent (1.34)
  1963. Locate a component by name from the list of components and
  1964. then remove it from the list of components.
  1965. Arguments:
  1966. tszComponentId: supplies the id for the component to remove.
  1967. Return Value:
  1968. void
  1969. --*/
  1970. VOID RemoveComponent(IN LPCTSTR tszComponentId)
  1971. {
  1972. PCOMPONENT_DATA pcdAux, pcdPrev;
  1973. for (pcdPrev = NULL, pcdAux = g_pcdComponents;
  1974. pcdAux;
  1975. pcdPrev = pcdAux, pcdAux = pcdAux->Next)
  1976. {
  1977. if (!(_tcscmp(pcdAux->tszComponentId, tszComponentId)))
  1978. {
  1979. __Free(&(PTCHAR)(pcdAux->tszComponentId));
  1980. if (pcdPrev)
  1981. {
  1982. pcdPrev->Next = pcdAux->Next;
  1983. }
  1984. else
  1985. {
  1986. g_pcdComponents = pcdAux->Next;
  1987. }
  1988. __Free(&pcdAux);
  1989. break;
  1990. }
  1991. }
  1992. return;
  1993. } // RemoveComponent //
  1994. /*++
  1995. Routine Description: CleanUpTest (1.35)
  1996. Frees globally allocated memory before the test exits
  1997. Arguments:
  1998. none
  1999. Return Value:
  2000. void
  2001. --*/
  2002. VOID CleanUpTest()
  2003. {
  2004. USHORT i;
  2005. PCOMPONENT_DATA pcdAux = g_pcdComponents, pcdNext;
  2006. while (pcdAux)
  2007. {
  2008. pcdNext = pcdAux->Next;
  2009. __Free(&(PTCHAR)(pcdAux->tszComponentId));
  2010. __Free(&pcdAux);
  2011. pcdAux = pcdNext;
  2012. }
  2013. FreeSubcomponentInformationList();
  2014. return;
  2015. } // CleanUpTest //
  2016. /*++
  2017. Routine Description: CreateSubcomponentInformationList (1.23)
  2018. Creates a linked list of every subcomponent. For each subcomponent,
  2019. tells the parent of the subcomponent and whether or not the
  2020. subcomponent has any children.
  2021. Arguments:
  2022. hinf: handle to inf file
  2023. Return Value:
  2024. BOOL: TRUE if function succeeds, FALSE if it fails
  2025. --*/
  2026. BOOL CreateSubcomponentInformationList(IN HINF hinf)
  2027. {
  2028. double fn = 1.23;
  2029. int i, j;
  2030. USHORT usIdLen;
  2031. USHORT usParentIndex;
  2032. LONG lLine, lLineCount;
  2033. DWORD dwSize;
  2034. BOOL bRetval;
  2035. BOOL bFound;
  2036. TCHAR tszSubcomponent[MAX_PATH];
  2037. TCHAR tszParent[MAX_PATH];
  2038. TCHAR tszError[MAX_ERROR_LEN];
  2039. TCHAR tszNeeds[MAX_PATH];
  2040. TCHAR tszExclude[MAX_PATH];
  2041. INFCONTEXT infContext;
  2042. PSUBCOMP pscSubcomponent, pscTemp, pscParent, pscChild;
  2043. PCOMPLIST pclNeeds, pclExclude, pclChild, pclTemp;
  2044. lLineCount = SetupGetLineCount(hinf, TEXT("Optional Components"));
  2045. if (lLineCount < 0)
  2046. {
  2047. Log(fn, SEV2, TEXT("Could not get number of lines in Optional ")
  2048. TEXT("Components section of inf file: %s"),
  2049. ErrorMsg(GetLastError(), tszError));
  2050. return FALSE;
  2051. }
  2052. for (lLine = 0; lLine < lLineCount; lLine++)
  2053. {
  2054. bRetval = SetupGetLineByIndex(hinf,
  2055. TEXT("Optional Components"),
  2056. lLine,
  2057. &infContext);
  2058. if (!bRetval)
  2059. {
  2060. Log(fn, SEV2, TEXT("Could not get line %d from Optional ")
  2061. TEXT("Components section of inf file: %s"),
  2062. lLine, ErrorMsg(GetLastError(), tszError));
  2063. return FALSE;
  2064. }
  2065. bRetval = SetupGetLineText(&infContext,
  2066. NULL,
  2067. NULL,
  2068. NULL,
  2069. tszSubcomponent,
  2070. MAX_PATH,
  2071. &dwSize);
  2072. if (!bRetval)
  2073. {
  2074. Log(fn, SEV2, TEXT("Could not get text of line %d from ")
  2075. TEXT("Optional Components section of inf file: %s"),
  2076. lLine, ErrorMsg(GetLastError(), tszError));
  2077. return FALSE;
  2078. }
  2079. //
  2080. // Allocate a new subcomponent structure
  2081. //
  2082. if (!__Malloc(&pscSubcomponent, sizeof(SUBCOMP)))
  2083. {
  2084. Log(fn, SEV2, TEXT("Could not allocate space for ")
  2085. TEXT("pscSubcomponent"));
  2086. return FALSE;
  2087. }
  2088. pscSubcomponent->pclNeeds = NULL;
  2089. pscSubcomponent->pclExclude = NULL;
  2090. pscSubcomponent->pclChildren = NULL;
  2091. pscSubcomponent->Next = NULL;
  2092. //
  2093. // Find out the subcomponent id's length
  2094. //
  2095. usIdLen = (USHORT) _tcslen(tszSubcomponent);
  2096. //
  2097. // Copy the ComponentId. All of the test inf's use a special
  2098. // SubcomponentId naming format, so that the subcomponent is a
  2099. // superset of the ComponentId. For example, if the component
  2100. // name is "component" the subcomponet names will be
  2101. // "component_1", "component_2", "component_1_2", etc.
  2102. //
  2103. for (i = 0; i < usIdLen; i++)
  2104. {
  2105. if (tszSubcomponent[i] == TEXT('_'))
  2106. {
  2107. break;
  2108. }
  2109. else
  2110. {
  2111. pscSubcomponent->tszComponentId[i] = tszSubcomponent[i];
  2112. }
  2113. }
  2114. pscSubcomponent->tszComponentId[i] = TEXT('\0');
  2115. //
  2116. // if the subcomponent has a parent, get the name of the parent, store
  2117. // it, and then search for this parent amongst the subcomponents
  2118. // we've already processed. If the parent is found, mark the parent
  2119. // so we know that the parent has children.
  2120. //
  2121. //
  2122. // Record the name of the parent.
  2123. //
  2124. if (SetupFindFirstLine(hinf,
  2125. tszSubcomponent,
  2126. TEXT("Parent"),
  2127. &infContext))
  2128. {
  2129. bRetval = SetupGetStringField(&infContext,
  2130. 1,
  2131. tszParent,
  2132. MAX_PATH,
  2133. NULL);
  2134. if (!bRetval)
  2135. {
  2136. //
  2137. // Parent name is empty. This is an invalid INF, but
  2138. // we'll go with it.
  2139. //
  2140. ZeroMemory(tszParent, MAX_PATH);
  2141. }
  2142. else
  2143. {
  2144. //
  2145. // Search through the subcomponent list for this parent
  2146. //
  2147. for (pscParent = g_pscHead;
  2148. pscParent != NULL;
  2149. pscParent = pscParent->Next)
  2150. {
  2151. if (_tcscmp(tszParent, pscParent->tszSubcomponentId) == 0)
  2152. {
  2153. //
  2154. // Found the parent subcomponent node. Add the current
  2155. // subcomponent to the parent node's children list,
  2156. // if it isn't there already
  2157. //
  2158. bFound = FALSE;
  2159. for (pclTemp = pscParent->pclChildren;
  2160. pclTemp != NULL;
  2161. pclTemp = pclTemp->Next)
  2162. {
  2163. if (_tcscmp(pclTemp->tszSubcomponentId,
  2164. tszSubcomponent) == 0)
  2165. {
  2166. bFound = TRUE;
  2167. }
  2168. }
  2169. if (!bFound)
  2170. {
  2171. if (!__Malloc(&pclChild, sizeof(COMPLIST)))
  2172. {
  2173. Log(fn, SEV2, TEXT("Out of memory"));
  2174. break;
  2175. }
  2176. _tcscpy(pclChild->tszSubcomponentId, tszSubcomponent);
  2177. pclChild->Next = pscParent->pclChildren;
  2178. pscParent->pclChildren = pclChild;
  2179. }
  2180. }
  2181. }
  2182. }
  2183. }
  2184. else
  2185. {
  2186. //
  2187. // This component has no parent. Assume this is the top-level
  2188. // component and assign it's parent's name as itself
  2189. //
  2190. _tcscpy(tszParent, tszSubcomponent);
  2191. }
  2192. _tcscpy(pscSubcomponent->tszParentId, tszParent);
  2193. //
  2194. // Now search through the list to see if any of the subcomponents
  2195. // in the list are children of this new subcomponent
  2196. //
  2197. for (pscChild = g_pscHead; pscChild != NULL; pscChild = pscChild->Next)
  2198. {
  2199. if (_tcscmp(tszSubcomponent, pscChild->tszParentId) == 0)
  2200. {
  2201. //
  2202. // Found a node that is the child of the current
  2203. // node. Add this child to the current node's
  2204. // child list, if it isn't there already
  2205. //
  2206. bFound = FALSE;
  2207. for (pclTemp = pscSubcomponent->pclChildren;
  2208. pclTemp != NULL;
  2209. pclTemp = pclTemp->Next)
  2210. {
  2211. if (_tcscmp(pclTemp->tszSubcomponentId,
  2212. pscChild->tszSubcomponentId) == 0)
  2213. {
  2214. bFound = TRUE;
  2215. }
  2216. }
  2217. if (!bFound)
  2218. {
  2219. if (!__Malloc(&pclChild, sizeof(COMPLIST)))
  2220. {
  2221. Log(fn, SEV2, TEXT("Out of memory"));
  2222. break;
  2223. }
  2224. _tcscpy(pclChild->tszSubcomponentId,
  2225. pscChild->tszSubcomponentId);
  2226. pclChild->Next = pscSubcomponent->pclChildren;
  2227. pscSubcomponent->pclChildren = pclChild;
  2228. }
  2229. }
  2230. }
  2231. //
  2232. // Fill in the rest of the data for the new node
  2233. //
  2234. _tcscpy(pscSubcomponent->tszSubcomponentId, tszSubcomponent);
  2235. //
  2236. // See if this node has any needs relationships. If it does,
  2237. // record them.
  2238. //
  2239. if (SetupFindFirstLine(hinf,
  2240. tszSubcomponent,
  2241. TEXT("Needs"),
  2242. &infContext))
  2243. {
  2244. for (i = 1, bRetval = TRUE; bRetval; i++)
  2245. {
  2246. bRetval = SetupGetStringField(&infContext,
  2247. i,
  2248. tszNeeds,
  2249. MAX_PATH,
  2250. NULL);
  2251. if (bRetval)
  2252. {
  2253. if (!__Malloc(&pclNeeds, sizeof(COMPLIST)))
  2254. {
  2255. Log(fn, SEV2, TEXT("Out of memory"));
  2256. break;
  2257. }
  2258. _tcscpy(pclNeeds->tszSubcomponentId, tszNeeds);
  2259. pclNeeds->Next = pscSubcomponent->pclNeeds;
  2260. pscSubcomponent->pclNeeds = pclNeeds;
  2261. }
  2262. }
  2263. }
  2264. //
  2265. // See if this node has any exclude relationships. If it does,
  2266. // record them.
  2267. //
  2268. if (SetupFindFirstLine(hinf,
  2269. tszSubcomponent,
  2270. TEXT("Exclude"),
  2271. &infContext))
  2272. {
  2273. for (i = 1, bRetval = TRUE; bRetval; i++)
  2274. {
  2275. bRetval = SetupGetStringField(&infContext,
  2276. i,
  2277. tszExclude,
  2278. MAX_PATH,
  2279. NULL);
  2280. if (bRetval)
  2281. {
  2282. if (!__Malloc(&pclExclude, sizeof(COMPLIST)))
  2283. {
  2284. Log(fn, SEV2, TEXT("Out of memory"));
  2285. break;
  2286. }
  2287. _tcscpy(pclExclude->tszSubcomponentId, tszExclude);
  2288. pclExclude->Next = pscSubcomponent->pclExclude;
  2289. pscSubcomponent->pclExclude = pclExclude;
  2290. }
  2291. }
  2292. }
  2293. //
  2294. // Add the new component to the beginning of the linked list
  2295. //
  2296. pscSubcomponent->Next = g_pscHead;
  2297. g_pscHead = pscSubcomponent;
  2298. } // for (lLine...
  2299. return TRUE;
  2300. } // CreateSubcomponentInformationList //
  2301. /*++
  2302. Routine Description: FreeSubcomponentInformationList (1.36)
  2303. Frees the global linked list of subcomponent information.
  2304. Arguments:
  2305. none
  2306. Return Value:
  2307. void
  2308. --*/
  2309. VOID FreeSubcomponentInformationList()
  2310. {
  2311. PSUBCOMP pscTemp = g_pscHead;
  2312. PSUBCOMP pscNext;
  2313. PCOMPLIST pclTemp, pclNext;
  2314. //
  2315. // Delete all the SUBCOMP nodes
  2316. //
  2317. while (pscTemp)
  2318. {
  2319. pscNext = pscTemp->Next;
  2320. //
  2321. // Delete all the COMPLIST pclNeeds nodes
  2322. //
  2323. pclTemp = pscTemp->pclNeeds;
  2324. while (pclTemp)
  2325. {
  2326. pclNext = pclTemp->Next;
  2327. __Free(&pclTemp);
  2328. pclTemp = pclNext;
  2329. }
  2330. //
  2331. // Delete all the COMPLIST pcdExclude nodes
  2332. //
  2333. pclTemp = pscTemp->pclExclude;
  2334. while (pclTemp)
  2335. {
  2336. pclNext = pclTemp->Next;
  2337. __Free(&pclTemp);
  2338. pclTemp = pclNext;
  2339. }
  2340. //
  2341. // Delete all the COMPLIST pclChildren nodes
  2342. //
  2343. pclTemp = pscTemp->pclChildren;
  2344. while (pclTemp)
  2345. {
  2346. pclNext = pclTemp->Next;
  2347. __Free(&pclTemp);
  2348. pclTemp = pclNext;
  2349. }
  2350. __Free(&pscTemp);
  2351. pscTemp = pscNext;
  2352. }
  2353. g_pscHead = NULL;
  2354. } // FreeSubcomponentInformationList //
  2355. /*++
  2356. Routine Description: ClearSubcomponentInformationMarks (1.37)
  2357. Clears the marks on each of the subcomponent information nodes
  2358. Arguments:
  2359. none
  2360. Return Value:
  2361. void
  2362. --*/
  2363. VOID ClearSubcomponentInformationMarks()
  2364. {
  2365. PSUBCOMP pscTemp;
  2366. for (pscTemp = g_pscHead; pscTemp != NULL; pscTemp = pscTemp->Next)
  2367. {
  2368. pscTemp->bMarked = FALSE;
  2369. }
  2370. } // ClearSubcomponentInformationMarks //
  2371. /*++
  2372. Routine Description: CheckSubcomponentInformationMarks (1.38)
  2373. Clears the marks on each of the subcomponent information nodes
  2374. Arguments:
  2375. none
  2376. Return Value:
  2377. void
  2378. --*/
  2379. VOID CheckSubcomponentInformationMarks()
  2380. {
  2381. double fn = 1.38;
  2382. PSUBCOMP pscTemp;
  2383. for (pscTemp = g_pscHead; pscTemp != NULL; pscTemp = pscTemp->Next)
  2384. {
  2385. if (!(pscTemp->pclChildren) && !(pscTemp->bMarked))
  2386. {
  2387. Log(fn, SEV2, TEXT("%s.%s was not processed"),
  2388. pscTemp->tszComponentId,
  2389. pscTemp->tszSubcomponentId);
  2390. }
  2391. }
  2392. } // CheckSubcomponentInformationMarks //
  2393. /*++
  2394. Routine Description: FindSubcomponentInformationNode (1.39)
  2395. Tries to find a node with matching ComponentId and SubcomponentId
  2396. Arguments:
  2397. tszComponentId: name of the component
  2398. tszSubcomponentId: name of the subcomponent
  2399. Return Value:
  2400. PSUBCOMP: if node is found, returns pointer to node.
  2401. if node is not found, returns NULL
  2402. --*/
  2403. PSUBCOMP FindSubcomponentInformationNode(IN PTCHAR tszComponentId,
  2404. IN PTCHAR tszSubcomponentId)
  2405. {
  2406. PSUBCOMP pscTemp;
  2407. TCHAR tszSubcomp[MAX_PATH];
  2408. __ASSERT(tszComponentId != NULL);
  2409. //
  2410. // If subcomponent is null, this is probably the master component.
  2411. // In this case, subcomponent name should be same as component name.
  2412. //
  2413. if (tszSubcomponentId == NULL ||
  2414. _tcscmp(tszSubcomponentId, TEXT("(null)")) == 0 ||
  2415. tszSubcomponentId[0] == TEXT('\0'))
  2416. {
  2417. _tcscpy(tszSubcomp, tszComponentId);
  2418. }
  2419. else
  2420. {
  2421. _tcscpy(tszSubcomp, tszSubcomponentId);
  2422. }
  2423. //
  2424. // Look for the node
  2425. //
  2426. for (pscTemp = g_pscHead; pscTemp != NULL; pscTemp = pscTemp->Next)
  2427. {
  2428. if (_tcscmp(tszComponentId, pscTemp->tszComponentId) == 0 &&
  2429. _tcscmp(tszSubcomp, pscTemp->tszSubcomponentId) == 0)
  2430. {
  2431. return pscTemp;
  2432. }
  2433. }
  2434. return NULL;
  2435. } // FindSubcomponentInformationNode //
  2436. /*++
  2437. Routine Description: CheckNeedsDependencies (1.41)
  2438. Checks the selection status of every component and subcomponent to
  2439. make sure all needs relationships are being upheld.
  2440. Arguments:
  2441. none
  2442. Return Value:
  2443. void
  2444. --*/
  2445. VOID CheckNeedsDependencies()
  2446. {
  2447. PSUBCOMP pscSubcomponent;
  2448. PCOMPONENT_DATA pcdComponentData;
  2449. TCHAR tszNodesVisited[NODES_VISITED_LENGTH];
  2450. ZeroMemory(tszNodesVisited, NODES_VISITED_LENGTH);
  2451. //
  2452. // Go through each subcomponent, check its selection state
  2453. // and the selection state of any subcomponents that it needs
  2454. //
  2455. for (pscSubcomponent = g_pscHead;
  2456. pscSubcomponent != NULL;
  2457. pscSubcomponent = pscSubcomponent->Next)
  2458. {
  2459. if (pcdComponentData = LocateComponent(pscSubcomponent->tszComponentId))
  2460. {
  2461. //
  2462. // If this component is selected, check out its needs
  2463. // dependencies
  2464. //
  2465. if (pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2466. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2467. pscSubcomponent->tszSubcomponentId,
  2468. OCSELSTATETYPE_CURRENT))
  2469. {
  2470. CheckNeedsDependenciesOfSubcomponent(
  2471. pcdComponentData->ocrHelperRoutines,
  2472. pscSubcomponent,
  2473. pscSubcomponent,
  2474. tszNodesVisited);
  2475. }
  2476. }
  2477. }
  2478. } // CheckNeedsDependencies //
  2479. /*++
  2480. Routine Description: CheckNeedsDependenciesOfSubcomponent (1.42)
  2481. Receives a subcomponent ID. Checks to see if this subcomponent is
  2482. checked, and if it is, recurses to check all the subcomponents
  2483. that are needed by this subcomponent (if any)
  2484. Arguments:
  2485. ocrHelper: helper routines
  2486. pscSubcomponent: contains data about subcomponent being checked
  2487. pscWhoNeedsMe: tells who needs this subcomponent
  2488. Return Value:
  2489. BOOL: TRUE if all needs dependencies check out, FALSE if not
  2490. --*/
  2491. BOOL CheckNeedsDependenciesOfSubcomponent(IN OCMANAGER_ROUTINES ocrHelper,
  2492. IN PSUBCOMP pscSubcomponent,
  2493. IN PSUBCOMP pscWhoNeedsMe,
  2494. IN OUT PTCHAR tszNodesVisited)
  2495. {
  2496. double fn = 1.42;
  2497. PCOMPLIST pclNeeds;
  2498. PSUBCOMP pscNeeds;
  2499. UINT uiRemoteResult;
  2500. CHECK_NEEDS cnCheckNeeds;
  2501. TCHAR tsz[MAX_PATH];
  2502. ULONG ulError;
  2503. if (ocrHelper.QuerySelectionState(ocrHelper.OcManagerContext,
  2504. pscSubcomponent->tszSubcomponentId,
  2505. OCSELSTATETYPE_CURRENT))
  2506. {
  2507. //
  2508. // Check to see if we've already checked out this node
  2509. //
  2510. if (!AlreadyVisitedNode(pscSubcomponent->tszSubcomponentId,
  2511. tszNodesVisited))
  2512. {
  2513. //
  2514. // Add this node to the list of nodes we've already checked
  2515. //
  2516. _tcscat(tszNodesVisited, pscSubcomponent->tszSubcomponentId);
  2517. _tcscat(tszNodesVisited, TEXT(" "));
  2518. //
  2519. // Go through each subcomponent that is needed by this subcomponent
  2520. //
  2521. for (pclNeeds = pscSubcomponent->pclNeeds;
  2522. pclNeeds != NULL;
  2523. pclNeeds = pclNeeds->Next)
  2524. {
  2525. //
  2526. // Check to see if this needed subcomponent belongs to the
  2527. // current component. If it does, just check here.
  2528. // If it doesn't, call private function of the component
  2529. // that it does belong to. This private function will
  2530. // do the checking and return the result
  2531. //
  2532. if (_tcsncmp(pscSubcomponent->tszSubcomponentId,
  2533. pclNeeds->tszSubcomponentId,
  2534. _tcslen(pscSubcomponent->tszComponentId)) == 0)
  2535. {
  2536. if (!CheckLocalNeedsDependencies(ocrHelper,
  2537. pscSubcomponent,
  2538. pclNeeds,
  2539. tszNodesVisited))
  2540. {
  2541. return FALSE;
  2542. }
  2543. }
  2544. else
  2545. {
  2546. cnCheckNeeds.pclNeeds = pclNeeds;
  2547. cnCheckNeeds.tszNodesVisited = tszNodesVisited;
  2548. ulError = ocrHelper.CallPrivateFunction(
  2549. ocrHelper.OcManagerContext,
  2550. GetComponent(pclNeeds->tszSubcomponentId, tsz),
  2551. pclNeeds->tszSubcomponentId,
  2552. OCP_CHECK_NEEDS,
  2553. (UINT)pscSubcomponent,
  2554. &cnCheckNeeds,
  2555. (PUINT)&cnCheckNeeds);
  2556. if (ulError != NO_ERROR)
  2557. {
  2558. Log(fn, SEV2, TEXT("CallPrivateFunction failed for ")
  2559. TEXT("%s called from %s: %lu"),
  2560. pclNeeds->tszSubcomponentId,
  2561. pscSubcomponent->tszComponentId,
  2562. ulError);
  2563. return FALSE;
  2564. }
  2565. if (!cnCheckNeeds.bResult) return FALSE;
  2566. }
  2567. }
  2568. }
  2569. //
  2570. // All the needs dependencies checked out
  2571. //
  2572. return TRUE;
  2573. }
  2574. //
  2575. // This component is not selected, return FALSE
  2576. //
  2577. Log(fn, SEV2, TEXT("%s needs %s. %s is selected, ")
  2578. TEXT("but %s is not."),
  2579. pscWhoNeedsMe->tszSubcomponentId,
  2580. pscSubcomponent->tszComponentId,
  2581. pscWhoNeedsMe->tszSubcomponentId,
  2582. pscSubcomponent->tszComponentId);
  2583. return FALSE;
  2584. } // CheckNeedsDependenciesOfSubcomponent //
  2585. /*++
  2586. Routine Description: CheckLocalNeedsDependencies (1.43)
  2587. Receives a subcomponent ID. Checks to see if this subcomponent is
  2588. checked, and if it is, recurses to check all the subcomponents
  2589. that are needed by this subcomponent (if any)
  2590. Arguments:
  2591. ocrHelper: helper routines
  2592. pscSubcomponent: contains data about subcomponent being checked
  2593. pclNeeds: tells who this subcomponent needs
  2594. Return Value:
  2595. BOOL: TRUE if all needs dependencies check out, FALSE if not
  2596. --*/
  2597. BOOL CheckLocalNeedsDependencies(IN OCMANAGER_ROUTINES ocrHelper,
  2598. IN PSUBCOMP pscSubcomponent,
  2599. IN PCOMPLIST pclNeeds,
  2600. IN OUT PTCHAR tszNodesVisited)
  2601. {
  2602. PSUBCOMP pscNeeds;
  2603. //
  2604. // Find the PSUBCOMP node for this subcomponent
  2605. //
  2606. for (pscNeeds = g_pscHead;
  2607. pscNeeds != NULL;
  2608. pscNeeds = pscNeeds->Next)
  2609. {
  2610. if (_tcscmp(pscNeeds->tszSubcomponentId,
  2611. pclNeeds->tszSubcomponentId) == 0)
  2612. {
  2613. if (!CheckNeedsDependenciesOfSubcomponent(ocrHelper,
  2614. pscNeeds,
  2615. pscSubcomponent,
  2616. tszNodesVisited))
  2617. {
  2618. return FALSE;
  2619. }
  2620. break;
  2621. }
  2622. }
  2623. return TRUE;
  2624. } // CheckLocalNeedsDependencies //
  2625. /*++
  2626. Routine Description: CheckExcludeDependencies (1.46)
  2627. Checks the selection status of every component and subcomponent to
  2628. make sure all exclude relationships are being upheld.
  2629. Arguments:
  2630. none
  2631. Return Value:
  2632. void
  2633. --*/
  2634. VOID CheckExcludeDependencies()
  2635. {
  2636. double fn = 1.46;
  2637. PSUBCOMP pscSubcomponent;
  2638. PCOMPLIST pclExclude;
  2639. PCOMPONENT_DATA pcdComponentData;
  2640. //
  2641. // Go through each subcomponent, check its selection state
  2642. // and the selection state of any subcomponents that it excludes
  2643. //
  2644. for (pscSubcomponent = g_pscHead;
  2645. pscSubcomponent != NULL;
  2646. pscSubcomponent = pscSubcomponent->Next)
  2647. {
  2648. if (pcdComponentData = LocateComponent(pscSubcomponent->tszComponentId))
  2649. {
  2650. //
  2651. // If this component is selected, check out its exclude
  2652. // dependencies
  2653. //
  2654. if (pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2655. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2656. pscSubcomponent->tszSubcomponentId,
  2657. OCSELSTATETYPE_CURRENT))
  2658. {
  2659. //
  2660. // Go through each subcomponent that is
  2661. // excluded by this subcomponent
  2662. //
  2663. for (pclExclude = pscSubcomponent->pclExclude;
  2664. pclExclude != NULL;
  2665. pclExclude = pclExclude->Next)
  2666. {
  2667. if (pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2668. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2669. pclExclude->tszSubcomponentId,
  2670. OCSELSTATETYPE_CURRENT))
  2671. {
  2672. Log(fn, SEV2, TEXT("%s excludes %s. Both are selected"),
  2673. pscSubcomponent->tszSubcomponentId,
  2674. pclExclude->tszSubcomponentId);
  2675. }
  2676. }
  2677. }
  2678. }
  2679. }
  2680. } // CheckExcludeDependencies //
  2681. /*++
  2682. Routine Description: CheckParentDependencies (1.47)
  2683. Checks the selection status of every component and subcomponent to
  2684. make sure all parent relationships are being upheld.
  2685. Arguments:
  2686. none
  2687. Return Value:
  2688. void
  2689. --*/
  2690. VOID CheckParentDependencies()
  2691. {
  2692. double fn = 1.47;
  2693. PSUBCOMP pscSubcomponent;
  2694. PCOMPONENT_DATA pcdComponentData;
  2695. BOOL bState;
  2696. PCOMPLIST pclChildren;
  2697. PCOMPONENT_DATA pcdSubComponentData;
  2698. BOOL bParentState;
  2699. BOOL bAllCleared;
  2700. PSUBCOMP pscParent;
  2701. TCHAR tszMsg[256];
  2702. static BOOL bInformed1 = FALSE;
  2703. static BOOL bInformed2 = FALSE;
  2704. // QuerySelectionState returns TRUE when the component's state
  2705. // does not equal SELSTATE_NO
  2706. // This means it returns TRUE when the component is selected
  2707. // or partially selected
  2708. //
  2709. // Go through each subcomponent, check its selection state
  2710. // and the selection state of its parent
  2711. //
  2712. for (pscSubcomponent = g_pscHead;
  2713. pscSubcomponent != NULL;
  2714. pscSubcomponent = pscSubcomponent->Next)
  2715. {
  2716. bState = TRUE;
  2717. if (pcdComponentData = LocateComponent(pscSubcomponent->tszComponentId))
  2718. {
  2719. //
  2720. // Check to see if this subcomponent is selected
  2721. //
  2722. bState = pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2723. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2724. pscSubcomponent->tszSubcomponentId,
  2725. OCSELSTATETYPE_CURRENT);
  2726. // Let pass a NULL pointer to the helper routine
  2727. //pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2728. // NULL, NULL, OCSELSTATETYPE_CURRENT);
  2729. if (bState == TRUE) {
  2730. // The component is selected
  2731. //if (GetLastError() == ERROR_INVALID_NAME) {
  2732. // MessageBox(NULL, TEXT("There is an error when calling QuerySelectionState"), TEXT("CheckParentDependencies"), MB_OK);
  2733. // break;
  2734. //}
  2735. //
  2736. // Check to see if its parent is selected
  2737. //
  2738. bParentState = pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2739. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2740. pscSubcomponent->tszParentId,
  2741. OCSELSTATETYPE_CURRENT);
  2742. // If the component is selected, its parent should
  2743. // be selected or partially selected, thus bParentState
  2744. // should be TRUE
  2745. if (!bParentState)
  2746. {
  2747. Log(fn, SEV2, TEXT("%s is selected but its parent, %s, ")
  2748. TEXT("is not"),
  2749. pscSubcomponent->tszSubcomponentId,
  2750. pscSubcomponent->tszParentId);
  2751. }
  2752. }
  2753. else if (bState == FALSE) {
  2754. //
  2755. // The child is not selected, this means none of its children
  2756. // should be selected, and its parent should be greyed or
  2757. // unselected
  2758. //
  2759. // This will check its siblings to determine whether they
  2760. // are selected or not
  2761. // if none of its siblings are selected, the parent should be
  2762. // cleared.
  2763. // First find its parent in the list
  2764. if (_tcscmp(pscSubcomponent->tszSubcomponentId, pscSubcomponent->tszParentId) == 0) {
  2765. // This is a top level component
  2766. // we will skip the following test
  2767. continue;
  2768. }
  2769. for (pscParent = g_pscHead; pscParent != NULL; pscParent = pscParent->Next) {
  2770. if (_tcscmp(pscParent->tszSubcomponentId, pscSubcomponent->tszParentId) == 0) {
  2771. break;
  2772. }
  2773. }
  2774. pclChildren = pscParent->pclChildren;
  2775. bAllCleared = TRUE;
  2776. for (pclChildren = pscParent->pclChildren; pclChildren != NULL; pclChildren = pclChildren->Next) {
  2777. // Locate the child component
  2778. //pcdSubComponentData = LocateComponent(pclChildren->tszSubcomponentId);
  2779. //if (!pcdSubComponentData) {
  2780. // MessageBox(NULL, TEXT("Error locating subcomponent that is in the list"), TEXT("CheckParentDependencies"), MB_OK);
  2781. // break;
  2782. //}
  2783. // Now query the state of this subcomponent
  2784. if (pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2785. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2786. pclChildren->tszSubcomponentId,
  2787. OCSELSTATETYPE_CURRENT)){
  2788. bAllCleared = FALSE;
  2789. break;
  2790. }
  2791. }
  2792. //pcdSubComponentData = LocateComponent(pscParent->tszComponentId);
  2793. //if (!pcdSubComponentData) {
  2794. // MessageBox(NULL, TEXT("Error locating subcomponent that is in the list"), TEXT("CheckParentDependencies"), MB_OK);
  2795. // break;
  2796. //}
  2797. bParentState = pcdComponentData->ocrHelperRoutines.QuerySelectionState(
  2798. pcdComponentData->ocrHelperRoutines.OcManagerContext,
  2799. pscParent->tszSubcomponentId,
  2800. OCSELSTATETYPE_CURRENT);
  2801. if (bAllCleared) {
  2802. // None of the subcomponent is selected
  2803. // Check the state of the parent component
  2804. if (bParentState != FALSE) {
  2805. Log(fn, SEV2, TEXT("%s.%s is (partially) selected, but none")
  2806. TEXT(" of its subcomponent is selected"),
  2807. pscParent->tszParentId,
  2808. pscParent->tszComponentId);
  2809. if (!bInformed1) {
  2810. _stprintf(tszMsg, TEXT("%s is (partially) selected, but none of child is selected"), pscParent->tszSubcomponentId);
  2811. MessageBox(NULL,tszMsg, TEXT("CheckParentDependencies"), MB_OK);
  2812. bInformed1 = TRUE;
  2813. }
  2814. }
  2815. }
  2816. else{
  2817. // At least one of the subcomponent is selected
  2818. // Parent should be (partially) selected
  2819. if (bParentState == FALSE) {
  2820. Log(fn, SEV2, TEXT("%s.%s is not selected, but one")
  2821. TEXT(" of its subcomponent is selected"),
  2822. pscParent->tszParentId,
  2823. pscParent->tszComponentId);
  2824. if (!bInformed2) {
  2825. _stprintf(tszMsg, TEXT("%s is not selected, but at least one of child is selected"), pscParent->tszSubcomponentId);
  2826. MessageBox(NULL,tszMsg, TEXT("CheckParentDependencies"), MB_OK);
  2827. bInformed2 = TRUE;
  2828. }
  2829. }
  2830. }
  2831. }
  2832. }
  2833. }
  2834. } // CheckParentDependencies //
  2835. /*++
  2836. Routine Description: AlreadyVisitedNode (1.44)
  2837. Receives a subcomponent ID and a list of subcomponents that
  2838. have already been checked. Looks in the list to see if this
  2839. subcomponent has already been checked.
  2840. Arguments:
  2841. tszSubcomponentId: the new subcomponent
  2842. tszNodesVisited: list of what's already been checked
  2843. Return Value:
  2844. BOOL: TRUE if this subcomponent has already been checked, FALSE if not
  2845. --*/
  2846. BOOL AlreadyVisitedNode(IN PTCHAR tszSubcomponentId,
  2847. IN PTCHAR tszNodesVisited)
  2848. {
  2849. PTCHAR tszMarker;
  2850. TCHAR tszName[MAX_PATH];
  2851. USHORT usCount, i;
  2852. tszMarker = tszNodesVisited;
  2853. for (usCount = 0; usCount < _tcslen(tszNodesVisited);)
  2854. {
  2855. for (i = 0; i < _tcslen(tszMarker); i++)
  2856. {
  2857. if (tszMarker[i] == TEXT(' ')) break;
  2858. tszName[i] = tszMarker[i];
  2859. }
  2860. tszName[i] = TEXT('\0');
  2861. if (_tcscmp(tszName, tszSubcomponentId) == 0)
  2862. {
  2863. return TRUE;
  2864. }
  2865. usCount += _tcslen(tszName) + 1;
  2866. tszMarker += _tcslen(tszName) + 1;
  2867. }
  2868. return FALSE;
  2869. } // AlreadyVisitedNode //
  2870. /*++
  2871. Routine Description: GetComponent (1.45)
  2872. Receives a subcomponent ID and returns the ID of the master component
  2873. that owns this subcomponent
  2874. Arguments:
  2875. tszSubcomponentId: the subcomponent
  2876. tszComponentId: returns component ID using this string.
  2877. must be a valid buffer
  2878. Return Value:
  2879. PTCHAR: returns component ID
  2880. --*/
  2881. PTCHAR GetComponent(IN PTCHAR tszSubcomponentId,
  2882. IN OUT PTCHAR tszComponentId)
  2883. {
  2884. USHORT i;
  2885. __ASSERT(tszComponentId != NULL);
  2886. for (i = 0; i < _tcslen(tszSubcomponentId); i++)
  2887. {
  2888. if (tszSubcomponentId[i] == TEXT('_'))
  2889. {
  2890. break;
  2891. }
  2892. tszComponentId[i] = tszSubcomponentId[i];
  2893. }
  2894. tszComponentId[i] = TEXT('\0');
  2895. return tszComponentId;
  2896. } // GetComponent //
  2897. /*++
  2898. Routine Description: ParseCommandLine (1.47)
  2899. Checks the command line to see if there are any arguments that
  2900. pertain to the component DLLs
  2901. Arguments:
  2902. none
  2903. Return Value:
  2904. VOID
  2905. --*/
  2906. VOID ParseCommandLine()
  2907. {
  2908. USHORT i;
  2909. USHORT usMarker;
  2910. //TCHAR usMarker;
  2911. BOOL bCheckArgs = FALSE;
  2912. PTCHAR tszCommandLine;
  2913. PTCHAR tszMarker;
  2914. TCHAR tszArg[MAX_PATH];
  2915. TCHAR tszDlgMessage[256];
  2916. tszCommandLine = GetCommandLine();
  2917. tszMarker = tszCommandLine;
  2918. usMarker = (USHORT)tszMarker;
  2919. while ((USHORT)((USHORT)tszMarker - usMarker) < (USHORT)_tcslen(tszCommandLine) * sizeof(TCHAR))
  2920. {
  2921. for (i = 0; i < _tcslen(tszMarker); i++)
  2922. {
  2923. if (tszMarker[i] == TEXT(' ') ||
  2924. tszMarker[i] == TEXT('\0'))
  2925. {
  2926. break;
  2927. }
  2928. tszArg[i] = tszMarker[i];
  2929. }
  2930. tszArg[i] = TEXT('\0');
  2931. tszMarker += _tcslen(tszArg) + 1;
  2932. while (tszMarker[0] == TEXT(' ')) tszMarker++;
  2933. if (bCheckArgs)
  2934. {
  2935. //
  2936. // Check the value of this argument
  2937. //
  2938. if (_tcscmp(tszArg, TEXT("/av")) == 0 ||
  2939. _tcscmp(tszArg, TEXT("/AV")) == 0 ||
  2940. _tcscmp(tszArg, TEXT("-av")) == 0 ||
  2941. _tcscmp(tszArg, TEXT("-AV")) == 0)
  2942. {
  2943. g_bAccessViolation = TRUE;
  2944. }
  2945. //
  2946. // Check the value of this argument
  2947. //
  2948. if (_tcscmp(tszArg, TEXT("/e")) == 0 ||
  2949. _tcscmp(tszArg, TEXT("/E")) == 0 ||
  2950. _tcscmp(tszArg, TEXT("-e")) == 0 ||
  2951. _tcscmp(tszArg, TEXT("-E")) == 0)
  2952. {
  2953. g_bTestExtended = TRUE;
  2954. }
  2955. //
  2956. // negstep make the return value of OC_QUERY_STEP_COUNT negative one
  2957. //
  2958. if (_tcscmp(tszArg, TEXT("/negstep")) == 0 ||
  2959. _tcscmp(tszArg, TEXT("/NEGSTEP")) == 0 ||
  2960. _tcscmp(tszArg, TEXT("-negstep")) == 0 ||
  2961. _tcscmp(tszArg, TEXT("-NEGSTEP")) == 0)
  2962. {
  2963. nStepsFinal = -1;
  2964. }
  2965. if (_tcscmp(tszArg, TEXT("/nowiz")) == 0 ||
  2966. _tcscmp(tszArg, TEXT("/NOWIZ")) == 0 ||
  2967. _tcscmp(tszArg, TEXT("-nowiz")) == 0 ||
  2968. _tcscmp(tszArg, TEXT("-NOWIZ")) == 0)
  2969. {
  2970. g_bNoWizPage = TRUE;
  2971. }
  2972. if (_tcscmp(tszArg, TEXT("/crashunicode")) == 0 ||
  2973. _tcscmp(tszArg, TEXT("/CRASHUNICODE")) == 0 ||
  2974. _tcscmp(tszArg, TEXT("-crashunicode")) == 0 ||
  2975. _tcscmp(tszArg, TEXT("-CRASHUNICODE")) == 0)
  2976. {
  2977. g_bCrashUnicode = TRUE;
  2978. }
  2979. if (_tcscmp(tszArg, TEXT("/invalidbitmap")) == 0 ||
  2980. _tcscmp(tszArg, TEXT("/INVALIDBITMAP")) == 0 ||
  2981. _tcscmp(tszArg, TEXT("-invalidbitmap")) == 0 ||
  2982. _tcscmp(tszArg, TEXT("-INVALIDBITMAP")) == 0)
  2983. {
  2984. g_bInvalidBitmap = TRUE;
  2985. }
  2986. if (_tcscmp(tszArg, TEXT("/closeinf")) == 0 ||
  2987. _tcscmp(tszArg, TEXT("/CLOSEINF")) == 0 ||
  2988. _tcscmp(tszArg, TEXT("-closeinf")) == 0 ||
  2989. _tcscmp(tszArg, TEXT("-CLOSEINF")) == 0)
  2990. {
  2991. g_bCloseInf = TRUE;
  2992. }
  2993. if (_tcscmp(tszArg, TEXT("/hugesize")) == 0 ||
  2994. _tcscmp(tszArg, TEXT("/HUGESIZE")) == 0 ||
  2995. _tcscmp(tszArg, TEXT("-hugesize")) == 0 ||
  2996. _tcscmp(tszArg, TEXT("-HUGESIZE")) == 0)
  2997. {
  2998. g_bHugeSize = TRUE;
  2999. }
  3000. if (_tcscmp(tszArg, TEXT("/noneedmedia")) == 0 ||
  3001. _tcscmp(tszArg, TEXT("/NONEEDMEDIA")) == 0 ||
  3002. _tcscmp(tszArg, TEXT("-noneedmedia")) == 0 ||
  3003. _tcscmp(tszArg, TEXT("-NONEEDMEDIA")) == 0)
  3004. {
  3005. g_bNoNeedMedia = TRUE;
  3006. }
  3007. if (_tcscmp(tszArg, TEXT("/reboot")) == 0 ||
  3008. _tcscmp(tszArg, TEXT("/reboot")) == 0 ||
  3009. _tcscmp(tszArg, TEXT("-reboot")) == 0 ||
  3010. _tcscmp(tszArg, TEXT("-reboot")) == 0)
  3011. {
  3012. g_bReboot = TRUE;
  3013. }
  3014. if (_tcscmp(tszArg, TEXT("/cleanreg")) == 0 ||
  3015. _tcscmp(tszArg, TEXT("/CLEANREG")) == 0 ||
  3016. _tcscmp(tszArg, TEXT("-cleanreg")) == 0 ||
  3017. _tcscmp(tszArg, TEXT("-CLEANREG")) == 0)
  3018. {
  3019. g_bCleanReg = TRUE;
  3020. }
  3021. if (_tcscmp(tszArg, TEXT("/nolang")) == 0 ||
  3022. _tcscmp(tszArg, TEXT("/NOLANG")) == 0 ||
  3023. _tcscmp(tszArg, TEXT("-nolang")) == 0 ||
  3024. _tcscmp(tszArg, TEXT("-NOLANG")) == 0)
  3025. {
  3026. g_bNoLangSupport = TRUE;
  3027. }
  3028. }
  3029. if (_tcscmp(tszArg, TEXT("/z")) == 0 ||
  3030. _tcscmp(tszArg, TEXT("/Z")) == 0)
  3031. {
  3032. bCheckArgs = TRUE;
  3033. }
  3034. }
  3035. } // ParseCommandLine //
  3036. /*++
  3037. Routine Description: testAV (1.0)
  3038. Procedure to generate an access violation
  3039. Argument:
  3040. If true, an access violation is generated
  3041. Return Value:
  3042. None
  3043. --*/
  3044. VOID testAV(BOOL bDoIt){
  3045. /* The Following variables are used for access violation test */
  3046. COMPONENT_DATA *g_pcdAccessViolation;
  3047. if (bDoIt){
  3048. g_pcdAccessViolation = NULL;
  3049. g_pcdAccessViolation->hinfMyInfHandle = NULL;
  3050. }
  3051. }
  3052. /*++
  3053. Routine Description: TestReturnValueAndAV (1.0)
  3054. Procdefure to give the user control of what to return and when to cause an access violation
  3055. Argument:
  3056. Arguments to ComponentSetupProc plus and bOverride
  3057. Return Value:
  3058. The return value that user gives.
  3059. --*/
  3060. BOOL TestReturnValueAndAV(IN LPCVOID lpcvComponentId,
  3061. IN LPCVOID lpcvSubcomponentId,
  3062. IN UINT uiFunction,
  3063. IN UINT uiParam1,
  3064. IN PVOID pvParam2,
  3065. IN OUT PReturnOrAV praValue)
  3066. {
  3067. int returnValue;
  3068. if (!BeginTest()){
  3069. praValue->bOverride = FALSE;
  3070. return ((DWORD)0);
  3071. }
  3072. //ChooseAccessViolationEx();
  3073. //Now fill in the fields of raValue
  3074. praValue->tszComponent = (PTCHAR)lpcvComponentId;
  3075. praValue->tszSubComponent = (PTCHAR)lpcvSubcomponentId;
  3076. switch(uiFunction){
  3077. case OC_PREINITIALIZE:
  3078. praValue->tszSubComponent[0]=TEXT('\0');
  3079. _tcscpy(praValue->tszAPICall, TEXT("OC_PREINITIALIZE"));
  3080. break;
  3081. case OC_INIT_COMPONENT:
  3082. _tcscpy(praValue->tszAPICall, TEXT("OC_INIT_COMPONENT"));
  3083. break;
  3084. case OC_QUERY_STATE:
  3085. _tcscpy(praValue->tszAPICall, TEXT("OC_QUERY_STATE"));
  3086. break;
  3087. case OC_SET_LANGUAGE:
  3088. _tcscpy(praValue->tszAPICall, TEXT("OC_SET_LANGUAGE"));
  3089. break;
  3090. case OC_QUERY_IMAGE:
  3091. _tcscpy(praValue->tszAPICall, TEXT("OC_QUERY_IMAGE"));
  3092. break;
  3093. case OC_REQUEST_PAGES:
  3094. _tcscpy(praValue->tszAPICall, TEXT("OC_REQUEST_PAGES"));
  3095. break;
  3096. case OC_QUERY_CHANGE_SEL_STATE:
  3097. _tcscpy(praValue->tszAPICall, TEXT("OC_QUERY_CHANGE_SEL_STATE"));
  3098. break;
  3099. case OC_CALC_DISK_SPACE:
  3100. _tcscpy(praValue->tszAPICall, TEXT("OC_CALC_DISK_SPACE"));
  3101. break;
  3102. case OC_QUEUE_FILE_OPS:
  3103. _tcscpy(praValue->tszAPICall, TEXT("OC_QUEUE_FILE_OPS"));
  3104. break;
  3105. case OC_NEED_MEDIA:
  3106. _tcscpy(praValue->tszAPICall, TEXT("OC_NEED_MEDIA"));
  3107. break;
  3108. case OC_QUERY_STEP_COUNT:
  3109. _tcscpy(praValue->tszAPICall, TEXT("OC_QUERY_STEP_COUNT"));
  3110. break;
  3111. case OC_COMPLETE_INSTALLATION:
  3112. _tcscpy(praValue->tszAPICall, TEXT("OC_COMPLETE_INSTALLATION"));
  3113. break;
  3114. case OC_CLEANUP:
  3115. _tcscpy(praValue->tszAPICall, TEXT("OC_CLEANUP"));
  3116. break;
  3117. case OCP_TEST_PRIVATE_BASE:
  3118. _tcscpy(praValue->tszAPICall, TEXT("OC_TEST_PRIVATE_BASE"));
  3119. break;
  3120. case OCP_CHECK_NEEDS:
  3121. _tcscpy(praValue->tszAPICall, TEXT("OC_CHECK_NEEDS"));
  3122. break;
  3123. default:
  3124. _tcscpy(praValue->tszAPICall, TEXT("Unknown call"));
  3125. break;
  3126. }
  3127. //Now everything is ready, let's make the call
  3128. returnValue = DialogBoxParam(g_hDllInstance,
  3129. MAKEINTRESOURCE(IDD_CHOOSERETURNANDAV),
  3130. NULL,
  3131. ChooseReturnOrAVDlgProc,
  3132. (LPARAM)praValue);
  3133. praValue = (PReturnOrAV)returnValue;
  3134. return TRUE;
  3135. }
  3136. /*++
  3137. Routine Description: BeginTest (1.0)
  3138. Let the user decide whether to test the return values of each API
  3139. Arguments:
  3140. None
  3141. Return Value:
  3142. Whether to do extended test
  3143. --*/
  3144. BOOL BeginTest(){
  3145. static BOOL bStart = FALSE;
  3146. static BOOL bFirstTime = TRUE;
  3147. static int iMsgReturn;
  3148. TCHAR tszDlgMessage[256];
  3149. TCHAR tszDlgTitle[256];
  3150. if (bFirstTime){
  3151. bFirstTime = FALSE;
  3152. #ifdef UNICODE
  3153. _stprintf(tszDlgMessage, TEXT("Do you want to test return values and/or access violations of each API call in the UNICODE DLL? It may take a long long time"));
  3154. _stprintf(tszDlgTitle, TEXT("Begin Test For UNICODE?"));
  3155. #else
  3156. _stprintf(tszDlgMessage, TEXT("Do you want to test return values and/or access violations of each API call in the ANSI DLL? It may take a long long time"));
  3157. _stprintf(tszDlgTitle, TEXT("Begin Test For ANSI?"));
  3158. #endif
  3159. iMsgReturn = MessageBox(NULL, tszDlgMessage, tszDlgTitle, MB_YESNO|MB_ICONQUESTION);
  3160. if (iMsgReturn == IDNO){
  3161. bStart = FALSE;
  3162. return (FALSE);
  3163. }
  3164. else{
  3165. bStart = TRUE;
  3166. return (TRUE);
  3167. }
  3168. }
  3169. else{
  3170. return bStart;
  3171. }
  3172. }
  3173. /*++
  3174. Routine Description: ChooseReturnOrAVDlgProc (1.27)
  3175. Dialog procedure that allows the user to select a different
  3176. return value of an API call, and/or to cause a access violation
  3177. Arguments:
  3178. Standard dialog procedure parameters
  3179. Return Value:
  3180. Standard dialog procedure return value
  3181. --*/
  3182. BOOL CALLBACK ChooseReturnOrAVDlgProc(IN HWND hwnd,
  3183. IN UINT uiMsg,
  3184. IN WPARAM wParam,
  3185. IN LPARAM lParam)
  3186. {
  3187. BOOL bSuccess = FALSE;
  3188. PReturnOrAV praValue = NULL;
  3189. static HWND hOldWnd = NULL;
  3190. switch (uiMsg)
  3191. {
  3192. case WM_INITDIALOG:
  3193. hOldWnd = hwnd;
  3194. CheckRadioButton(hwnd, IDC_USE_OLDVALUE, IDC_USE_NEWVALUE, IDC_USE_OLDVALUE);
  3195. CheckDlgButton(hwnd, IDC_CAUSEAV, 0);
  3196. praValue = (PReturnOrAV)lParam;
  3197. if (praValue){
  3198. if (praValue->tszComponent){
  3199. SetDlgItemText(hwnd, IDC_STATIC_COMPONENT, praValue->tszComponent);
  3200. }
  3201. else{
  3202. SetDlgItemText(hwnd, IDC_STATIC_COMPONENT, TEXT("null"));
  3203. }
  3204. if (praValue->tszSubComponent && praValue->tszSubComponent[0]!=TEXT('\0')){
  3205. SetDlgItemText(hwnd, IDC_STATIC_SUBCOMPONENT, praValue->tszSubComponent);
  3206. }
  3207. else{
  3208. SetDlgItemText(hwnd, IDC_STATIC_SUBCOMPONENT, TEXT("null"));
  3209. }
  3210. SetDlgItemText(hwnd, IDC_STATIC_APICALL, praValue->tszAPICall);
  3211. }
  3212. return TRUE;
  3213. break;
  3214. case WM_COMMAND:
  3215. switch (LOWORD(wParam))
  3216. {
  3217. case IDOK:
  3218. //
  3219. // Retrieve the current selection
  3220. //
  3221. if (QueryButtonCheck(hwnd, IDC_USE_NEWVALUE))
  3222. {
  3223. praValue->iReturnValue = GetDlgItemInt(hwnd, IDC_NEWVALUE, &bSuccess, TRUE);
  3224. if (bSuccess){
  3225. praValue->bOverride = TRUE;
  3226. }
  3227. else{
  3228. praValue->bOverride = FALSE;
  3229. praValue->iReturnValue = 0;
  3230. }
  3231. }
  3232. if (QueryButtonCheck(hwnd, IDC_USE_OLDVALUE))
  3233. {
  3234. praValue->bOverride = FALSE;
  3235. praValue->iReturnValue = 0;
  3236. }
  3237. if (QueryButtonCheck(hwnd, IDC_CAUSEAV))
  3238. {
  3239. praValue->bOverride = FALSE;
  3240. praValue->iReturnValue = 0;
  3241. testAV(TRUE);
  3242. }
  3243. EndDialog(hOldWnd, (int)praValue);
  3244. return TRUE;
  3245. case IDCANCEL:
  3246. praValue->bOverride = FALSE;
  3247. EndDialog(hOldWnd, 0);
  3248. return TRUE;
  3249. default:
  3250. break;
  3251. }
  3252. default:
  3253. break;
  3254. }
  3255. return FALSE;
  3256. } // ChooseReturnOrAVDlgProc //
  3257. /*++
  3258. Routine: causeAV
  3259. Description: pops up a dialog box and ask the user where to av
  3260. Argument: Function that the DLL receives from ComponentSetupProc
  3261. --*/
  3262. void causeAV(IN UINT uiFunction){
  3263. static BOOL bFirstTime = TRUE;
  3264. static UINT uiFunctionToAV = 0;
  3265. if (bFirstTime) {
  3266. // Display dialog box, asks the user where to av
  3267. bFirstTime = FALSE;
  3268. uiFunctionToAV = DialogBoxParam(g_hDllInstance,
  3269. MAKEINTRESOURCE(IDD_DIALOG4),
  3270. NULL,
  3271. CauseAVDlgProc,
  3272. (LPARAM)NULL);
  3273. }
  3274. if (uiFunction == uiFunctionToAV) {
  3275. testAV(TRUE);
  3276. }
  3277. }
  3278. /*++
  3279. Routine Description: CauseAVDlgProc (1.26)
  3280. Dialog Procedure to allow the user to choose where to cause an access violation
  3281. Arguments:
  3282. Standard dialog procedure parameters
  3283. Return Value:
  3284. Standard dialog procedure return value
  3285. --*/
  3286. BOOL CALLBACK CauseAVDlgProc(IN HWND hwnd,
  3287. IN UINT uiMsg,
  3288. IN WPARAM wParam,
  3289. IN LPARAM lParam)
  3290. {
  3291. UINT uiFunction;
  3292. TCHAR tszFunctionName[256];
  3293. BOOL bSuccess;
  3294. switch (uiMsg)
  3295. {
  3296. case WM_INITDIALOG:
  3297. break;
  3298. case WM_COMMAND:
  3299. switch (LOWORD(wParam))
  3300. {
  3301. case IDOK:
  3302. //
  3303. // Retrieve the current text in the edit box
  3304. //
  3305. GetDlgItemText(hwnd, IDC_FUNCTION, tszFunctionName, 255);
  3306. if (*tszFunctionName) {
  3307. uiFunction = GetOCFunctionName(tszFunctionName);
  3308. }
  3309. //
  3310. // Send the version chosen back to ChooseVersionEx
  3311. //
  3312. EndDialog(hwnd, uiFunction);
  3313. return TRUE;
  3314. case IDCANCEL:
  3315. EndDialog(hwnd, -1);
  3316. return TRUE;
  3317. default:
  3318. break;
  3319. }
  3320. default:
  3321. break;
  3322. }
  3323. return FALSE;
  3324. } // CauseAVDlgProc //
  3325. UINT GetOCFunctionName(IN PTCHAR tszFunctionName){
  3326. // Now tszFunctionName should contains the function name that user wants to cause an AV
  3327. if (!_tcsicmp(tszFunctionName, TEXT("OC_PREINITIALIZE"))) {
  3328. return(OC_PREINITIALIZE);
  3329. }
  3330. else if (!_tcsicmp(tszFunctionName, TEXT("OC_INIT_COMPONENT"))) {
  3331. return(OC_INIT_COMPONENT);
  3332. }
  3333. else if (!_tcsicmp(tszFunctionName, TEXT("OC_QUERY_STATE"))) {
  3334. return(OC_QUERY_STATE);
  3335. }
  3336. else if (!_tcsicmp(tszFunctionName, TEXT("OC_SET_LANGUAGE"))) {
  3337. return(OC_SET_LANGUAGE);
  3338. }
  3339. else if (!_tcsicmp(tszFunctionName, TEXT("OC_QUERY_IMAGE"))) {
  3340. return(OC_QUERY_IMAGE);
  3341. }
  3342. else if (!_tcsicmp(tszFunctionName, TEXT("OC_REQUEST_PAGES"))) {
  3343. return(OC_REQUEST_PAGES);
  3344. }
  3345. else if (!_tcsicmp(tszFunctionName, TEXT("OC_QUERY_SKIP_PAGE"))) {
  3346. return(OC_QUERY_SKIP_PAGE);
  3347. }
  3348. else if (!_tcsicmp(tszFunctionName, TEXT("OC_QUERY_CHANGE_SEL_STATE"))) {
  3349. return(OC_QUERY_CHANGE_SEL_STATE);
  3350. }
  3351. else if (!_tcsicmp(tszFunctionName, TEXT("OC_CALC_DISK_SPACE"))) {
  3352. return(OC_CALC_DISK_SPACE);
  3353. }
  3354. else if (!_tcsicmp(tszFunctionName, TEXT("OC_QUEUE_FILE_OPS"))) {
  3355. return(OC_QUEUE_FILE_OPS);
  3356. }
  3357. else if (!_tcsicmp(tszFunctionName, TEXT("OC_NEED_MEDIA"))) {
  3358. return(OC_NEED_MEDIA);
  3359. }
  3360. else if (!_tcsicmp(tszFunctionName, TEXT("OC_QUERY_STEP_COUNT"))) {
  3361. return(OC_QUERY_STEP_COUNT);
  3362. }
  3363. else if (!_tcsicmp(tszFunctionName, TEXT("OC_ABOUT_TO_COMMIT_QUEUE"))) {
  3364. return(OC_ABOUT_TO_COMMIT_QUEUE);
  3365. }
  3366. else if (!_tcsicmp(tszFunctionName, TEXT("OC_COMPLETE_INSTALLATION"))) {
  3367. return(OC_COMPLETE_INSTALLATION);
  3368. }
  3369. else if (!_tcsicmp(tszFunctionName, TEXT("OC_CLEANUP"))) {
  3370. return(OC_CLEANUP);
  3371. }
  3372. else{
  3373. MessageBox(NULL, TEXT("Unknown Function"), TEXT("Test Routine"), MB_OK);
  3374. return(0);
  3375. }
  3376. }
  3377. void SetGlobalsFromINF(HINF hinfHandle){
  3378. PTCHAR tszOCTestSection = TEXT("OCTest");
  3379. PTCHAR tszAccessViolation = TEXT("AccessViolation");
  3380. PTCHAR tszNoWizard = TEXT("NoWizardPage");
  3381. TCHAR tszFunctionName[256];
  3382. int nRequiredBufferSize;
  3383. INFCONTEXT infContext;
  3384. BOOL bSuccess = TRUE;
  3385. TCHAR tszMsg[256];
  3386. int nError;
  3387. /*
  3388. bSuccess = SetupFindFirstLine(hinfHandle, tszOCTestSection, tszAccessViolation, &infContext);
  3389. if (bSuccess) {
  3390. #ifdef DEBUG
  3391. MessageBox(NULL, TEXT("AccessViolation Found in INF File"), TEXT("AccessViolation"), MB_OK);
  3392. #endif
  3393. g_bAccessViolation = TRUE;
  3394. bSuccess = SetupGetStringField(&infContext, 1, tszFunctionName, 255, &nRequiredBufferSize);
  3395. if (bSuccess) {
  3396. g_uiFunctionToAV = GetOCFunctionName(tszFunctionName);
  3397. }
  3398. }
  3399. */
  3400. bSuccess = SetupFindFirstLine(hinfHandle, TEXT("OCTest"), TEXT("NoWizardPage"), &infContext);
  3401. if (bSuccess) {
  3402. #ifdef DEBUG
  3403. MessageBox(NULL, TEXT("NoWizard Found in INF File"), TEXT("NoWizard"), MB_OK);
  3404. #endif
  3405. g_bNoWizPage = TRUE;
  3406. }
  3407. else{
  3408. #ifdef DEBUG
  3409. nError = GetLastError();
  3410. MessageBox(NULL, TEXT("NoWizard NOT Found in INF File"), TEXT("NoWizard"), MB_OK);
  3411. _stprintf(tszMsg, TEXT("The Last Error value for SetupFIndFirstLine is %d"), nError);
  3412. MessageBox(NULL, tszMsg, TEXT("GetLastError"), MB_OK);
  3413. #endif
  3414. }
  3415. bSuccess = SetupFindFirstLine(hinfHandle, TEXT("OCTest"), TEXT("Reboot"), &infContext);
  3416. if (bSuccess) {
  3417. g_bReboot = TRUE;
  3418. }
  3419. }
  3420. void causeAVPerComponent(IN UINT uiFunction, IN LPCVOID lpcvComponentId){
  3421. PCOMPONENT_DATA pcdComponentData;
  3422. TCHAR tszMsg[256];
  3423. if (uiFunction != OC_PREINITIALIZE && uiFunction != OC_INIT_COMPONENT) {
  3424. pcdComponentData = LocateComponent(lpcvComponentId);
  3425. //MessageBox(NULL, TEXT("Component Found"), TEXT("Fount"), MB_OK);
  3426. if (pcdComponentData->bAccessViolation) {
  3427. //MessageBox(NULL, TEXT("It allows use to cause AV"), TEXT("Cause AV"), MB_OK);
  3428. if (pcdComponentData->uiFunctionToAV == uiFunction) {
  3429. //MessageBox(NULL, TEXT("Start to cause access violation"), TEXT("Starting"), MB_OK);
  3430. testAV(TRUE);
  3431. }
  3432. }
  3433. }
  3434. }
  3435. void SetDefaultMode(PCOMPONENT_DATA pcdComponentData){
  3436. BOOL bSuccess;
  3437. INFCONTEXT infContext;
  3438. TCHAR tszMode[256];
  3439. bSuccess = SetupFindFirstLine(pcdComponentData->hinfMyInfHandle,
  3440. TEXT("OCTest"),
  3441. TEXT("DefaultMode"),
  3442. &infContext);
  3443. if (bSuccess) {
  3444. //MessageBox(NULL, TEXT("DefaultMode= found in OCTest section"), TEXT("DefaultMode"), MB_OK);
  3445. bSuccess = SetupGetStringField(&infContext, 1, tszMode, 255, NULL);
  3446. if (bSuccess) {
  3447. //MessageBox(NULL, TEXT("The default Mode should be in the title"), tszMode, MB_OK);
  3448. if (!_tcscmp(tszMode, TEXT("TYPICAL"))) {
  3449. pcdComponentData->ocrHelperRoutines.SetSetupMode(pcdComponentData->ocrHelperRoutines.OcManagerContext,
  3450. SETUPMODE_TYPICAL);
  3451. }
  3452. else if (!_tcscmp(tszMode, TEXT("MINIMAL"))) {
  3453. pcdComponentData->ocrHelperRoutines.SetSetupMode(pcdComponentData->ocrHelperRoutines.OcManagerContext,
  3454. SETUPMODE_MINIMAL);
  3455. }
  3456. else if (!_tcscmp(tszMode, TEXT("LAPTOP"))) {
  3457. pcdComponentData->ocrHelperRoutines.SetSetupMode(pcdComponentData->ocrHelperRoutines.OcManagerContext,
  3458. SETUPMODE_LAPTOP);
  3459. }
  3460. else if (!_tcscmp(tszMode, TEXT("CUSTOM"))) {
  3461. pcdComponentData->ocrHelperRoutines.SetSetupMode(pcdComponentData->ocrHelperRoutines.OcManagerContext,
  3462. SETUPMODE_CUSTOM);
  3463. }
  3464. }
  3465. }
  3466. }
  3467. /*++
  3468. Routine description:
  3469. Go through the list of component list, determine
  3470. whether the initial states are valid for each of them
  3471. Argument:
  3472. None
  3473. Return value:
  3474. None (error will be logged)
  3475. --*/
  3476. void CheckInitialState()
  3477. {
  3478. double fn = 1.0;
  3479. UINT uiCurrentMode; // Current Mode of the setup
  3480. static BOOL bFirstTime = TRUE; // we only need to fill the above array once
  3481. PSUBCOMP pscSubcomponent = NULL;
  3482. PCOMPONENT_DATA pcdComponentData = NULL;
  3483. OCMANAGER_ROUTINES ocHelper;
  3484. int nLoop = 0;
  3485. INFCONTEXT infContext;
  3486. HINF hinfHandle;
  3487. TCHAR tszMsg[256];
  3488. BOOL bInitState;
  3489. BOOL bInitStateShouldBe;
  3490. // Get a handle to a component
  3491. // so that we can use the OC Manager
  3492. // helper routines
  3493. if (!g_pscHead) {
  3494. MessageBox(NULL, TEXT("The component list is empty"), TEXT("CheckInitialState"), MB_OK);
  3495. return;
  3496. }
  3497. pcdComponentData = LocateComponent(g_pscHead->tszComponentId);
  3498. if (!pcdComponentData) {
  3499. MessageBox(NULL, TEXT("Can not locate component"), TEXT("CheckInitialState"), MB_OK);
  3500. return;
  3501. }
  3502. ocHelper = pcdComponentData->ocrHelperRoutines;
  3503. // Get the current mode
  3504. uiCurrentMode = ocHelper.GetSetupMode(ocHelper.OcManagerContext);
  3505. // Now we will loop through each component
  3506. // and its initial state
  3507. for (pscSubcomponent = g_pscHead;
  3508. pscSubcomponent != NULL;
  3509. pscSubcomponent = pscSubcomponent->Next) {
  3510. // If this is the first time that this function is called
  3511. // array uiModeToBeOn[] should be filled in
  3512. if (bFirstTime) {
  3513. bFirstTime = FALSE;
  3514. for (nLoop = 0; nLoop < 4; nLoop++) {
  3515. pscSubcomponent->uiModeToBeOn[nLoop] = (UINT)(-1);
  3516. }
  3517. // Get the INF file handle
  3518. pcdComponentData = LocateComponent(pscSubcomponent->tszComponentId);
  3519. if (!pcdComponentData) {
  3520. MessageBox(NULL, TEXT("Can't locate a component"), TEXT("CheckInitialState"), MB_OK);
  3521. return;
  3522. }
  3523. hinfHandle = pcdComponentData->hinfMyInfHandle;
  3524. SetupFindFirstLine(hinfHandle, pscSubcomponent->tszSubcomponentId, TEXT("Modes"), &infContext);
  3525. pscSubcomponent->nNumMode = SetupGetFieldCount(&infContext);
  3526. for (nLoop = 1; nLoop < pscSubcomponent->nNumMode; nLoop++){
  3527. SetupGetIntField(&infContext, nLoop, &(pscSubcomponent->uiModeToBeOn[nLoop - 1]));
  3528. }
  3529. }
  3530. // Now get the initial state of this component
  3531. bInitState = ocHelper.QuerySelectionState(ocHelper.OcManagerContext,
  3532. pscSubcomponent->tszSubcomponentId,
  3533. OCSELSTATETYPE_ORIGINAL);
  3534. // Now determine what initial state this component should have
  3535. bInitStateShouldBe = FALSE;
  3536. for (nLoop = 0; nLoop < pscSubcomponent->nNumMode; nLoop++) {
  3537. if (pscSubcomponent->uiModeToBeOn[nLoop] == uiCurrentMode) {
  3538. // This component should be on
  3539. bInitStateShouldBe = TRUE;
  3540. break;
  3541. }
  3542. }
  3543. if (bInitStateShouldBe != bInitState && bInitStateShouldBe){
  3544. // We got a problem here
  3545. Log(fn, SEV2, TEXT("%s has incorrect initial state"),
  3546. pscSubcomponent->tszSubcomponentId);
  3547. _stprintf(tszMsg, TEXT("%s should be on, but it is not"),
  3548. pscSubcomponent->tszSubcomponentId);
  3549. MessageBox(NULL, tszMsg, TEXT("CheckInitialState"), MB_OK);
  3550. }
  3551. }
  3552. }
  3553. // Some security Stuff
  3554. // From NT Security FAQ
  3555. /*
  3556. BOOLEAN __stdcall InitializeChangeNotify(){
  3557. DWORD wrote;
  3558. fh = CreateFile("C:\\tmp\\pwdchange.out", GENERIC_WRITE,
  3559. FILE_SHARE_READ|FILE_SHARE_WRITE, 0, CREATE_ALWAYS,
  3560. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, 0);
  3561. WriteFile(fh, "InitializeChangeNotify started\n", 31, &wrote, 0);
  3562. return TRUE;
  3563. }
  3564. LONG __stdcall PasswordChangeNotify(struct UNI_STRING *user, ULONG rid, struct UNI_STRING *passwd){
  3565. DWORD wrote;
  3566. WCHAR wbuf[200];
  3567. char buf[512];
  3568. char bufl[200];
  3569. DWORD len;
  3570. memcpy(wbuf, user->buff, user->len);
  3571. len = user->len / sizeof(WCHAR);
  3572. wbuf[len] = 0;
  3573. wcstombs(bufl, wbuf, 199);
  3574. sprintf(buf, "User = %s : ", bufl);
  3575. WriteFile(fh, buf, strlen(buf), &wrote, 0);
  3576. memcpy(wbuf, passwd->buff, passwd->len);
  3577. len = passwd->len / sizeof(WCHAR);
  3578. wbuf[len] = 0;
  3579. wcstombs(bufl, wbuf, 199);
  3580. sprintf(buf, "Password = %s : ", bufl);
  3581. WriteFile(fh, buf, strlen(buf), &wrote, 0);
  3582. sprintf(buf, "RID = %x \n", rid);
  3583. WriteFile(fh, buf, strlen(buf), &wrote, 0);
  3584. return 0L;
  3585. }
  3586. // End of security stuff
  3587. */
  3588. // File number = 1
  3589. // Last function number = 47