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.

455 lines
12 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. device.c
  5. Abstract:
  6. This module contains code which implements the DEVICE object.
  7. Routines are provided to reference, and dereference transport device
  8. context objects.
  9. The transport device context object is a structure which contains a
  10. system-defined DEVICE_OBJECT followed by information which is maintained
  11. by the transport provider, called the context.
  12. Environment:
  13. Kernel mode
  14. Revision History:
  15. --*/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE,NbiCreateDevice)
  20. #endif
  21. VOID
  22. NbiRefDevice(
  23. IN PDEVICE Device
  24. )
  25. /*++
  26. Routine Description:
  27. This routine increments the reference count on a device context.
  28. Arguments:
  29. Device - Pointer to a transport device context object.
  30. Return Value:
  31. none.
  32. --*/
  33. {
  34. CTEAssert (Device->ReferenceCount > 0); // not perfect, but...
  35. (VOID)InterlockedIncrement (&Device->ReferenceCount);
  36. } /* NbiRefDevice */
  37. VOID
  38. NbiDerefDevice(
  39. IN PDEVICE Device
  40. )
  41. /*++
  42. Routine Description:
  43. This routine dereferences a device context by decrementing the
  44. reference count contained in the structure. Currently, we don't
  45. do anything special when the reference count drops to zero, but
  46. we could dynamically unload stuff then.
  47. Arguments:
  48. Device - Pointer to a transport device context object.
  49. Return Value:
  50. none.
  51. --*/
  52. {
  53. LONG result;
  54. result = InterlockedDecrement (&Device->ReferenceCount);
  55. CTEAssert (result >= 0);
  56. if (result == 0) {
  57. NbiDestroyDevice (Device);
  58. }
  59. } /* NbiDerefDevice */
  60. NTSTATUS
  61. NbiCreateDevice(
  62. IN PDRIVER_OBJECT DriverObject,
  63. IN PUNICODE_STRING DeviceName,
  64. IN OUT PDEVICE *DevicePtr
  65. )
  66. /*++
  67. Routine Description:
  68. This routine creates and initializes a device context structure.
  69. Arguments:
  70. DriverObject - pointer to the IO subsystem supplied driver object.
  71. Device - Pointer to a pointer to a transport device context object.
  72. DeviceName - pointer to the name of the device this device object points to.
  73. Return Value:
  74. STATUS_SUCCESS if all is well; STATUS_INSUFFICIENT_RESOURCES otherwise.
  75. --*/
  76. {
  77. NTSTATUS status;
  78. PDEVICE_OBJECT deviceObject;
  79. PDEVICE Device;
  80. ULONG DeviceSize;
  81. UINT i;
  82. //
  83. // Create the device object for the sample transport, allowing
  84. // room at the end for the device name to be stored (for use
  85. // in logging errors) and the RIP fields.
  86. //
  87. DeviceSize = sizeof(DEVICE) - sizeof(DEVICE_OBJECT) +
  88. DeviceName->Length + sizeof(UNICODE_NULL);
  89. status = IoCreateDevice(
  90. DriverObject,
  91. DeviceSize,
  92. DeviceName,
  93. FILE_DEVICE_TRANSPORT,
  94. FILE_DEVICE_SECURE_OPEN,
  95. FALSE,
  96. &deviceObject);
  97. if (!NT_SUCCESS(status)) {
  98. NB_DEBUG(DEVICE, ("Create device %ws failed %lx\n", DeviceName->Buffer, status));
  99. return status;
  100. }
  101. deviceObject->Flags |= DO_DIRECT_IO;
  102. Device = (PDEVICE)deviceObject;
  103. NB_DEBUG2 (DEVICE, ("Create device %ws succeeded %lx\n", DeviceName->Buffer, Device));
  104. //
  105. // Initialize our part of the device context.
  106. //
  107. RtlZeroMemory(((PUCHAR)Device)+sizeof(DEVICE_OBJECT), sizeof(DEVICE)-sizeof(DEVICE_OBJECT));
  108. //
  109. // Copy over the device name.
  110. //
  111. Device->DeviceString.Length = DeviceName->Length;
  112. Device->DeviceString.MaximumLength = DeviceName->Length + sizeof(WCHAR);
  113. Device->DeviceString.Buffer = (PWCHAR)(Device+1);
  114. RtlCopyMemory (Device->DeviceString.Buffer, DeviceName->Buffer, DeviceName->Length);
  115. Device->DeviceString.Buffer[DeviceName->Length/sizeof(WCHAR)] = UNICODE_NULL;
  116. //
  117. // Initialize the reference count.
  118. //
  119. Device->ReferenceCount = 1;
  120. #if DBG
  121. Device->RefTypes[DREF_CREATE] = 1;
  122. #endif
  123. #if DBG
  124. RtlCopyMemory(Device->Signature1, "NDC1", 4);
  125. RtlCopyMemory(Device->Signature2, "NDC2", 4);
  126. #endif
  127. Device->Information.Version = 0x0100;
  128. Device->Information.MaxSendSize = 65535;
  129. Device->Information.MaxConnectionUserData = 0;
  130. Device->Information.MaxDatagramSize = 500;
  131. Device->Information.ServiceFlags =
  132. TDI_SERVICE_CONNECTION_MODE | TDI_SERVICE_ERROR_FREE_DELIVERY |
  133. TDI_SERVICE_MULTICAST_SUPPORTED | TDI_SERVICE_BROADCAST_SUPPORTED |
  134. TDI_SERVICE_DELAYED_ACCEPTANCE | TDI_SERVICE_CONNECTIONLESS_MODE |
  135. TDI_SERVICE_MESSAGE_MODE | TDI_SERVICE_FORCE_ACCESS_CHECK;
  136. Device->Information.MinimumLookaheadData = 128;
  137. Device->Information.MaximumLookaheadData = 1500;
  138. Device->Information.NumberOfResources = 0;
  139. KeQuerySystemTime (&Device->Information.StartTime);
  140. Device->Statistics.Version = 0x0100;
  141. Device->Statistics.MaximumSendWindow = 4;
  142. Device->Statistics.AverageSendWindow = 4;
  143. #ifdef _PNP_POWER_
  144. Device->NetAddressRegistrationHandle = NULL; // We have not yet registered the Net Address
  145. #endif // _PNP_POWER_
  146. //
  147. // Set this so we won't ignore the broadcast name.
  148. //
  149. Device->AddressCounts['*'] = 1;
  150. //
  151. // Initialize the resource that guards address ACLs.
  152. //
  153. ExInitializeResourceLite (&Device->AddressResource);
  154. //
  155. // initialize the various fields in the device context
  156. //
  157. CTEInitLock (&Device->Interlock.Lock);
  158. CTEInitLock (&Device->Lock.Lock);
  159. CTEInitTimer (&Device->FindNameTimer);
  160. Device->ControlChannelIdentifier = 1;
  161. InitializeListHead (&Device->GlobalSendPacketList);
  162. InitializeListHead (&Device->GlobalReceivePacketList);
  163. InitializeListHead (&Device->GlobalReceiveBufferList);
  164. InitializeListHead (&Device->AddressDatabase);
  165. #if defined(_PNP_POWER)
  166. InitializeListHead (&Device->AdapterAddressDatabase);
  167. #endif _PNP_POWER
  168. InitializeListHead (&Device->WaitingFindNames);
  169. InitializeListHead (&Device->WaitingConnects);
  170. InitializeListHead (&Device->WaitingDatagrams);
  171. InitializeListHead (&Device->WaitingAdapterStatus);
  172. InitializeListHead (&Device->ActiveAdapterStatus);
  173. InitializeListHead (&Device->WaitingNetbiosFindName);
  174. InitializeListHead (&Device->ReceiveDatagrams);
  175. InitializeListHead (&Device->ConnectIndicationInProgress);
  176. InitializeListHead (&Device->ListenQueue);
  177. InitializeListHead (&Device->ReceiveCompletionQueue);
  178. InitializeListHead (&Device->WaitPacketConnections);
  179. InitializeListHead (&Device->PacketizeConnections);
  180. InitializeListHead (&Device->DataAckConnections);
  181. Device->MemoryUsage = 0;
  182. InitializeListHead (&Device->SendPoolList);
  183. InitializeListHead (&Device->ReceivePoolList);
  184. InitializeListHead (&Device->ReceiveBufferPoolList);
  185. ExInitializeSListHead( &Device->SendPacketList );
  186. ExInitializeSListHead( &Device->ReceivePacketList );
  187. Device->ReceiveBufferList.Next = NULL;
  188. for (i = 0; i < CONNECTION_HASH_COUNT; i++) {
  189. Device->ConnectionHash[i].Connections = NULL;
  190. Device->ConnectionHash[i].ConnectionCount = 0;
  191. Device->ConnectionHash[i].NextConnectionId = 1;
  192. }
  193. KeQuerySystemTime (&Device->NbiStartTime);
  194. Device->State = DEVICE_STATE_CLOSED;
  195. Device->Type = NB_DEVICE_SIGNATURE;
  196. Device->Size = sizeof (DEVICE);
  197. *DevicePtr = Device;
  198. return STATUS_SUCCESS;
  199. } /* NbiCreateDevice */
  200. VOID
  201. NbiDestroyDevice(
  202. IN PDEVICE Device
  203. )
  204. /*++
  205. Routine Description:
  206. This routine destroys a device context structure.
  207. Arguments:
  208. Device - Pointer to a pointer to a transport device context object.
  209. Return Value:
  210. None.
  211. --*/
  212. {
  213. PLIST_ENTRY p;
  214. PNB_SEND_POOL SendPool;
  215. PNB_SEND_PACKET SendPacket;
  216. UINT SendPoolSize;
  217. PNB_RECEIVE_POOL ReceivePool;
  218. PNB_RECEIVE_PACKET ReceivePacket;
  219. UINT ReceivePoolSize;
  220. PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
  221. PNB_RECEIVE_BUFFER ReceiveBuffer;
  222. UINT ReceiveBufferPoolSize;
  223. ULONG HeaderLength;
  224. UINT i;
  225. NB_DEBUG2 (DEVICE, ("Destroy device %lx\n", Device));
  226. //
  227. // Take all the connectionless packets out of its pools.
  228. //
  229. HeaderLength = Device->Bind.MacHeaderNeeded + sizeof(NB_CONNECTIONLESS);
  230. SendPoolSize = FIELD_OFFSET (NB_SEND_POOL, Packets[0]) +
  231. (sizeof(NB_SEND_PACKET) * Device->InitPackets) +
  232. (HeaderLength * Device->InitPackets);
  233. while (!IsListEmpty (&Device->SendPoolList)) {
  234. p = RemoveHeadList (&Device->SendPoolList);
  235. SendPool = CONTAINING_RECORD (p, NB_SEND_POOL, Linkage);
  236. for (i = 0; i < SendPool->PacketCount; i++) {
  237. SendPacket = &SendPool->Packets[i];
  238. NbiDeinitializeSendPacket (Device, SendPacket, HeaderLength);
  239. }
  240. NB_DEBUG2 (PACKET, ("Free packet pool %lx\n", SendPool));
  241. #if !defined(NB_OWN_PACKETS)
  242. NdisFreePacketPool(SendPool->PoolHandle);
  243. #endif
  244. NbiFreeMemory (SendPool, SendPoolSize, MEMORY_PACKET, "SendPool");
  245. }
  246. ReceivePoolSize = FIELD_OFFSET (NB_RECEIVE_POOL, Packets[0]) +
  247. (sizeof(NB_RECEIVE_PACKET) * Device->InitPackets);
  248. while (!IsListEmpty (&Device->ReceivePoolList)) {
  249. p = RemoveHeadList (&Device->ReceivePoolList);
  250. ReceivePool = CONTAINING_RECORD (p, NB_RECEIVE_POOL, Linkage);
  251. for (i = 0; i < ReceivePool->PacketCount; i++) {
  252. ReceivePacket = &ReceivePool->Packets[i];
  253. NbiDeinitializeReceivePacket (Device, ReceivePacket);
  254. }
  255. NB_DEBUG2 (PACKET, ("Free packet pool %lx\n", ReceivePool));
  256. #if !defined(NB_OWN_PACKETS)
  257. NdisFreePacketPool(ReceivePool->PoolHandle);
  258. #endif
  259. NbiFreeMemory (ReceivePool, ReceivePoolSize, MEMORY_PACKET, "ReceivePool");
  260. }
  261. #if defined(_PNP_POWER)
  262. NbiDestroyReceiveBufferPools( Device );
  263. //
  264. // Destroy adapter address list.
  265. //
  266. while(!IsListEmpty( &Device->AdapterAddressDatabase ) ){
  267. PADAPTER_ADDRESS AdapterAddress;
  268. AdapterAddress = CONTAINING_RECORD( Device->AdapterAddressDatabase.Flink, ADAPTER_ADDRESS, Linkage );
  269. NbiDestroyAdapterAddress( AdapterAddress, NULL );
  270. }
  271. #else
  272. ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
  273. (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
  274. (Device->Bind.LineInfo.MaximumPacketSize * Device->InitPackets);
  275. while (!IsListEmpty (&Device->ReceiveBufferPoolList)) {
  276. p = RemoveHeadList (&Device->ReceiveBufferPoolList);
  277. ReceiveBufferPool = CONTAINING_RECORD (p, NB_RECEIVE_BUFFER_POOL, Linkage);
  278. for (i = 0; i < ReceiveBufferPool->BufferCount; i++) {
  279. ReceiveBuffer = &ReceiveBufferPool->Buffers[i];
  280. NbiDeinitializeReceiveBuffer (Device, ReceiveBuffer);
  281. }
  282. NB_DEBUG2 (PACKET, ("Free buffer pool %lx\n", ReceiveBufferPool));
  283. NbiFreeMemory (ReceiveBufferPool, ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
  284. }
  285. #endif _PNP_POWER
  286. NB_DEBUG (DEVICE, ("Final memory use is %d\n", Device->MemoryUsage));
  287. #if DBG
  288. for (i = 0; i < MEMORY_MAX; i++) {
  289. if (NbiMemoryTag[i].BytesAllocated != 0) {
  290. NB_DEBUG (DEVICE, ("Tag %d: %d bytes left\n", i, NbiMemoryTag[i].BytesAllocated));
  291. }
  292. }
  293. #endif
  294. //
  295. // If we are being unloaded then someone is waiting for this
  296. // event to finish the cleanup, since we may be at DISPATCH_LEVEL;
  297. // otherwise it is during load and we can just kill ourselves here.
  298. //
  299. if (Device->UnloadWaiting) {
  300. KeSetEvent(
  301. &Device->UnloadEvent,
  302. 0L,
  303. FALSE);
  304. } else {
  305. CTEAssert (KeGetCurrentIrql() < DISPATCH_LEVEL);
  306. ExDeleteResourceLite (&Device->AddressResource);
  307. IoDeleteDevice ((PDEVICE_OBJECT)Device);
  308. }
  309. } /* NbiDestroyDevice */