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.

1959 lines
51 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. driver.c
  5. Abstract:
  6. This module contains the DriverEntry and other initialization
  7. code for the Netbios module of the ISN transport.
  8. Author:
  9. Adam Barr (adamba) 16-November-1993
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. PDEVICE NbiDevice = NULL;
  20. HANDLE TdiProviderHandle = NULL;
  21. #ifdef BIND_FIX
  22. HANDLE TdiClientHandle = NULL;
  23. PDRIVER_OBJECT NbiDriverObject = NULL;
  24. UNICODE_STRING NbiRegistryPath;
  25. PEPROCESS NbiFspProcess;
  26. UNICODE_STRING NbiBindString;
  27. EXTERNAL_LOCK(NbiTdiRequestInterlock);
  28. extern LIST_ENTRY NbiTdiRequestList;
  29. WCHAR BIND_STRING_NAME[50] = L"\\Device\\NwlnkIpx";
  30. VOID
  31. NbiUnbindFromIpx(
  32. );
  33. #endif // BIND_FIX
  34. DEFINE_LOCK_STRUCTURE(NbiGlobalPoolInterlock);
  35. #ifdef RSRC_TIMEOUT_DBG
  36. // RSRC_TIMEOUT_DBG is currently not defined!
  37. ULONG NbiGlobalDebugResTimeout = 1;
  38. LARGE_INTEGER NbiGlobalMaxResTimeout;
  39. // the packet is allocated from ndis pool.
  40. NB_SEND_PACKET NbiGlobalDeathPacket; // try to use this first for sends
  41. UCHAR NbiGlobalDeathPacketHeader[100];
  42. VOID
  43. NbiInitDeathPacket()
  44. {
  45. NDIS_HANDLE PoolHandle; // poolhandle for sendpacket below when
  46. NTSTATUS Status;
  47. //
  48. // if we are using ndis packets, first create packet pool for 1 packet descriptor
  49. //
  50. PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NWLNKNB; // Dbg info for Ndis!
  51. NdisAllocatePacketPoolEx (&Status, &PoolHandle, 1, 0, sizeof(NB_SEND_RESERVED));
  52. if (!NT_SUCCESS(Status)){
  53. DbgPrint("Could not allocatee death packet %lx\n", Status);
  54. NbiGlobalDebugResTimeout = 0;
  55. } else {
  56. NdisSetPacketPoolProtocolId (PoolHandle, NDIS_PROTOCOL_ID_IPX);
  57. if (NbiInitializeSendPacket(
  58. NbiDevice,
  59. PoolHandle,
  60. &NbiGlobalDeathPacket,
  61. NbiGlobalDeathPacketHeader,
  62. NbiDevice->Bind.MacHeaderNeeded + sizeof(NB_CONNECTION)) != STATUS_SUCCESS) {
  63. DbgPrint("Could not allocatee death packet %lx\n", Status);
  64. NbiGlobalDebugResTimeout = 0;
  65. //
  66. // Also free up the pool which we allocated above.
  67. //
  68. NdisFreePacketPool(PoolHandle);
  69. }
  70. }
  71. }
  72. #endif //RSRC_TIMEOUT_DBG
  73. #if DBG
  74. ULONG NbiDebug = 0xffffffff;
  75. ULONG NbiDebug2 = 0x00000000;
  76. ULONG NbiMemoryDebug = 0x0002482c;
  77. UCHAR NbiTempDebugBuffer[TEMP_BUF_LEN];
  78. UCHAR NbiDebugMemory [NB_MEMORY_LOG_SIZE][MAX_ARGLEN];
  79. PUCHAR NbiDebugMemoryLoc = NbiDebugMemory[0];
  80. PUCHAR NbiDebugMemoryEnd = NbiDebugMemory[NB_MEMORY_LOG_SIZE];
  81. DEFINE_LOCK_STRUCTURE(NbiDebugLogLock);
  82. VOID
  83. NbiDebugMemoryLog(
  84. IN PUCHAR FormatString,
  85. ...
  86. )
  87. {
  88. INT ArgLen;
  89. va_list ArgumentPointer;
  90. PUCHAR DebugMemoryLoc;
  91. CTELockHandle LockHandle;
  92. va_start(ArgumentPointer, FormatString);
  93. //
  94. // To avoid any overflows, copy this in a temp buffer first.
  95. RtlZeroMemory (NbiTempDebugBuffer, TEMP_BUF_LEN);
  96. ArgLen = vsprintf(NbiTempDebugBuffer, FormatString, ArgumentPointer);
  97. va_end(ArgumentPointer);
  98. if (ArgLen > MAX_ARGLEN)
  99. {
  100. ArgLen = MAX_ARGLEN;
  101. }
  102. CTEGetLock (&NbiDebugLogLock, &LockHandle);
  103. DebugMemoryLoc = NbiDebugMemoryLoc;
  104. NbiDebugMemoryLoc += MAX_ARGLEN;
  105. if (NbiDebugMemoryLoc >= NbiDebugMemoryEnd)
  106. {
  107. NbiDebugMemoryLoc = NbiDebugMemory[0];
  108. }
  109. CTEFreeLock (&NbiDebugLogLock, LockHandle);
  110. RtlZeroMemory (NbiDebugMemoryLoc, MAX_ARGLEN);
  111. RtlCopyMemory( NbiDebugMemoryLoc, NbiTempDebugBuffer, ArgLen);
  112. } /* NbiDebugMemoryLog */
  113. DEFINE_LOCK_STRUCTURE(NbiMemoryInterlock);
  114. MEMORY_TAG NbiMemoryTag[MEMORY_MAX];
  115. #endif
  116. //
  117. // This is used only for CHK build. For
  118. // tracking the refcount problem on connection, this
  119. // is moved here for now.
  120. //
  121. DEFINE_LOCK_STRUCTURE(NbiGlobalInterlock);
  122. #ifdef RASAUTODIAL
  123. VOID
  124. NbiAcdBind();
  125. VOID
  126. NbiAcdUnbind();
  127. #endif
  128. #ifdef NB_PACKET_LOG
  129. ULONG NbiPacketLogDebug = NB_PACKET_LOG_RCV_OTHER | NB_PACKET_LOG_SEND_OTHER;
  130. USHORT NbiPacketLogSocket = 0;
  131. DEFINE_LOCK_STRUCTURE(NbiPacketLogLock);
  132. NB_PACKET_LOG_ENTRY NbiPacketLog[NB_PACKET_LOG_LENGTH];
  133. PNB_PACKET_LOG_ENTRY NbiPacketLogLoc = NbiPacketLog;
  134. PNB_PACKET_LOG_ENTRY NbiPacketLogEnd = &NbiPacketLog[NB_PACKET_LOG_LENGTH];
  135. VOID
  136. NbiLogPacket(
  137. IN BOOLEAN Send,
  138. IN PUCHAR DestMac,
  139. IN PUCHAR SrcMac,
  140. IN USHORT Length,
  141. IN PVOID NbiHeader,
  142. IN PVOID Data
  143. )
  144. {
  145. CTELockHandle LockHandle;
  146. PNB_PACKET_LOG_ENTRY PacketLog;
  147. LARGE_INTEGER TickCount;
  148. ULONG DataLength;
  149. CTEGetLock (&NbiPacketLogLock, &LockHandle);
  150. PacketLog = NbiPacketLogLoc;
  151. ++NbiPacketLogLoc;
  152. if (NbiPacketLogLoc >= NbiPacketLogEnd) {
  153. NbiPacketLogLoc = NbiPacketLog;
  154. }
  155. *(UNALIGNED ULONG *)NbiPacketLogLoc->TimeStamp = 0x3e3d3d3d; // "===>"
  156. CTEFreeLock (&NbiPacketLogLock, LockHandle);
  157. RtlZeroMemory (PacketLog, sizeof(NB_PACKET_LOG_ENTRY));
  158. PacketLog->SendReceive = Send ? '>' : '<';
  159. KeQueryTickCount(&TickCount);
  160. _itoa (TickCount.LowPart % 100000, PacketLog->TimeStamp, 10);
  161. RtlCopyMemory(PacketLog->DestMac, DestMac, 6);
  162. RtlCopyMemory(PacketLog->SrcMac, SrcMac, 6);
  163. PacketLog->Length[0] = Length / 256;
  164. PacketLog->Length[1] = Length % 256;
  165. if (Length < sizeof(IPX_HEADER)) {
  166. RtlCopyMemory(&PacketLog->NbiHeader, NbiHeader, Length);
  167. } else {
  168. RtlCopyMemory(&PacketLog->NbiHeader, NbiHeader, sizeof(IPX_HEADER));
  169. }
  170. DataLength = Length - sizeof(IPX_HEADER);
  171. if (DataLength < 14) {
  172. RtlCopyMemory(PacketLog->Data, Data, DataLength);
  173. } else {
  174. RtlCopyMemory(PacketLog->Data, Data, 14);
  175. }
  176. } /* NbiLogPacket */
  177. #endif // NB_PACKET_LOG
  178. //
  179. // Forward declaration of various routines used in this module.
  180. //
  181. NTSTATUS
  182. DriverEntry(
  183. IN PDRIVER_OBJECT DriverObject,
  184. IN PUNICODE_STRING RegistryPath
  185. );
  186. VOID
  187. NbiUnload(
  188. IN PDRIVER_OBJECT DriverObject
  189. );
  190. NTSTATUS
  191. NbiDispatchDeviceControl(
  192. IN PDEVICE_OBJECT DeviceObject,
  193. IN PIRP Irp
  194. );
  195. NTSTATUS
  196. NbiDispatchOpenClose(
  197. IN PDEVICE_OBJECT DeviceObject,
  198. IN PIRP Irp
  199. );
  200. NTSTATUS
  201. NbiDispatchInternal (
  202. IN PDEVICE_OBJECT DeviceObject,
  203. IN PIRP Irp
  204. );
  205. NTSTATUS
  206. NbiDispatchPnP(
  207. IN PDEVICE_OBJECT Device,
  208. IN PIRP pIrp
  209. );
  210. VOID
  211. NbiFreeResources (
  212. IN PVOID Adapter
  213. );
  214. #ifdef ALLOC_PRAGMA
  215. #pragma alloc_text(INIT,DriverEntry)
  216. #endif
  217. //
  218. // This prevents us from having a bss section.
  219. //
  220. ULONG _setjmpexused = 0;
  221. //
  222. // These two are used in various places in the driver.
  223. //
  224. #if defined(_PNP_POWER)
  225. IPX_LOCAL_TARGET BroadcastTarget = { {ITERATIVE_NIC_ID}, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
  226. #endif _PNP_POWER
  227. UCHAR BroadcastAddress[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  228. UCHAR NetbiosBroadcastName[16] = { '*', 0, 0, 0, 0, 0, 0, 0,
  229. 0, 0, 0, 0, 0, 0, 0, 0 };
  230. ULONG NbiFailLoad = FALSE;
  231. NTSTATUS
  232. DriverEntry(
  233. IN PDRIVER_OBJECT DriverObject,
  234. IN PUNICODE_STRING RegistryPath
  235. )
  236. /*++
  237. Routine Description:
  238. This routine performs initialization of the Netbios ISN module.
  239. It creates the device objects for the transport
  240. provider and performs other driver initialization.
  241. Arguments:
  242. DriverObject - Pointer to driver object created by the system.
  243. RegistryPath - The name of Netbios's node in the registry.
  244. Return Value:
  245. The function value is the final status from the initialization operation.
  246. --*/
  247. {
  248. NTSTATUS status;
  249. #ifdef BIND_FIX
  250. WCHAR wcNwlnkNbClientName[60] = L"NwlnkNb";
  251. UNICODE_STRING ucNwlnkNbClientName;
  252. TDI_CLIENT_INTERFACE_INFO TdiClientInterface;
  253. #else
  254. static const NDIS_STRING ProtocolName = NDIS_STRING_CONST("Netbios/IPX Transport");
  255. PDEVICE Device;
  256. PIPX_HEADER IpxHeader;
  257. CTELockHandle LockHandle;
  258. PCONFIG Config = NULL;
  259. WCHAR wcNwlnkNbProviderName[60] = L"\\Device\\NwlnkNb";
  260. UNICODE_STRING ucNwlnkNbProviderName;
  261. #endif // !BIND_FIX
  262. //
  263. // Initialize the Common Transport Environment.
  264. //
  265. if (CTEInitialize() == 0) {
  266. NB_DEBUG (DEVICE, ("CTEInitialize() failed\n"));
  267. NbiWriteGeneralErrorLog(
  268. (PVOID)DriverObject,
  269. EVENT_TRANSPORT_REGISTER_FAILED,
  270. 101,
  271. STATUS_UNSUCCESSFUL,
  272. NULL,
  273. 0,
  274. NULL);
  275. return STATUS_UNSUCCESSFUL;
  276. }
  277. #if DBG
  278. CTEInitLock (&NbiGlobalInterlock);
  279. CTEInitLock (&NbiMemoryInterlock);
  280. {
  281. UINT i;
  282. for (i = 0; i < MEMORY_MAX; i++) {
  283. NbiMemoryTag[i].Tag = i;
  284. NbiMemoryTag[i].BytesAllocated = 0;
  285. }
  286. }
  287. #endif
  288. #ifdef NB_PACKET_LOG
  289. CTEInitLock (&NbiPacketLogLock);
  290. #endif
  291. #if DBG
  292. CTEInitLock( &NbiDebugLogLock);
  293. #endif
  294. #if defined(NB_OWN_PACKETS)
  295. CTEAssert (NDIS_PACKET_SIZE == FIELD_OFFSET(NDIS_PACKET, ProtocolReserved[0]));
  296. #endif
  297. NB_DEBUG2 (DEVICE, ("ISN Netbios loaded\n"));
  298. #ifdef BIND_FIX
  299. //
  300. // Initialize the driver object with this driver's entry points.
  301. //
  302. DriverObject->MajorFunction [IRP_MJ_CREATE] = NbiDispatchOpenClose;
  303. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = NbiDispatchDeviceControl;
  304. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL]= NbiDispatchInternal;
  305. DriverObject->MajorFunction [IRP_MJ_CLEANUP] = NbiDispatchOpenClose;
  306. DriverObject->MajorFunction [IRP_MJ_CLOSE] = NbiDispatchOpenClose;
  307. DriverObject->MajorFunction [IRP_MJ_PNP] = NbiDispatchPnP;
  308. DriverObject->DriverUnload = NbiUnload;
  309. NbiDevice = NULL;
  310. NbiDriverObject = DriverObject;
  311. RtlInitUnicodeString(&NbiBindString, BIND_STRING_NAME);
  312. InitializeListHead(&NbiTdiRequestList);
  313. CTEInitLock (&NbiTdiRequestInterlock);
  314. //
  315. // Save the registry path
  316. //
  317. NbiRegistryPath.Buffer = (PWCHAR) NbiAllocateMemory (RegistryPath->Length + sizeof(WCHAR),
  318. MEMORY_CONFIG, "RegistryPathBuffer");
  319. if (NbiRegistryPath.Buffer == NULL) {
  320. NbiWriteResourceErrorLog ((PVOID)DriverObject, RegistryPath->Length + sizeof(WCHAR), MEMORY_CONFIG);
  321. return STATUS_INSUFFICIENT_RESOURCES;
  322. }
  323. RtlCopyMemory (NbiRegistryPath.Buffer, RegistryPath->Buffer, RegistryPath->Length);
  324. NbiRegistryPath.Buffer[RegistryPath->Length/sizeof(WCHAR)] = UNICODE_NULL;
  325. NbiRegistryPath.Length = RegistryPath->Length;
  326. NbiRegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
  327. NbiFspProcess =(PEPROCESS)PsGetCurrentProcess();
  328. //
  329. // Make Tdi ready for pnp notifications before binding to IPX
  330. //
  331. TdiInitialize();
  332. //
  333. // Register our Handlers with TDI
  334. //
  335. RtlInitUnicodeString(&ucNwlnkNbClientName, wcNwlnkNbClientName);
  336. ucNwlnkNbClientName.MaximumLength = sizeof (wcNwlnkNbClientName);
  337. RtlZeroMemory(&TdiClientInterface, sizeof(TdiClientInterface));
  338. TdiClientInterface.MajorTdiVersion = MAJOR_TDI_VERSION;
  339. TdiClientInterface.MinorTdiVersion = MINOR_TDI_VERSION;
  340. TdiClientInterface.ClientName = &ucNwlnkNbClientName;
  341. TdiClientInterface.BindingHandler = TdiBindHandler;
  342. if (!NT_SUCCESS(TdiRegisterPnPHandlers(&TdiClientInterface,sizeof(TdiClientInterface),&TdiClientHandle)))
  343. {
  344. TdiClientHandle = NULL;
  345. DbgPrint("Nbi.DriverEntry: FAILed to Register NwlnkNb as Client!\n");
  346. }
  347. #else
  348. //
  349. // This allocates the CONFIG structure and returns
  350. // it in Config.
  351. //
  352. status = NbiGetConfiguration(DriverObject, RegistryPath, &Config);
  353. if (!NT_SUCCESS (status)) {
  354. //
  355. // If it failed it logged an error.
  356. //
  357. PANIC (" Failed to initialize transport, ISN Netbios initialization failed.\n");
  358. return status;
  359. }
  360. //
  361. // Initialize the driver object with this driver's entry points.
  362. //
  363. DriverObject->MajorFunction [IRP_MJ_CREATE] = NbiDispatchOpenClose;
  364. DriverObject->MajorFunction [IRP_MJ_CLOSE] = NbiDispatchOpenClose;
  365. DriverObject->MajorFunction [IRP_MJ_CLEANUP] = NbiDispatchOpenClose;
  366. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = NbiDispatchInternal;
  367. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = NbiDispatchDeviceControl;
  368. DriverObject->DriverUnload = NbiUnload;
  369. //
  370. // Create the device object which exports our name.
  371. //
  372. status = NbiCreateDevice (DriverObject, &Config->DeviceName, &Device);
  373. if (!NT_SUCCESS (status)) {
  374. NbiWriteGeneralErrorLog(
  375. (PVOID)DriverObject,
  376. EVENT_IPX_CREATE_DEVICE,
  377. 801,
  378. status,
  379. NULL,
  380. 0,
  381. NULL);
  382. NbiFreeConfiguration(Config);
  383. return status;
  384. }
  385. NbiDevice = Device;
  386. //
  387. // Initialize the global pool interlock
  388. //
  389. CTEInitLock (&NbiGlobalPoolInterlock);
  390. //
  391. // Save the relevant configuration parameters.
  392. //
  393. Device->AckDelayTime = (Config->Parameters[CONFIG_ACK_DELAY_TIME] / SHORT_TIMER_DELTA) + 1;
  394. Device->AckWindow = Config->Parameters[CONFIG_ACK_WINDOW];
  395. Device->AckWindowThreshold = Config->Parameters[CONFIG_ACK_WINDOW_THRESHOLD];
  396. Device->EnablePiggyBackAck = Config->Parameters[CONFIG_ENABLE_PIGGYBACK_ACK];
  397. Device->Extensions = Config->Parameters[CONFIG_EXTENSIONS];
  398. Device->RcvWindowMax = Config->Parameters[CONFIG_RCV_WINDOW_MAX];
  399. Device->BroadcastCount = Config->Parameters[CONFIG_BROADCAST_COUNT];
  400. Device->BroadcastTimeout = Config->Parameters[CONFIG_BROADCAST_TIMEOUT];
  401. Device->ConnectionCount = Config->Parameters[CONFIG_CONNECTION_COUNT];
  402. Device->ConnectionTimeout = Config->Parameters[CONFIG_CONNECTION_TIMEOUT] * 500;
  403. Device->InitPackets = Config->Parameters[CONFIG_INIT_PACKETS];
  404. Device->MaxPackets = Config->Parameters[CONFIG_MAX_PACKETS];
  405. Device->InitialRetransmissionTime = Config->Parameters[CONFIG_INIT_RETRANSMIT_TIME];
  406. Device->Internet = Config->Parameters[CONFIG_INTERNET];
  407. Device->KeepAliveCount = Config->Parameters[CONFIG_KEEP_ALIVE_COUNT];
  408. Device->KeepAliveTimeout = Config->Parameters[CONFIG_KEEP_ALIVE_TIMEOUT];
  409. Device->RetransmitMax = Config->Parameters[CONFIG_RETRANSMIT_MAX];
  410. Device->RouterMtu = Config->Parameters[CONFIG_ROUTER_MTU];
  411. Device->FindNameTimeout =
  412. ((Config->Parameters[CONFIG_BROADCAST_TIMEOUT]) + (FIND_NAME_GRANULARITY/2)) /
  413. FIND_NAME_GRANULARITY;
  414. Device->MaxReceiveBuffers = 20; // Make it configurable?
  415. Device->NameCache = NULL; // MP bug: IPX tries to Flush it before it's initialized!
  416. //
  417. // Create Hash Table to store netbios cache entries
  418. // For server create a big table, for workstation a small one
  419. //
  420. if (MmIsThisAnNtAsSystem())
  421. {
  422. status = CreateNetbiosCacheTable( &Device->NameCache, NB_NETBIOS_CACHE_TABLE_LARGE );
  423. }
  424. else
  425. {
  426. status = CreateNetbiosCacheTable( &Device->NameCache, NB_NETBIOS_CACHE_TABLE_SMALL );
  427. }
  428. if (!NT_SUCCESS (status))
  429. {
  430. //
  431. // If it failed it logged an error.
  432. //
  433. NbiFreeConfiguration(Config);
  434. NbiDereferenceDevice (Device, DREF_LOADED);
  435. return status;
  436. }
  437. //
  438. // Make Tdi ready for pnp notifications before binding to IPX
  439. //
  440. TdiInitialize();
  441. // Initialize the timer system. This should be done before
  442. // binding to ipx because we should have timers intialized
  443. // before ipx calls our pnp indications.
  444. NbiInitializeTimers (Device);
  445. //
  446. // Register us as a provider with Tdi
  447. //
  448. RtlInitUnicodeString(&ucNwlnkNbProviderName, wcNwlnkNbProviderName);
  449. ucNwlnkNbProviderName.MaximumLength = sizeof (wcNwlnkNbProviderName);
  450. if (!NT_SUCCESS (TdiRegisterProvider (&ucNwlnkNbProviderName, &TdiProviderHandle)))
  451. {
  452. TdiProviderHandle = NULL;
  453. }
  454. //
  455. // Now bind to IPX via the internal interface.
  456. //
  457. status = NbiBind (Device, Config);
  458. if (!NT_SUCCESS (status)) {
  459. //
  460. // If it failed it logged an error.
  461. //
  462. if (TdiProviderHandle)
  463. {
  464. TdiDeregisterProvider (TdiProviderHandle);
  465. }
  466. NbiFreeConfiguration(Config);
  467. NbiDereferenceDevice (Device, DREF_LOADED);
  468. return status;
  469. }
  470. #ifdef RSRC_TIMEOUT_DBG
  471. NbiInitDeathPacket();
  472. // NbiGlobalMaxResTimeout.QuadPart = 50; // 1*1000*10000;
  473. NbiGlobalMaxResTimeout.QuadPart = 20*60*1000;
  474. NbiGlobalMaxResTimeout.QuadPart *= 10000;
  475. #endif // RSRC_TIMEOUT_DBG
  476. NB_GET_LOCK (&Device->Lock, &LockHandle);
  477. //
  478. // Allocate our initial connectionless packet pool.
  479. //
  480. NbiAllocateSendPool (Device);
  481. //
  482. // Allocate our initial receive packet pool.
  483. //
  484. NbiAllocateReceivePool (Device);
  485. //
  486. // Allocate our initial receive buffer pool.
  487. //
  488. //
  489. #if defined(_PNP_POWER)
  490. if ( DEVICE_STATE_CLOSED == Device->State ) {
  491. Device->State = DEVICE_STATE_LOADED;
  492. }
  493. #endif _PNP_POWER
  494. NB_FREE_LOCK (&Device->Lock, LockHandle);
  495. //
  496. // Fill in the default connnectionless header.
  497. //
  498. IpxHeader = &Device->ConnectionlessHeader;
  499. IpxHeader->CheckSum = 0xffff;
  500. IpxHeader->PacketLength[0] = 0;
  501. IpxHeader->PacketLength[1] = 0;
  502. IpxHeader->TransportControl = 0;
  503. IpxHeader->PacketType = 0;
  504. *(UNALIGNED ULONG *)(IpxHeader->DestinationNetwork) = 0;
  505. RtlCopyMemory(IpxHeader->DestinationNode, BroadcastAddress, 6);
  506. IpxHeader->DestinationSocket = NB_SOCKET;
  507. IpxHeader->SourceSocket = NB_SOCKET;
  508. #ifdef RASAUTODIAL
  509. //
  510. // Get the automatic connection
  511. // driver entry points.
  512. //
  513. NbiAcdBind();
  514. #endif
  515. NbiFreeConfiguration(Config);
  516. #endif // BIND_FIX
  517. return STATUS_SUCCESS;
  518. } /* DriverEntry */
  519. VOID
  520. NbiUnload(
  521. IN PDRIVER_OBJECT DriverObject
  522. )
  523. /*++
  524. Routine Description:
  525. This routine unloads the sample transport driver.
  526. It unbinds from any NDIS drivers that are open and frees all resources
  527. associated with the transport. The I/O system will not call us until
  528. nobody above has Netbios open.
  529. Arguments:
  530. DriverObject - Pointer to driver object created by the system.
  531. Return Value:
  532. None. When the function returns, the driver is unloaded.
  533. --*/
  534. {
  535. #ifdef BIND_FIX
  536. UNREFERENCED_PARAMETER (DriverObject);
  537. if (TdiClientHandle)
  538. {
  539. TdiDeregisterPnPHandlers (TdiClientHandle);
  540. TdiClientHandle = NULL;
  541. }
  542. if (TdiProviderHandle)
  543. {
  544. TdiDeregisterProvider (TdiProviderHandle);
  545. }
  546. if (NbiBindState & NBI_BOUND_TO_IPX)
  547. {
  548. NbiUnbindFromIpx();
  549. }
  550. NbiFreeMemory (NbiRegistryPath.Buffer, NbiRegistryPath.MaximumLength,MEMORY_CONFIG,"RegistryPathBuffer");
  551. #else
  552. PNETBIOS_CACHE CacheName;
  553. PDEVICE Device = NbiDevice;
  554. PLIST_ENTRY p;
  555. UNREFERENCED_PARAMETER (DriverObject);
  556. #ifdef RASAUTODIAL
  557. //
  558. // Unbind from the
  559. // automatic connection driver.
  560. //
  561. NbiAcdUnbind();
  562. #endif
  563. Device->State = DEVICE_STATE_STOPPING;
  564. //
  565. // Cancel the long timer.
  566. //
  567. if (CTEStopTimer (&Device->LongTimer)) {
  568. NbiDereferenceDevice (Device, DREF_LONG_TIMER);
  569. }
  570. //
  571. // Unbind from the IPX driver.
  572. //
  573. NbiUnbind (Device);
  574. //
  575. // This event will get set when the reference count
  576. // drops to 0.
  577. //
  578. KeInitializeEvent(
  579. &Device->UnloadEvent,
  580. NotificationEvent,
  581. FALSE);
  582. Device->UnloadWaiting = TRUE;
  583. //
  584. // Remove the reference for us being loaded.
  585. //
  586. NbiDereferenceDevice (Device, DREF_LOADED);
  587. //
  588. // Wait for our count to drop to zero.
  589. //
  590. KeWaitForSingleObject(
  591. &Device->UnloadEvent,
  592. Executive,
  593. KernelMode,
  594. TRUE,
  595. (PLARGE_INTEGER)NULL
  596. );
  597. //
  598. // Free the cache of netbios names.
  599. //
  600. DestroyNetbiosCacheTable( Device->NameCache );
  601. //
  602. // Do the cleanup that has to happen at IRQL 0.
  603. //
  604. ExDeleteResource (&Device->AddressResource);
  605. IoDeleteDevice ((PDEVICE_OBJECT)Device);
  606. if (TdiProviderHandle)
  607. {
  608. TdiDeregisterProvider (TdiProviderHandle);
  609. }
  610. #endif // BIND_FIX
  611. } /* NbiUnload */
  612. VOID
  613. NbiFreeResources (
  614. IN PVOID Adapter
  615. )
  616. /*++
  617. Routine Description:
  618. This routine is called by Netbios to clean up the data structures associated
  619. with a given Device. When this routine exits, the Device
  620. should be deleted as it no longer has any assocaited resources.
  621. Arguments:
  622. Device - Pointer to the Device we wish to clean up.
  623. Return Value:
  624. None.
  625. --*/
  626. {
  627. #if 0
  628. PLIST_ENTRY p;
  629. PSINGLE_LIST_ENTRY s;
  630. PTP_PACKET packet;
  631. PNDIS_PACKET ndisPacket;
  632. PBUFFER_TAG BufferTag;
  633. #endif
  634. #if 0
  635. //
  636. // Clean up packet pool.
  637. //
  638. while ( Device->PacketPool.Next != NULL ) {
  639. s = PopEntryList( &Device->PacketPool );
  640. packet = CONTAINING_RECORD( s, TP_PACKET, Linkage );
  641. NbiDeallocateSendPacket (Device, packet);
  642. }
  643. //
  644. // Clean up receive packet pool
  645. //
  646. while ( Device->ReceivePacketPool.Next != NULL) {
  647. s = PopEntryList (&Device->ReceivePacketPool);
  648. //
  649. // HACK: This works because Linkage is the first field in
  650. // ProtocolReserved for a receive packet.
  651. //
  652. ndisPacket = CONTAINING_RECORD (s, NDIS_PACKET, ProtocolReserved[0]);
  653. NbiDeallocateReceivePacket (Device, ndisPacket);
  654. }
  655. //
  656. // Clean up receive buffer pool.
  657. //
  658. while ( Device->ReceiveBufferPool.Next != NULL ) {
  659. s = PopEntryList( &Device->ReceiveBufferPool );
  660. BufferTag = CONTAINING_RECORD (s, BUFFER_TAG, Linkage );
  661. NbiDeallocateReceiveBuffer (Device, BufferTag);
  662. }
  663. #endif
  664. } /* NbiFreeResources */
  665. NTSTATUS
  666. NbiDispatchOpenClose(
  667. IN PDEVICE_OBJECT DeviceObject,
  668. IN PIRP Irp
  669. )
  670. /*++
  671. Routine Description:
  672. This routine is the main dispatch routine for the IPXNB device driver.
  673. It accepts an I/O Request Packet, performs the request, and then
  674. returns with the appropriate status.
  675. Arguments:
  676. DeviceObject - Pointer to the device object for this driver.
  677. Irp - Pointer to the request packet representing the I/O request.
  678. Return Value:
  679. The function value is the status of the operation.
  680. --*/
  681. {
  682. CTELockHandle LockHandle;
  683. PDEVICE Device = (PDEVICE)DeviceObject;
  684. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  685. PFILE_FULL_EA_INFORMATION openType;
  686. PADDRESS_FILE AddressFile;
  687. PCONNECTION Connection;
  688. PREQUEST Request;
  689. UINT i;
  690. NB_DEFINE_LOCK_HANDLE (LockHandle1)
  691. NB_DEFINE_SYNC_CONTEXT (SyncContext)
  692. #if !defined(_PNP_POWER)
  693. if (Device->State != DEVICE_STATE_OPEN) {
  694. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  695. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  696. return STATUS_INVALID_DEVICE_STATE;
  697. }
  698. #endif !_PNP_POWER
  699. //
  700. // Allocate a request to track this IRP.
  701. //
  702. Request = NbiAllocateRequest (Device, Irp);
  703. IF_NOT_ALLOCATED(Request) {
  704. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  705. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  706. return STATUS_INSUFFICIENT_RESOURCES;
  707. }
  708. //
  709. // Make sure status information is consistent every time.
  710. //
  711. MARK_REQUEST_PENDING(Request);
  712. REQUEST_STATUS(Request) = STATUS_PENDING;
  713. REQUEST_INFORMATION(Request) = 0;
  714. //
  715. // Case on the function that is being performed by the requestor. If the
  716. // operation is a valid one for this device, then make it look like it was
  717. // successfully completed, where possible.
  718. //
  719. switch (REQUEST_MAJOR_FUNCTION(Request)) {
  720. //
  721. // The Create function opens a transport object (either address or
  722. // connection). Access checking is performed on the specified
  723. // address to ensure security of transport-layer addresses.
  724. //
  725. case IRP_MJ_CREATE:
  726. #if defined(_PNP_POWER)
  727. if (Device->State != DEVICE_STATE_OPEN) {
  728. Status = STATUS_INVALID_DEVICE_STATE;
  729. break;
  730. }
  731. #endif _PNP_POWER
  732. openType = OPEN_REQUEST_EA_INFORMATION(Request);
  733. if (openType != NULL) {
  734. if (strncmp(openType->EaName,TdiTransportAddress,openType->EaNameLength) == 0)
  735. {
  736. Status = NbiOpenAddress (Device, Request);
  737. break;
  738. }
  739. else if (strncmp(openType->EaName,TdiConnectionContext,openType->EaNameLength) == 0)
  740. {
  741. Status = NbiOpenConnection (Device, Request);
  742. break;
  743. }
  744. } else {
  745. NB_GET_LOCK (&Device->Lock, &LockHandle);
  746. REQUEST_OPEN_CONTEXT(Request) = (PVOID)(Device->ControlChannelIdentifier);
  747. ++Device->ControlChannelIdentifier;
  748. if (Device->ControlChannelIdentifier == 0) {
  749. Device->ControlChannelIdentifier = 1;
  750. }
  751. NB_FREE_LOCK (&Device->Lock, LockHandle);
  752. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_CONTROL_CHANNEL_FILE;
  753. Status = STATUS_SUCCESS;
  754. }
  755. break;
  756. case IRP_MJ_CLOSE:
  757. #if defined(_PNP_POWER)
  758. if ( (Device->State != DEVICE_STATE_OPEN) && (Device->State != DEVICE_STATE_LOADED) ) {
  759. Status = STATUS_INVALID_DEVICE_STATE;
  760. break;
  761. }
  762. #endif _PNP_POWER
  763. //
  764. // The Close function closes a transport endpoint, terminates
  765. // all outstanding transport activity on the endpoint, and unbinds
  766. // the endpoint from its transport address, if any. If this
  767. // is the last transport endpoint bound to the address, then
  768. // the address is removed from the provider.
  769. //
  770. switch ((ULONG_PTR)REQUEST_OPEN_TYPE(Request)) {
  771. case TDI_TRANSPORT_ADDRESS_FILE:
  772. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  773. //
  774. // This creates a reference to AddressFile.
  775. //
  776. #if defined(_PNP_POWER)
  777. Status = NbiVerifyAddressFile(AddressFile, CONFLICT_IS_OK);
  778. #else
  779. Status = NbiVerifyAddressFile(AddressFile);
  780. #endif _PNP_POWER
  781. if (!NT_SUCCESS (Status)) {
  782. Status = STATUS_INVALID_HANDLE;
  783. } else {
  784. Status = NbiCloseAddressFile (Device, Request);
  785. NbiDereferenceAddressFile (AddressFile, AFREF_VERIFY);
  786. }
  787. break;
  788. case TDI_CONNECTION_FILE:
  789. Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request);
  790. //
  791. // We don't call VerifyConnection because the I/O
  792. // system should only give us one close and the file
  793. // object should be valid. This helps avoid a window
  794. // where two threads call HandleConnectionZero at the
  795. // same time.
  796. //
  797. Status = NbiCloseConnection (Device, Request);
  798. break;
  799. case TDI_CONTROL_CHANNEL_FILE:
  800. //
  801. // See if it is one of the upper driver's control channels.
  802. //
  803. Status = STATUS_SUCCESS;
  804. break;
  805. default:
  806. Status = STATUS_INVALID_HANDLE;
  807. }
  808. break;
  809. case IRP_MJ_CLEANUP:
  810. #if defined(_PNP_POWER)
  811. if ( (Device->State != DEVICE_STATE_OPEN) && (Device->State != DEVICE_STATE_LOADED) ) {
  812. Status = STATUS_INVALID_DEVICE_STATE;
  813. break;
  814. }
  815. #endif _PNP_POWER
  816. //
  817. // Handle the two stage IRP for a file close operation. When the first
  818. // stage hits, run down all activity on the object of interest. This
  819. // do everything to it but remove the creation hold. Then, when the
  820. // CLOSE irp hits, actually close the object.
  821. //
  822. switch ((ULONG_PTR)REQUEST_OPEN_TYPE(Request)) {
  823. case TDI_TRANSPORT_ADDRESS_FILE:
  824. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  825. #if defined(_PNP_POWER)
  826. Status = NbiVerifyAddressFile(AddressFile, CONFLICT_IS_OK);
  827. #else
  828. Status = NbiVerifyAddressFile(AddressFile);
  829. #endif _PNP_POWER
  830. if (!NT_SUCCESS (Status)) {
  831. Status = STATUS_INVALID_HANDLE;
  832. } else {
  833. NbiStopAddressFile (AddressFile, AddressFile->Address);
  834. NbiDereferenceAddressFile (AddressFile, AFREF_VERIFY);
  835. Status = STATUS_SUCCESS;
  836. }
  837. break;
  838. case TDI_CONNECTION_FILE:
  839. Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request);
  840. Status = NbiVerifyConnection(Connection);
  841. if (!NT_SUCCESS (Status)) {
  842. Status = STATUS_INVALID_HANDLE;
  843. } else {
  844. NB_BEGIN_SYNC (&SyncContext);
  845. NB_SYNC_GET_LOCK (&Connection->Lock, &LockHandle1);
  846. //
  847. // This call releases the lock.
  848. //
  849. NbiStopConnection(
  850. Connection,
  851. STATUS_INVALID_CONNECTION
  852. NB_LOCK_HANDLE_ARG (LockHandle1));
  853. NB_END_SYNC (&SyncContext);
  854. NbiDereferenceConnection (Connection, CREF_VERIFY);
  855. Status = STATUS_SUCCESS;
  856. }
  857. break;
  858. case TDI_CONTROL_CHANNEL_FILE:
  859. Status = STATUS_SUCCESS;
  860. break;
  861. default:
  862. Status = STATUS_INVALID_HANDLE;
  863. }
  864. break;
  865. default:
  866. Status = STATUS_INVALID_DEVICE_REQUEST;
  867. } /* major function switch */
  868. if (Status != STATUS_PENDING) {
  869. UNMARK_REQUEST_PENDING(Request);
  870. REQUEST_STATUS(Request) = Status;
  871. NbiCompleteRequest (Request);
  872. NbiFreeRequest (Device, Request);
  873. }
  874. //
  875. // Return the immediate status code to the caller.
  876. //
  877. return Status;
  878. } /* NbiDispatchOpenClose */
  879. NTSTATUS
  880. NbiDispatchDeviceControl(
  881. IN PDEVICE_OBJECT DeviceObject,
  882. IN PIRP Irp
  883. )
  884. /*++
  885. Routine Description:
  886. This routine dispatches TDI request types to different handlers based
  887. on the minor IOCTL function code in the IRP's current stack location.
  888. In addition to cracking the minor function code, this routine also
  889. reaches into the IRP and passes the packetized parameters stored there
  890. as parameters to the various TDI request handlers so that they are
  891. not IRP-dependent.
  892. Arguments:
  893. DeviceObject - Pointer to the device object for this driver.
  894. Irp - Pointer to the request packet representing the I/O request.
  895. Return Value:
  896. The function value is the status of the operation.
  897. --*/
  898. {
  899. NTSTATUS Status;
  900. PDEVICE Device = (PDEVICE)DeviceObject;
  901. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (Irp);
  902. //
  903. // Branch to the appropriate request handler. Preliminary checking of
  904. // the size of the request block is performed here so that it is known
  905. // in the handlers that the minimum input parameters are readable. It
  906. // is *not* determined here whether variable length input fields are
  907. // passed correctly; this is a check which must be made within each routine.
  908. //
  909. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  910. default:
  911. //
  912. // Convert the user call to the proper internal device call.
  913. //
  914. Status = TdiMapUserRequest (DeviceObject, Irp, IrpSp);
  915. if (Status == STATUS_SUCCESS) {
  916. //
  917. // If TdiMapUserRequest returns SUCCESS then the IRP
  918. // has been converted into an IRP_MJ_INTERNAL_DEVICE_CONTROL
  919. // IRP, so we dispatch it as usual. The IRP will
  920. // be completed by this call.
  921. //
  922. Status = NbiDispatchInternal (DeviceObject, Irp);
  923. } else {
  924. Irp->IoStatus.Status = Status;
  925. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  926. }
  927. break;
  928. }
  929. return Status;
  930. } /* NbiDeviceControl */
  931. NB_TDI_DISPATCH_ROUTINE NbiDispatchInternalTable[] = {
  932. NbiTdiAssociateAddress,
  933. NbiTdiDisassociateAddress,
  934. NbiTdiConnect,
  935. NbiTdiListen,
  936. NbiTdiAccept,
  937. NbiTdiDisconnect,
  938. NbiTdiSend,
  939. NbiTdiReceive,
  940. NbiTdiSendDatagram,
  941. NbiTdiReceiveDatagram,
  942. NbiTdiSetEventHandler,
  943. NbiTdiQueryInformation,
  944. NbiTdiSetInformation,
  945. NbiTdiAction
  946. };
  947. NTSTATUS
  948. NbiDispatchInternal(
  949. IN PDEVICE_OBJECT DeviceObject,
  950. IN PIRP Irp
  951. )
  952. /*++
  953. Routine Description:
  954. This routine dispatches TDI request types to different handlers based
  955. on the minor IOCTL function code in the IRP's current stack location.
  956. In addition to cracking the minor function code, this routine also
  957. reaches into the IRP and passes the packetized parameters stored there
  958. as parameters to the various TDI request handlers so that they are
  959. not IRP-dependent.
  960. Arguments:
  961. DeviceObject - Pointer to the device object for this driver.
  962. Irp - Pointer to the request packet representing the I/O request.
  963. Return Value:
  964. The function value is the status of the operation.
  965. --*/
  966. {
  967. NTSTATUS Status;
  968. PDEVICE Device = (PDEVICE)DeviceObject;
  969. PREQUEST Request;
  970. UCHAR MinorFunction;
  971. if (Device->State != DEVICE_STATE_OPEN) {
  972. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  973. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  974. return STATUS_INVALID_DEVICE_STATE;
  975. }
  976. //
  977. // Allocate a request to track this IRP.
  978. //
  979. Request = NbiAllocateRequest (Device, Irp);
  980. IF_NOT_ALLOCATED(Request) {
  981. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  982. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  983. return STATUS_INSUFFICIENT_RESOURCES;
  984. }
  985. //
  986. // Make sure status information is consistent every time.
  987. //
  988. MARK_REQUEST_PENDING(Request);
  989. REQUEST_STATUS(Request) = STATUS_PENDING;
  990. REQUEST_INFORMATION(Request) = 0;
  991. //
  992. // Branch to the appropriate request handler.
  993. //
  994. MinorFunction = REQUEST_MINOR_FUNCTION(Request) - 1;
  995. if (MinorFunction <= (TDI_ACTION-1)) {
  996. Status = (*NbiDispatchInternalTable[MinorFunction]) (
  997. Device,
  998. Request);
  999. } else {
  1000. NB_DEBUG (DRIVER, ("Unsupported minor code %d\n", MinorFunction+1));
  1001. if ((MinorFunction+1) == TDI_DISCONNECT) {
  1002. Status = STATUS_SUCCESS;
  1003. } else {
  1004. Status = STATUS_INVALID_DEVICE_REQUEST;
  1005. }
  1006. }
  1007. if (Status != STATUS_PENDING) {
  1008. UNMARK_REQUEST_PENDING(Request);
  1009. REQUEST_STATUS(Request) = Status;
  1010. NbiCompleteRequest (Request);
  1011. NbiFreeRequest (Device, Request);
  1012. }
  1013. //
  1014. // Return the immediate status code to the caller.
  1015. //
  1016. return Status;
  1017. } /* NbiDispatchInternal */
  1018. PVOID
  1019. NbipAllocateMemory(
  1020. IN ULONG BytesNeeded,
  1021. IN ULONG Tag,
  1022. IN BOOLEAN ChargeDevice
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. This routine allocates memory, making sure it is within
  1027. the limit allowed by the device.
  1028. Arguments:
  1029. BytesNeeded - The number of bytes to allocated.
  1030. ChargeDevice - TRUE if the device should be charged.
  1031. Return Value:
  1032. None.
  1033. --*/
  1034. {
  1035. PVOID Memory;
  1036. PDEVICE Device = NbiDevice;
  1037. if (ChargeDevice) {
  1038. if ((Device->MemoryLimit != 0) &&
  1039. (((LONG)(Device->MemoryUsage + BytesNeeded) >
  1040. Device->MemoryLimit))) {
  1041. NbiPrint1 ("Nbi: Could not allocate %d: limit\n", BytesNeeded);
  1042. NbiWriteResourceErrorLog (Device, BytesNeeded, Tag);
  1043. return NULL;
  1044. }
  1045. }
  1046. #if ISN_NT
  1047. Memory = ExAllocatePoolWithTag (NonPagedPool, BytesNeeded, ' IBN');
  1048. #else
  1049. Memory = CTEAllocMem (BytesNeeded);
  1050. #endif
  1051. if (Memory == NULL) {
  1052. NbiPrint1("Nbi: Could not allocate %d: no pool\n", BytesNeeded);
  1053. if (ChargeDevice) {
  1054. NbiWriteResourceErrorLog (Device, BytesNeeded, Tag);
  1055. }
  1056. return NULL;
  1057. }
  1058. if (ChargeDevice) {
  1059. Device->MemoryUsage += BytesNeeded;
  1060. }
  1061. return Memory;
  1062. } /* NbipAllocateMemory */
  1063. VOID
  1064. NbipFreeMemory(
  1065. IN PVOID Memory,
  1066. IN ULONG BytesAllocated,
  1067. IN BOOLEAN ChargeDevice
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. This routine frees memory allocated with NbipAllocateMemory.
  1072. Arguments:
  1073. Memory - The memory allocated.
  1074. BytesAllocated - The number of bytes to freed.
  1075. ChargeDevice - TRUE if the device should be charged.
  1076. Return Value:
  1077. None.
  1078. --*/
  1079. {
  1080. PDEVICE Device = NbiDevice;
  1081. #if ISN_NT
  1082. ExFreePool (Memory);
  1083. #else
  1084. CTEFreeMem (Memory);
  1085. #endif
  1086. if (ChargeDevice) {
  1087. Device->MemoryUsage -= BytesAllocated;
  1088. }
  1089. } /* NbipFreeMemory */
  1090. #if DBG
  1091. PVOID
  1092. NbipAllocateTaggedMemory(
  1093. IN ULONG BytesNeeded,
  1094. IN ULONG Tag,
  1095. IN PUCHAR Description
  1096. )
  1097. /*++
  1098. Routine Description:
  1099. This routine allocates memory, charging it to the device.
  1100. If it cannot allocate memory it uses the Tag and Descriptor
  1101. to log an error.
  1102. Arguments:
  1103. BytesNeeded - The number of bytes to allocated.
  1104. Tag - A unique ID used in the error log.
  1105. Description - A text description of the allocation.
  1106. Return Value:
  1107. None.
  1108. --*/
  1109. {
  1110. PVOID Memory;
  1111. UNREFERENCED_PARAMETER(Description);
  1112. Memory = NbipAllocateMemory(BytesNeeded, Tag, (BOOLEAN)(Tag != MEMORY_CONFIG));
  1113. if (Memory) {
  1114. ExInterlockedAddUlong(
  1115. &NbiMemoryTag[Tag].BytesAllocated,
  1116. BytesNeeded,
  1117. &NbiMemoryInterlock);
  1118. }
  1119. return Memory;
  1120. } /* NbipAllocateTaggedMemory */
  1121. VOID
  1122. NbipFreeTaggedMemory(
  1123. IN PVOID Memory,
  1124. IN ULONG BytesAllocated,
  1125. IN ULONG Tag,
  1126. IN PUCHAR Description
  1127. )
  1128. /*++
  1129. Routine Description:
  1130. This routine frees memory allocated with NbipAllocateTaggedMemory.
  1131. Arguments:
  1132. Memory - The memory allocated.
  1133. BytesAllocated - The number of bytes to freed.
  1134. Tag - A unique ID used in the error log.
  1135. Description - A text description of the allocation.
  1136. Return Value:
  1137. None.
  1138. --*/
  1139. {
  1140. UNREFERENCED_PARAMETER(Description);
  1141. ExInterlockedAddUlong(
  1142. &NbiMemoryTag[Tag].BytesAllocated,
  1143. (ULONG)(-(LONG)BytesAllocated),
  1144. &NbiMemoryInterlock);
  1145. NbipFreeMemory (Memory, BytesAllocated, (BOOLEAN)(Tag != MEMORY_CONFIG));
  1146. } /* NbipFreeTaggedMemory */
  1147. #endif
  1148. VOID
  1149. NbiWriteResourceErrorLog(
  1150. IN PDEVICE Device,
  1151. IN ULONG BytesNeeded,
  1152. IN ULONG UniqueErrorValue
  1153. )
  1154. /*++
  1155. Routine Description:
  1156. This routine allocates and writes an error log entry indicating
  1157. an out of resources condition.
  1158. Arguments:
  1159. Device - Pointer to the device context.
  1160. BytesNeeded - If applicable, the number of bytes that could not
  1161. be allocated.
  1162. UniqueErrorValue - Used as the UniqueErrorValue in the error log
  1163. packet.
  1164. Return Value:
  1165. None.
  1166. --*/
  1167. {
  1168. PIO_ERROR_LOG_PACKET errorLogEntry;
  1169. UCHAR EntrySize;
  1170. PUCHAR StringLoc;
  1171. ULONG TempUniqueError;
  1172. static WCHAR UniqueErrorBuffer[4] = L"000";
  1173. INT i;
  1174. EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
  1175. Device->DeviceString.MaximumLength +
  1176. sizeof(UniqueErrorBuffer);
  1177. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1178. (PDEVICE_OBJECT)Device,
  1179. EntrySize
  1180. );
  1181. //
  1182. // Convert the error value into a buffer.
  1183. //
  1184. TempUniqueError = UniqueErrorValue;
  1185. for (i=1; i>=0; i--) {
  1186. UniqueErrorBuffer[i] = (WCHAR)((TempUniqueError % 10) + L'0');
  1187. TempUniqueError /= 10;
  1188. }
  1189. if (errorLogEntry != NULL) {
  1190. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  1191. errorLogEntry->RetryCount = (UCHAR)-1;
  1192. errorLogEntry->DumpDataSize = sizeof(ULONG);
  1193. errorLogEntry->NumberOfStrings = 2;
  1194. errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
  1195. errorLogEntry->EventCategory = 0;
  1196. errorLogEntry->ErrorCode = EVENT_TRANSPORT_RESOURCE_POOL;
  1197. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  1198. errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  1199. errorLogEntry->SequenceNumber = (ULONG)-1;
  1200. errorLogEntry->IoControlCode = 0;
  1201. errorLogEntry->DumpData[0] = BytesNeeded;
  1202. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  1203. RtlCopyMemory (StringLoc, Device->DeviceString.Buffer, Device->DeviceString.MaximumLength);
  1204. StringLoc += Device->DeviceString.MaximumLength;
  1205. RtlCopyMemory (StringLoc, UniqueErrorBuffer, sizeof(UniqueErrorBuffer));
  1206. IoWriteErrorLogEntry(errorLogEntry);
  1207. }
  1208. } /* NbiWriteResourceErrorLog */
  1209. VOID
  1210. NbiWriteGeneralErrorLog(
  1211. IN PDEVICE Device,
  1212. IN NTSTATUS ErrorCode,
  1213. IN ULONG UniqueErrorValue,
  1214. IN NTSTATUS FinalStatus,
  1215. IN PWSTR SecondString,
  1216. IN ULONG DumpDataCount,
  1217. IN ULONG DumpData[]
  1218. )
  1219. /*++
  1220. Routine Description:
  1221. This routine allocates and writes an error log entry indicating
  1222. a general problem as indicated by the parameters. It handles
  1223. event codes REGISTER_FAILED, BINDING_FAILED, ADAPTER_NOT_FOUND,
  1224. TRANSFER_DATA, TOO_MANY_LINKS, and BAD_PROTOCOL. All these
  1225. events have messages with one or two strings in them.
  1226. Arguments:
  1227. Device - Pointer to the device context, or this may be
  1228. a driver object instead.
  1229. ErrorCode - The transport event code.
  1230. UniqueErrorValue - Used as the UniqueErrorValue in the error log
  1231. packet.
  1232. FinalStatus - Used as the FinalStatus in the error log packet.
  1233. SecondString - If not NULL, the string to use as the %3
  1234. value in the error log packet.
  1235. DumpDataCount - The number of ULONGs of dump data.
  1236. DumpData - Dump data for the packet.
  1237. Return Value:
  1238. None.
  1239. --*/
  1240. {
  1241. PIO_ERROR_LOG_PACKET errorLogEntry;
  1242. UCHAR EntrySize;
  1243. ULONG SecondStringSize;
  1244. PUCHAR StringLoc;
  1245. static WCHAR DriverName[8] = L"NwlnkNb";
  1246. EntrySize = (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  1247. (DumpDataCount * sizeof(ULONG)));
  1248. if (Device->Type == IO_TYPE_DEVICE) {
  1249. EntrySize += (UCHAR)Device->DeviceString.MaximumLength;
  1250. } else {
  1251. EntrySize += sizeof(DriverName);
  1252. }
  1253. if (SecondString) {
  1254. SecondStringSize = (wcslen(SecondString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
  1255. EntrySize += (UCHAR)SecondStringSize;
  1256. }
  1257. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1258. (PDEVICE_OBJECT)Device,
  1259. EntrySize
  1260. );
  1261. if (errorLogEntry != NULL) {
  1262. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  1263. errorLogEntry->RetryCount = (UCHAR)-1;
  1264. errorLogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
  1265. errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 1 : 2;
  1266. errorLogEntry->StringOffset =
  1267. (USHORT)(sizeof(IO_ERROR_LOG_PACKET) + ((DumpDataCount-1) * sizeof(ULONG)));
  1268. errorLogEntry->EventCategory = 0;
  1269. errorLogEntry->ErrorCode = ErrorCode;
  1270. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  1271. errorLogEntry->FinalStatus = FinalStatus;
  1272. errorLogEntry->SequenceNumber = (ULONG)-1;
  1273. errorLogEntry->IoControlCode = 0;
  1274. if (DumpDataCount) {
  1275. RtlCopyMemory(errorLogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
  1276. }
  1277. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  1278. if (Device->Type == IO_TYPE_DEVICE) {
  1279. RtlCopyMemory (StringLoc, Device->DeviceString.Buffer, Device->DeviceString.MaximumLength);
  1280. StringLoc += Device->DeviceString.MaximumLength;
  1281. } else {
  1282. RtlCopyMemory (StringLoc, DriverName, sizeof(DriverName));
  1283. StringLoc += sizeof(DriverName);
  1284. }
  1285. if (SecondString) {
  1286. RtlCopyMemory (StringLoc, SecondString, SecondStringSize);
  1287. }
  1288. IoWriteErrorLogEntry(errorLogEntry);
  1289. }
  1290. } /* NbiWriteGeneralErrorLog */
  1291. VOID
  1292. NbiWriteOidErrorLog(
  1293. IN PDEVICE Device,
  1294. IN NTSTATUS ErrorCode,
  1295. IN NTSTATUS FinalStatus,
  1296. IN PWSTR AdapterString,
  1297. IN ULONG OidValue
  1298. )
  1299. /*++
  1300. Routine Description:
  1301. This routine allocates and writes an error log entry indicating
  1302. a problem querying or setting an OID on an adapter. It handles
  1303. event codes SET_OID_FAILED and QUERY_OID_FAILED.
  1304. Arguments:
  1305. Device - Pointer to the device context.
  1306. ErrorCode - Used as the ErrorCode in the error log packet.
  1307. FinalStatus - Used as the FinalStatus in the error log packet.
  1308. AdapterString - The name of the adapter we were bound to.
  1309. OidValue - The OID which could not be set or queried.
  1310. Return Value:
  1311. None.
  1312. --*/
  1313. {
  1314. PIO_ERROR_LOG_PACKET errorLogEntry;
  1315. UCHAR EntrySize;
  1316. ULONG AdapterStringSize;
  1317. PUCHAR StringLoc;
  1318. static WCHAR OidBuffer[9] = L"00000000";
  1319. INT i;
  1320. UINT CurrentDigit;
  1321. AdapterStringSize = (wcslen(AdapterString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
  1322. EntrySize = (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) -
  1323. sizeof(ULONG) +
  1324. Device->DeviceString.MaximumLength +
  1325. AdapterStringSize +
  1326. sizeof(OidBuffer));
  1327. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1328. (PDEVICE_OBJECT)Device,
  1329. EntrySize
  1330. );
  1331. //
  1332. // Convert the OID into a buffer.
  1333. //
  1334. for (i=7; i>=0; i--) {
  1335. CurrentDigit = OidValue & 0xf;
  1336. OidValue >>= 4;
  1337. if (CurrentDigit >= 0xa) {
  1338. OidBuffer[i] = (WCHAR)(CurrentDigit - 0xa + L'A');
  1339. } else {
  1340. OidBuffer[i] = (WCHAR)(CurrentDigit + L'0');
  1341. }
  1342. }
  1343. if (errorLogEntry != NULL) {
  1344. errorLogEntry->MajorFunctionCode = (UCHAR)-1;
  1345. errorLogEntry->RetryCount = (UCHAR)-1;
  1346. errorLogEntry->DumpDataSize = 0;
  1347. errorLogEntry->NumberOfStrings = 3;
  1348. errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG);
  1349. errorLogEntry->EventCategory = 0;
  1350. errorLogEntry->ErrorCode = ErrorCode;
  1351. errorLogEntry->UniqueErrorValue = 0;
  1352. errorLogEntry->FinalStatus = FinalStatus;
  1353. errorLogEntry->SequenceNumber = (ULONG)-1;
  1354. errorLogEntry->IoControlCode = 0;
  1355. StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
  1356. RtlCopyMemory (StringLoc, Device->DeviceString.Buffer, Device->DeviceString.MaximumLength);
  1357. StringLoc += Device->DeviceString.MaximumLength;
  1358. RtlCopyMemory (StringLoc, OidBuffer, sizeof(OidBuffer));
  1359. StringLoc += sizeof(OidBuffer);
  1360. RtlCopyMemory (StringLoc, AdapterString, AdapterStringSize);
  1361. IoWriteErrorLogEntry(errorLogEntry);
  1362. }
  1363. } /* NbiWriteOidErrorLog */
  1364. //----------------------------------------------------------------------------
  1365. NTSTATUS
  1366. NbiDispatchPnP(
  1367. IN PDEVICE_OBJECT DeviceObject,
  1368. IN PIRP pIrp
  1369. )
  1370. {
  1371. PVOID PDOInfo = NULL;
  1372. PIO_STACK_LOCATION pIrpSp;
  1373. PREQUEST Request;
  1374. PCONNECTION Connection;
  1375. PDEVICE_RELATIONS pDeviceRelations = NULL;
  1376. PVOID pnpDeviceContext = NULL;
  1377. PDEVICE Device = (PDEVICE)DeviceObject;
  1378. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  1379. Request = NbiAllocateRequest (Device, pIrp);
  1380. Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request); // This references the connection.
  1381. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1382. switch (pIrpSp->MinorFunction)
  1383. {
  1384. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1385. {
  1386. if (pIrpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
  1387. {
  1388. //
  1389. // Check for a valid Connection file type and Connection Context itself
  1390. //
  1391. if ((REQUEST_OPEN_TYPE(Request) == (PVOID)TDI_CONNECTION_FILE) &&
  1392. (NT_SUCCESS (NbiVerifyConnection (Connection))))
  1393. {
  1394. if (pDeviceRelations = (PDEVICE_RELATIONS) NbipAllocateMemory (sizeof (DEVICE_RELATIONS),
  1395. MEMORY_QUERY,
  1396. FALSE))
  1397. {
  1398. Status = (*Device->Bind.QueryHandler) (IPX_QUERY_DEVICE_RELATION,
  1399. &Connection->LocalTarget.NicHandle,
  1400. &pnpDeviceContext,
  1401. sizeof (PVOID),
  1402. NULL);
  1403. if (STATUS_SUCCESS == Status)
  1404. {
  1405. CTEAssert (pnpDeviceContext);
  1406. ObReferenceObject (pnpDeviceContext);
  1407. //
  1408. // TargetDeviceRelation allows exactly one PDO. fill it up.
  1409. //
  1410. pDeviceRelations->Count = 1;
  1411. pDeviceRelations->Objects[0] = pnpDeviceContext;
  1412. //
  1413. // invoker of this irp will free the information buffer.
  1414. //
  1415. }
  1416. else
  1417. {
  1418. NbipFreeMemory (pDeviceRelations, sizeof (DEVICE_RELATIONS), FALSE);
  1419. pDeviceRelations = NULL;
  1420. }
  1421. }
  1422. else
  1423. {
  1424. Status = STATUS_INSUFFICIENT_RESOURCES;
  1425. }
  1426. NbiDereferenceConnection (Connection, CREF_VERIFY);
  1427. }
  1428. else if (REQUEST_OPEN_TYPE(Request) == (PVOID)TDI_TRANSPORT_ADDRESS_FILE)
  1429. {
  1430. Status = STATUS_UNSUCCESSFUL;
  1431. }
  1432. }
  1433. break;
  1434. }
  1435. default:
  1436. {
  1437. break;
  1438. }
  1439. }
  1440. REQUEST_STATUS(Request) = Status;
  1441. REQUEST_INFORMATION(Request) = (ULONG_PTR) pDeviceRelations;
  1442. NbiCompleteRequest (Request);
  1443. NbiFreeRequest (Device, Request);
  1444. return Status;
  1445. }