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.

334 lines
8.5 KiB

  1. #include "spprecmp.h"
  2. #pragma hdrstop
  3. NTSTATUS
  4. SpDeleteServiceEntry(
  5. IN PWCHAR ServiceKey
  6. )
  7. {
  8. NTSTATUS Status;
  9. HANDLE KeyHandle;
  10. UNICODE_STRING UnicodeString;
  11. OBJECT_ATTRIBUTES Obja;
  12. RtlInitUnicodeString(&UnicodeString,ServiceKey);
  13. InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
  14. Status = ZwOpenKey(&KeyHandle,KEY_WRITE|DELETE,&Obja);
  15. if(NT_SUCCESS(Status)) {
  16. Status = ZwDeleteKey(KeyHandle);
  17. if(!NT_SUCCESS(Status)) {
  18. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: ZwDeleteKey of %ws returned %lx\n",ServiceKey,Status));
  19. }
  20. } else {
  21. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: ZwOpenKey of %ws returned %lx\n",ServiceKey,Status));
  22. }
  23. return(Status);
  24. }
  25. NTSTATUS
  26. SpCreateServiceEntry(
  27. IN PWCHAR ImagePath,
  28. IN OUT PWCHAR *ServiceKey
  29. )
  30. /*++
  31. Routine Description:
  32. Create an services entry in the registry suitable for loading
  33. a given device driver file.
  34. Arguments:
  35. ImagePath - supplies the fully-qualified pathname of the device driver.
  36. ServiceKey - If *ServiceKey is not NULL, then it specifies the registry
  37. path to the service node for this driver. If it is NULL, then it
  38. receives a pointer to a buffer containing the name of the
  39. service node created by this routine. The caller must free this
  40. buffer via SpMemFree when finished.
  41. Return Value:
  42. Status code indicating outcome.
  43. --*/
  44. {
  45. WCHAR KeyName[128];
  46. WCHAR FilePart[32];
  47. OBJECT_ATTRIBUTES Obja;
  48. UNICODE_STRING UnicodeString;
  49. HANDLE KeyHandle;
  50. ULONG u;
  51. NTSTATUS Status;
  52. PWSTR p;
  53. BYTE DataBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)];
  54. ULONG ResultLength;
  55. if (*ServiceKey) {
  56. wcscpy(KeyName, *ServiceKey);
  57. } else {
  58. //
  59. // Isolate the name of the device driver file from its path.
  60. //
  61. if(p = wcsrchr(ImagePath,L'\\')) {
  62. p++;
  63. } else {
  64. p = ImagePath;
  65. }
  66. wcsncpy(FilePart,p,(sizeof(FilePart)/sizeof(FilePart[0]))-1);
  67. FilePart[(sizeof(FilePart)/sizeof(FilePart[0]))-1] = 0;
  68. if(p=wcsrchr(FilePart,L'.')) {
  69. *p = 0;
  70. }
  71. //
  72. // Form a unique key name in
  73. // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services.
  74. //
  75. swprintf(
  76. KeyName,
  77. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%ws",
  78. FilePart
  79. );
  80. }
  81. //
  82. // Attempt to create the key for the service.
  83. //
  84. RtlInitUnicodeString(&UnicodeString,KeyName);
  85. InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
  86. Status = ZwCreateKey(
  87. &KeyHandle,
  88. KEY_READ | KEY_WRITE,
  89. &Obja,
  90. 0,
  91. NULL,
  92. REG_OPTION_NON_VOLATILE,
  93. NULL
  94. );
  95. if(!NT_SUCCESS(Status)) {
  96. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpCreateServiceEntry: ZwCreateKey %ws returns %lx\n",KeyName,Status));
  97. return(Status);
  98. }
  99. //
  100. // Set the ImagePath value in the service key.
  101. //
  102. RtlInitUnicodeString(&UnicodeString,L"ImagePath");
  103. Status = ZwSetValueKey(
  104. KeyHandle,
  105. &UnicodeString,
  106. 0,
  107. REG_SZ,
  108. ImagePath,
  109. (wcslen(ImagePath) + 1) * sizeof(WCHAR)
  110. );
  111. if(!NT_SUCCESS(Status)) {
  112. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set ImagePath value in key %ws (%lx)\n",KeyName,Status));
  113. goto cs1;
  114. }
  115. //
  116. // Set the Type value in the service key. If the type is preset in the registry to SERVICE_FILE_SYSTEM_DRIVER
  117. // leave it alone. Otherwise set it to SERVICE_KERNEL_DRIVER.
  118. //
  119. RtlInitUnicodeString(&UnicodeString, REGSTR_VALUE_TYPE);
  120. ResultLength = 0;
  121. Status = ZwQueryValueKey(KeyHandle,
  122. &UnicodeString,
  123. KeyValuePartialInformation,
  124. (PKEY_VALUE_PARTIAL_INFORMATION)DataBuffer,
  125. sizeof(DataBuffer),
  126. &ResultLength);
  127. if( NT_SUCCESS(Status) &&
  128. ResultLength &&
  129. ( (INT) ( (PKEY_VALUE_PARTIAL_INFORMATION) DataBuffer)->Type == REG_DWORD ) &&
  130. ( (INT) *(( (PKEY_VALUE_PARTIAL_INFORMATION) DataBuffer)->Data) == SERVICE_FILE_SYSTEM_DRIVER ) ) {
  131. u = SERVICE_FILE_SYSTEM_DRIVER;
  132. }
  133. else {
  134. //
  135. // If the type is not preset in the registry to SERVICE_FILE_SYSTEM_DRIVER set it to SERVICE_KERNEL_DRIVER by default.
  136. //
  137. u = SERVICE_KERNEL_DRIVER;
  138. }
  139. Status = ZwSetValueKey(
  140. KeyHandle,
  141. &UnicodeString,
  142. 0,
  143. REG_DWORD,
  144. &u,
  145. sizeof(ULONG)
  146. );
  147. if(!NT_SUCCESS(Status)) {
  148. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set Type value in key %ws (%lx)\n",KeyName,Status));
  149. goto cs1;
  150. }
  151. //
  152. // Set the Start value in the service key.
  153. //
  154. u = SERVICE_DEMAND_START;
  155. RtlInitUnicodeString(&UnicodeString,L"Start");
  156. Status = ZwSetValueKey(
  157. KeyHandle,
  158. &UnicodeString,
  159. 0,
  160. REG_DWORD,
  161. &u,
  162. sizeof(ULONG)
  163. );
  164. if(!NT_SUCCESS(Status)) {
  165. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set Start value in key %ws (%lx)\n",KeyName,Status));
  166. goto cs1;
  167. }
  168. cs1:
  169. //
  170. // If we were not entirely successful creating the service,
  171. // we'll want to clean it out here. Otherwise duplicate the KeyName
  172. // string to return to the caller, if it was not passed in.
  173. //
  174. if(NT_SUCCESS(Status)) {
  175. if (*ServiceKey == NULL) {
  176. if((*ServiceKey = SpDupStringW(KeyName)) == NULL) {
  177. Status = STATUS_INSUFFICIENT_RESOURCES;
  178. }
  179. }
  180. }
  181. if(!NT_SUCCESS(Status)) {
  182. NTSTATUS s;
  183. //
  184. // Remove the key we just created.
  185. //
  186. s = ZwDeleteKey(KeyHandle);
  187. if(!NT_SUCCESS(s)) {
  188. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: ZwDeleteKey of %ws returned %lx\n",KeyName,s));
  189. }
  190. }
  191. NtClose(KeyHandle);
  192. return(Status);
  193. }
  194. NTSTATUS
  195. SpLoadDeviceDriver(
  196. IN PWSTR Description,
  197. IN PWSTR PathPart1,
  198. IN PWSTR PathPart2, OPTIONAL
  199. IN PWSTR PathPart3 OPTIONAL
  200. )
  201. /*++
  202. Routine Description:
  203. Load a device driver by creating a services entry for the driver and
  204. then calling the I/O subsystem.
  205. Arguments:
  206. Description - supplies a human-readable description of the driver
  207. or hardware that the driver targets.
  208. PathPart1 - supplies first part of full pathname to driver file.
  209. PathPart2 - if specified, supplies the second part of the full pathname;
  210. PathPart2 will be concatenated to PathPart1. If not specified,
  211. then PathPart1 is the full path.
  212. PathPart3 - if specified, supplies a third part of the full pathname;
  213. PathPart3 will be concatenated to PathPart1 and PathPart2.
  214. Return Value:
  215. Status code indicating outcome.
  216. --*/
  217. {
  218. PWCHAR FullName;
  219. NTSTATUS Status;
  220. PWCHAR ServiceKey;
  221. UNICODE_STRING ServiceKeyU;
  222. PWSTR pwstr;
  223. SpDisplayStatusText(
  224. SP_STAT_LOADING_DRIVER,
  225. DEFAULT_STATUS_ATTRIBUTE,
  226. Description
  227. );
  228. pwstr = TemporaryBuffer;
  229. //
  230. // Form the full name of the device driver file.
  231. //
  232. wcscpy(pwstr,PathPart1);
  233. if(PathPart2) {
  234. SpConcatenatePaths(pwstr,PathPart2);
  235. }
  236. if(PathPart3) {
  237. SpConcatenatePaths(pwstr,PathPart3);
  238. }
  239. FullName = SpDupStringW(pwstr);
  240. //
  241. // Create a service entry for the driver.
  242. //
  243. ServiceKey = NULL;
  244. Status = SpCreateServiceEntry(FullName,&ServiceKey);
  245. if(NT_SUCCESS(Status)) {
  246. RtlInitUnicodeString(&ServiceKeyU,ServiceKey);
  247. //
  248. // Attempt to load the driver.
  249. //
  250. Status = ZwLoadDriver(&ServiceKeyU);
  251. if(!NT_SUCCESS(Status)) {
  252. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: ZwLoadDriver %ws returned %lx\n",FullName,Status));
  253. //
  254. // Remove the service entry we created in the registry.
  255. //
  256. SpDeleteServiceEntry(ServiceKey);
  257. }
  258. SpMemFree(ServiceKey);
  259. }
  260. SpMemFree(FullName);
  261. return(Status);
  262. }