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.

823 lines
14 KiB

  1. /*++
  2. Copyright (c) 1999-1999 Microsoft Corporation
  3. Module Name:
  4. dtsetup.c
  5. Abstract:
  6. Simple Duct-Tape setup.
  7. Author:
  8. Keith Moore (keithmo) 02-Sep-1999
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Configuration data.
  15. //
  16. #define UL_SERVICE_NAME L"UL"
  17. #define UL_DISPLAY_NAME L"UL"
  18. #define UL_DRIVER_NAME L"UL.SYS"
  19. #define UL_DEPENDENCIES NULL
  20. #define WAS_SERVICE_NAME L"IISW3ADM"
  21. #define WAS_DISPLAY_NAME L"IIS Web Admin Service"
  22. #define WAS_DLL_NAME L"iisw3adm.dll"
  23. #define WAS_DEPENDENCIES L"UL"
  24. #define WAS_COMMAND_LINE L"%SystemRoot%\\System32\\svchost.exe -k iissvcs"
  25. #define WAS_PARAM_KEY L"System\\CurrentControlSet\\Services\\iisw3adm\\Parameters"
  26. #define WAS_EVENT_KEY L"System\\CurrentControlSet\\Services\\EventLog\\System\\WAS"
  27. #define WAS_SVCHOST_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"
  28. #define SERVICE_DLL_VALUE L"ServiceDll"
  29. #define EVENT_MESSAGE_VALUE L"EventMessageFile"
  30. #define SVCHOST_VALUE L"iissvcs"
  31. #define CATALOG_DLL_NAME L"catalog.dll"
  32. #define CATALOG_KEY L"Software\\Microsoft\\Catalog42"
  33. #define CATALOG_URT_VALUE L"URT"
  34. //
  35. // Our command table.
  36. //
  37. typedef
  38. VOID
  39. (* PFN_COMMAND)(
  40. IN INT argc,
  41. IN PWSTR argv[]
  42. );
  43. typedef struct _COMMAND_ENTRY
  44. {
  45. PWSTR pCommandName;
  46. PWSTR pUsageHelp;
  47. PFN_COMMAND pCommandHandler;
  48. } COMMAND_ENTRY, *PCOMMAND_ENTRY;
  49. //
  50. // Private prototypes.
  51. //
  52. VOID
  53. Usage(
  54. VOID
  55. );
  56. PCOMMAND_ENTRY
  57. FindCommandByName(
  58. IN PWSTR pCommand
  59. );
  60. VOID
  61. DoInstall(
  62. IN INT argc,
  63. IN PWSTR argv[]
  64. );
  65. VOID
  66. DoRemove(
  67. IN INT argc,
  68. IN PWSTR argv[]
  69. );
  70. DWORD
  71. InstallUL(
  72. IN PWSTR pBaseDirectory
  73. );
  74. DWORD
  75. InstallWAS(
  76. IN PWSTR pBaseDirectory
  77. );
  78. DWORD
  79. InstallCatalog(
  80. IN PWSTR pBaseDirectory
  81. );
  82. VOID
  83. RemoveCatalog(
  84. VOID
  85. );
  86. VOID
  87. RemoveWAS(
  88. VOID
  89. );
  90. VOID
  91. RemoveUL(
  92. VOID
  93. );
  94. DWORD
  95. InstallService(
  96. IN PWSTR pServiceName,
  97. IN PWSTR pDisplayName OPTIONAL,
  98. IN PWSTR pBinPath,
  99. IN PWSTR pDependencies OPTIONAL,
  100. IN DWORD ServiceType,
  101. IN DWORD StartType,
  102. IN DWORD ErrorControl
  103. );
  104. DWORD
  105. RemoveService(
  106. IN PWSTR pServiceName
  107. );
  108. DWORD
  109. WriteRegValue(
  110. IN PWSTR pKeyName,
  111. IN PWSTR pValueName,
  112. IN PWSTR pValue
  113. );
  114. DWORD
  115. DeleteRegKey(
  116. IN PWSTR pKeyName
  117. );
  118. //
  119. // Private globals.
  120. //
  121. COMMAND_ENTRY CommandTable[] =
  122. {
  123. {
  124. L"install",
  125. L"install UL and WAS",
  126. &DoInstall
  127. },
  128. {
  129. L"remove",
  130. L"remove UL and WAS",
  131. &DoRemove
  132. }
  133. };
  134. #define NUM_COMMAND_ENTRIES (sizeof(CommandTable) / sizeof(CommandTable[0]))
  135. //
  136. // Public functions.
  137. //
  138. INT
  139. __cdecl
  140. wmain(
  141. INT argc,
  142. PWSTR argv[]
  143. )
  144. {
  145. PCOMMAND_ENTRY pEntry;
  146. //
  147. // Find the command handler.
  148. //
  149. if (argc == 1)
  150. {
  151. pEntry = NULL;
  152. }
  153. else
  154. {
  155. pEntry = FindCommandByName( argv[1] );
  156. }
  157. if (pEntry == NULL)
  158. {
  159. Usage();
  160. return 1;
  161. }
  162. //
  163. // Call the handler.
  164. //
  165. argc--;
  166. argv++;
  167. (pEntry->pCommandHandler)( argc, argv );
  168. return 0;
  169. } // wmain
  170. //
  171. // Private functions.
  172. //
  173. PCOMMAND_ENTRY
  174. FindCommandByName(
  175. IN PWSTR pCommand
  176. )
  177. {
  178. PCOMMAND_ENTRY pEntry;
  179. INT i;
  180. for (i = NUM_COMMAND_ENTRIES, pEntry = &CommandTable[0] ;
  181. i > 0 ;
  182. i--, pEntry++)
  183. {
  184. if (_wcsicmp( pCommand, pEntry->pCommandName ) == 0)
  185. {
  186. return pEntry;
  187. }
  188. }
  189. return NULL;
  190. } // FindCommandByName
  191. VOID
  192. Usage(
  193. VOID
  194. )
  195. {
  196. PCOMMAND_ENTRY pEntry;
  197. INT i;
  198. INT maxLength;
  199. INT len;
  200. //
  201. // Scan the command table, searching for the longest command name.
  202. // (This makes the output much prettier...)
  203. //
  204. maxLength = 0;
  205. for (i = NUM_COMMAND_ENTRIES, pEntry = &CommandTable[0] ;
  206. i > 0 ;
  207. i--, pEntry++)
  208. {
  209. len = wcslen( pEntry->pCommandName );
  210. if (len > maxLength)
  211. {
  212. maxLength = len;
  213. }
  214. }
  215. //
  216. // Now display the usage information.
  217. //
  218. wprintf(
  219. L"use: dtsetup action [options]\n"
  220. L"\n"
  221. L"valid actions are:\n"
  222. L"\n"
  223. );
  224. for (i = NUM_COMMAND_ENTRIES, pEntry = &CommandTable[0] ;
  225. i > 0 ;
  226. i--, pEntry++)
  227. {
  228. wprintf(
  229. L" %-*s - %s\n",
  230. maxLength,
  231. pEntry->pCommandName,
  232. pEntry->pUsageHelp
  233. );
  234. }
  235. } // Usage
  236. VOID
  237. DoInstall(
  238. IN INT argc,
  239. IN PWSTR argv[]
  240. )
  241. {
  242. PWSTR pBaseDirectory;
  243. DWORD err;
  244. //
  245. // Validate the arguments.
  246. //
  247. if (argc != 2)
  248. {
  249. wprintf( L"use: dtsetup install directory\n" );
  250. return;
  251. }
  252. //
  253. // Install 'em.
  254. //
  255. wprintf( L"installing UL..." );
  256. err = InstallUL( argv[1] );
  257. if (err != NO_ERROR)
  258. {
  259. wprintf( L"error %lu\n", err );
  260. return;
  261. }
  262. wprintf( L"done\n" );
  263. wprintf( L"installing WAS..." );
  264. err = InstallWAS( argv[1] );
  265. if (err != NO_ERROR)
  266. {
  267. wprintf( L"error %lu\n", err );
  268. RemoveUL();
  269. return;
  270. }
  271. wprintf( L"done\n" );
  272. wprintf( L"installing Catalog..." );
  273. err = InstallCatalog( argv[1] );
  274. if (err != NO_ERROR)
  275. {
  276. wprintf( L"error %lu\n", err );
  277. RemoveWAS();
  278. RemoveUL();
  279. return;
  280. }
  281. wprintf( L"done\n" );
  282. //
  283. // Success!
  284. //
  285. } // DoInstall
  286. VOID
  287. DoRemove(
  288. IN INT argc,
  289. IN PWSTR argv[]
  290. )
  291. {
  292. //
  293. // Validate the arguments.
  294. //
  295. if (argc != 1)
  296. {
  297. wprintf( L"use: dtsetup remove\n" );
  298. return;
  299. }
  300. //
  301. // Remove 'em.
  302. //
  303. wprintf( L"removing Catalog..." );
  304. RemoveCatalog();
  305. wprintf( L"done\n" );
  306. wprintf( L"removing WAS..." );
  307. RemoveWAS();
  308. wprintf( L"done\n" );
  309. wprintf( L"removing UL..." );
  310. RemoveUL();
  311. wprintf( L"done\n" );
  312. } // DoRemove
  313. DWORD
  314. InstallUL(
  315. IN PWSTR pBaseDirectory
  316. )
  317. {
  318. DWORD err;
  319. WCHAR binPath[MAX_PATH];
  320. //
  321. // Build the path to the driver.
  322. //
  323. wcscpy( binPath, pBaseDirectory );
  324. if (binPath[wcslen(binPath) - 1] != L'\\')
  325. {
  326. wcscat( binPath, L"\\" );
  327. }
  328. wcscat( binPath, UL_DRIVER_NAME );
  329. //
  330. // Install it.
  331. //
  332. err = InstallService(
  333. UL_SERVICE_NAME, // pServiceName
  334. UL_DISPLAY_NAME, // pDisplayName
  335. binPath, // pBinPath
  336. UL_DEPENDENCIES, // pDependencies
  337. SERVICE_KERNEL_DRIVER, // ServiceType
  338. SERVICE_DEMAND_START, // StartType
  339. SERVICE_ERROR_NORMAL // ErrorControl
  340. );
  341. return err;
  342. } // InstallUL
  343. DWORD
  344. InstallWAS(
  345. IN PWSTR pBaseDirectory
  346. )
  347. {
  348. DWORD err;
  349. WCHAR binPath[MAX_PATH];
  350. //
  351. // Build the path to the service.
  352. //
  353. wcscpy( binPath, pBaseDirectory );
  354. if (binPath[wcslen(binPath) - 1] != L'\\')
  355. {
  356. wcscat( binPath, L"\\" );
  357. }
  358. wcscat( binPath, WAS_DLL_NAME );
  359. //
  360. // Install it.
  361. //
  362. err = InstallService(
  363. WAS_SERVICE_NAME, // pServiceName
  364. WAS_DISPLAY_NAME, // pDisplayName
  365. WAS_COMMAND_LINE, // pBinPath
  366. WAS_DEPENDENCIES, // pDependencies
  367. SERVICE_WIN32_SHARE_PROCESS | // ServiceType
  368. SERVICE_INTERACTIVE_PROCESS,
  369. SERVICE_DEMAND_START, // StartType
  370. SERVICE_ERROR_NORMAL // ErrorControl
  371. );
  372. if (err == NO_ERROR)
  373. {
  374. err = WriteRegValue(
  375. WAS_PARAM_KEY, // pKeyName
  376. SERVICE_DLL_VALUE, // pValueName
  377. binPath // pValue
  378. );
  379. }
  380. if (err == NO_ERROR)
  381. {
  382. err = WriteRegValue(
  383. WAS_EVENT_KEY, // pKeyName
  384. EVENT_MESSAGE_VALUE, // pValueName
  385. binPath // pValue
  386. );
  387. }
  388. if (err == NO_ERROR)
  389. {
  390. err = WriteRegValue(
  391. WAS_SVCHOST_KEY, // pKeyName
  392. SVCHOST_VALUE, // pValueName
  393. WAS_SERVICE_NAME // pValue
  394. );
  395. }
  396. return err;
  397. } // InstallWAS
  398. DWORD
  399. InstallCatalog(
  400. IN PWSTR pBaseDirectory
  401. )
  402. {
  403. DWORD err;
  404. WCHAR binPath[MAX_PATH];
  405. //
  406. // Build the path to the service.
  407. //
  408. wcscpy( binPath, pBaseDirectory );
  409. if (binPath[wcslen(binPath) - 1] != L'\\')
  410. {
  411. wcscat( binPath, L"\\" );
  412. }
  413. wcscat( binPath, CATALOG_DLL_NAME );
  414. //
  415. // Install it.
  416. //
  417. err = WriteRegValue(
  418. CATALOG_KEY, // pKeyName
  419. CATALOG_URT_VALUE, // pValueName
  420. binPath // pValue
  421. );
  422. return err;
  423. } // InstallCatalog
  424. VOID
  425. RemoveCatalog(
  426. VOID
  427. )
  428. {
  429. (VOID)DeleteRegKey( CATALOG_KEY );
  430. } // RemoveCatalog
  431. VOID
  432. RemoveWAS(
  433. VOID
  434. )
  435. {
  436. (VOID)RemoveService( WAS_SERVICE_NAME );
  437. (VOID)DeleteRegKey( WAS_EVENT_KEY );
  438. } // RemoveWAS
  439. VOID
  440. RemoveUL(
  441. VOID
  442. )
  443. {
  444. (VOID)RemoveService( UL_SERVICE_NAME );
  445. } // RemoveUL
  446. DWORD
  447. InstallService(
  448. IN PWSTR pServiceName,
  449. IN PWSTR pDisplayName OPTIONAL,
  450. IN PWSTR pBinPath,
  451. IN PWSTR pDependencies OPTIONAL,
  452. IN DWORD ServiceType,
  453. IN DWORD StartType,
  454. IN DWORD ErrorControl
  455. )
  456. {
  457. SC_HANDLE scHandle;
  458. SC_HANDLE svcHandle;
  459. DWORD err;
  460. //
  461. // Setup locals so we know how to cleanup on exit.
  462. //
  463. scHandle = NULL;
  464. svcHandle = NULL;
  465. //
  466. // If no display name specified, just use the service name.
  467. //
  468. if (pDisplayName == NULL)
  469. {
  470. pDisplayName = pServiceName;
  471. }
  472. //
  473. // Open the service controller.
  474. //
  475. scHandle = OpenSCManagerW(
  476. NULL, // lpMachineName
  477. NULL, // lpDatabaseName
  478. SC_MANAGER_ALL_ACCESS // dwDesiredAccess
  479. );
  480. if (scHandle == NULL)
  481. {
  482. err = GetLastError();
  483. goto cleanup;
  484. }
  485. //
  486. // Create the service.
  487. //
  488. svcHandle = CreateServiceW(
  489. scHandle, // hSCManager
  490. pServiceName, // lpServiceName
  491. pDisplayName, // lpDisplayName
  492. SERVICE_ALL_ACCESS, // dwDesiredAccess
  493. ServiceType, // dwServiceType
  494. StartType, // dwStartType
  495. ErrorControl, // dwErrorControl
  496. pBinPath, // lpBinaryPathName
  497. NULL, // lpLoadOrderGroup
  498. NULL, // lpdwTagId
  499. pDependencies, // lpDependencies
  500. NULL, // lpServiceStartName
  501. NULL // lpPassword
  502. );
  503. if (svcHandle == NULL)
  504. {
  505. err = GetLastError();
  506. goto cleanup;
  507. }
  508. //
  509. // Success!
  510. //
  511. err = 0;
  512. cleanup:
  513. if (svcHandle != NULL)
  514. {
  515. CloseServiceHandle( svcHandle );
  516. }
  517. if (scHandle != NULL)
  518. {
  519. CloseServiceHandle( scHandle );
  520. }
  521. return err;
  522. } // InstallService
  523. DWORD
  524. RemoveService(
  525. IN PWSTR pServiceName
  526. )
  527. {
  528. SC_HANDLE scHandle;
  529. SC_HANDLE svcHandle;
  530. DWORD err;
  531. //
  532. // Setup locals so we know how to cleanup on exit.
  533. //
  534. scHandle = NULL;
  535. svcHandle = NULL;
  536. //
  537. // Open the service controller.
  538. //
  539. scHandle = OpenSCManagerW(
  540. NULL, // lpMachineName
  541. NULL, // lpDatabaseName
  542. SC_MANAGER_ALL_ACCESS // dwDesiredAccess
  543. );
  544. if (scHandle == NULL)
  545. {
  546. err = GetLastError();
  547. goto cleanup;
  548. }
  549. //
  550. // Open the service.
  551. //
  552. svcHandle = OpenServiceW(
  553. scHandle, // hSCManager
  554. pServiceName, // lpServiceName
  555. SERVICE_ALL_ACCESS // dwDesiredAccess
  556. );
  557. if (svcHandle == NULL)
  558. {
  559. err = GetLastError();
  560. goto cleanup;
  561. }
  562. //
  563. // Delete it.
  564. //
  565. if (!DeleteService( svcHandle ))
  566. {
  567. err = GetLastError();
  568. goto cleanup;
  569. }
  570. //
  571. // Success!
  572. //
  573. err = 0;
  574. cleanup:
  575. if (svcHandle != NULL)
  576. {
  577. CloseServiceHandle( svcHandle );
  578. }
  579. if (scHandle != NULL)
  580. {
  581. CloseServiceHandle( scHandle );
  582. }
  583. return err;
  584. } // RemoveService
  585. DWORD
  586. WriteRegValue(
  587. IN PWSTR pKeyName,
  588. IN PWSTR pValueName,
  589. IN PWSTR pValue
  590. )
  591. {
  592. DWORD err;
  593. HKEY key;
  594. DWORD disposition;
  595. DWORD length;
  596. err = RegCreateKeyExW(
  597. HKEY_LOCAL_MACHINE, // hKey
  598. pKeyName, // lpSubKey
  599. 0, // Reserved
  600. NULL, // lpClass
  601. REG_OPTION_NON_VOLATILE, // dwOptions
  602. KEY_ALL_ACCESS, // samDesired
  603. NULL, // lpSecurityAttributes,
  604. &key, // phkResult
  605. &disposition // lpdwDisposition
  606. );
  607. if (err == NO_ERROR)
  608. {
  609. length = (wcslen(pValue) + 1) * sizeof(pValue[0]);
  610. err = RegSetValueExW(
  611. key, // hKey
  612. pValueName, // lpValueName
  613. 0, // Reserved
  614. REG_EXPAND_SZ, // dwType
  615. (CONST BYTE *)pValue, // lpData
  616. length // cbData
  617. );
  618. RegCloseKey( key );
  619. }
  620. return err;
  621. } // WriteRegValue
  622. DWORD
  623. DeleteRegKey(
  624. IN PWSTR pKeyName
  625. )
  626. {
  627. DWORD err;
  628. err = RegDeleteKeyW(
  629. HKEY_LOCAL_MACHINE,
  630. pKeyName
  631. );
  632. return err;
  633. } // DeleteRegKey