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.

294 lines
7.8 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. PURPOSE.
  7. Module Name:
  8. IOCTL.C
  9. Abstract:
  10. This modules contains functions to register/deregsiter a control-
  11. deviceobject for ioctl purposes and dispatch routine for handling
  12. ioctl requests from usermode.
  13. Revision History:
  14. Notes:
  15. --*/
  16. #if defined(IOCTL_INTERFACE)
  17. #include "miniport.h"
  18. #include "public.h"
  19. //
  20. // Simple Mutual Exclusion constructs used in preference to
  21. // using KeXXX calls since we don't have Mutex calls in NDIS.
  22. // These can only be called at passive IRQL.
  23. //
  24. typedef struct _NIC_MUTEX
  25. {
  26. ULONG Counter;
  27. ULONG ModuleAndLine; // useful for debugging
  28. } NIC_MUTEX, *PNIC_MUTEX;
  29. #define NIC_INIT_MUTEX(_pMutex) \
  30. { \
  31. (_pMutex)->Counter = 0; \
  32. (_pMutex)->ModuleAndLine = 0; \
  33. }
  34. #define NIC_ACQUIRE_MUTEX(_pMutex) \
  35. { \
  36. while (NdisInterlockedIncrement((PLONG)&((_pMutex)->Counter)) != 1)\
  37. { \
  38. NdisInterlockedDecrement((PLONG)&((_pMutex)->Counter)); \
  39. NdisMSleep(10000); \
  40. } \
  41. (_pMutex)->ModuleAndLine = ('I' << 16) | __LINE__;\
  42. }
  43. #define NIC_RELEASE_MUTEX(_pMutex) \
  44. { \
  45. (_pMutex)->ModuleAndLine = 0; \
  46. NdisInterlockedDecrement((PLONG)&(_pMutex)->Counter); \
  47. }
  48. #define LINKNAME_STRING L"\\DosDevices\\NETVMINI"
  49. #define NTDEVICE_STRING L"\\Device\\NETVMINI"
  50. //
  51. // Global variables
  52. //
  53. NDIS_HANDLE NdisDeviceHandle = NULL; // From NdisMRegisterDevice
  54. LONG MiniportCount = 0; // Total number of miniports in existance
  55. PDEVICE_OBJECT ControlDeviceObject = NULL; // Device for IOCTLs
  56. NIC_MUTEX ControlDeviceMutex;
  57. extern NDIS_HANDLE NdisWrapperHandle;
  58. #pragma NDIS_PAGEABLE_FUNCTION(NICRegisterDevice)
  59. #pragma NDIS_PAGEABLE_FUNCTION(NICDeregisterDevice)
  60. #pragma NDIS_PAGEABLE_FUNCTION(NICDispatch)
  61. NDIS_STATUS
  62. NICRegisterDevice(
  63. VOID
  64. )
  65. /*++
  66. Routine Description:
  67. Register an ioctl interface - a device object to be used for this
  68. purpose is created by NDIS when we call NdisMRegisterDevice.
  69. This routine is called whenever a new miniport instance is
  70. initialized. However, we only create one global device object,
  71. when the first miniport instance is initialized. This routine
  72. handles potential race conditions with NICDeregisterDevice via
  73. the ControlDeviceMutex.
  74. NOTE: do not call this from DriverEntry; it will prevent the driver
  75. from being unloaded (e.g. on uninstall).
  76. Arguments:
  77. None
  78. Return Value:
  79. NDIS_STATUS_SUCCESS if we successfully register a device object.
  80. --*/
  81. {
  82. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  83. UNICODE_STRING DeviceName;
  84. UNICODE_STRING DeviceLinkUnicodeString;
  85. PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
  86. DEBUGP(MP_TRACE, ("==>NICRegisterDevice\n"));
  87. NIC_ACQUIRE_MUTEX(&ControlDeviceMutex);
  88. ++MiniportCount;
  89. if (1 == MiniportCount)
  90. {
  91. NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));
  92. DispatchTable[IRP_MJ_CREATE] = NICDispatch;
  93. DispatchTable[IRP_MJ_CLEANUP] = NICDispatch;
  94. DispatchTable[IRP_MJ_CLOSE] = NICDispatch;
  95. DispatchTable[IRP_MJ_DEVICE_CONTROL] = NICDispatch;
  96. NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
  97. NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
  98. //
  99. // Create a device object and register our dispatch handlers
  100. //
  101. Status = NdisMRegisterDevice(
  102. NdisWrapperHandle,
  103. &DeviceName,
  104. &DeviceLinkUnicodeString,
  105. &DispatchTable[0],
  106. &ControlDeviceObject,
  107. &NdisDeviceHandle
  108. );
  109. }
  110. NIC_RELEASE_MUTEX(&ControlDeviceMutex);
  111. DEBUGP(MP_TRACE, ("<==NICRegisterDevice: %x\n", Status));
  112. return (Status);
  113. }
  114. NTSTATUS
  115. NICDispatch(
  116. IN PDEVICE_OBJECT DeviceObject,
  117. IN PIRP Irp
  118. )
  119. /*++
  120. Routine Description:
  121. Process IRPs sent to this device.
  122. Arguments:
  123. DeviceObject - pointer to a device object
  124. Irp - pointer to an I/O Request Packet
  125. Return Value:
  126. NTSTATUS - STATUS_SUCCESS always - change this when adding
  127. real code to handle ioctls.
  128. --*/
  129. {
  130. PIO_STACK_LOCATION irpStack;
  131. NTSTATUS status = STATUS_SUCCESS;
  132. ULONG inlen;
  133. PVOID buffer;
  134. irpStack = IoGetCurrentIrpStackLocation(Irp);
  135. DEBUGP(MP_TRACE, ("==>NICDispatch %d\n", irpStack->MajorFunction));
  136. switch (irpStack->MajorFunction)
  137. {
  138. case IRP_MJ_CREATE:
  139. break;
  140. case IRP_MJ_CLEANUP:
  141. break;
  142. case IRP_MJ_CLOSE:
  143. break;
  144. case IRP_MJ_DEVICE_CONTROL:
  145. {
  146. buffer = Irp->AssociatedIrp.SystemBuffer;
  147. inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  148. switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  149. {
  150. //
  151. // Add code here to handle ioctl commands.
  152. //
  153. case IOCTL_NETVMINI_READ_DATA:
  154. DEBUGP(MP_TRACE, ("Received Read IOCTL\n"));
  155. break;
  156. case IOCTL_NETVMINI_WRITE_DATA:
  157. DEBUGP(MP_TRACE, ("Received Write IOCTL\n"));
  158. break;
  159. default:
  160. status = STATUS_UNSUCCESSFUL;
  161. break;
  162. }
  163. break;
  164. }
  165. default:
  166. break;
  167. }
  168. Irp->IoStatus.Information = 0;
  169. Irp->IoStatus.Status = status;
  170. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  171. DEBUGP(MP_TRACE, ("<== NIC Dispatch\n"));
  172. return status;
  173. }
  174. NDIS_STATUS
  175. NICDeregisterDevice(
  176. VOID
  177. )
  178. /*++
  179. Routine Description:
  180. Deregister the ioctl interface. This is called whenever a miniport
  181. instance is halted. When the last miniport instance is halted, we
  182. request NDIS to delete the device object
  183. Arguments:
  184. NdisDeviceHandle - Handle returned by NdisMRegisterDevice
  185. Return Value:
  186. NDIS_STATUS_SUCCESS if everything worked ok
  187. --*/
  188. {
  189. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  190. DEBUGP(MP_TRACE, ("==>NICDeregisterDevice\n"));
  191. NIC_ACQUIRE_MUTEX(&ControlDeviceMutex);
  192. ASSERT(MiniportCount > 0);
  193. --MiniportCount;
  194. if (0 == MiniportCount)
  195. {
  196. //
  197. // All miniport instances have been halted.
  198. // Deregister the control device.
  199. //
  200. if (NdisDeviceHandle != NULL)
  201. {
  202. Status = NdisMDeregisterDevice(NdisDeviceHandle);
  203. NdisDeviceHandle = NULL;
  204. }
  205. }
  206. NIC_RELEASE_MUTEX(&ControlDeviceMutex);
  207. DEBUGP(MP_TRACE, ("<== NICDeregisterDevice: %x\n", Status));
  208. return Status;
  209. }
  210. #endif