Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1583 lines
42 KiB

  1. /*
  2. * Copyright (c) 1996 Microsoft Corporation
  3. *
  4. * Module Name:
  5. *
  6. * ocgen.cpp
  7. *
  8. * Abstract:
  9. *
  10. * This file handles all messages passed by the OC Manager
  11. *
  12. * Author:
  13. *
  14. * Pat Styles (patst) Jan-20-1998
  15. *
  16. * Environment:
  17. *
  18. * User Mode
  19. */
  20. #define _OCGEN_CPP_
  21. #include <stdlib.h>
  22. #include <assert.h>
  23. #include <tchar.h>
  24. #include <objbase.h>
  25. #include <shlwapi.h>
  26. #include <lm.h>
  27. #include "ocgen.h"
  28. #pragma hdrstop
  29. // also referred to in ocgen.h // forward reference
  30. DWORD OnPreinitialize();
  31. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc);
  32. DWORD OnSetLanguage();
  33. DWORD_PTR OnQueryImage();
  34. DWORD OnSetupRequestPages(UINT type, PVOID srp);
  35. DWORD OnQuerySelStateChange(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state, UINT flags);
  36. DWORD OnCalcDiskSpace(LPCTSTR ComponentId, LPCTSTR SubcomponentId, DWORD addComponent, HDSKSPC dspace);
  37. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue);
  38. DWORD OnNotificationFromQueue();
  39. DWORD OnQueryStepCount();
  40. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  41. DWORD OnCleanup();
  42. DWORD OnQueryState(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state);
  43. DWORD OnNeedMedia();
  44. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  45. DWORD OnQuerySkipPage();
  46. DWORD OnWizardCreated();
  47. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per);
  48. PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId);
  49. PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId);
  50. VOID RemoveComponent(LPCTSTR ComponentId);
  51. BOOL StateInfo(PPER_COMPONENT_DATA cd, LPCTSTR SubcomponentId, BOOL *state);
  52. DWORD RegisterServers(HINF hinf, LPCTSTR component, DWORD state);
  53. DWORD EnumSections(HINF hinf, const TCHAR *component, const TCHAR *key, DWORD index, INFCONTEXT *pic, TCHAR *name);
  54. DWORD RegisterServices(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  55. DWORD CleanupNetShares(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  56. DWORD RunExternalProgram(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  57. DWORD OnQuerySelStateChangeIEHardenUser(LPCTSTR ComponentId,
  58. LPCTSTR SubcomponentId,
  59. UINT state,
  60. UINT flags);
  61. DWORD OnQueryStateIEHardenUser(
  62. LPCTSTR ComponentId,
  63. LPCTSTR SubcomponentId,
  64. UINT state);
  65. // for registering dlls
  66. typedef HRESULT (__stdcall *pfn)(void);
  67. #define KEYWORD_REGSVR TEXT("RegSvr")
  68. #define KEYWORD_UNREGSVR TEXT("UnregSvr")
  69. #define KEYWORD_UNINSTALL TEXT("Uninstall")
  70. #define KEYWORD_SOURCEPATH TEXT("SourcePath")
  71. #define KEYWORD_DELSHARE TEXT("DelShare")
  72. #define KEYWORD_ADDSERVICE TEXT("AddService")
  73. #define KEYWORD_DELSERVICE TEXT("DelService")
  74. #define KEYWORD_SHARENAME TEXT("Share")
  75. #define KEYWORD_RUN TEXT("Run")
  76. #define KEYVAL_SYSTEMSRC TEXT("SystemSrc")
  77. #define KEYWORD_COMMANDLINE TEXT("CommandLine")
  78. #define KEYWORD_TICKCOUNT TEXT("TickCount")
  79. // Services keywords/options
  80. #define KEYWORD_SERVICENAME TEXT("ServiceName")
  81. #define KEYWORD_DISPLAYNAME TEXT("DisplayName")
  82. #define KEYWORD_SERVICETYPE TEXT("ServiceType")
  83. #define KEYWORD_STARTTYPE TEXT("StartType")
  84. #define KEYWORD_ERRORCONTROL TEXT("ErrorControl")
  85. #define KEYWORD_IMAGEPATH TEXT("BinaryPathName")
  86. #define KEYWORD_LOADORDER TEXT("LoadOrderGroup")
  87. #define KEYWORD_DEPENDENCIES TEXT("Dependencies")
  88. #define KEYWORD_STARTNAME TEXT("ServiceStartName")
  89. #define KEYWORD_PASSWORD TEXT("Password")
  90. #define KEYVAL_ON TEXT("on")
  91. #define KEYVAL_OFF TEXT("off")
  92. #define KEYVAL_DEFAULT TEXT("default")
  93. const char gszRegisterSvrRoutine[] = "DllRegisterServer";
  94. const char gszUnregisterSvrRoutine[] = "DllUnregisterServer";
  95. BOOL g_fRebootNeed = FALSE;
  96. PPER_COMPONENT_DATA _cd;
  97. void av()
  98. {
  99. _cd = NULL;
  100. _cd->hinf = NULL;
  101. }
  102. /*
  103. * called by CRT when _DllMainCRTStartup is the DLL entry point
  104. */
  105. BOOL
  106. WINAPI
  107. DllMain(
  108. IN HINSTANCE hinstance,
  109. IN DWORD reason,
  110. IN LPVOID reserved
  111. )
  112. {
  113. BOOL b;
  114. UNREFERENCED_PARAMETER(reserved);
  115. b = true;
  116. switch(reason)
  117. {
  118. case DLL_PROCESS_ATTACH:
  119. ghinst = hinstance;
  120. loginit();
  121. // Fall through to process first thread
  122. case DLL_THREAD_ATTACH:
  123. b = true;
  124. break;
  125. case DLL_PROCESS_DETACH:
  126. break;
  127. case DLL_THREAD_DETACH:
  128. break;
  129. }
  130. return(b);
  131. }
  132. DWORD_PTR
  133. OcEntry(
  134. IN LPCTSTR ComponentId,
  135. IN LPCTSTR SubcomponentId,
  136. IN UINT Function,
  137. IN UINT Param1,
  138. IN OUT PVOID Param2
  139. )
  140. {
  141. DWORD_PTR rc;
  142. DebugTraceOCNotification(Function, ComponentId);
  143. logOCNotification(Function, ComponentId);
  144. switch(Function)
  145. {
  146. case OC_PREINITIALIZE:
  147. rc = OnPreinitialize();
  148. break;
  149. case OC_INIT_COMPONENT:
  150. rc = OnInitComponent(ComponentId, (PSETUP_INIT_COMPONENT)Param2);
  151. break;
  152. case OC_EXTRA_ROUTINES:
  153. rc = OnExtraRoutines(ComponentId, (PEXTRA_ROUTINES)Param2);
  154. break;
  155. case OC_SET_LANGUAGE:
  156. rc = OnSetLanguage();
  157. break;
  158. case OC_QUERY_IMAGE:
  159. rc = OnQueryImage();
  160. break;
  161. case OC_REQUEST_PAGES:
  162. rc = OnSetupRequestPages(Param1, Param2);
  163. break;
  164. case OC_QUERY_CHANGE_SEL_STATE:
  165. rc = OnQuerySelStateChange(ComponentId, SubcomponentId, Param1, (UINT)((UINT_PTR)Param2));
  166. break;
  167. case OC_CALC_DISK_SPACE:
  168. rc = OnCalcDiskSpace(ComponentId, SubcomponentId, Param1, Param2);
  169. break;
  170. case OC_QUEUE_FILE_OPS:
  171. rc = OnQueueFileOps(ComponentId, SubcomponentId, (HSPFILEQ)Param2);
  172. break;
  173. case OC_NOTIFICATION_FROM_QUEUE:
  174. rc = OnNotificationFromQueue();
  175. break;
  176. case OC_QUERY_STEP_COUNT:
  177. rc = OnQueryStepCount();
  178. break;
  179. case OC_COMPLETE_INSTALLATION:
  180. rc = OnCompleteInstallation(ComponentId, SubcomponentId);
  181. break;
  182. case OC_CLEANUP:
  183. rc = OnCleanup();
  184. break;
  185. case OC_QUERY_STATE:
  186. rc = OnQueryState(ComponentId, SubcomponentId, Param1);
  187. break;
  188. case OC_NEED_MEDIA:
  189. rc = OnNeedMedia();
  190. break;
  191. case OC_ABOUT_TO_COMMIT_QUEUE:
  192. rc = OnAboutToCommitQueue(ComponentId,SubcomponentId);
  193. break;
  194. case OC_QUERY_SKIP_PAGE:
  195. rc = OnQuerySkipPage();
  196. break;
  197. case OC_WIZARD_CREATED:
  198. rc = OnWizardCreated();
  199. break;
  200. default:
  201. rc = NO_ERROR;
  202. break;
  203. }
  204. DebugTrace(1, TEXT("processing completed"));
  205. logOCNotificationCompletion();
  206. return rc;
  207. }
  208. /*-------------------------------------------------------*/
  209. /*
  210. * OC Manager message handlers
  211. *
  212. *-------------------------------------------------------*/
  213. /* OnPreinitialize()
  214. *
  215. * handler for OC_PREINITIALIZE
  216. */
  217. DWORD
  218. OnPreinitialize(
  219. VOID
  220. )
  221. {
  222. #ifdef ANSI
  223. return OCFLAG_ANSI;
  224. #else
  225. return OCFLAG_UNICODE;
  226. #endif
  227. }
  228. /*
  229. * OnInitComponent()
  230. *
  231. * handler for OC_INIT_COMPONENT
  232. */
  233. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc)
  234. {
  235. PPER_COMPONENT_DATA cd;
  236. INFCONTEXT context;
  237. TCHAR buf[256];
  238. HINF hinf;
  239. BOOL rc;
  240. // assert(0);
  241. // av();
  242. // add component to linked list
  243. if (!(cd = AddNewComponent(ComponentId)))
  244. return ERROR_NOT_ENOUGH_MEMORY;
  245. // store component inf handle
  246. cd->hinf = (psc->ComponentInfHandle == INVALID_HANDLE_VALUE)
  247. ? NULL
  248. : psc->ComponentInfHandle;
  249. // open the inf
  250. if (cd->hinf)
  251. SetupOpenAppendInfFile(NULL, cd->hinf,NULL);
  252. // copy helper routines and flags
  253. cd->HelperRoutines = psc->HelperRoutines;
  254. cd->Flags = psc->SetupData.OperationFlags;
  255. cd->SourcePath = NULL;
  256. #if 0
  257. // Setup the SourcePath. Read inf and see if we should use the NT setup source.
  258. // If so, set to null and setupapi will take care of this for us. If there is
  259. // something specified in the inf, use it, otherwise use what is passed to us.
  260. *buf = 0;
  261. rc = SetupFindFirstLine(cd->hinf,
  262. ComponentId,
  263. KEYWORD_SOURCEPATH,
  264. &context);
  265. if (rc) {
  266. rc = SetupGetStringField(&context,
  267. 1,
  268. buf,
  269. sizeof(buf) / sizeof(TCHAR),
  270. NULL);
  271. }
  272. if (!_tcsicmp(buf, KEYVAL_SYSTEMSRC)) {
  273. cd->SourcePath = NULL;
  274. } else {
  275. cd->SourcePath = (TCHAR *)LocalAlloc(LMEM_FIXED, SBUF_SIZE);
  276. if (!cd->SourcePath)
  277. return ERROR_CANCELLED;
  278. if (!*buf)
  279. _tcscpy(cd->SourcePath, psc->SetupData.SourcePath);
  280. else
  281. ExpandEnvironmentStrings(buf, cd->SourcePath, S_SIZE);
  282. }
  283. #endif
  284. // play
  285. srand(GetTickCount());
  286. return NO_ERROR;
  287. }
  288. /*
  289. * OnExtraRoutines()
  290. *
  291. * handler for OC_EXTRA_ROUTINES
  292. */
  293. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per)
  294. {
  295. PPER_COMPONENT_DATA cd;
  296. if (!(cd = LocateComponent(ComponentId)))
  297. return NO_ERROR;
  298. memcpy(&cd->ExtraRoutines, per, per->size);
  299. return NO_ERROR;
  300. }
  301. /*
  302. * OnSetLanguage()
  303. *
  304. * handler for OC_SET_LANGUAGE
  305. */
  306. DWORD OnSetLanguage()
  307. {
  308. return false;
  309. }
  310. /*
  311. * OnSetLanguage()
  312. *
  313. * handler for OC_SET_LANGUAGE
  314. */
  315. DWORD_PTR OnQueryImage()
  316. {
  317. return (DWORD_PTR)LoadBitmap(NULL,MAKEINTRESOURCE(32754)); // OBM_CLOSE
  318. }
  319. /*
  320. * OnSetupRequestPages
  321. *
  322. * Prepares wizard pages and returns them to the OC Manager
  323. */
  324. DWORD OnSetupRequestPages(UINT type, PVOID srp)
  325. {
  326. return 0;
  327. }
  328. /*
  329. * OnWizardCreated()
  330. */
  331. DWORD OnWizardCreated()
  332. {
  333. return NO_ERROR;
  334. }
  335. /*
  336. * OnQuerySkipPage()
  337. *
  338. * don't let the user deselect the sam component
  339. */
  340. DWORD OnQuerySkipPage()
  341. {
  342. return false;
  343. }
  344. /*
  345. * OnQuerySelStateChange()
  346. *
  347. * don't let the user deselect the sam component
  348. */
  349. DWORD OnQuerySelStateChange(LPCTSTR ComponentId,
  350. LPCTSTR SubcomponentId,
  351. UINT state,
  352. UINT flags)
  353. {
  354. /*
  355. * IEHarden/IEHardenUser component has some dependancies with TS.
  356. * Lets handle this subcomp in a seperate function.
  357. */
  358. if (SubcomponentId && !_tcsicmp(SubcomponentId, TEXT("IEHardenUser")))
  359. {
  360. assert(_tcsicmp(ComponentId, TEXT("IEHarden")) == 0);
  361. return OnQuerySelStateChangeIEHardenUser(ComponentId, SubcomponentId, state, flags);
  362. }
  363. DWORD rc = true;
  364. #if 0
  365. // if (!(flags & OCQ_ACTUAL_SELECTION)) {
  366. if (!_tcsicmp(SubcomponentId, TEXT("three"))) {
  367. if (!state) {
  368. return false;
  369. }
  370. }
  371. if (!_tcsicmp(ComponentId, TEXT("three"))) {
  372. if (!state) {
  373. return false;
  374. }
  375. }
  376. if (!_tcsicmp(SubcomponentId, TEXT("gs7"))) {
  377. if (state) {
  378. return false;
  379. }
  380. }
  381. if (!_tcsicmp(ComponentId, TEXT("gs7"))) {
  382. if (state) {
  383. return false;
  384. }
  385. }
  386. // }
  387. #endif
  388. if (!rc && (flags & OCQ_ACTUAL_SELECTION))
  389. MessageBeep(MB_ICONEXCLAMATION);
  390. return rc;
  391. }
  392. /*
  393. * OnCalcDiskSpace()
  394. *
  395. * handler for OC_ON_CALC_DISK_SPACE
  396. */
  397. DWORD OnCalcDiskSpace(LPCTSTR ComponentId,
  398. LPCTSTR SubcomponentId,
  399. DWORD addComponent,
  400. HDSKSPC dspace)
  401. {
  402. DWORD rc = NO_ERROR;
  403. TCHAR section[S_SIZE];
  404. PPER_COMPONENT_DATA cd;
  405. //
  406. // Param1 = 0 if for removing component or non-0 if for adding component
  407. // Param2 = HDSKSPC to operate on
  408. //
  409. // Return value is Win32 error code indicating outcome.
  410. //
  411. // In our case the private section for this component/subcomponent pair
  412. // is a simple standard inf install section, so we can use the high-level
  413. // disk space list api to do what we want.
  414. //
  415. if (!(cd = LocateComponent(ComponentId)))
  416. return NO_ERROR;
  417. _tcscpy(section, SubcomponentId);
  418. if (addComponent)
  419. {
  420. rc = SetupAddInstallSectionToDiskSpaceList(dspace,
  421. cd->hinf,
  422. NULL,
  423. section,
  424. 0,
  425. 0);
  426. }
  427. else
  428. {
  429. rc = SetupRemoveInstallSectionFromDiskSpaceList(dspace,
  430. cd->hinf,
  431. NULL,
  432. section,
  433. 0,
  434. 0);
  435. }
  436. if (!rc)
  437. rc = GetLastError();
  438. else
  439. rc = NO_ERROR;
  440. return rc;
  441. }
  442. /*
  443. * OnQueueFileOps()
  444. *
  445. * handler for OC_QUEUE_FILE_OPS
  446. */
  447. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue)
  448. {
  449. PPER_COMPONENT_DATA cd;
  450. BOOL state;
  451. BOOL rc;
  452. INFCONTEXT context;
  453. TCHAR section[256];
  454. TCHAR srcpathbuf[256];
  455. TCHAR *srcpath;
  456. if (!(cd = LocateComponent(ComponentId)))
  457. return NO_ERROR;
  458. if (!SubcomponentId || !*SubcomponentId)
  459. return NO_ERROR;
  460. cd->queue = queue;
  461. if (!StateInfo(cd, SubcomponentId, &state))
  462. return NO_ERROR;
  463. wsprintf(section, SubcomponentId);
  464. rc = TRUE;
  465. if (!state) {
  466. // being uninstalled. Fetch uninstall section name.
  467. rc = SetupFindFirstLine(cd->hinf,
  468. SubcomponentId,
  469. KEYWORD_UNINSTALL,
  470. &context);
  471. if (rc) {
  472. rc = SetupGetStringField(&context,
  473. 1,
  474. section,
  475. sizeof(section) / sizeof(TCHAR),
  476. NULL);
  477. }
  478. // also, unregister the dlls and kill services before deletion
  479. SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  480. SetupInstallFromInfSection(NULL,cd->hinf,section,SPINST_UNREGSVR,NULL,NULL,0,NULL,NULL,NULL,NULL);
  481. }
  482. if (rc) {
  483. // if uninstalling, don't use version checks
  484. rc = SetupInstallFilesFromInfSection(cd->hinf,
  485. NULL,
  486. queue,
  487. section,
  488. cd->SourcePath,
  489. state ? SP_COPY_NEWER : 0);
  490. }
  491. if (!rc)
  492. return GetLastError();
  493. return NO_ERROR;
  494. }
  495. /*
  496. * OnNotificationFromQueue()
  497. *
  498. * handler for OC_NOTIFICATION_FROM_QUEUE
  499. *
  500. * NOTE: although this notification is defined,
  501. * it is currently unimplemented in oc manager
  502. */
  503. DWORD OnNotificationFromQueue()
  504. {
  505. return NO_ERROR;
  506. }
  507. /*
  508. * OnQueryStepCount
  509. *
  510. * handler forOC_QUERY_STEP_COUNT
  511. */
  512. DWORD OnQueryStepCount()
  513. {
  514. return 2;
  515. }
  516. /*
  517. * OnCompleteInstallation
  518. *
  519. * handler for OC_COMPLETE_INSTALLATION
  520. */
  521. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  522. {
  523. PPER_COMPONENT_DATA cd;
  524. INFCONTEXT context;
  525. TCHAR section[256];
  526. BOOL state;
  527. BOOL rc;
  528. DWORD Error = NO_ERROR;
  529. // Do post-installation processing in the cleanup section.
  530. // This way we know all compoents queued for installation
  531. // have beein installed before we do our stuff.
  532. if (!(cd = LocateComponent(ComponentId)))
  533. return NO_ERROR;
  534. if (!SubcomponentId || !*SubcomponentId)
  535. return NO_ERROR;
  536. if (!StateInfo(cd, SubcomponentId, &state))
  537. return NO_ERROR;
  538. wsprintf(section, SubcomponentId);
  539. rc = TRUE;
  540. if (!state) {
  541. // being uninstalled. Fetch uninstall section name.
  542. rc = SetupFindFirstLine(cd->hinf,
  543. SubcomponentId,
  544. KEYWORD_UNINSTALL,
  545. &context);
  546. if (rc) {
  547. rc = SetupGetStringField(&context,
  548. 1,
  549. section,
  550. sizeof(section) / sizeof(TCHAR),
  551. NULL);
  552. }
  553. }
  554. if (state) {
  555. //
  556. // installation
  557. //
  558. if (rc) {
  559. // process the inf file
  560. rc = SetupInstallFromInfSection(NULL, // hwndOwner
  561. cd->hinf, // inf handle
  562. section, // name of component
  563. SPINST_ALL & ~SPINST_FILES,
  564. NULL, // relative key root
  565. NULL, // source root path
  566. 0, // copy flags
  567. NULL, // callback routine
  568. NULL, // callback routine context
  569. NULL, // device info set
  570. NULL); // device info struct
  571. if (rc) {
  572. rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  573. Error = GetLastError();
  574. if (!rc && Error == ERROR_SECTION_NOT_FOUND) {
  575. rc = TRUE;
  576. Error = NO_ERROR;
  577. }
  578. if (rc) {
  579. if (Error == ERROR_SUCCESS_REBOOT_REQUIRED) {
  580. cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext,TRUE);
  581. }
  582. Error = NO_ERROR;
  583. rc = RunExternalProgram(cd, section, state);
  584. }
  585. }
  586. }
  587. } else {
  588. //
  589. // uninstallation
  590. //
  591. if (rc)
  592. {
  593. rc = RunExternalProgram(cd, section, state);
  594. }
  595. if (rc) {
  596. rc = CleanupNetShares(cd, section, state);
  597. }
  598. }
  599. if (!rc && (Error == NO_ERROR) ) {
  600. Error = GetLastError( );
  601. }
  602. return Error;
  603. }
  604. /*
  605. * OnCleanup()
  606. *
  607. * handler for OC_CLEANUP
  608. */
  609. DWORD OnCleanup()
  610. {
  611. return NO_ERROR;
  612. }
  613. /*
  614. * OnQueryState()
  615. *
  616. * handler for OC_QUERY_STATE
  617. */
  618. DWORD OnQueryState(LPCTSTR ComponentId,
  619. LPCTSTR SubcomponentId,
  620. UINT state)
  621. {
  622. PPER_COMPONENT_DATA cd;
  623. #if 0
  624. if (!_tcsicmp(SubcomponentId, TEXT("alone2"))
  625. || !_tcsicmp(ComponentId, TEXT("alone2"))) {
  626. if (state == OCSELSTATETYPE_CURRENT) {
  627. if (!_tcsicmp(SubcomponentId, TEXT("alone2"))) {
  628. return SubcompOff;
  629. }
  630. }
  631. }
  632. #endif
  633. #if 0
  634. if (state == OCSELSTATETYPE_FINAL) {
  635. if (!_tcsicmp(SubcomponentId, TEXT("four"))) {
  636. tmbox(SubcomponentId);
  637. }
  638. }
  639. #endif
  640. /*
  641. * IEHarden/IEHardenUser component has some dependancies with TS.
  642. * Lets handle this subcomp in a seperate function.
  643. */
  644. if (SubcomponentId && !_tcsicmp(SubcomponentId, TEXT("IEHardenUser")))
  645. {
  646. assert(_tcsicmp(ComponentId, TEXT("IEHarden")) == 0);
  647. log(_T("makarp:Entering OnQueryStateIEHardenUser, Component=%s, SubComponent=%s, State=%d\n"), ComponentId, SubcomponentId, state);
  648. return OnQueryStateIEHardenUser(ComponentId, SubcomponentId, state);
  649. }
  650. return SubcompUseOcManagerDefault;
  651. }
  652. /*
  653. * OnNeedMedia()
  654. *
  655. * handler for OC_NEED_MEDIA
  656. */
  657. DWORD OnNeedMedia()
  658. {
  659. return false;
  660. }
  661. /*
  662. * OnAboutToCommitQueue()
  663. *
  664. * handler for OC_ABOUT_TO_COMMIT_QUEUE
  665. */
  666. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  667. {
  668. PPER_COMPONENT_DATA cd;
  669. BOOL state;
  670. BOOL rc;
  671. INFCONTEXT context;
  672. TCHAR section[256];
  673. TCHAR srcpathbuf[256];
  674. TCHAR *srcpath;
  675. if (!(cd = LocateComponent(ComponentId)))
  676. return NO_ERROR;
  677. if (!SubcomponentId || !*SubcomponentId)
  678. return NO_ERROR;
  679. if (!StateInfo(cd, SubcomponentId, &state))
  680. return NO_ERROR;
  681. //
  682. // only do stuff on uninstall
  683. //
  684. if (state) {
  685. return NO_ERROR;
  686. }
  687. // Fetch uninstall section name.
  688. rc = SetupFindFirstLine(
  689. cd->hinf,
  690. SubcomponentId,
  691. KEYWORD_UNINSTALL,
  692. &context);
  693. if (rc) {
  694. rc = SetupGetStringField(
  695. &context,
  696. 1,
  697. section,
  698. sizeof(section) / sizeof(TCHAR),
  699. NULL);
  700. }
  701. if (rc)
  702. rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  703. if (rc) {
  704. rc = SetupInstallFromInfSection(
  705. NULL,
  706. cd->hinf,
  707. section,
  708. SPINST_ALL & ~SPINST_FILES,
  709. NULL,
  710. NULL,
  711. 0,
  712. NULL,
  713. NULL,
  714. NULL,
  715. NULL);
  716. }
  717. if (rc) {
  718. SetLastError(NO_ERROR);
  719. }
  720. return GetLastError();
  721. }
  722. /*
  723. * AddNewComponent()
  724. *
  725. * add new compononent to the top of the component list
  726. */
  727. PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId)
  728. {
  729. PPER_COMPONENT_DATA data;
  730. data = (PPER_COMPONENT_DATA)LocalAlloc(LPTR,sizeof(PER_COMPONENT_DATA));
  731. if (!data)
  732. return data;
  733. data->ComponentId = (TCHAR *)LocalAlloc(LMEM_FIXED,
  734. (_tcslen(ComponentId) + 1) * sizeof(TCHAR));
  735. if(data->ComponentId)
  736. {
  737. _tcscpy((TCHAR *)data->ComponentId, ComponentId);
  738. // Stick at head of list
  739. data->Next = gcd;
  740. gcd = data;
  741. }
  742. else
  743. {
  744. LocalFree((HLOCAL)data);
  745. data = NULL;
  746. }
  747. return(data);
  748. }
  749. /*
  750. * LocateComponent()
  751. *
  752. * returns a compoent struct that matches the
  753. * passed component id.
  754. */
  755. PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId)
  756. {
  757. PPER_COMPONENT_DATA p;
  758. for (p = gcd; p; p=p->Next)
  759. {
  760. if (!_tcsicmp(p->ComponentId, ComponentId))
  761. return p;
  762. }
  763. return NULL;
  764. }
  765. /*
  766. * RemoveComponent()
  767. *
  768. * yanks a component from our linked list of components
  769. */
  770. VOID RemoveComponent(LPCTSTR ComponentId)
  771. {
  772. PPER_COMPONENT_DATA p, prev;
  773. for (prev = NULL, p = gcd; p; prev = p, p = p->Next)
  774. {
  775. if (!_tcsicmp(p->ComponentId, ComponentId))
  776. {
  777. LocalFree((HLOCAL)p->ComponentId);
  778. if (p->SourcePath)
  779. LocalFree((HLOCAL)p->SourcePath);
  780. if (prev)
  781. prev->Next = p->Next;
  782. else
  783. gcd = p->Next;
  784. LocalFree((HLOCAL)p);
  785. return;
  786. }
  787. }
  788. }
  789. // loads current selection state info into "state" and
  790. // returns whether the selection state was changed
  791. BOOL
  792. StateInfo(
  793. PPER_COMPONENT_DATA cd,
  794. LPCTSTR SubcomponentId,
  795. BOOL *state
  796. )
  797. {
  798. BOOL rc = TRUE;
  799. assert(state);
  800. // otherwise, check for a change in installation state
  801. *state = cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
  802. SubcomponentId,
  803. OCSELSTATETYPE_CURRENT);
  804. if (*state == cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
  805. SubcomponentId,
  806. OCSELSTATETYPE_ORIGINAL))
  807. {
  808. // no change
  809. rc = FALSE;
  810. }
  811. // if this is gui mode setup, presume the state has changed to force
  812. // an installation (or uninstallation)
  813. if (!(cd->Flags & SETUPOP_STANDALONE) && *state)
  814. rc = TRUE;
  815. return rc;
  816. }
  817. #if 0
  818. //
  819. // Andrewr -- get rid of RegisterServices and RegisterServers and have the oc gen component use setupapi instead.
  820. // this reduces the amount of redundant code
  821. //
  822. DWORD RegisterServices(
  823. PPER_COMPONENT_DATA cd,
  824. LPCTSTR component,
  825. DWORD state)
  826. {
  827. INFCONTEXT ic;
  828. TCHAR buf[MAX_PATH];
  829. TCHAR path[MAX_PATH];
  830. TCHAR sname[S_SIZE];
  831. TCHAR file[MAX_PATH];
  832. DWORD section;
  833. ULONG size;
  834. pfn pfreg;
  835. HINSTANCE hinst;
  836. HRESULT hr;
  837. TCHAR *keyword;
  838. SC_HANDLE schSystem;
  839. schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  840. if ( !schSystem ) {
  841. DWORD dwError = GetLastError( );
  842. if( !IsNT() && ( ERROR_CALL_NOT_IMPLEMENTED == dwError ) )
  843. {
  844. return( NO_ERROR );
  845. }
  846. else
  847. {
  848. return( dwError );
  849. }
  850. }
  851. if (state) {
  852. keyword = KEYWORD_ADDSERVICE;
  853. } else {
  854. keyword = KEYWORD_DELSERVICE;
  855. }
  856. for (section = 1;
  857. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  858. section++)
  859. {
  860. INFCONTEXT sic;
  861. SC_HANDLE schService;
  862. CHAR Temp[SBUF_SIZE];
  863. TCHAR ServiceName[ SBUF_SIZE ];
  864. TCHAR DisplayName[ SBUF_SIZE ];
  865. DWORD ServiceType;
  866. DWORD StartType;
  867. DWORD ErrorControl;
  868. TCHAR ImagePath[ SBUF_SIZE ];
  869. TCHAR LoadOrder[ SBUF_SIZE ];
  870. TCHAR Dependencies[ SBUF_SIZE ];
  871. TCHAR StartName[ SBUF_SIZE ];
  872. TCHAR Password[ SBUF_SIZE ];
  873. BOOL fDisplayName = FALSE;
  874. BOOL fServiceType = FALSE;
  875. BOOL fStartType = FALSE;
  876. BOOL fErrorControl = FALSE;
  877. BOOL fLoadOrder = FALSE;
  878. BOOL fDependencies = FALSE;
  879. BOOL fStartName = FALSE;
  880. BOOL fPassword = FALSE;
  881. BOOL fDontReboot = FALSE;
  882. //
  883. // Must have ServiceName
  884. //
  885. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SERVICENAME, &sic))
  886. {
  887. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SERVICENAME );
  888. continue;
  889. }
  890. if (!SetupGetStringField(&sic, 1, ServiceName, SBUF_SIZE, NULL))
  891. {
  892. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SERVICENAME );
  893. continue;
  894. }
  895. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_STARTTYPE, &sic))
  896. {
  897. if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
  898. {
  899. StartType = atoi( Temp );
  900. fStartType = TRUE;
  901. }
  902. }
  903. if ( state )
  904. {
  905. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_DISPLAYNAME, &sic))
  906. {
  907. if (SetupGetStringField(&sic, 1, DisplayName, SBUF_SIZE, NULL))
  908. {
  909. fDisplayName = TRUE;
  910. }
  911. }
  912. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_SERVICETYPE, &sic))
  913. {
  914. if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
  915. {
  916. ServiceType = atoi( Temp );
  917. fServiceType = TRUE;
  918. }
  919. }
  920. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_ERRORCONTROL, &sic))
  921. {
  922. if (SetupGetStringFieldA(&sic, 1, Temp, SBUF_SIZE, NULL))
  923. {
  924. ErrorControl = atoi( Temp );
  925. fErrorControl = TRUE;
  926. }
  927. }
  928. //
  929. // Must have ImagePath
  930. //
  931. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_IMAGEPATH, &sic))
  932. {
  933. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_IMAGEPATH );
  934. continue;
  935. }
  936. if (!SetupGetStringField(&sic, 1, ImagePath, SBUF_SIZE, NULL))
  937. {
  938. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_IMAGEPATH );
  939. continue;
  940. }
  941. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_LOADORDER, &sic))
  942. {
  943. if (SetupGetStringField(&sic, 1, LoadOrder, SBUF_SIZE, NULL))
  944. {
  945. fLoadOrder = TRUE;
  946. }
  947. }
  948. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_DEPENDENCIES, &sic))
  949. {
  950. if (SetupGetStringField(&sic, 1, Dependencies, SBUF_SIZE-1, NULL))
  951. {
  952. LPTSTR psz = Dependencies;
  953. // needs to be a double-null terminated string
  954. Dependencies[ lstrlen(Dependencies) + 1] = TEXT('\0');
  955. // change commas into NULL characters
  956. while ( *psz )
  957. {
  958. if ( *psz == TEXT(',') )
  959. {
  960. *psz = TEXT('\0');
  961. }
  962. psz++;
  963. }
  964. fDependencies = TRUE;
  965. }
  966. }
  967. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_STARTNAME, &sic))
  968. {
  969. if (SetupGetStringField(&sic, 1, StartName, SBUF_SIZE, NULL))
  970. {
  971. fStartName = TRUE;
  972. }
  973. }
  974. if (SetupFindFirstLine(cd->hinf, sname, KEYWORD_PASSWORD, &sic))
  975. {
  976. if (SetupGetStringField(&sic, 1, Password, SBUF_SIZE, NULL))
  977. {
  978. fPassword = TRUE;
  979. }
  980. }
  981. schService = CreateService(
  982. schSystem,
  983. ServiceName,
  984. ( fDisplayName == TRUE ? DisplayName : ServiceName ),
  985. STANDARD_RIGHTS_REQUIRED | SERVICE_START,
  986. ( fServiceType == TRUE ? ServiceType : SERVICE_WIN32_OWN_PROCESS),
  987. ( fStartType == TRUE ? StartType : SERVICE_AUTO_START),
  988. ( fErrorControl == TRUE ? ErrorControl : SERVICE_ERROR_NORMAL),
  989. ImagePath,
  990. (fLoadOrder == TRUE ? LoadOrder : NULL),
  991. NULL, // tag id
  992. ( fDependencies == TRUE ? Dependencies : NULL ),
  993. ( fStartName == TRUE ? StartName : NULL),
  994. ( fPassword == TRUE ? Password : NULL ));
  995. if ( !schService )
  996. {
  997. DWORD Error = GetLastError( );
  998. log( TEXT("OCGEN: CreateService() error 0x%08x\r\n"), Error );
  999. return Error;
  1000. }
  1001. if ( (!fStartType)
  1002. || ( fStartType && StartType == SERVICE_AUTO_START ))
  1003. {
  1004. if( !StartService( schService, 0, NULL ) )
  1005. {
  1006. DWORD Error = GetLastError( );
  1007. switch ( Error )
  1008. {
  1009. case ERROR_SERVICE_EXISTS:
  1010. {
  1011. log( TEXT("OCGEN: %s was already exists.\r\n"), ServiceName );
  1012. if ( fStartType && StartType == SERVICE_BOOT_START )
  1013. {
  1014. fDontReboot = TRUE;
  1015. }
  1016. }
  1017. break;
  1018. case ERROR_SERVICE_ALREADY_RUNNING:
  1019. {
  1020. log( TEXT("OCGEN: %s was already started.\r\n"), ServiceName );
  1021. if ( fStartType && StartType == SERVICE_BOOT_START )
  1022. {
  1023. fDontReboot = TRUE;
  1024. }
  1025. }
  1026. break;
  1027. default:
  1028. log( TEXT("OCGEN: StartService() error 0x%08x\r\n"), Error );
  1029. return Error;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. else
  1035. {
  1036. schService = OpenService( schSystem,
  1037. ServiceName,
  1038. STANDARD_RIGHTS_REQUIRED | DELETE );
  1039. if ( schService )
  1040. {
  1041. SERVICE_STATUS ss;
  1042. DeleteService( schService );
  1043. ControlService( schService, SERVICE_CONTROL_STOP, &ss );
  1044. }
  1045. }
  1046. //
  1047. // BOOT drivers require a reboot unless they were already started.
  1048. //
  1049. if ( schService
  1050. && fStartType && StartType == SERVICE_BOOT_START
  1051. && fDontReboot == FALSE)
  1052. {
  1053. cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext, NULL);
  1054. }
  1055. if ( schService )
  1056. {
  1057. CloseServiceHandle( schService );
  1058. }
  1059. }
  1060. return NO_ERROR;
  1061. }
  1062. #endif
  1063. #if 0
  1064. DWORD
  1065. RegisterServers(
  1066. HINF hinf,
  1067. LPCTSTR component,
  1068. DWORD state
  1069. )
  1070. {
  1071. INFCONTEXT ic;
  1072. TCHAR buf[MAX_PATH];
  1073. TCHAR path[MAX_PATH];
  1074. TCHAR sname[S_SIZE];
  1075. TCHAR file[MAX_PATH];
  1076. DWORD section;
  1077. ULONG size;
  1078. pfn pfreg;
  1079. HINSTANCE hinst;
  1080. HRESULT hr;
  1081. TCHAR *keyword;
  1082. LPCSTR routine;
  1083. CoInitialize(NULL);
  1084. if (state) {
  1085. keyword = KEYWORD_REGSVR;
  1086. routine = (LPCSTR)gszRegisterSvrRoutine;
  1087. } else {
  1088. keyword = KEYWORD_UNREGSVR;
  1089. routine = (LPCSTR)gszUnregisterSvrRoutine;
  1090. }
  1091. for (section = 1;
  1092. EnumSections(hinf, component, keyword, section, &ic, sname);
  1093. section++)
  1094. {
  1095. if (!SetupGetTargetPath(hinf, NULL, sname, path, sizeof(path), &size))
  1096. continue;
  1097. PathAddBackslash(path);
  1098. do {
  1099. // get fully qualified path to dll to register
  1100. if (!SetupGetStringField(&ic, 0, buf, sizeof(buf)/sizeof(buf[0]), NULL))
  1101. continue;
  1102. _tcscpy(file, path);
  1103. _tcscat(file, buf);
  1104. // call the dll's RegisterServer routine
  1105. if (!(hinst = LoadLibrary(file)))
  1106. continue;
  1107. if (!(pfreg = (pfn)GetProcAddress(hinst, routine)))
  1108. continue;
  1109. hr = pfreg();
  1110. assert(hr == NO_ERROR);
  1111. FreeLibrary(hinst);
  1112. // on to the next
  1113. } while (SetupFindNextLine(&ic, &ic));
  1114. }
  1115. CoUninitialize();
  1116. return TRUE;
  1117. }
  1118. #endif
  1119. /*
  1120. * EnumSections()
  1121. *
  1122. * finds the name of a section for a specified keyword
  1123. */
  1124. DWORD
  1125. EnumSections(
  1126. HINF hinf,
  1127. const TCHAR *component,
  1128. const TCHAR *key,
  1129. DWORD index,
  1130. INFCONTEXT *pic,
  1131. TCHAR *name
  1132. )
  1133. {
  1134. TCHAR section[S_SIZE];
  1135. if (!SetupFindFirstLine(hinf, component, NULL, pic))
  1136. return 0;
  1137. if (!SetupFindNextMatchLine(pic, key, pic))
  1138. return 0;
  1139. if (index > SetupGetFieldCount(pic))
  1140. return 0;
  1141. if (!SetupGetStringField(pic, index, section, sizeof(section)/sizeof(section[0]), NULL))
  1142. return 0;
  1143. if (name)
  1144. _tcscpy(name, section);
  1145. return SetupFindFirstLine(hinf, section, NULL, pic);
  1146. }
  1147. DWORD
  1148. OcLog(
  1149. LPCTSTR ComponentId,
  1150. UINT level,
  1151. LPCTSTR sz
  1152. )
  1153. {
  1154. TCHAR fmt[5000];
  1155. PPER_COMPONENT_DATA cd;
  1156. if (!(cd = LocateComponent(ComponentId)))
  1157. return NO_ERROR;
  1158. assert(cd->ExtraRoutines.LogError);
  1159. assert(level);
  1160. assert(sz);
  1161. _tcscpy(fmt, TEXT("%s: %s"));
  1162. return cd->ExtraRoutines.LogError(cd->HelperRoutines.OcManagerContext,
  1163. level,
  1164. fmt,
  1165. ComponentId,
  1166. sz);
  1167. }
  1168. DWORD
  1169. CleanupNetShares(
  1170. PPER_COMPONENT_DATA cd,
  1171. LPCTSTR component,
  1172. DWORD state)
  1173. {
  1174. INFCONTEXT ic;
  1175. TCHAR sname[S_SIZE];
  1176. DWORD section;
  1177. TCHAR *keyword;
  1178. if (state) {
  1179. return NO_ERROR;
  1180. } else {
  1181. keyword = KEYWORD_DELSHARE;
  1182. }
  1183. for (section = 1;
  1184. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  1185. section++)
  1186. {
  1187. INFCONTEXT sic;
  1188. NET_API_STATUS netStat;
  1189. CHAR Temp[SBUF_SIZE];
  1190. TCHAR ShareName[ SBUF_SIZE ];
  1191. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SHARENAME, &sic))
  1192. {
  1193. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SHARENAME );
  1194. continue;
  1195. }
  1196. if (!SetupGetStringField(&sic, 1, ShareName, SBUF_SIZE, NULL))
  1197. {
  1198. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_SHARENAME );
  1199. continue;
  1200. }
  1201. #ifdef UNICODE
  1202. netStat = NetShareDel( NULL, ShareName, 0 );
  1203. #else // UNICODE
  1204. WCHAR ShareNameW[ SBUF_SIZE ];
  1205. mbstowcs( ShareNameW, ShareName, lstrlen(ShareName));
  1206. netStat = NetShareDel( NULL, ShareNameW, 0 );
  1207. #endif // UNICODE
  1208. if ( netStat != NERR_Success )
  1209. {
  1210. log( TEXT("OCGEN: Failed to remove %s share. Error 0x%08x\r\n"), ShareName, netStat );
  1211. continue;
  1212. }
  1213. log( TEXT("OCGEN: %s share removed successfully.\r\n"), ShareName );
  1214. }
  1215. return TRUE;
  1216. }
  1217. DWORD
  1218. RunExternalProgram(
  1219. PPER_COMPONENT_DATA cd,
  1220. LPCTSTR component,
  1221. DWORD state)
  1222. {
  1223. INFCONTEXT ic;
  1224. TCHAR sname[S_SIZE];
  1225. DWORD section;
  1226. TCHAR *keyword;
  1227. keyword = KEYWORD_RUN;
  1228. for (section = 1;
  1229. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  1230. section++)
  1231. {
  1232. INFCONTEXT sic;
  1233. TCHAR CommandLine[ SBUF_SIZE ];
  1234. CHAR szTickCount[ SBUF_SIZE ];
  1235. ULONG TickCount;
  1236. BOOL b;
  1237. STARTUPINFO startupinfo;
  1238. PROCESS_INFORMATION process_information;
  1239. DWORD dwErr;
  1240. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_COMMANDLINE , &sic))
  1241. {
  1242. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_COMMANDLINE );
  1243. continue;
  1244. }
  1245. if (!SetupGetStringField(&sic, 1, CommandLine, SBUF_SIZE, NULL))
  1246. {
  1247. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_COMMANDLINE );
  1248. continue;
  1249. }
  1250. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_TICKCOUNT, &sic))
  1251. {
  1252. log( TEXT("OCGEN: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_TICKCOUNT );
  1253. continue;
  1254. }
  1255. if (!SetupGetStringFieldA(&sic, 1, szTickCount, SBUF_SIZE, NULL))
  1256. {
  1257. log( TEXT("OCGEN: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_TICKCOUNT );
  1258. continue;
  1259. }
  1260. TickCount = atoi( szTickCount );
  1261. ZeroMemory( &startupinfo, sizeof(startupinfo) );
  1262. startupinfo.cb = sizeof(startupinfo);
  1263. startupinfo.dwFlags = STARTF_USESHOWWINDOW;
  1264. startupinfo.wShowWindow = SW_HIDE | SW_SHOWMINNOACTIVE;
  1265. b = CreateProcess( NULL,
  1266. CommandLine,
  1267. NULL,
  1268. NULL,
  1269. FALSE,
  1270. CREATE_DEFAULT_ERROR_MODE,
  1271. NULL,
  1272. NULL,
  1273. &startupinfo,
  1274. &process_information );
  1275. if ( !b )
  1276. {
  1277. log( TEXT("OCGEN: failed to spawn %s process.\r\n"), CommandLine );
  1278. continue;
  1279. }
  1280. dwErr = WaitForSingleObject( process_information.hProcess, TickCount * 1000 );
  1281. if ( dwErr != NO_ERROR )
  1282. {
  1283. log( TEXT("OCGEN: WaitForSingleObject() failed. Error 0x%08x\r\n"), dwErr );
  1284. TerminateProcess( process_information.hProcess, -1 );
  1285. CloseHandle( process_information.hProcess );
  1286. CloseHandle( process_information.hThread );
  1287. continue;
  1288. }
  1289. CloseHandle( process_information.hProcess );
  1290. CloseHandle( process_information.hThread );
  1291. log( TEXT("OCGEN: %s successfully completed within %u seconds.\r\n"), CommandLine, TickCount );
  1292. }
  1293. return TRUE;
  1294. }