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.

403 lines
16 KiB

  1. /*======================================================================================//
  2. | //
  3. |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated //
  4. | //
  5. |Description: //
  6. | //
  7. |---------------------------------------------------------------------------------------//
  8. | This file contains the ProcCon NT service install and remove functions //
  9. |---------------------------------------------------------------------------------------//
  10. | //
  11. |Created: //
  12. | //
  13. | Jarl McDonald 07-98 //
  14. | //
  15. |Revision History: //
  16. | Jarl McDonald 19-08-99 change service start type to auto //
  17. | //
  18. |=======================================================================================*/
  19. #include "ProcConSvc.h"
  20. //========================================================================================
  21. // function to install the ProcCon service... no input or output
  22. // Note: installation also includes the EventLog entries necessary to
  23. // resolve our event log messages.
  24. //
  25. void PCInstallService(int argc, TCHAR **argv) {
  26. TCHAR path[MAX_PATH], err[512];
  27. // Use security descriptor that allows admin access for our registry data.
  28. // Post-installation the access list may need to be tailored.
  29. SECURITY_ATTRIBUTES adminAttr;
  30. if ( !PCBuildAdminSecAttr( adminAttr ) ) {
  31. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME };
  32. PCLogErrStdout( PC_SERVICE_UNABLE_TO_INSTALL, GetLastError(), args );
  33. return;
  34. }
  35. // Get our module name -- needed to install service and error log message file...
  36. if ( !GetModuleFileName( NULL, path, MAX_PATH ) ) {
  37. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME };
  38. PCLogErrStdout( PC_SERVICE_UNABLE_TO_INSTALL, GetLastError(), args );
  39. return;
  40. }
  41. // Open SCM and install ourselves...
  42. SC_HANDLE hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE );
  43. PCULONG32 rc = GetLastError();
  44. TCHAR *acct = NULL, *pswd = NULL;
  45. if ( argc > 0 ) acct = argv[0];
  46. if ( argc > 1 ) pswd = argv[1];
  47. if ( hSCManager ) {
  48. SC_HANDLE hService = CreateService( hSCManager, // SCManager database
  49. PROCCON_SVC_NAME, // name of service
  50. PROCCON_SVC_DISP_NAME, // name to display
  51. GENERIC_READ, // desired access
  52. SERVICE_WIN32_OWN_PROCESS, // service type
  53. SERVICE_AUTO_START, // start type -- auto by MS req.
  54. SERVICE_ERROR_NORMAL, // error control type
  55. path, // service's binary
  56. NULL, // no load ordering group
  57. NULL, // no tag identifier
  58. TEXT(""), // dependencies
  59. acct, // account or NULL
  60. pswd); // password or NULL
  61. // If installed, add related registry keys...
  62. rc = GetLastError();
  63. if ( hService ) {
  64. PCLogStdout( PC_SERVICE_SERVICE_INSTALLED, PROCCON_SVC_DISP_NAME );
  65. CloseServiceHandle(hService);
  66. HKEY hKey;
  67. PCULONG32 regDisp, types = 0x07;
  68. TCHAR key[512];
  69. // Add registry key describing service...
  70. PCBuildBaseKey( key );
  71. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, key, 0, KEY_READ + KEY_WRITE, &hKey );
  72. if ( rc != ERROR_SUCCESS ) {
  73. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
  74. PCLogErrStdout( PC_SERVICE_REGISTRY_OPEN_FAILED,
  75. rc,
  76. args );
  77. } else {
  78. rc = RegSetValueEx( hKey, PROCCON_SERVICE_DESCRIPTION_NAME, NULL, REG_SZ,
  79. (UCHAR *) PROCCON_SERVICE_DESCRIPTION,
  80. (_tcslen( PROCCON_SERVICE_DESCRIPTION ) + 1) * sizeof(TCHAR) );
  81. if ( rc != ERROR_SUCCESS ) {
  82. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVICE_DESCRIPTION_NAME };
  83. PCLogErrStdout( PC_SERVICE_ADD_VALUE_SERVICE_DESC_FAILED, rc, args );
  84. }
  85. RegCloseKey( hKey );
  86. }
  87. // Add registry key describing server application...
  88. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, PROCCON_SERVER_APP_KEY, 0, KEY_SET_VALUE, &hKey );
  89. if ( rc != ERROR_SUCCESS ) {
  90. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVER_APP_KEY };
  91. PCLogErrStdout( PC_SERVICE_APP_KEY_OPEN_FAILED, rc, args );
  92. } else {
  93. rc = RegSetValueEx( hKey, PROCCON_SERVER_APP_VALUE_NAME, NULL, REG_SZ,
  94. (UCHAR *) PROCCON_SVC_DISP_NAME,
  95. (_tcslen( PROCCON_SVC_DISP_NAME ) + 1) * sizeof(TCHAR) );
  96. if ( rc == ERROR_SUCCESS )
  97. PCLogStdout( PC_SERVICE_APP_KEY_CREATED, PROCCON_SVC_DISP_NAME );
  98. else {
  99. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVER_APP_VALUE_NAME };
  100. PCLogErrStdout( PC_SERVICE_APP_KEY_ADD_FAILED,
  101. rc,
  102. args );
  103. }
  104. RegCloseKey( hKey );
  105. }
  106. // Add registry key to support ProcCon event log messages...
  107. // NULL security attribute is used to cause inheritance of attributes.
  108. PCBuildMsgKey( key );
  109. rc = RegCreateKeyEx( HKEY_LOCAL_MACHINE, key,
  110. 0, TEXT(""), 0, KEY_READ + KEY_WRITE, NULL, &hKey, &regDisp );
  111. if ( rc != ERROR_SUCCESS ) {
  112. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
  113. PCLogErrStdout( PC_SERVICE_REG_KEY_CREATE_FAILED,
  114. rc,
  115. args );
  116. } else {
  117. BOOL fname = TRUE;
  118. rc = RegSetValueEx( hKey, EVENT_MSG_FILE_NAME, NULL, REG_SZ,
  119. (UCHAR *) path, (_tcslen( path ) + 1) * sizeof(path[0]) );
  120. if ( rc == ERROR_SUCCESS ) {
  121. fname = FALSE;
  122. rc = RegSetValueEx( hKey, EVENT_MSG_TYPES_SUPPORT, NULL, REG_DWORD,
  123. (UCHAR *) &types, sizeof( types ) );
  124. }
  125. if ( rc != ERROR_SUCCESS ) {
  126. const VOID *args[] = { NULL,
  127. PROCCON_SVC_DISP_NAME,
  128. fname
  129. ? EVENT_MSG_FILE_NAME
  130. : EVENT_MSG_TYPES_SUPPORT };
  131. PCLogErrStdout( PC_SERVICE_EVENTLOG_REG_SETUP_FAILED,
  132. rc,
  133. args );
  134. } else {
  135. PCLogStdout( PC_SERVICE_EVENTLOG_REG_SETUP, PROCCON_SVC_DISP_NAME );
  136. }
  137. RegCloseKey( hKey );
  138. }
  139. // Add registry keys to support ProcCon...
  140. // Security attribute for the PARAMETERS key is local administrators only.
  141. // Security attribute for the access keys is local administrators only also.
  142. PCBuildParmKey( key );
  143. rc = RegCreateKeyEx( HKEY_LOCAL_MACHINE, key,
  144. 0, TEXT(""), 0, KEY_READ + KEY_WRITE, &adminAttr, &hKey, &regDisp );
  145. if ( rc != ERROR_SUCCESS ) {
  146. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
  147. PCLogErrStdout( PC_SERVICE_PARAM_KEY_CREATE_FAILED, rc, args );
  148. } else {
  149. rc = RegSetValueEx( hKey, PROCCON_DATA_NAMERULES, NULL, REG_MULTI_SZ,
  150. (UCHAR *) TEXT("\0\0"), 2 * sizeof(TCHAR) );
  151. if ( rc != ERROR_SUCCESS ) {
  152. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_DATA_NAMERULES };
  153. PCLogErrStdout( PC_SERVICE_PARAM_DATA_UPDATE_FAILED, rc, args );
  154. } else {
  155. HKEY hTemp;
  156. for ( int i = 0; i < ENTRY_COUNT( accessKeyList ); ++i ) {
  157. rc = RegCreateKeyEx( hKey, accessKeyList[i], 0, TEXT(""), 0,
  158. KEY_WRITE, &adminAttr, &hTemp, &regDisp );
  159. if ( rc == ERROR_SUCCESS ) RegCloseKey( hTemp );
  160. else {
  161. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, accessKeyList[i] };
  162. PCLogErrStdout( PC_SERVICE_PARAM_DATA_UPDATE_FAILED, rc, args );
  163. break;
  164. }
  165. }
  166. }
  167. if ( rc == ERROR_SUCCESS ) {
  168. PCLogStdout( PC_SERVICE_PARAM_DATA_CREATED, PROCCON_SVC_DISP_NAME );
  169. }
  170. RegCloseKey( hKey );
  171. }
  172. }
  173. else {
  174. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME };
  175. PCLogErrStdout( PC_SERVICE_CREATESERVICE_FAILED, rc, args );
  176. }
  177. CloseServiceHandle(hSCManager);
  178. }
  179. else {
  180. PCLogErrStdout( PC_SERVICE_OPENSCMGR_FAILED, rc, NULL );
  181. }
  182. PCFreeSecAttr( adminAttr );
  183. }
  184. //=============================================================================================
  185. // function to remove (deinstall) the service... no input or output
  186. //
  187. void PCRemoveService(int argc, TCHAR **argv) {
  188. TCHAR err[512];
  189. // Open SCM and service then proceed with stop and delete...
  190. SC_HANDLE hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  191. if ( hSCManager ) {
  192. SC_HANDLE hService = OpenService( hSCManager, PROCCON_SVC_NAME, SERVICE_ALL_ACCESS );
  193. if ( hService ) {
  194. // try to stop the service...
  195. if ( ControlService( hService, SERVICE_CONTROL_STOP, &ssStatus ) ) {
  196. PCLogStdout( PC_SERVICE_STOPPING, PROCCON_SVC_DISP_NAME );
  197. Sleep( 1000 );
  198. while( QueryServiceStatus( hService, &ssStatus ) ) {
  199. if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
  200. PCLogStdout( PC_SERVICE_DOT );
  201. Sleep( 1000 );
  202. }
  203. else
  204. break;
  205. }
  206. if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) {
  207. PCLogStdout( PC_SERVICE_STOPPING_STOPPED, PROCCON_SVC_DISP_NAME );
  208. } else {
  209. PCLogStdout( PC_SERVICE_FAILED_TO_STOP, PROCCON_SVC_DISP_NAME );
  210. }
  211. }
  212. // now remove the service...
  213. if( DeleteService( hService ) ) {
  214. PCLogStdout( PC_SERVICE_REG_ENTRIES_REMOVED, PROCCON_SVC_DISP_NAME );
  215. }
  216. else {
  217. PCLogErrStdout( PC_SERVICE_DELETE_SVC_FAILED, GetLastError(), NULL );
  218. }
  219. CloseServiceHandle( hService );
  220. }
  221. else {
  222. PCLogErrStdout( PC_SERVICE_OPEN_SVC_FAILED, GetLastError(), NULL );
  223. }
  224. CloseServiceHandle( hSCManager );
  225. }
  226. else {
  227. PCLogErrStdout( PC_SERVICE_OPENSCMGR_FAILED, GetLastError(), NULL );
  228. }
  229. HKEY hKey;
  230. TCHAR key[512];
  231. // now remove server application registry keys...
  232. PCULONG32 rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, PROCCON_SERVER_APP_KEY, 0, KEY_SET_VALUE, &hKey );
  233. if ( rc == ERROR_SUCCESS ) {
  234. rc = RegDeleteValue( hKey, PROCCON_SERVER_APP_VALUE_NAME );
  235. RegCloseKey( hKey );
  236. }
  237. if ( rc == ERROR_SUCCESS ) {
  238. PCLogStdout( PC_SERVICE_APP_REG_ENTRY_DELETED, PROCCON_SVC_DISP_NAME );
  239. } else if ( rc != ERROR_FILE_NOT_FOUND ) {
  240. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVER_APP_VALUE_NAME };
  241. PCLogErrStdout( PC_SERVICE_APP_REG_ENTRY_DEL_FAILED, rc, args );
  242. }
  243. // now remove message registry keys...
  244. PCBuildMsgKey( key );
  245. rc = RegDeleteKey( HKEY_LOCAL_MACHINE, key );
  246. if ( rc == ERROR_SUCCESS || rc == ERROR_KEY_DELETED ) {
  247. PCLogStdout( PC_SERVICE_EVTLOG_REG_DELETED, PROCCON_SVC_DISP_NAME );
  248. } else if ( rc != ERROR_FILE_NOT_FOUND ) {
  249. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
  250. PCLogErrStdout( PC_SERVICE_EVTLOG_REG_DEL_FAILED, rc, args );
  251. }
  252. // now attempt removal of parameter registry keys...
  253. // (Delete of the service should have already deleted the Parameters sub-key)
  254. PCBuildParmKey( key );
  255. rc = PCDeleteKeyTree( HKEY_LOCAL_MACHINE, key );
  256. // PCDeleteKeyTree does not return ERROR_KEY_DELETED or ERROR_FILE_NOT_FOUND
  257. if ( rc != ERROR_SUCCESS ) {
  258. const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
  259. PCLogErrStdout( PC_SERVICE_REG_TREE_DEL_FAILED, rc, args );
  260. }
  261. }
  262. void
  263. PCWriteStdout(
  264. PTCHAR Buffer,
  265. DWORD BufferLen
  266. )
  267. {
  268. DWORD Written;
  269. static BOOL ConsoleWorks = TRUE;
  270. static HANDLE StdOutHandle = INVALID_HANDLE_VALUE;
  271. if (StdOutHandle == INVALID_HANDLE_VALUE) {
  272. StdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  273. }
  274. if (ConsoleWorks) {
  275. ConsoleWorks = WriteConsole(StdOutHandle,
  276. Buffer,
  277. BufferLen,
  278. &Written,
  279. NULL);
  280. }
  281. if (! ConsoleWorks) {
  282. WriteFile(StdOutHandle,
  283. Buffer,
  284. BufferLen * sizeof(TCHAR),
  285. &Written,
  286. NULL);
  287. }
  288. }
  289. void
  290. CDECL
  291. PCLogStdout(
  292. const PCULONG32 msgCode,
  293. ...
  294. )
  295. {
  296. va_list args;
  297. PTCHAR Buffer;
  298. DWORD BufferLen;
  299. va_start(args, msgCode);
  300. BufferLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  301. | FORMAT_MESSAGE_FROM_HMODULE,
  302. NULL,
  303. msgCode,
  304. 0,
  305. (LPWSTR) &Buffer,
  306. 1,
  307. &args);
  308. va_end(args);
  309. if (BufferLen) {
  310. PCWriteStdout(Buffer, BufferLen);
  311. LocalFree(Buffer);
  312. }
  313. }
  314. void
  315. PCLogErrStdout(
  316. const PCULONG32 msgCode,
  317. const PCULONG32 errCode,
  318. const VOID **args
  319. )
  320. {
  321. PTCHAR Buffer;
  322. PTCHAR ErrBuffer;
  323. DWORD BufferLen;
  324. DWORD ErrBufferLen;
  325. ErrBufferLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  326. | FORMAT_MESSAGE_IGNORE_INSERTS
  327. | FORMAT_MESSAGE_FROM_SYSTEM,
  328. 0,
  329. errCode,
  330. 0,
  331. (LPWSTR) &ErrBuffer,
  332. 1,
  333. NULL);
  334. if (ErrBufferLen) {
  335. if (args) {
  336. args[0] = ErrBuffer;
  337. }
  338. BufferLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  339. | FORMAT_MESSAGE_FROM_HMODULE
  340. | (args
  341. ? FORMAT_MESSAGE_ARGUMENT_ARRAY
  342. : 0),
  343. NULL,
  344. msgCode,
  345. 0,
  346. (LPWSTR) &Buffer,
  347. 1,
  348. (va_list *) (args
  349. ? (PVOID) args
  350. : (PVOID) ErrBuffer));
  351. if (BufferLen) {
  352. PCWriteStdout(Buffer, BufferLen);
  353. LocalFree(Buffer);
  354. }
  355. LocalFree(ErrBuffer);
  356. }
  357. }
  358. // End of PCService.cpp
  359. //============================================================================J McDonald fecit====//