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.

1058 lines
26 KiB

  1. /*
  2. * server.cxx
  3. */
  4. #ifdef UNICODE
  5. #define _UNICODE 1
  6. #endif
  7. #include "server.hxx"
  8. #include "factory.hxx"
  9. #include "tchar.h"
  10. long ObjectCount = 0;
  11. TCHAR * AtStorageFileName = TEXT("c:\\tmp\\atbits.dat");
  12. #ifdef USERPCPERFDOMAIN
  13. TCHAR * UserName = TEXT("rpcperf\\oleuser");
  14. #else
  15. TCHAR * UserName = TEXT("redmond\\oleuser");
  16. #endif
  17. TCHAR * Password = TEXT("TwoFor1");
  18. TCHAR * ServiceName = TEXT("ActTestService");
  19. TCHAR * ServiceDisplayName = TEXT("ActTestService");
  20. BOOL fStartedAsService = FALSE;
  21. HANDLE hStopServiceEvent;
  22. #ifdef FREETHREADED
  23. HANDLE hFreeThreadEvent;
  24. #endif
  25. SERVICE_STATUS SStatus;
  26. SERVICE_STATUS_HANDLE hService;
  27. BOOL InstallService(TCHAR * );
  28. HKEY ghClsidRootKey = 0;
  29. HKEY ghAppIDRootKey = 0;
  30. DWORD RegHandleLocal;
  31. DWORD RegHandleRemote;
  32. DWORD RegHandleAtStorage;
  33. DWORD RegHandlePreConfig;
  34. DWORD RegHandleRunAsLoggedOn;
  35. DWORD RegHandleService;
  36. DWORD RegHandleServerOnly;
  37. unsigned uClassIndex = 0;
  38. //+---------------------------------------------------------------------------
  39. //
  40. // Function: main
  41. //
  42. // Synopsis: main entry point for SCM
  43. //
  44. // History: 1-18-96 stevebl Created
  45. //
  46. //----------------------------------------------------------------------------
  47. void _cdecl RealMain( int argc, char ** argv )
  48. {
  49. HRESULT hr;
  50. MSG msg;
  51. if ( (argc > 1) &&
  52. ((strcmp(argv[1],"-?") == 0) || (strcmp(argv[1],"/?") == 0)) )
  53. PrintUsageAndExit();
  54. if ( (argc > 1) && (strcmp(argv[1],"-r") == 0) )
  55. {
  56. DebuggerType eDebug = same_debugger;
  57. int n;
  58. n = 2;
  59. if ( n < argc )
  60. {
  61. if (strcmp(argv[n],"-d") == 0)
  62. eDebug = windbg_debugger;
  63. else if (strcmp(argv[n],"-n") == 0 )
  64. eDebug = ntsd_debugger;
  65. else if (strcmp(argv[n],"-x") == 0 )
  66. eDebug = clear_debugger;
  67. }
  68. if ( hr = InitializeRegistry( eDebug ) )
  69. printf("InitializeRegistry failed with %08x\n", hr);
  70. else
  71. printf("Registry updated successfully.\n");
  72. return;
  73. }
  74. // Started manually. Don't go away.
  75. if ( (argc == 1) && ! fStartedAsService )
  76. ObjectCount = 1;
  77. if ( ! fStartedAsService )
  78. {
  79. if ( (argc >= 3 && strcmp(argv[2], "-Embedding") == 0) )
  80. uClassIndex = argv[1][0] - '0';
  81. else
  82. uClassIndex = 0;
  83. }
  84. if ( fStartedAsService )
  85. {
  86. uClassIndex = 8;
  87. #ifdef NT351
  88. hr = E_FAIL;
  89. #else
  90. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  91. #endif
  92. }
  93. else
  94. {
  95. #ifdef FREETHREADED
  96. hFreeThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  97. hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
  98. #else
  99. hr = CoInitialize(NULL);
  100. #endif
  101. }
  102. if ( FAILED(hr) )
  103. {
  104. printf( "Server: CoInitialize failed(%x)\n", hr );
  105. return;
  106. }
  107. if (0 == uClassIndex || 2 == uClassIndex)
  108. {
  109. hr = CoRegisterClassObject( CLSID_ActLocal,
  110. (IUnknown *)new FactoryLocal(),
  111. CLSCTX_LOCAL_SERVER,
  112. REGCLS_MULTIPLEUSE,
  113. &RegHandleLocal );
  114. if ( FAILED(hr) )
  115. {
  116. printf("Server: CoRegisterClassObject failed %x\n", hr);
  117. CoUninitialize();
  118. return;
  119. }
  120. }
  121. if (0 == uClassIndex || 3 == uClassIndex)
  122. {
  123. hr = CoRegisterClassObject( CLSID_ActRemote,
  124. (IUnknown *)new FactoryRemote(),
  125. CLSCTX_LOCAL_SERVER,
  126. REGCLS_MULTIPLEUSE,
  127. &RegHandleRemote );
  128. if ( FAILED(hr) )
  129. {
  130. printf("Server: CoRegisterClassObject failed %x\n", hr);
  131. if (0 == uClassIndex)
  132. {
  133. CoRevokeClassObject( RegHandleLocal );
  134. }
  135. CoUninitialize();
  136. return;
  137. }
  138. }
  139. if (0 == uClassIndex || 4 == uClassIndex)
  140. {
  141. hr = CoRegisterClassObject( CLSID_ActAtStorage,
  142. (IUnknown *)new FactoryAtStorage(),
  143. CLSCTX_LOCAL_SERVER,
  144. REGCLS_MULTIPLEUSE,
  145. &RegHandleAtStorage );
  146. if ( FAILED(hr) )
  147. {
  148. printf("Server: CoRegisterClassObject failed %x\n", hr);
  149. if (0 == uClassIndex)
  150. {
  151. CoRevokeClassObject( RegHandleLocal );
  152. CoRevokeClassObject( RegHandleRemote );
  153. }
  154. CoUninitialize();
  155. return;
  156. }
  157. }
  158. if (0 == uClassIndex || 6 == uClassIndex)
  159. {
  160. hr = CoRegisterClassObject( CLSID_ActPreConfig,
  161. (IUnknown *)new FactoryAtStorage(),
  162. CLSCTX_LOCAL_SERVER,
  163. REGCLS_MULTIPLEUSE,
  164. &RegHandlePreConfig );
  165. if ( FAILED(hr) )
  166. {
  167. printf("Server: CoRegisterClassObject failed %x\n", hr);
  168. if (0 == uClassIndex)
  169. {
  170. CoRevokeClassObject( RegHandleLocal );
  171. CoRevokeClassObject( RegHandleRemote );
  172. CoRevokeClassObject( RegHandleAtStorage );
  173. }
  174. CoUninitialize();
  175. return;
  176. }
  177. }
  178. if (0 == uClassIndex || 7 == uClassIndex)
  179. {
  180. hr = CoRegisterClassObject( CLSID_ActRunAsLoggedOn,
  181. (IUnknown *)new FactoryAtStorage(),
  182. CLSCTX_LOCAL_SERVER,
  183. REGCLS_MULTIPLEUSE,
  184. &RegHandleRunAsLoggedOn );
  185. if ( FAILED(hr) )
  186. {
  187. printf("Server: CoRegisterClassObject failed %x\n", hr);
  188. if (0 == uClassIndex)
  189. {
  190. CoRevokeClassObject( RegHandleLocal );
  191. CoRevokeClassObject( RegHandleRemote );
  192. CoRevokeClassObject( RegHandleAtStorage );
  193. CoRevokeClassObject( RegHandlePreConfig );
  194. }
  195. CoUninitialize();
  196. return;
  197. }
  198. }
  199. if (0 == uClassIndex || 9 == uClassIndex)
  200. {
  201. hr = CoRegisterClassObject( CLSID_ActServerOnly,
  202. (IUnknown *)new FactoryAtStorage(),
  203. CLSCTX_LOCAL_SERVER,
  204. REGCLS_MULTIPLEUSE,
  205. &RegHandleServerOnly );
  206. if ( FAILED(hr) )
  207. {
  208. printf("Server: CoRegisterClassObject failed %x\n", hr);
  209. if (0 == uClassIndex)
  210. {
  211. CoRevokeClassObject( RegHandleLocal );
  212. CoRevokeClassObject( RegHandleRemote );
  213. CoRevokeClassObject( RegHandleAtStorage );
  214. CoRevokeClassObject( RegHandlePreConfig );
  215. CoRevokeClassObject( RegHandleRunAsLoggedOn );
  216. }
  217. CoUninitialize();
  218. return;
  219. }
  220. }
  221. if (fStartedAsService)
  222. {
  223. hr = CoRegisterClassObject( CLSID_ActService,
  224. (IUnknown *)new FactoryAtStorage(),
  225. CLSCTX_LOCAL_SERVER,
  226. REGCLS_MULTIPLEUSE,
  227. &RegHandleService );
  228. if ( FAILED(hr) )
  229. {
  230. CoUninitialize();
  231. return;
  232. }
  233. WaitForSingleObject(hStopServiceEvent, INFINITE);
  234. }
  235. else
  236. {
  237. #ifdef FREETHREADED
  238. WaitForSingleObject(hFreeThreadEvent, INFINITE);
  239. //
  240. // Make sure the thread who signaled the event executes for a while
  241. // before we exit.
  242. //
  243. Sleep(100);
  244. #else
  245. // Only do message loop if apartment threaded non-service.
  246. while (GetMessage(&msg, NULL, 0, 0))
  247. {
  248. TranslateMessage(&msg);
  249. DispatchMessage(&msg);
  250. }
  251. #endif
  252. }
  253. CoUninitialize();
  254. return;
  255. }
  256. int gargc;
  257. char * gargv[100];
  258. BOOL UpdateStatus(DWORD dwState)
  259. {
  260. if (SERVICE_RUNNING == SStatus.dwCurrentState &&
  261. SERVICE_START_PENDING == dwState)
  262. {
  263. return(TRUE);
  264. }
  265. SStatus.dwCurrentState = dwState;
  266. if (SERVICE_START_PENDING == dwState ||
  267. SERVICE_STOP_PENDING == dwState)
  268. {
  269. SStatus.dwCheckPoint++;
  270. SStatus.dwWaitHint = 1;
  271. }
  272. else
  273. {
  274. SStatus.dwCheckPoint = 0;
  275. SStatus.dwWaitHint = 0;
  276. }
  277. return(SetServiceStatus(hService, &SStatus));
  278. }
  279. DWORD StartMyMain(void * pArg)
  280. {
  281. // reconstruct the command line args and call the real main
  282. RealMain(gargc, gargv);
  283. UpdateStatus(SERVICE_STOPPED);
  284. return(0);
  285. }
  286. void Handler(DWORD fdwControl)
  287. {
  288. switch (fdwControl)
  289. {
  290. case SERVICE_CONTROL_STOP:
  291. UpdateStatus(SERVICE_STOP_PENDING);
  292. SetEvent(hStopServiceEvent);
  293. break;
  294. case SERVICE_CONTROL_INTERROGATE:
  295. UpdateStatus(SERVICE_RUNNING);
  296. break;
  297. default:
  298. break;
  299. }
  300. }
  301. //+---------------------------------------------------------------------------
  302. //
  303. // Function: ServiceMain
  304. //
  305. // Synopsis: main entry point for service
  306. //
  307. // History: 1-18-96 stevebl Created
  308. //
  309. //----------------------------------------------------------------------------
  310. void ServiceMain(DWORD argc, LPTSTR * argv)
  311. {
  312. fStartedAsService = TRUE;
  313. // register the service handler
  314. hService = RegisterServiceCtrlHandler(ServiceName, Handler);
  315. if (!hService)
  316. return;
  317. SStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS |
  318. SERVICE_INTERACTIVE_PROCESS,
  319. SStatus.dwControlsAccepted = SERVICE_CONTROL_STOP |
  320. SERVICE_CONTROL_INTERROGATE;
  321. SStatus.dwWin32ExitCode = NO_ERROR;
  322. SStatus.dwServiceSpecificExitCode = 0;
  323. SStatus.dwCheckPoint = 0;
  324. SStatus.dwWaitHint = 0;
  325. if (!UpdateStatus(SERVICE_START_PENDING))
  326. return;
  327. // create an event to signal when the service is to stop
  328. hStopServiceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  329. if (!hStopServiceEvent)
  330. {
  331. return;
  332. }
  333. UpdateStatus(SERVICE_RUNNING);
  334. StartMyMain( NULL );
  335. }
  336. void _cdecl main( int argc, char ** argv)
  337. {
  338. if (argc > 1 && strcmp(argv[1], "8") == 0)
  339. {
  340. gargc = argc;
  341. // save the command line arguments
  342. gargc = (int) argc;
  343. if (gargc > 100)
  344. {
  345. gargc = 100;
  346. }
  347. for (int k = 1; k <= gargc; k++)
  348. {
  349. gargv[k-1] = (char *) malloc(strlen(argv[k-1]) + 1);
  350. strcpy(gargv[k-1], argv[k-1]);
  351. }
  352. // Start as a service
  353. SERVICE_TABLE_ENTRY ServiceStart[2];
  354. ServiceStart[0].lpServiceName = ServiceName;
  355. ServiceStart[0].lpServiceProc = ServiceMain;
  356. ServiceStart[1].lpServiceName = NULL;
  357. ServiceStart[1].lpServiceProc = NULL;
  358. if (!StartServiceCtrlDispatcher (ServiceStart))
  359. {
  360. ExitProcess(GetLastError());
  361. }
  362. ExitProcess(0);
  363. }
  364. else
  365. {
  366. // start as a regular app
  367. RealMain(argc, argv);
  368. }
  369. }
  370. long InitializeRegistry( DebuggerType eDebugServer )
  371. {
  372. long RegStatus;
  373. ulong Disposition;
  374. HKEY hActKey;
  375. HKEY hDebugKey;
  376. HANDLE hFile;
  377. TCHAR Path[256];
  378. TCHAR * pwszServerExe;
  379. TCHAR * pwszDebuggerName;
  380. DWORD DebugFlags;
  381. if ( ! GetModuleFileName( 0, Path, sizeof(Path) ) )
  382. return ERROR_BAD_PATHNAME;
  383. hFile = CreateFile( AtStorageFileName,
  384. GENERIC_WRITE,
  385. 0,
  386. NULL,
  387. CREATE_ALWAYS,
  388. 0,
  389. 0 );
  390. if ( hFile == INVALID_HANDLE_VALUE )
  391. {
  392. printf("Couldn't create file %ws\n", AtStorageFileName );
  393. return GetLastError();
  394. }
  395. CloseHandle( hFile );
  396. RegStatus = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  397. TEXT("CLSID"),
  398. 0,
  399. KEY_ALL_ACCESS,
  400. &ghClsidRootKey );
  401. if ( RegStatus != ERROR_SUCCESS )
  402. return RegStatus;
  403. RegStatus = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  404. TEXT("APPID"),
  405. 0,
  406. KEY_ALL_ACCESS,
  407. &ghAppIDRootKey );
  408. if ( RegStatus != ERROR_SUCCESS )
  409. return RegStatus;
  410. DeleteClsidKey( ClsidGoober32String );
  411. DeleteClsidKey( ClsidActLocalString );
  412. DeleteClsidKey( ClsidActRemoteString );
  413. DeleteClsidKey( ClsidActAtStorageString );
  414. DeleteClsidKey( ClsidActInprocString );
  415. DeleteClsidKey( ClsidActPreConfigString );
  416. DeleteClsidKey( ClsidActRunAsLoggedOnString );
  417. DeleteClsidKey( ClsidActServiceString );
  418. DeleteClsidKey( ClsidActServerOnlyString );
  419. //
  420. // Local CLSID entries.
  421. //
  422. _tcscat(Path, TEXT(" 2"));
  423. RegStatus = SetClsidRegKeyAndStringValue(
  424. ClsidActLocalString,
  425. TEXT("LocalServer32"),
  426. Path,
  427. NULL,
  428. NULL );
  429. if ( RegStatus != ERROR_SUCCESS )
  430. return RegStatus;
  431. RegStatus = SetAppIDSecurity( ClsidActLocalString );
  432. if ( RegStatus != ERROR_SUCCESS )
  433. return RegStatus;
  434. //
  435. // Remote CLSID entries.
  436. //
  437. Path[_tcslen(Path)-1] = TEXT('3');
  438. RegStatus = SetClsidRegKeyAndStringValue(
  439. ClsidActRemoteString,
  440. TEXT("LocalServer32"),
  441. Path,
  442. NULL,
  443. NULL );
  444. if ( RegStatus != ERROR_SUCCESS )
  445. return RegStatus;
  446. RegStatus = SetAppIDSecurity( ClsidActRemoteString );
  447. if ( RegStatus != ERROR_SUCCESS )
  448. return RegStatus;
  449. //
  450. // AtStorage CLSID entries.
  451. //
  452. Path[_tcslen(Path)-1] = TEXT('4');
  453. RegStatus = SetClsidRegKeyAndStringValue(
  454. ClsidActAtStorageString,
  455. TEXT("LocalServer32"),
  456. Path,
  457. NULL,
  458. NULL );
  459. if ( RegStatus != ERROR_SUCCESS )
  460. return RegStatus;
  461. RegStatus = SetAppIDSecurity( ClsidActAtStorageString );
  462. if ( RegStatus != ERROR_SUCCESS )
  463. return RegStatus;
  464. //
  465. // RunAs CLSID entries.'
  466. //
  467. Path[_tcslen(Path)-1] = TEXT('6');
  468. RegStatus = SetClsidRegKeyAndStringValue(
  469. ClsidActPreConfigString,
  470. TEXT("LocalServer32"),
  471. Path,
  472. NULL,
  473. NULL );
  474. if ( RegStatus != ERROR_SUCCESS )
  475. return RegStatus;
  476. RegStatus = SetAppIDRegKeyAndNamedValue(
  477. ClsidActPreConfigString,
  478. TEXT("RunAs"),
  479. UserName,
  480. NULL );
  481. if ( RegStatus != ERROR_SUCCESS )
  482. return RegStatus;
  483. RegStatus = SetAppIDSecurity( ClsidActPreConfigString );
  484. if ( RegStatus != ERROR_SUCCESS )
  485. return RegStatus;
  486. if (!SetPassword(ClsidActPreConfigString, Password))
  487. return(FALSE);
  488. if (!AddBatchPrivilege( UserName ) )
  489. return(FALSE);
  490. //
  491. // RunAs logged on user CLSID entries.
  492. //
  493. Path[_tcslen(Path)-1] = TEXT('7');
  494. RegStatus = SetClsidRegKeyAndStringValue(
  495. ClsidActRunAsLoggedOnString,
  496. TEXT("LocalServer32"),
  497. Path,
  498. NULL,
  499. NULL );
  500. if ( RegStatus != ERROR_SUCCESS )
  501. return RegStatus;
  502. RegStatus = SetAppIDRegKeyAndNamedValue(
  503. ClsidActRunAsLoggedOnString,
  504. TEXT("RunAs"),
  505. TEXT("Interactive User"),
  506. NULL );
  507. if ( RegStatus != ERROR_SUCCESS )
  508. return RegStatus;
  509. RegStatus = SetAppIDSecurity( ClsidActRunAsLoggedOnString );
  510. if ( RegStatus != ERROR_SUCCESS )
  511. return RegStatus;
  512. //
  513. // Service CLSID entries.
  514. //
  515. RegStatus = SetAppIDRegKeyAndNamedValue(
  516. ClsidActServiceString,
  517. TEXT("LocalService"),
  518. ServiceName,
  519. NULL );
  520. if ( RegStatus != ERROR_SUCCESS )
  521. return RegStatus;
  522. RegStatus = SetAppIDSecurity( ClsidActServiceString );
  523. if ( RegStatus != ERROR_SUCCESS )
  524. return RegStatus;
  525. // Get the services key
  526. HKEY hServices;
  527. RegStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  528. TEXT("SYSTEM\\CurrentControlSet\\Services"),
  529. 0,
  530. KEY_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  531. &hServices );
  532. if ( RegStatus != ERROR_SUCCESS )
  533. return RegStatus;
  534. Path[_tcslen(Path)-1] = TEXT('8');
  535. if (!InstallService(Path))
  536. return TRUE;
  537. //
  538. // Server only CLSID entry.
  539. //
  540. Path[_tcslen(Path)-1] = TEXT('9');
  541. RegStatus = SetClsidRegKeyAndStringValue(
  542. ClsidActServerOnlyString,
  543. TEXT("LocalServer32"),
  544. Path,
  545. NULL,
  546. NULL );
  547. if ( RegStatus != ERROR_SUCCESS )
  548. return RegStatus;
  549. RegStatus = SetAppIDSecurity( ClsidActServerOnlyString );
  550. if ( RegStatus != ERROR_SUCCESS )
  551. return RegStatus;
  552. //
  553. // Add entries to launch server in debugger.
  554. //
  555. if ( eDebugServer == same_debugger )
  556. return ERROR_SUCCESS;
  557. Path[_tcslen(Path)-2] = 0;
  558. pwszServerExe = Path + _tcslen(Path);
  559. while ( (pwszServerExe > Path) && (pwszServerExe[-1] != TEXT('\\')) )
  560. pwszServerExe--;
  561. RegStatus = RegOpenKeyEx(
  562. HKEY_LOCAL_MACHINE,
  563. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
  564. 0,
  565. KEY_ALL_ACCESS,
  566. &hDebugKey );
  567. if ( RegStatus != ERROR_SUCCESS )
  568. return RegStatus;
  569. RegStatus = RegCreateKeyEx(
  570. hDebugKey,
  571. TEXT("Image File Execution Options"),
  572. 0,
  573. TEXT("REG_SZ"),
  574. REG_OPTION_NON_VOLATILE,
  575. KEY_ALL_ACCESS,
  576. NULL,
  577. &hDebugKey,
  578. &Disposition );
  579. if ( RegStatus != ERROR_SUCCESS )
  580. return RegStatus;
  581. if ( eDebugServer == clear_debugger )
  582. {
  583. RegDeleteKey( hDebugKey, pwszServerExe );
  584. return ERROR_SUCCESS;
  585. }
  586. RegStatus = RegCreateKeyEx(
  587. hDebugKey,
  588. pwszServerExe,
  589. 0,
  590. TEXT("REG_SZ"),
  591. REG_OPTION_NON_VOLATILE,
  592. KEY_ALL_ACCESS,
  593. NULL,
  594. &hDebugKey,
  595. &Disposition );
  596. if ( RegStatus != ERROR_SUCCESS )
  597. return RegStatus;
  598. if ( eDebugServer == ntsd_debugger )
  599. {
  600. pwszDebuggerName = TEXT("ntsd.exe -d");
  601. }
  602. else
  603. {
  604. pwszDebuggerName = TEXT("windbg.exe");
  605. }
  606. DebugFlags = 0x10f0;
  607. RegStatus = RegSetValueEx(
  608. hDebugKey,
  609. TEXT("Debugger"),
  610. 0,
  611. REG_SZ,
  612. (const BYTE *)pwszDebuggerName,
  613. (_tcslen(pwszDebuggerName) + 1) * sizeof(TCHAR) );
  614. if ( RegStatus != ERROR_SUCCESS )
  615. return RegStatus;
  616. RegStatus = RegSetValueEx(
  617. hDebugKey,
  618. TEXT("GlobalFlag"),
  619. 0,
  620. REG_DWORD,
  621. (const BYTE *)&DebugFlags,
  622. sizeof(DWORD) );
  623. if ( RegStatus != ERROR_SUCCESS )
  624. return RegStatus;
  625. return ERROR_SUCCESS;
  626. }
  627. long SetClsidRegKeyAndStringValue(
  628. TCHAR * pwszClsid,
  629. TCHAR * pwszKey,
  630. TCHAR * pwszValue,
  631. HKEY * phClsidKey,
  632. HKEY * phNewKey )
  633. {
  634. long RegStatus;
  635. DWORD Disposition;
  636. HKEY hClsidKey;
  637. if ( phClsidKey )
  638. *phClsidKey = 0;
  639. if ( phNewKey )
  640. *phNewKey = 0;
  641. RegStatus = RegCreateKeyEx(
  642. ghClsidRootKey,
  643. pwszClsid,
  644. 0,
  645. TEXT("REG_SZ"),
  646. REG_OPTION_NON_VOLATILE,
  647. KEY_ALL_ACCESS,
  648. NULL,
  649. &hClsidKey,
  650. &Disposition );
  651. if ( RegStatus != ERROR_SUCCESS )
  652. return RegStatus;
  653. if ( phClsidKey )
  654. *phClsidKey = hClsidKey;
  655. return SetRegKeyAndStringValue(
  656. hClsidKey,
  657. pwszKey,
  658. pwszValue,
  659. phNewKey );
  660. }
  661. long SetAppIDRegKeyAndNamedValue(
  662. TCHAR * pwszAppID,
  663. TCHAR * pwszKey,
  664. TCHAR * pwszValue,
  665. HKEY * phClsidKey )
  666. {
  667. long RegStatus;
  668. DWORD Disposition;
  669. HKEY hClsidKey;
  670. if ( phClsidKey )
  671. *phClsidKey = 0;
  672. // first, make sure the clsid has appid={appid}
  673. RegStatus = RegCreateKeyEx(
  674. ghClsidRootKey,
  675. pwszAppID,
  676. 0,
  677. TEXT("REG_SZ"),
  678. REG_OPTION_NON_VOLATILE,
  679. KEY_ALL_ACCESS,
  680. NULL,
  681. &hClsidKey,
  682. &Disposition );
  683. if ( RegStatus != ERROR_SUCCESS )
  684. return RegStatus;
  685. RegStatus = SetNamedStringValue(
  686. hClsidKey,
  687. TEXT("AppID"),
  688. pwszAppID );
  689. if ( RegStatus != ERROR_SUCCESS )
  690. return RegStatus;
  691. RegStatus = RegCreateKeyEx(
  692. ghAppIDRootKey,
  693. pwszAppID,
  694. 0,
  695. TEXT("REG_SZ"),
  696. REG_OPTION_NON_VOLATILE,
  697. KEY_ALL_ACCESS,
  698. NULL,
  699. &hClsidKey,
  700. &Disposition );
  701. if ( RegStatus != ERROR_SUCCESS )
  702. return RegStatus;
  703. if ( phClsidKey )
  704. *phClsidKey = hClsidKey;
  705. return SetNamedStringValue(
  706. hClsidKey,
  707. pwszKey,
  708. pwszValue );
  709. }
  710. long SetNamedStringValue(
  711. HKEY hKey,
  712. TCHAR * pwszKey,
  713. TCHAR * pwszValue )
  714. {
  715. long RegStatus;
  716. DWORD Disposition;
  717. RegStatus = RegSetValueEx(
  718. hKey,
  719. pwszKey,
  720. 0,
  721. REG_SZ,
  722. (const BYTE *)pwszValue,
  723. (_tcslen(pwszValue) + 1) * sizeof(TCHAR) );
  724. return RegStatus;
  725. }
  726. long SetRegKeyAndStringValue(
  727. HKEY hKey,
  728. TCHAR * pwszKey,
  729. TCHAR * pwszValue,
  730. HKEY * phNewKey )
  731. {
  732. long RegStatus;
  733. DWORD Disposition;
  734. HKEY hNewKey;
  735. if ( phNewKey )
  736. *phNewKey = 0;
  737. RegStatus = RegCreateKeyEx(
  738. hKey,
  739. pwszKey,
  740. 0,
  741. TEXT("REG_SZ"),
  742. REG_OPTION_NON_VOLATILE,
  743. KEY_ALL_ACCESS,
  744. NULL,
  745. &hNewKey,
  746. &Disposition );
  747. if ( RegStatus != ERROR_SUCCESS )
  748. return RegStatus;
  749. RegStatus = RegSetValueEx(
  750. hNewKey,
  751. TEXT(""),
  752. 0,
  753. REG_SZ,
  754. (const BYTE *)pwszValue,
  755. (_tcslen(pwszValue) + 1) * sizeof(TCHAR) );
  756. if ( phNewKey )
  757. *phNewKey = hNewKey;
  758. return RegStatus;
  759. }
  760. BOOL InstallService(TCHAR * Path)
  761. {
  762. #ifndef CHICO
  763. SC_HANDLE hManager = OpenSCManager(
  764. NULL,
  765. NULL,
  766. SC_MANAGER_ALL_ACCESS);
  767. if (NULL == hManager)
  768. {
  769. printf("OpenSCManager returned %d\n",GetLastError());
  770. return(FALSE);
  771. }
  772. SC_HANDLE hService = OpenService(
  773. hManager,
  774. ServiceName,
  775. SERVICE_ALL_ACCESS);
  776. if (NULL != hService)
  777. {
  778. if (!ChangeServiceConfig(
  779. hService,
  780. SERVICE_WIN32_OWN_PROCESS |
  781. SERVICE_INTERACTIVE_PROCESS,
  782. SERVICE_DEMAND_START,
  783. SERVICE_ERROR_NORMAL,
  784. Path,
  785. NULL,
  786. NULL,
  787. NULL,
  788. NULL,
  789. NULL,
  790. ServiceDisplayName
  791. )
  792. )
  793. {
  794. printf("ChangeService returned %d\n",GetLastError());
  795. CloseServiceHandle(hService);
  796. CloseServiceHandle(hManager);
  797. return(FALSE);
  798. }
  799. return(TRUE);
  800. }
  801. hService = CreateService(
  802. hManager,
  803. ServiceName,
  804. ServiceDisplayName,
  805. SERVICE_ALL_ACCESS,
  806. SERVICE_WIN32_OWN_PROCESS |
  807. SERVICE_INTERACTIVE_PROCESS,
  808. SERVICE_DEMAND_START,
  809. SERVICE_ERROR_NORMAL,
  810. Path,
  811. NULL,
  812. NULL,
  813. NULL,
  814. NULL,
  815. NULL);
  816. if (NULL == hService)
  817. {
  818. printf("CreateService returned %d\n",GetLastError());
  819. CloseServiceHandle(hManager);
  820. return(FALSE);
  821. }
  822. CloseServiceHandle(hService);
  823. CloseServiceHandle(hManager);
  824. #endif
  825. return(TRUE);
  826. }
  827. void PrintUsageAndExit()
  828. {
  829. printf("Usage : actsrv [-r [-d | -n | -x]]\n");
  830. printf("\t-r : Make necessary registry changes.\n");
  831. printf("\t-d : Register server to start in windbg.\n");
  832. printf("\t-n : Register server to start with ntsd -d.\n");
  833. printf("\t-x : Register server and clear debugger.\n");
  834. ExitProcess(0);
  835. }
  836. void ShutDown()
  837. {
  838. // The last object has been destroyed.
  839. if (fStartedAsService)
  840. {
  841. CoRevokeClassObject( RegHandleService );
  842. }
  843. switch( uClassIndex )
  844. {
  845. case 0 :
  846. CoRevokeClassObject( RegHandleLocal );
  847. CoRevokeClassObject( RegHandleRemote );
  848. CoRevokeClassObject( RegHandleAtStorage );
  849. CoRevokeClassObject( RegHandlePreConfig );
  850. CoRevokeClassObject( RegHandleRunAsLoggedOn );
  851. CoRevokeClassObject( RegHandleServerOnly );
  852. break;
  853. case 2:
  854. CoRevokeClassObject( RegHandleLocal );
  855. break;
  856. case 3:
  857. CoRevokeClassObject( RegHandleRemote );
  858. break;
  859. case 4:
  860. CoRevokeClassObject( RegHandleAtStorage );
  861. break;
  862. case 6:
  863. CoRevokeClassObject( RegHandlePreConfig );
  864. break;
  865. case 7 :
  866. CoRevokeClassObject( RegHandleRunAsLoggedOn );
  867. break;
  868. case 9 :
  869. CoRevokeClassObject( RegHandleServerOnly );
  870. break;
  871. }
  872. if (fStartedAsService)
  873. {
  874. SetEvent(hStopServiceEvent);
  875. }
  876. else
  877. {
  878. #ifdef FREETHREADED
  879. SetEvent(hFreeThreadEvent);
  880. #else
  881. PostQuitMessage(0);
  882. #endif
  883. }
  884. }