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.

353 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ntinit.c
  5. Abstract:
  6. NT specific routines for loading and configuring the
  7. automatic connection notification driver (acd.sys).
  8. Author:
  9. Anthony Discolo (adiscolo) 18-Apr-1995
  10. Revision History:
  11. --*/
  12. #include <ndis.h>
  13. #include <cxport.h>
  14. #include <tdi.h>
  15. #include <tdikrnl.h>
  16. #include <tdistat.h>
  17. #include <tdiinfo.h>
  18. #include <acd.h>
  19. #include "acdapi.h"
  20. #include "acddefs.h"
  21. #include "mem.h"
  22. #include "debug.h"
  23. //
  24. // Global variables
  25. //
  26. #if DBG
  27. ULONG AcdDebugG = 0x0; // see debug.h for flags
  28. #endif
  29. PDRIVER_OBJECT pAcdDriverObjectG;
  30. PDEVICE_OBJECT pAcdDeviceObjectG;
  31. PACD_DISABLED_ADDRESSES pDisabledAddressesG = NULL;
  32. HANDLE hSignalNotificationThreadG;
  33. BOOLEAN AcdStopThread = FALSE; // Set to TRUE to stop system thread
  34. PETHREAD NotificationThread;
  35. BOOLEAN fAcdEnableRedirNotifs = FALSE;
  36. extern LONG lOutstandingRequestsG;
  37. //
  38. // Imported routines
  39. //
  40. VOID
  41. AcdNotificationRequestThread(
  42. PVOID context
  43. );
  44. //
  45. // External function prototypes
  46. //
  47. NTSTATUS
  48. AcdDispatch(
  49. IN PDEVICE_OBJECT pDeviceObject,
  50. IN PIRP pIrp
  51. );
  52. VOID
  53. AcdConnectionTimer(
  54. IN PDEVICE_OBJECT pDeviceObject,
  55. IN PVOID pContext
  56. );
  57. //
  58. // Internal function prototypes
  59. //
  60. NTSTATUS
  61. DriverEntry(
  62. IN PDRIVER_OBJECT pDriverObject,
  63. IN PUNICODE_STRING pRegistryPath
  64. );
  65. BOOLEAN
  66. GetComputerName(
  67. IN PUCHAR szName,
  68. IN USHORT cbName
  69. );
  70. VOID
  71. AcdUnload(
  72. IN PDRIVER_OBJECT pDriverObject
  73. );
  74. #ifdef ALLOC_PRAGMA
  75. #pragma alloc_text(INIT, DriverEntry)
  76. #pragma alloc_text(PAGE, AcdUnload)
  77. #endif // ALLOC_PRAGMA
  78. NTSTATUS
  79. DriverEntry(
  80. IN PDRIVER_OBJECT pDriverObject,
  81. IN PUNICODE_STRING pRegistryPath
  82. )
  83. /*++
  84. DESCRIPTION
  85. Initialization routine for the network connection notification driver.
  86. It creates the device object and initializes the driver.
  87. ARGUMENTS
  88. pDriverObject: a pointer to the driver object created by the system.
  89. pRegistryPath - the name of the configuration node in the registry.
  90. RETURN VALUE
  91. The final status from the initialization operation.
  92. --*/
  93. {
  94. NTSTATUS status;
  95. UNICODE_STRING deviceName;
  96. ULONG i;
  97. OBJECT_ATTRIBUTES objectAttributes;
  98. IO_STATUS_BLOCK ioStatusBlock;
  99. PDEVICE_OBJECT pDeviceObject;
  100. PFILE_OBJECT pFileObject;
  101. PACD_DISABLED_ADDRESS pDisabledAddress = NULL;
  102. //
  103. // Initialize the spin lock.
  104. //
  105. KeInitializeSpinLock(&AcdSpinLockG);
  106. //
  107. // Initialize the notification and completion
  108. // connection queues.
  109. //
  110. InitializeListHead(&AcdNotificationQueueG);
  111. InitializeListHead(&AcdCompletionQueueG);
  112. InitializeListHead(&AcdConnectionQueueG);
  113. InitializeListHead(&AcdDriverListG);
  114. lOutstandingRequestsG = 0;
  115. //
  116. // Initialize our zone allocator.
  117. //
  118. status = InitializeObjectAllocator();
  119. if(!NT_SUCCESS(status))
  120. {
  121. #if DBG
  122. DbgPrint("AcdDriverEntry: InitializeObjectAllocator"
  123. " failed. (status=0x%x)\n",
  124. status);
  125. #endif
  126. return status;
  127. }
  128. //
  129. // Create the device object.
  130. //
  131. pAcdDriverObjectG = pDriverObject;
  132. RtlInitUnicodeString(&deviceName, ACD_DEVICE_NAME);
  133. status = IoCreateDevice(
  134. pDriverObject,
  135. 0,
  136. &deviceName,
  137. FILE_DEVICE_ACD,
  138. 0,
  139. FALSE,
  140. &pAcdDeviceObjectG);
  141. if (!NT_SUCCESS(status)) {
  142. DbgPrint(
  143. "AcdDriverEntry: IoCreateDevice failed (status=0x%x)\n",
  144. status);
  145. FreeObjectAllocator();
  146. return status;
  147. }
  148. //
  149. // Initialize the driver object.
  150. //
  151. pDriverObject->DriverUnload = AcdUnload;
  152. for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
  153. pDriverObject->MajorFunction[i] = AcdDispatch;
  154. pDriverObject->FastIoDispatch = NULL;
  155. //
  156. // Initialize the connection timer. This is
  157. // used to make sure pending requests aren't
  158. // blocked forever because the user-space
  159. // process died trying to make a connection.
  160. //
  161. IoInitializeTimer(pAcdDeviceObjectG, AcdConnectionTimer, NULL);
  162. {
  163. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  164. PWSTR EnableRedirNotifs = L"EnableRedirNotifications";
  165. PWSTR ParameterKey = L"RasAcd\\Parameters";
  166. ULONG ulEnableRedirNotifs = 0;
  167. //
  168. // Read the registry key that enables redir notifications
  169. //
  170. RtlZeroMemory(QueryTable, 2 * sizeof(RTL_QUERY_REGISTRY_TABLE));
  171. QueryTable[0].QueryRoutine = NULL;
  172. QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  173. QueryTable[0].Name = EnableRedirNotifs;
  174. QueryTable[0].EntryContext = (PVOID)&ulEnableRedirNotifs;
  175. QueryTable[0].DefaultType = 0;
  176. status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
  177. ParameterKey,
  178. &QueryTable[0],
  179. NULL,
  180. NULL);
  181. if((status == STATUS_SUCCESS) && (ulEnableRedirNotifs != 0))
  182. {
  183. fAcdEnableRedirNotifs = TRUE;
  184. }
  185. // KdPrint(("AcdDriverEntry: EnableRedirNotifs=%d\n", fAcdEnableRedirNotifs));
  186. status = STATUS_SUCCESS;
  187. }
  188. //
  189. // Create the worker thread. We need
  190. // a thread because these operations can occur at
  191. // DPC irql.
  192. //
  193. KeInitializeEvent(
  194. &AcdRequestThreadEventG,
  195. NotificationEvent,
  196. FALSE);
  197. status = PsCreateSystemThread(
  198. &hSignalNotificationThreadG,
  199. THREAD_ALL_ACCESS,
  200. NULL,
  201. NULL,
  202. NULL,
  203. AcdNotificationRequestThread,
  204. NULL);
  205. if (!NT_SUCCESS(status)) {
  206. DbgPrint(
  207. "AcdDriverEntry: PsCreateSystemThread failed (status=0x%x)\n",
  208. status);
  209. IoDeleteDevice(pAcdDeviceObjectG);
  210. FreeObjectAllocator();
  211. return status;
  212. }
  213. //
  214. // Allocate memory for keeping track of disabled addresses
  215. //
  216. ALLOCATE_MEMORY(sizeof(ACD_DISABLED_ADDRESSES), pDisabledAddressesG);
  217. if(pDisabledAddressesG == NULL)
  218. {
  219. status = STATUS_INSUFFICIENT_RESOURCES;
  220. IoDeleteDevice(pAcdDeviceObjectG);
  221. FreeObjectAllocator();
  222. return status;
  223. }
  224. ALLOCATE_MEMORY(sizeof(ACD_DISABLED_ADDRESS), pDisabledAddress);
  225. if(pDisabledAddress == NULL)
  226. {
  227. status = STATUS_INSUFFICIENT_RESOURCES;
  228. IoDeleteDevice(pAcdDeviceObjectG);
  229. FREE_MEMORY(pDisabledAddressesG);
  230. FreeObjectAllocator();
  231. return status;
  232. }
  233. RtlZeroMemory(pDisabledAddressesG, sizeof(ACD_DISABLED_ADDRESSES));
  234. RtlZeroMemory(pDisabledAddress, sizeof(ACD_DISABLED_ADDRESS));
  235. InitializeListHead(&pDisabledAddressesG->ListEntry);
  236. InsertTailList(&pDisabledAddressesG->ListEntry, &pDisabledAddress->ListEntry);
  237. pDisabledAddressesG->ulNumAddresses = 1;
  238. pDisabledAddressesG->ulMaxAddresses = 10;
  239. //
  240. // If this fails then we have no way to wait for the thread to terminate
  241. //
  242. status = ObReferenceObjectByHandle (hSignalNotificationThreadG,
  243. 0,
  244. NULL,
  245. KernelMode,
  246. &NotificationThread,
  247. NULL);
  248. ASSERT (NT_SUCCESS (status));
  249. return STATUS_SUCCESS;
  250. } // DriverEntry
  251. VOID
  252. AcdUnload(
  253. IN PDRIVER_OBJECT pDriverObject
  254. )
  255. {
  256. NTSTATUS status;
  257. //
  258. // Terminate the system thread and wait for it to exit
  259. //
  260. AcdStopThread = TRUE;
  261. KeSetEvent(&AcdRequestThreadEventG, 0, FALSE); // Wake the thread so it sees to exit
  262. //
  263. // Wait for the thread to leave the drivers address space.
  264. //
  265. KeWaitForSingleObject (NotificationThread, Executive, KernelMode, FALSE, 0);
  266. ObDereferenceObject (NotificationThread);
  267. ZwClose (hSignalNotificationThreadG);
  268. //
  269. // Make sure to unlink all driver
  270. // blocks before unloading!
  271. //
  272. IoDeleteDevice(pAcdDeviceObjectG);
  273. if(pDisabledAddressesG)
  274. {
  275. PLIST_ENTRY pListEntry;
  276. PACD_DISABLED_ADDRESS pDisabledAddress;
  277. while(!IsListEmpty(&pDisabledAddressesG->ListEntry))
  278. {
  279. pListEntry = RemoveHeadList(&pDisabledAddressesG->ListEntry);
  280. pDisabledAddress =
  281. CONTAINING_RECORD(pListEntry, ACD_DISABLED_ADDRESS, ListEntry);
  282. FREE_MEMORY(pDisabledAddress);
  283. }
  284. FREE_MEMORY(pDisabledAddressesG);
  285. pDisabledAddressesG = NULL;
  286. }
  287. //
  288. // Free zone allocator.
  289. //
  290. FreeObjectAllocator();
  291. } // AcdUnload