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.

407 lines
13 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. /*
  5. This is not really how things should be done.
  6. Write an .inf. I need to learn how.
  7. */
  8. #include <stdio.h>
  9. #include <stdarg.h>
  10. #include "nt.h"
  11. #include "ntrtl.h"
  12. #include "nturtl.h"
  13. #include "windows.h"
  14. #include "delayimp.h"
  15. #include "strsafe.h"
  16. #include "sxsvc1.h"
  17. #include "resource.h"
  18. #define USE_CREATESERVICE 1
  19. #define COPY_FROM_FILE_TO_SYSTEM32 0
  20. #define COPY_FROM_RESOURCE_TO_SYSTEM32 1
  21. #define SERVICE_NAME L"sxsvc1"
  22. extern const WCHAR ServiceName[] = SERVICE_NAME L"\0"; // extra nul terminal for REG_MULTI_SZ
  23. typedef struct _REGISTRY_VALUE {
  24. DWORD Type;
  25. PCWSTR Name;
  26. union {
  27. PCWSTR String;
  28. DWORD Dword;
  29. } Value;
  30. } REGISTRY_VALUE;
  31. extern const WCHAR DescriptionValue[] = L"This is an example sidebyside installed service.";
  32. extern const WCHAR DisplayNameValue[] = L"This is the display name.";
  33. #define StartTypeValue SERVICE_AUTO_START
  34. #define ServiceTypeValue SERVICE_WIN32_OWN_PROCESS /* SERVICE_WIN32_OWN_PROCESS, SERVICE_WIN32_SHARE_PROCESS */
  35. #define ErrorControlValue SERVICE_ERROR_NORMAL
  36. extern const WCHAR ImagePathValue[] = L"%SystemRoot%\\System32\\svchost.exe -k " SERVICE_NAME;
  37. #if !USE_CREATESERVICE
  38. extern const REGISTRY_VALUE RegistryValues1[] =
  39. {
  40. { REG_SZ, L"Description", DescriptionValue },
  41. { REG_SZ, L"DisplayName", DisplayNameValue },
  42. { REG_EXPAND_SZ, L"ImagePath", ImagePathValue },
  43. { REG_DWORD, L"Start", (PCWSTR)(ULONG_PTR)StartTypeValue },
  44. { REG_DWORD, L"Type", (PCWSTR)(ULONG_PTR)ServiceTypeValue },
  45. { REG_DWORD, L"ErrorControl", (PCWSTR)(ULONG_PTR)ErrorControlValue }
  46. };
  47. #endif
  48. const REGISTRY_VALUE RegistryValues2[] =
  49. {
  50. { REG_EXPAND_SZ, L"ServiceManifest", L"%SystemRoot%\\System32\\" SERVICE_NAME L".manifest" },
  51. { REG_EXPAND_SZ, L"ServiceDll", SERVICE_NAME L".dll" },
  52. };
  53. LONG
  54. SetRegistryValues(
  55. HKEY RegistryKeyHandle,
  56. const REGISTRY_VALUE * RegistryValues,
  57. SIZE_T NumberOfRegistryValues
  58. )
  59. {
  60. LONG RegResult = ERROR_SUCCESS;
  61. SIZE_T i;
  62. for (i = 0 ; i != NumberOfRegistryValues ; ++i)
  63. {
  64. const REGISTRY_VALUE * RegistryValue = &RegistryValues[i];
  65. DWORD Size = 0;
  66. const BYTE * Data = 0;
  67. switch (RegistryValue->Type)
  68. {
  69. case REG_DWORD:
  70. Size = sizeof(RegistryValue->Value.Dword);
  71. Data = (const BYTE *)&RegistryValue->Value.Dword;
  72. break;
  73. case REG_SZ:
  74. case REG_EXPAND_SZ:
  75. Size = (wcslen(RegistryValue->Value.String) + 1) * sizeof(WCHAR);
  76. Data = (const BYTE *)RegistryValue->Value.String;
  77. break;
  78. }
  79. RegResult = RegSetValueExW(RegistryKeyHandle, RegistryValue->Name, 0, RegistryValue->Type, Data, Size);
  80. if (RegResult != ERROR_SUCCESS)
  81. goto RegExit;
  82. }
  83. RegExit:
  84. return RegResult;
  85. }
  86. STDAPI DllRegisterServer(void) { return NOERROR; }
  87. STDAPI DllUnregisterServer(void) { return NOERROR; }
  88. STDAPI
  89. DllInstall(
  90. BOOL fInstall,
  91. LPCWSTR pszCmdLine
  92. )
  93. {
  94. const static WCHAR s1[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost";
  95. const static WCHAR s2[] = L"System\\CurrentControlSet\\Services\\" SERVICE_NAME;
  96. HANDLE ServiceControlManager = 0;
  97. HANDLE ServiceHandle = 0;
  98. HKEY RegistryHandles[4] = { 0 };
  99. DWORD Disposition = 0;
  100. LONG RegResult = ERROR_SUCCESS;
  101. SIZE_T i = 0;
  102. PWSTR InstallManifestFrom1 = 0;
  103. PWSTR InstallManifestFrom2 = 0;
  104. PWSTR InstallManifestFrom = 0;
  105. PWSTR InstallManifestTo = 0;
  106. HRSRC ResourceHandle = 0;
  107. HMODULE MyModule = 0;
  108. HGLOBAL GlobalResourceHandle = 0;
  109. PVOID PointerToResource = 0;
  110. DWORD ResourceSize = 0;
  111. DWORD BytesWritten = 0;
  112. HANDLE FileHandle = 0;
  113. DWORD Retried = 0;
  114. if (!fInstall)
  115. {
  116. return NOERROR;
  117. }
  118. InstallManifestFrom1 = (PWSTR)MemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
  119. InstallManifestFrom2 = (PWSTR)MemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
  120. InstallManifestTo = (PWSTR)MemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
  121. if (InstallManifestFrom1 == NULL
  122. || InstallManifestFrom2 == NULL
  123. || InstallManifestTo == NULL
  124. )
  125. {
  126. goto OutOfMemory;
  127. }
  128. InstallManifestFrom1[0] = 0;
  129. InstallManifestFrom2[0] = 0;
  130. ServiceControlManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  131. if (ServiceControlManager == NULL || ServiceControlManager == INVALID_HANDLE_VALUE)
  132. {
  133. DbgPrint("OpenSCManager failed 0x%lx\n", (ULONG)GetLastError());
  134. goto LastErrorExit;
  135. }
  136. RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, s1, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[0], &Disposition);
  137. if (RegResult != ERROR_SUCCESS)
  138. {
  139. DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
  140. goto RegExit;
  141. }
  142. RegResult = RegCreateKeyExW(RegistryHandles[0], ServiceName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[1], &Disposition);
  143. if (RegResult != ERROR_SUCCESS)
  144. {
  145. DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
  146. goto RegExit;
  147. }
  148. //
  149. // In reality this needs to append to the possibly preexisting REG_MULTI_SZE.
  150. //
  151. RegResult = RegSetValueExW(RegistryHandles[0], ServiceName, 0, REG_MULTI_SZ, (const BYTE*)&ServiceName, sizeof(ServiceName));
  152. if (RegResult != ERROR_SUCCESS)
  153. {
  154. DbgPrint("RegSetValueExW failed 0x%lx\n", (ULONG)RegResult);
  155. goto RegExit;
  156. }
  157. #if !USE_CREATESERVICE
  158. RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, s2, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[2], &Disposition);
  159. if (RegResult != ERROR_SUCCESS)
  160. {
  161. DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
  162. goto RegExit;
  163. }
  164. RegResult = SetRegistryValues(RegistryHandles[2], RegistryValues1, NUMBER_OF(RegistryValues1));
  165. if (RegResult != ERROR_SUCCESS)
  166. goto RegExit;
  167. #else
  168. //
  169. // First stop and delete the service.
  170. //
  171. ServiceHandle =
  172. OpenServiceW(
  173. ServiceControlManager,
  174. ServiceName,
  175. GENERIC_ALL
  176. );
  177. if (ServiceHandle != NULL && ServiceHandle != INVALID_HANDLE_VALUE)
  178. {
  179. SERVICE_STATUS ServiceStatus;
  180. ControlService(ServiceHandle, SERVICE_STOP, &ServiceStatus);
  181. if (!DeleteService(ServiceHandle))
  182. {
  183. DWORD Error = GetLastError();
  184. if (Error != ERROR_SERVICE_MARKED_FOR_DELETE
  185. && Error != ERROR_KEY_DELETED
  186. )
  187. {
  188. DbgPrint("sxsvc1: DeleteService failed 0x%lx\n", (ULONG)Error);
  189. goto LastErrorExit;
  190. }
  191. }
  192. CloseServiceHandle(ServiceHandle);
  193. ServiceHandle = NULL;
  194. //
  195. // close and reopen to avoid use-after-delete / use-while-delete-pending errors (0x430/0x3fa) ?
  196. //
  197. CloseServiceHandle(ServiceControlManager);
  198. ServiceControlManager = NULL;
  199. ServiceControlManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  200. if (ServiceControlManager == NULL || ServiceControlManager == INVALID_HANDLE_VALUE)
  201. {
  202. DbgPrint("OpenSCManager failed 0x%lx\n", (ULONG)GetLastError());
  203. goto LastErrorExit;
  204. }
  205. }
  206. RetryCreate:
  207. ServiceHandle =
  208. CreateServiceW(
  209. ServiceControlManager,
  210. ServiceName,
  211. DisplayNameValue,
  212. GENERIC_ALL,
  213. ServiceTypeValue,
  214. StartTypeValue,
  215. ErrorControlValue,
  216. ImagePathValue,
  217. NULL,
  218. NULL,
  219. NULL,
  220. NULL,
  221. NULL
  222. );
  223. if (ServiceHandle == NULL || ServiceHandle == INVALID_HANDLE_VALUE)
  224. {
  225. if ((Retried & 1) == 0 && GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE)
  226. {
  227. Sleep(500);
  228. Retried |= 1;
  229. goto RetryCreate;
  230. }
  231. DbgPrint("sxsvc1: CreateService failed 0x%lx\n", (ULONG)GetLastError());
  232. goto LastErrorExit;
  233. }
  234. #endif
  235. #if USE_CREATESERVICE
  236. //
  237. // close and reopen to avoid use-after-delete / use-while-delete-pending errors (0x430/0x3fa) ?
  238. //
  239. if (RegistryHandles[2] != NULL)
  240. {
  241. RegCloseKey(RegistryHandles[2]);
  242. RegistryHandles[2] = NULL;
  243. }
  244. RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, s2, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[2], &Disposition);
  245. if (RegResult != ERROR_SUCCESS)
  246. {
  247. DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
  248. goto RegExit;
  249. }
  250. #endif
  251. // But need to put in the svchost parameters ourselves.
  252. RegResult = RegCreateKeyExW(RegistryHandles[2], L"Parameters", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[3], &Disposition);
  253. if (RegResult != ERROR_SUCCESS)
  254. {
  255. DbgPrint("sxsvc1: RegCreateKeyExW(Parameters) failed 0x%lx\n", (ULONG)RegResult);
  256. goto RegExit;
  257. }
  258. RegResult = SetRegistryValues(RegistryHandles[3], RegistryValues2, NUMBER_OF(RegistryValues2));
  259. if (RegResult != ERROR_SUCCESS)
  260. {
  261. DbgPrint("sxsvc1: SetRegistryValues(3) failed 0x%lx\n", (ULONG)RegResult);
  262. goto RegExit;
  263. }
  264. #if COPY_FROM_FILE_TO_SYSTEM32
  265. InstallManifestFrom1[0] = 0;
  266. InstallManifestFrom2[0] = 0;
  267. GetMyFullPathW(InstallManifestFrom1, MAX_PATH);
  268. CopyMemory(InstallManifestFrom2, InstallManifestFrom1, (wcslen(InstallManifestFrom1) + 1) * sizeof(WCHAR));
  269. RegResult = ERROR_BUFFER_OVERFLOW;
  270. if (!ChangePathExtensionW(InstallManifestFrom1, MAX_PATH, L".man"))
  271. goto RegExit;
  272. if (!ChangePathExtensionW(InstallManifestFrom2, MAX_PATH, L".manifest"))
  273. goto RegExit;
  274. if (GetFileAttributesW(InstallManifestFrom1) != 0xFFFFFFFF)
  275. {
  276. InstallManifestFrom = InstallManifestFrom1;
  277. }
  278. else if (GetFileAttributesW(InstallManifestFrom2) != 0xFFFFFFFF)
  279. {
  280. InstallManifestFrom = InstallManifestFrom2;
  281. }
  282. else
  283. {
  284. goto LastErrorExit;
  285. }
  286. #endif
  287. #if COPY_FROM_FILE_TO_SYSTEM32 || COPY_FROM_RESOURCE_TO_SYSTEM32
  288. InstallManifestTo[0] = 0;
  289. if (ExpandEnvironmentStringsW(RegistryValues2[0].Value.String, InstallManifestTo, MAX_PATH) == 0)
  290. {
  291. goto LastErrorExit;
  292. }
  293. #endif
  294. #if COPY_FROM_FILE_TO_SYSTEM32
  295. if (!CopyFileW(InstallManifestFrom, InstallManifestTo, FALSE))
  296. {
  297. goto LastErrorExit;
  298. }
  299. #endif
  300. #if COPY_FROM_RESOURCE_TO_SYSTEM32
  301. ResourceHandle = FindResourceW(MyModule = GetMyModule(), MAKEINTRESOURCEW(SYSTEM32_MANIFEST_ID), MAKEINTRESOURCEW(RT_MANIFEST));
  302. if (ResourceHandle == NULL)
  303. {
  304. goto LastErrorExit;
  305. }
  306. GlobalResourceHandle = LoadResource(MyModule, ResourceHandle);
  307. if (GlobalResourceHandle == NULL)
  308. {
  309. goto LastErrorExit;
  310. }
  311. PointerToResource = LockResource(GlobalResourceHandle);
  312. if (PointerToResource == NULL)
  313. {
  314. goto LastErrorExit;
  315. }
  316. ResourceSize = SizeofResource(MyModule, ResourceHandle);
  317. if (ResourceSize == 0)
  318. {
  319. goto LastErrorExit;
  320. }
  321. FileHandle = CreateFileW(InstallManifestTo, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  322. if (FileHandle == INVALID_HANDLE_VALUE)
  323. {
  324. goto LastErrorExit;
  325. }
  326. if (!WriteFile(FileHandle, PointerToResource, ResourceSize, &BytesWritten, NULL))
  327. {
  328. goto LastErrorExit;
  329. }
  330. CloseHandle(FileHandle);
  331. FileHandle = NULL;
  332. #endif
  333. RegResult = ERROR_SUCCESS;
  334. RegExit:
  335. #if DBG
  336. if (RegResult != ERROR_SUCCESS)
  337. {
  338. DbgPrint("%ls:%s: Registry Error 0x%lx\n", ServiceName, __FUNCTION__, RegResult);
  339. }
  340. #endif
  341. if (ServiceHandle != NULL)
  342. {
  343. CloseServiceHandle(ServiceHandle);
  344. }
  345. if (ServiceControlManager != NULL)
  346. {
  347. CloseServiceHandle(ServiceControlManager);
  348. }
  349. for (i = 0 ; i != NUMBER_OF(RegistryHandles) ; ++i )
  350. {
  351. if (RegistryHandles[i] != NULL)
  352. {
  353. RegCloseKey(RegistryHandles[i]);
  354. }
  355. }
  356. if (FileHandle != NULL || FileHandle != INVALID_HANDLE_VALUE)
  357. {
  358. CloseHandle(FileHandle);
  359. }
  360. MemFree(InstallManifestFrom1);
  361. MemFree(InstallManifestFrom2);
  362. MemFree(InstallManifestTo);
  363. if (RegResult == ERROR_SUCCESS)
  364. {
  365. return NOERROR;
  366. }
  367. else
  368. {
  369. return HRESULT_FROM_WIN32(RegResult);
  370. }
  371. LastErrorExit:
  372. RegResult = GetLastError();
  373. goto RegExit;
  374. OutOfMemory:
  375. RegResult = ERROR_OUTOFMEMORY;
  376. goto RegExit;
  377. }