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.

622 lines
16 KiB

  1. #include "sacsvr.h"
  2. #include "sacmsg.h"
  3. #define SACSVR_SERVICE_KEY L"System\\CurrentControlSet\\Services\\SacSvr"
  4. #define SACSVR_PARAMETERS_KEY L"System\\CurrentControlSet\\Services\\SacSvr\\Parameters"
  5. #define SVCHOST_LOCATION L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"
  6. #define SERVICE_NAME L"sacsvr"
  7. #define SERVICE_IMAGEPATH L"%SystemRoot%\\System32\\svchost.exe -k "
  8. #define SERVICE_DLL L"%SystemRoot%\\System32\\sacsvr.dll"
  9. #define SVCHOST_GROUP L"netsvcs"
  10. #define SERVICE_OBJECTNAME L"LocalSystem"
  11. SERVICE_STATUS MyServiceStatus;
  12. SERVICE_STATUS_HANDLE MyServiceStatusHandle;
  13. VOID
  14. MyServiceStart(
  15. DWORD argc,
  16. LPTSTR *argv
  17. );
  18. VOID
  19. MyServiceCtrlHandler(
  20. DWORD opcode
  21. );
  22. DWORD
  23. MyServiceInitialization(
  24. DWORD argc,
  25. LPTSTR *argv,
  26. DWORD *specificError
  27. );
  28. void WINAPI
  29. ServiceMain(
  30. DWORD argc,
  31. LPTSTR *argv
  32. )
  33. {
  34. DWORD status;
  35. UNREFERENCED_PARAMETER(argc);
  36. UNREFERENCED_PARAMETER(argv);
  37. MyServiceStatus.dwServiceType = SERVICE_WIN32;
  38. MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  39. MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
  40. MyServiceStatus.dwWin32ExitCode = 0;
  41. MyServiceStatus.dwServiceSpecificExitCode = 0;
  42. MyServiceStatus.dwCheckPoint = 0;
  43. MyServiceStatus.dwWaitHint = 3000;
  44. MyServiceStatusHandle = RegisterServiceCtrlHandler(
  45. L"sacsvr",
  46. MyServiceCtrlHandler
  47. );
  48. if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  49. SvcDebugOut(" [MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  50. return;
  51. }
  52. // Initialization complete - report running status.
  53. MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
  54. MyServiceStatus.dwCheckPoint = 0;
  55. MyServiceStatus.dwWaitHint = 0;
  56. if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus)) {
  57. status = GetLastError();
  58. SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",status);
  59. }
  60. //
  61. // Service specific code goes here
  62. //
  63. Run();
  64. // Service complete - report running status.
  65. MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
  66. if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus)) {
  67. status = GetLastError();
  68. SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",status);
  69. }
  70. return;
  71. }
  72. VOID SvcDebugOut(LPSTR String, DWORD Status)
  73. {
  74. #if 0
  75. CHAR Buffer[1024];
  76. if (strlen(String) < 1000) {
  77. sprintf(Buffer, String, Status);
  78. OutputDebugStringA(Buffer);
  79. printf("%s", Buffer);
  80. }
  81. #else
  82. UNREFERENCED_PARAMETER(String);
  83. UNREFERENCED_PARAMETER(Status);
  84. #endif
  85. }
  86. BOOL
  87. pStartService(
  88. IN PCWSTR ServiceName
  89. )
  90. {
  91. SC_HANDLE hSC,hSCService;
  92. BOOL b = FALSE;
  93. //
  94. // Open a handle to the service controller manager
  95. //
  96. hSC = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  97. if(hSC == NULL) {
  98. return(FALSE);
  99. }
  100. hSCService = OpenService(hSC,ServiceName,SERVICE_START);
  101. if(hSCService) {
  102. b = StartService(hSCService,0,NULL);
  103. if(!b && (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)) {
  104. //
  105. // Service is already running.
  106. //
  107. b = TRUE;
  108. }
  109. }
  110. CloseServiceHandle(hSC);
  111. return(b);
  112. }
  113. BOOL
  114. LoadStringResource(
  115. IN PUNICODE_STRING pUnicodeString,
  116. IN INT MsgId
  117. )
  118. /*++
  119. Routine Description:
  120. This is a simple implementation of LoadString().
  121. Arguments:
  122. usString - Returns the resource string.
  123. MsgId - Supplies the message id of the resource string.
  124. Return Value:
  125. FALSE - Failure.
  126. TRUE - Success.
  127. --*/
  128. {
  129. NTSTATUS Status;
  130. PMESSAGE_RESOURCE_ENTRY MessageEntry;
  131. ANSI_STRING AnsiString;
  132. HANDLE myHandle = 0;
  133. myHandle = GetModuleHandle((LPWSTR)L"sacsvr.dll");
  134. if( !myHandle ) {
  135. return FALSE;
  136. }
  137. Status = RtlFindMessage( myHandle,
  138. (ULONG_PTR) RT_MESSAGETABLE,
  139. 0,
  140. (ULONG)MsgId,
  141. &MessageEntry
  142. );
  143. if (!NT_SUCCESS( Status )) {
  144. return FALSE;
  145. }
  146. if (!(MessageEntry->Flags & MESSAGE_RESOURCE_UNICODE)) {
  147. RtlInitAnsiString( &AnsiString, (PCSZ)&MessageEntry->Text[ 0 ] );
  148. Status = RtlAnsiStringToUnicodeString( pUnicodeString, &AnsiString, TRUE );
  149. if (!NT_SUCCESS( Status )) {
  150. return FALSE;
  151. }
  152. } else {
  153. RtlCreateUnicodeString(pUnicodeString, (PWSTR)MessageEntry->Text);
  154. }
  155. return TRUE;
  156. }
  157. STDAPI
  158. DllRegisterServer(
  159. VOID
  160. )
  161. /*++
  162. Routine Description:
  163. Add entries to the system registry.
  164. Arguments:
  165. NONE
  166. Return Value:
  167. S_OK if everything went okay.
  168. --*/
  169. {
  170. UNICODE_STRING UnicodeString = {0};
  171. HKEY hKey = INVALID_HANDLE_VALUE;
  172. PWSTR Data = NULL;
  173. PWSTR p = NULL;
  174. HRESULT ReturnValue = S_OK;
  175. ULONG dw, Size, Type, BufferSize, dwDisposition;
  176. BOOLEAN ServiceAlreadyPresent;
  177. HANDLE Handle = INVALID_HANDLE_VALUE;
  178. NTSTATUS Status;
  179. OBJECT_ATTRIBUTES ObjectAttributes;
  180. IO_STATUS_BLOCK StatusBlock;
  181. UINT OldMode;
  182. //
  183. // See if the machine is running headless right now.
  184. //
  185. RtlInitUnicodeString(&UnicodeString,L"\\Device\\SAC");
  186. InitializeObjectAttributes(
  187. &ObjectAttributes,
  188. &UnicodeString,
  189. OBJ_CASE_INSENSITIVE,
  190. NULL,
  191. NULL
  192. );
  193. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  194. Status = NtCreateFile(
  195. &Handle,
  196. FILE_READ_ATTRIBUTES,
  197. &ObjectAttributes,
  198. &StatusBlock,
  199. NULL,
  200. FILE_ATTRIBUTE_NORMAL,
  201. FILE_SHARE_READ,
  202. FILE_OPEN,
  203. 0,
  204. NULL,
  205. 0
  206. );
  207. SetErrorMode(OldMode);
  208. CloseHandle(Handle);
  209. if (!NT_SUCCESS(Status)) {
  210. return S_OK;
  211. }
  212. //
  213. // Add our entry into HKLM\Software\Microsoft\Windows NT\CurrentVersion\Svchost\<SVCHOST_GROUP>
  214. //
  215. dw = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  216. SVCHOST_LOCATION,
  217. 0,
  218. KEY_ALL_ACCESS,
  219. &hKey );
  220. if( dw != ERROR_SUCCESS ) {
  221. ReturnValue = E_UNEXPECTED;
  222. goto DllRegisterServer_Exit;
  223. }
  224. Size = 0;
  225. dw = RegQueryValueEx( hKey,
  226. SVCHOST_GROUP,
  227. NULL,
  228. &Type,
  229. NULL,
  230. &Size );
  231. if( (dw != ERROR_SUCCESS) || (Size == 0) ) {
  232. ReturnValue = E_UNEXPECTED;
  233. goto DllRegisterServer_Exit;
  234. }
  235. //
  236. // allocate a new buffer to hold the list + possobly the new
  237. // sacsvr entry (we may not need it)
  238. //
  239. BufferSize = Size + (ULONG)((wcslen(SERVICE_NAME) + 1) * sizeof(WCHAR));
  240. Data = malloc(BufferSize);
  241. if (Data == NULL) {
  242. ReturnValue = E_OUTOFMEMORY;
  243. goto DllRegisterServer_Exit;
  244. }
  245. dw = RegQueryValueEx( hKey,
  246. SVCHOST_GROUP,
  247. NULL,
  248. &Type,
  249. (LPBYTE)Data,
  250. &Size );
  251. if( (dw != ERROR_SUCCESS) || (Size == 0) ) {
  252. ReturnValue = E_UNEXPECTED;
  253. goto DllRegisterServer_Exit;
  254. }
  255. //
  256. // Do we need to add our entry?
  257. //
  258. p = Data;
  259. ServiceAlreadyPresent = FALSE;
  260. while( (*p != '\0') && (p < (Data+(Size/sizeof(WCHAR)))) ) {
  261. if( !_wcsicmp( p, SERVICE_NAME ) ) {
  262. ServiceAlreadyPresent = TRUE;
  263. break;
  264. }
  265. p += wcslen(p);
  266. p++;
  267. }
  268. if( !ServiceAlreadyPresent ) {
  269. //
  270. // Jump to the end of our buffer, append our service,
  271. // double-terminate the MULTI_SZ structure, then write
  272. // it all back out.
  273. //
  274. p = Data + (Size/sizeof(WCHAR));
  275. p--;
  276. wcscpy( p, SERVICE_NAME );
  277. p = p + wcslen(SERVICE_NAME);
  278. p++;
  279. *p = L'\0';
  280. dw = RegSetValueEx( hKey,
  281. SVCHOST_GROUP,
  282. 0,
  283. Type,
  284. (LPBYTE)Data,
  285. BufferSize );
  286. if( (dw != ERROR_SUCCESS) || (Size == 0) ) {
  287. ReturnValue = E_UNEXPECTED;
  288. goto DllRegisterServer_Exit;
  289. }
  290. }
  291. free( Data );
  292. Data = NULL;
  293. RegCloseKey( hKey );
  294. hKey = INVALID_HANDLE_VALUE;
  295. //
  296. // Create/populate the sacsvr key under HKLM\System\CCS\Service
  297. //
  298. dw = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  299. SACSVR_SERVICE_KEY,
  300. 0,
  301. NULL,
  302. REG_OPTION_NON_VOLATILE,
  303. KEY_WRITE,
  304. NULL,
  305. &hKey,
  306. &dwDisposition );
  307. if( dw != ERROR_SUCCESS ) {
  308. ReturnValue = E_UNEXPECTED;
  309. goto DllRegisterServer_Exit;
  310. }
  311. //
  312. // Description Value.
  313. //
  314. if( LoadStringResource(&UnicodeString, SERVICE_DESCRIPTION) ) {
  315. //
  316. // Terminate the string at the %0 marker, if it is present
  317. //
  318. if( wcsstr( UnicodeString.Buffer, L"%0" ) ) {
  319. *((PWCHAR)wcsstr( UnicodeString.Buffer, L"%0" )) = L'\0';
  320. }
  321. } else {
  322. ReturnValue = E_UNEXPECTED;
  323. goto DllRegisterServer_Exit;
  324. }
  325. dw = RegSetValueEx( hKey,
  326. L"Description",
  327. 0,
  328. REG_SZ,
  329. (LPBYTE)UnicodeString.Buffer,
  330. (ULONG)(wcslen( UnicodeString.Buffer) * sizeof(WCHAR) ));
  331. if( dw != ERROR_SUCCESS ) {
  332. ReturnValue = E_UNEXPECTED;
  333. goto DllRegisterServer_Exit;
  334. }
  335. //
  336. // Display Value.
  337. //
  338. if( LoadStringResource(&UnicodeString, SERVICE_DISPLAY_NAME) ) {
  339. //
  340. // Terminate the string at the %0 marker, if it is present
  341. //
  342. if( wcsstr( UnicodeString.Buffer, L"%0" ) ) {
  343. *((PWCHAR)wcsstr( UnicodeString.Buffer, L"%0" )) = L'\0';
  344. }
  345. } else {
  346. ReturnValue = E_UNEXPECTED;
  347. goto DllRegisterServer_Exit;
  348. }
  349. dw = RegSetValueEx( hKey,
  350. L"DisplayName",
  351. 0,
  352. REG_SZ,
  353. (LPBYTE)UnicodeString.Buffer,
  354. (ULONG)(wcslen( UnicodeString.Buffer) * sizeof(WCHAR) ));
  355. if( dw != ERROR_SUCCESS ) {
  356. ReturnValue = E_UNEXPECTED;
  357. goto DllRegisterServer_Exit;
  358. }
  359. //
  360. // ErrorControl.
  361. //
  362. Size = 1;
  363. dw = RegSetValueEx( hKey,
  364. L"ErrorControl",
  365. 0,
  366. REG_DWORD,
  367. (LPBYTE)&Size,
  368. sizeof(DWORD) );
  369. if( dw != ERROR_SUCCESS ) {
  370. ReturnValue = E_UNEXPECTED;
  371. goto DllRegisterServer_Exit;
  372. }
  373. //
  374. // ImagePath
  375. //
  376. dw = RegSetValueEx( hKey,
  377. L"ImagePath",
  378. 0,
  379. REG_EXPAND_SZ,
  380. (LPBYTE)(SERVICE_IMAGEPATH SVCHOST_GROUP),
  381. (ULONG)(wcslen(SERVICE_IMAGEPATH SVCHOST_GROUP) * sizeof(WCHAR) ));
  382. if( dw != ERROR_SUCCESS ) {
  383. ReturnValue = E_UNEXPECTED;
  384. goto DllRegisterServer_Exit;
  385. }
  386. //
  387. // ObjectName
  388. //
  389. dw = RegSetValueEx( hKey,
  390. L"ObjectName",
  391. 0,
  392. REG_SZ,
  393. (LPBYTE)SERVICE_OBJECTNAME,
  394. (ULONG)(wcslen(SERVICE_OBJECTNAME) * sizeof(WCHAR) ));
  395. if( dw != ERROR_SUCCESS ) {
  396. ReturnValue = E_UNEXPECTED;
  397. goto DllRegisterServer_Exit;
  398. }
  399. //
  400. // Start
  401. //
  402. Size = 2;
  403. dw = RegSetValueEx( hKey,
  404. L"Start",
  405. 0,
  406. REG_DWORD,
  407. (LPBYTE)&Size,
  408. sizeof(DWORD) );
  409. if( dw != ERROR_SUCCESS ) {
  410. ReturnValue = E_UNEXPECTED;
  411. goto DllRegisterServer_Exit;
  412. }
  413. //
  414. // Type
  415. //
  416. Size = 32;
  417. dw = RegSetValueEx( hKey,
  418. L"Type",
  419. 0,
  420. REG_DWORD,
  421. (LPBYTE)&Size,
  422. sizeof(DWORD) );
  423. if( dw != ERROR_SUCCESS ) {
  424. ReturnValue = E_UNEXPECTED;
  425. goto DllRegisterServer_Exit;
  426. }
  427. RegCloseKey( hKey );
  428. hKey = INVALID_HANDLE_VALUE;
  429. //
  430. // Create/populate the Parameters key under HKLM\System\CCS\Service\sacsvr
  431. //
  432. dw = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  433. SACSVR_PARAMETERS_KEY,
  434. 0,
  435. NULL,
  436. REG_OPTION_NON_VOLATILE,
  437. KEY_WRITE,
  438. NULL,
  439. &hKey,
  440. &dwDisposition );
  441. if( dw != ERROR_SUCCESS ) {
  442. ReturnValue = E_UNEXPECTED;
  443. goto DllRegisterServer_Exit;
  444. }
  445. //
  446. // ServiceDll
  447. //
  448. dw = RegSetValueEx( hKey,
  449. L"ServiceDll",
  450. 0,
  451. REG_EXPAND_SZ,
  452. (LPBYTE)SERVICE_DLL,
  453. (ULONG)(wcslen( SERVICE_DLL) * sizeof(WCHAR) ));
  454. if( dw != ERROR_SUCCESS ) {
  455. ReturnValue = E_UNEXPECTED;
  456. goto DllRegisterServer_Exit;
  457. }
  458. RegCloseKey( hKey );
  459. hKey = INVALID_HANDLE_VALUE;
  460. //
  461. // Try to start the service.
  462. //
  463. if( !pStartService(SERVICE_NAME) ) {
  464. //
  465. // That's okay.
  466. //
  467. // ReturnValue = E_UNEXPECTED;
  468. // goto DllRegisterServer_Exit;
  469. }
  470. DllRegisterServer_Exit:
  471. if( hKey != INVALID_HANDLE_VALUE ) {
  472. RegCloseKey( hKey );
  473. }
  474. if( Data != NULL ) {
  475. free( Data );
  476. }
  477. return ReturnValue;
  478. }
  479. STDAPI
  480. DllUnregisterServer(
  481. VOID
  482. )
  483. /*++
  484. Routine Description:
  485. Delete entries to the system registry.
  486. Arguments:
  487. NONE
  488. Return Value:
  489. S_OK if everything went okay.
  490. --*/
  491. {
  492. HRESULT ReturnValue = S_OK;
  493. ULONG dw, StartType;
  494. HKEY hKey = INVALID_HANDLE_VALUE;
  495. //
  496. // turn off the sacsvr start value.
  497. //
  498. dw = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  499. SACSVR_SERVICE_KEY,
  500. 0,
  501. KEY_ALL_ACCESS,
  502. &hKey );
  503. if( dw != ERROR_SUCCESS ) {
  504. ReturnValue = E_UNEXPECTED;
  505. goto DllUnRegisterServer_Exit;
  506. }
  507. StartType = 4;
  508. dw = RegSetValueEx( hKey,
  509. L"Start",
  510. 0,
  511. REG_DWORD,
  512. (LPBYTE)&StartType,
  513. sizeof(DWORD) );
  514. if( dw != ERROR_SUCCESS ) {
  515. ReturnValue = E_UNEXPECTED;
  516. goto DllUnRegisterServer_Exit;
  517. }
  518. RegCloseKey( hKey );
  519. hKey = INVALID_HANDLE_VALUE;
  520. DllUnRegisterServer_Exit:
  521. if( hKey != INVALID_HANDLE_VALUE ) {
  522. RegCloseKey( hKey );
  523. }
  524. return ReturnValue;
  525. }