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.

452 lines
12 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. passthru.c
  5. Abstract:
  6. Ndis Intermediate Miniport driver sample. This is a passthru driver.
  7. Author:
  8. Environment:
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #pragma NDIS_INIT_FUNCTION(DriverEntry)
  14. NDIS_HANDLE ProtHandle = NULL;
  15. NDIS_HANDLE DriverHandle = NULL;
  16. NDIS_MEDIUM MediumArray[4] =
  17. {
  18. NdisMedium802_3, // Ethernet
  19. NdisMedium802_5, // Token-ring
  20. NdisMediumFddi, // Fddi
  21. NdisMediumWan // NDISWAN
  22. };
  23. NDIS_SPIN_LOCK GlobalLock;
  24. PADAPT pAdaptList = NULL;
  25. LONG MiniportCount = 0;
  26. NDIS_HANDLE NdisWrapperHandle;
  27. //
  28. // To support ioctls from user-mode:
  29. //
  30. #define LINKNAME_STRING L"\\DosDevices\\Passthru"
  31. #define NTDEVICE_STRING L"\\Device\\Passthru"
  32. NDIS_HANDLE NdisDeviceHandle = NULL;
  33. PDEVICE_OBJECT ControlDeviceObject = NULL;
  34. enum _DEVICE_STATE
  35. {
  36. PS_DEVICE_STATE_READY = 0, // ready for create/delete
  37. PS_DEVICE_STATE_CREATING, // create operation in progress
  38. PS_DEVICE_STATE_DELETING // delete operation in progress
  39. } ControlDeviceState = PS_DEVICE_STATE_READY;
  40. NTSTATUS
  41. DriverEntry(
  42. IN PDRIVER_OBJECT DriverObject,
  43. IN PUNICODE_STRING RegistryPath
  44. )
  45. /*++
  46. Routine Description:
  47. First entry point to be called, when this driver is loaded.
  48. Register with NDIS as an intermediate driver.
  49. Arguments:
  50. DriverObject - pointer to the system's driver object structure
  51. for this driver
  52. RegistryPath - system's registry path for this driver
  53. Return Value:
  54. STATUS_SUCCESS if all initialization is successful, STATUS_XXX
  55. error code if not.
  56. --*/
  57. {
  58. NDIS_STATUS Status;
  59. NDIS_PROTOCOL_CHARACTERISTICS PChars;
  60. NDIS_MINIPORT_CHARACTERISTICS MChars;
  61. NDIS_STRING Name;
  62. Status = NDIS_STATUS_SUCCESS;
  63. NdisAllocateSpinLock(&GlobalLock);
  64. NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);
  65. do
  66. {
  67. //
  68. // Register the miniport with NDIS. Note that it is the miniport
  69. // which was started as a driver and not the protocol. Also the miniport
  70. // must be registered prior to the protocol since the protocol's BindAdapter
  71. // handler can be initiated anytime and when it is, it must be ready to
  72. // start driver instances.
  73. //
  74. NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
  75. MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;
  76. MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;
  77. MChars.InitializeHandler = MPInitialize;
  78. MChars.QueryInformationHandler = MPQueryInformation;
  79. MChars.SetInformationHandler = MPSetInformation;
  80. MChars.ResetHandler = NULL;
  81. MChars.TransferDataHandler = MPTransferData;
  82. MChars.HaltHandler = MPHalt;
  83. #ifdef NDIS51_MINIPORT
  84. MChars.CancelSendPacketsHandler = MPCancelSendPackets;
  85. MChars.PnPEventNotifyHandler = MPDevicePnPEvent;
  86. MChars.AdapterShutdownHandler = MPAdapterShutdown;
  87. #endif // NDIS51_MINIPORT
  88. //
  89. // We will disable the check for hang timeout so we do not
  90. // need a check for hang handler!
  91. //
  92. MChars.CheckForHangHandler = NULL;
  93. MChars.ReturnPacketHandler = MPReturnPacket;
  94. //
  95. // Either the Send or the SendPackets handler should be specified.
  96. // If SendPackets handler is specified, SendHandler is ignored
  97. //
  98. MChars.SendHandler = NULL; // MPSend;
  99. MChars.SendPacketsHandler = MPSendPackets;
  100. Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,
  101. &MChars,
  102. sizeof(MChars),
  103. &DriverHandle);
  104. if (Status != NDIS_STATUS_SUCCESS)
  105. {
  106. break;
  107. }
  108. #ifndef WIN9X
  109. NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);
  110. #endif
  111. //
  112. // Now register the protocol.
  113. //
  114. NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  115. PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
  116. PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;
  117. //
  118. // Make sure the protocol-name matches the service-name
  119. // (from the INF) under which this protocol is installed.
  120. // This is needed to ensure that NDIS can correctly determine
  121. // the binding and call us to bind to miniports below.
  122. //
  123. NdisInitUnicodeString(&Name, L"Passthru"); // Protocol name
  124. PChars.Name = Name;
  125. PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
  126. PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
  127. PChars.SendCompleteHandler = PtSendComplete;
  128. PChars.TransferDataCompleteHandler = PtTransferDataComplete;
  129. PChars.ResetCompleteHandler = PtResetComplete;
  130. PChars.RequestCompleteHandler = PtRequestComplete;
  131. PChars.ReceiveHandler = PtReceive;
  132. PChars.ReceiveCompleteHandler = PtReceiveComplete;
  133. PChars.StatusHandler = PtStatus;
  134. PChars.StatusCompleteHandler = PtStatusComplete;
  135. PChars.BindAdapterHandler = PtBindAdapter;
  136. PChars.UnbindAdapterHandler = PtUnbindAdapter;
  137. PChars.UnloadHandler = PtUnloadProtocol;
  138. PChars.ReceivePacketHandler = PtReceivePacket;
  139. PChars.PnPEventHandler= PtPNPHandler;
  140. NdisRegisterProtocol(&Status,
  141. &ProtHandle,
  142. &PChars,
  143. sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  144. if (Status != NDIS_STATUS_SUCCESS)
  145. {
  146. NdisIMDeregisterLayeredMiniport(DriverHandle);
  147. break;
  148. }
  149. NdisIMAssociateMiniport(DriverHandle, ProtHandle);
  150. }
  151. while (FALSE);
  152. if (Status != NDIS_STATUS_SUCCESS)
  153. {
  154. NdisTerminateWrapper(NdisWrapperHandle, NULL);
  155. }
  156. return(Status);
  157. }
  158. NDIS_STATUS
  159. PtRegisterDevice(
  160. VOID
  161. )
  162. /*++
  163. Routine Description:
  164. Register an ioctl interface - a device object to be used for this
  165. purpose is created by NDIS when we call NdisMRegisterDevice.
  166. This routine is called whenever a new miniport instance is
  167. initialized. However, we only create one global device object,
  168. when the first miniport instance is initialized. This routine
  169. handles potential race conditions with PtDeregisterDevice via
  170. the ControlDeviceState and MiniportCount variables.
  171. NOTE: do not call this from DriverEntry; it will prevent the driver
  172. from being unloaded (e.g. on uninstall).
  173. Arguments:
  174. None
  175. Return Value:
  176. NDIS_STATUS_SUCCESS if we successfully register a device object.
  177. --*/
  178. {
  179. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  180. UNICODE_STRING DeviceName;
  181. UNICODE_STRING DeviceLinkUnicodeString;
  182. PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
  183. DBGPRINT(("==>PtRegisterDevice\n"));
  184. NdisAcquireSpinLock(&GlobalLock);
  185. ++MiniportCount;
  186. if (1 == MiniportCount)
  187. {
  188. ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING);
  189. //
  190. // Another thread could be running PtDeregisterDevice on
  191. // behalf of another miniport instance. If so, wait for
  192. // it to exit.
  193. //
  194. while (ControlDeviceState != PS_DEVICE_STATE_READY)
  195. {
  196. NdisReleaseSpinLock(&GlobalLock);
  197. NdisMSleep(1);
  198. NdisAcquireSpinLock(&GlobalLock);
  199. }
  200. ControlDeviceState = PS_DEVICE_STATE_CREATING;
  201. NdisReleaseSpinLock(&GlobalLock);
  202. NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
  203. DispatchTable[IRP_MJ_CREATE] = PtDispatch;
  204. DispatchTable[IRP_MJ_CLEANUP] = PtDispatch;
  205. DispatchTable[IRP_MJ_CLOSE] = PtDispatch;
  206. DispatchTable[IRP_MJ_DEVICE_CONTROL] = PtDispatch;
  207. NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
  208. NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
  209. //
  210. // Create a device object and register our dispatch handlers
  211. //
  212. Status = NdisMRegisterDevice(
  213. NdisWrapperHandle,
  214. &DeviceName,
  215. &DeviceLinkUnicodeString,
  216. &DispatchTable[0],
  217. &ControlDeviceObject,
  218. &NdisDeviceHandle
  219. );
  220. NdisAcquireSpinLock(&GlobalLock);
  221. ControlDeviceState = PS_DEVICE_STATE_READY;
  222. }
  223. NdisReleaseSpinLock(&GlobalLock);
  224. DBGPRINT(("<==PtRegisterDevice: %x\n", Status));
  225. return (Status);
  226. }
  227. NTSTATUS
  228. PtDispatch(
  229. IN PDEVICE_OBJECT DeviceObject,
  230. IN PIRP Irp
  231. )
  232. /*++
  233. Routine Description:
  234. Process IRPs sent to this device.
  235. Arguments:
  236. DeviceObject - pointer to a device object
  237. Irp - pointer to an I/O Request Packet
  238. Return Value:
  239. NTSTATUS - STATUS_SUCCESS always - change this when adding
  240. real code to handle ioctls.
  241. --*/
  242. {
  243. PIO_STACK_LOCATION irpStack;
  244. NTSTATUS status = STATUS_SUCCESS;
  245. UNREFERENCED_PARAMETER(DeviceObject);
  246. DBGPRINT(("==>Pt Dispatch\n"));
  247. irpStack = IoGetCurrentIrpStackLocation(Irp);
  248. switch (irpStack->MajorFunction)
  249. {
  250. case IRP_MJ_CREATE:
  251. break;
  252. case IRP_MJ_CLEANUP:
  253. break;
  254. case IRP_MJ_CLOSE:
  255. break;
  256. case IRP_MJ_DEVICE_CONTROL:
  257. //
  258. // Add code here to handle ioctl commands sent to passthru.
  259. //
  260. break;
  261. default:
  262. break;
  263. }
  264. Irp->IoStatus.Status = status;
  265. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  266. DBGPRINT(("<== Pt Dispatch\n"));
  267. return status;
  268. }
  269. NDIS_STATUS
  270. PtDeregisterDevice(
  271. VOID
  272. )
  273. /*++
  274. Routine Description:
  275. Deregister the ioctl interface. This is called whenever a miniport
  276. instance is halted. When the last miniport instance is halted, we
  277. request NDIS to delete the device object
  278. Arguments:
  279. NdisDeviceHandle - Handle returned by NdisMRegisterDevice
  280. Return Value:
  281. NDIS_STATUS_SUCCESS if everything worked ok
  282. --*/
  283. {
  284. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  285. DBGPRINT(("==>PassthruDeregisterDevice\n"));
  286. NdisAcquireSpinLock(&GlobalLock);
  287. ASSERT(MiniportCount > 0);
  288. --MiniportCount;
  289. if (0 == MiniportCount)
  290. {
  291. //
  292. // All miniport instances have been halted. Deregister
  293. // the control device.
  294. //
  295. ASSERT(ControlDeviceState == PS_DEVICE_STATE_READY);
  296. //
  297. // Block PtRegisterDevice() while we release the control
  298. // device lock and deregister the device.
  299. //
  300. ControlDeviceState = PS_DEVICE_STATE_DELETING;
  301. NdisReleaseSpinLock(&GlobalLock);
  302. if (NdisDeviceHandle != NULL)
  303. {
  304. Status = NdisMDeregisterDevice(NdisDeviceHandle);
  305. NdisDeviceHandle = NULL;
  306. }
  307. NdisAcquireSpinLock(&GlobalLock);
  308. ControlDeviceState = PS_DEVICE_STATE_READY;
  309. }
  310. NdisReleaseSpinLock(&GlobalLock);
  311. DBGPRINT(("<== PassthruDeregisterDevice: %x\n", Status));
  312. return Status;
  313. }
  314. VOID
  315. PtUnload(
  316. IN PDRIVER_OBJECT DriverObject
  317. )
  318. //
  319. // PassThru driver unload function
  320. //
  321. {
  322. UNREFERENCED_PARAMETER(DriverObject);
  323. DBGPRINT(("PtUnload: entered\n"));
  324. PtUnloadProtocol();
  325. NdisIMDeregisterLayeredMiniport(DriverHandle);
  326. DBGPRINT(("PtUnload: done!\n"));
  327. }