Source code of Windows XP (NT5)
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.

334 lines
7.0 KiB

  1. #include "timestmp.h"
  2. #define FRIENDLY_NAME L"\\DosDevices\\Timestmp"
  3. NTSTATUS
  4. IoctlInitialize(
  5. PDRIVER_OBJECT DriverObject
  6. )
  7. /*++
  8. Routine Description:
  9. Perform initialization
  10. Arguments:
  11. DriverObject - pointer to DriverObject from DriverEntry
  12. InitShutdownMask - pointer to mask used to indicate which events have been
  13. successfully init'ed
  14. Return Value:
  15. STATUS_SUCCESS if everything worked ok
  16. --*/
  17. {
  18. NTSTATUS Status;
  19. UINT FuncIndex;
  20. //
  21. // Initialize the driver object's entry points
  22. //
  23. DriverObject->FastIoDispatch = NULL;
  24. for (FuncIndex = 0; FuncIndex <= IRP_MJ_MAXIMUM_FUNCTION; FuncIndex++) {
  25. DriverObject->MajorFunction[FuncIndex] = IoctlHandler;
  26. }
  27. RtlInitUnicodeString(&TimestmpDriverName,
  28. L"\\Device\\Timestmp");
  29. Status = IoCreateDevice(DriverObject,
  30. 0,
  31. &TimestmpDriverName,
  32. FILE_DEVICE_NETWORK,
  33. FILE_DEVICE_SECURE_OPEN,
  34. FALSE,
  35. &TimestmpDeviceObject);
  36. if ( NT_SUCCESS( Status )) {
  37. // Now create a symbolic link so that apps can open with createfile.
  38. DbgPrint("IoCreateDevice SUCCESS!\n");
  39. RtlInitUnicodeString (&symbolicLinkName, FRIENDLY_NAME);
  40. DbgPrint("The DeviceName(%ws) and FriendlyName(%ws) are OK\n", TimestmpDriverName, symbolicLinkName);
  41. Status = IoCreateSymbolicLink(&symbolicLinkName, &TimestmpDriverName);
  42. if (!NT_SUCCESS (Status)) {
  43. DbgPrint("Failed to create symbolic link: %lx\n", Status);
  44. //IoDeleteDevice(TimestmpDeviceObject);
  45. return STATUS_UNSUCCESSFUL;
  46. }
  47. TimestmpDeviceObject->Flags |= DO_BUFFERED_IO;
  48. } else {
  49. DbgPrint("IoCreateDevice failed. Status = %x\n", Status);
  50. TimestmpDeviceObject = NULL;
  51. }
  52. return Status;
  53. }
  54. NTSTATUS
  55. IoctlHandler(
  56. IN PDEVICE_OBJECT DeviceObject,
  57. IN PIRP Irp
  58. )
  59. /*++
  60. Routine Description:
  61. Process the IRPs sent to this device.
  62. Arguments:
  63. DeviceObject - pointer to a device object
  64. Irp - pointer to an I/O Request Packet
  65. Return Value:
  66. None
  67. --*/
  68. {
  69. PIO_STACK_LOCATION irpStack;
  70. PVOID ioBuffer;
  71. ULONG inputBufferLength;
  72. ULONG outputBufferLength;
  73. ULONG ioControlCode;
  74. UCHAR saveControlFlags;
  75. NTSTATUS Status = STATUS_SUCCESS;
  76. PPORT_ENTRY pPortEntry;
  77. PLIST_ENTRY ListEntry;
  78. USHORT Port = 0;
  79. PAGED_CODE();
  80. //
  81. // Init to default settings- we only expect 1 type of
  82. // IOCTL to roll through here, all others an error.
  83. //
  84. Irp->IoStatus.Status = STATUS_SUCCESS;
  85. Irp->IoStatus.Information = 0;
  86. //
  87. // Get a pointer to the current location in the Irp. This is where
  88. // the function codes and parameters are located.
  89. //
  90. irpStack = IoGetCurrentIrpStackLocation(Irp);
  91. //
  92. // Get the pointer to the input/output buffer and it's length
  93. //
  94. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  95. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  96. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  97. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  98. saveControlFlags = irpStack->Control;
  99. switch (irpStack->MajorFunction) {
  100. case IRP_MJ_CREATE:
  101. DbgPrint("CREATE\n");
  102. break;
  103. case IRP_MJ_READ:
  104. DbgPrint("READ\n");
  105. break;
  106. case IRP_MJ_CLOSE:
  107. DbgPrint("CLOSE\n");
  108. DbgPrint("FileObject %X\n", irpStack->FileObject);
  109. RemoveAllPortsForFileObject(irpStack->FileObject);
  110. //
  111. // make sure we clean all the objects for this particular
  112. // file object, since it's closing right now.
  113. //
  114. break;
  115. case IRP_MJ_CLEANUP:
  116. DbgPrint("CLEANUP\n");
  117. break;
  118. case IRP_MJ_SHUTDOWN:
  119. DbgPrint("Shutdown\n");
  120. break;
  121. case IRP_MJ_DEVICE_CONTROL:
  122. DbgPrint("The ioBuffer is %X and the contents are %d\n", ioBuffer, Port);
  123. Port = *(USHORT *)ioBuffer;
  124. DbgPrint("The Port number being added is %d\n", Port);
  125. switch (ioControlCode) {
  126. case IOCTL_TIMESTMP_REGISTER_PORT:
  127. DbgPrint("Register\n");
  128. //
  129. // Grab the PortList lock and Insert the new port.
  130. //
  131. NdisAcquireSpinLock(&PortSpinLock);
  132. pPortEntry = ExAllocatePool(
  133. NonPagedPool,
  134. sizeof(PORT_ENTRY));
  135. if (pPortEntry) {
  136. InitializeListHead(&pPortEntry->Linkage);
  137. pPortEntry->Port = Port;
  138. pPortEntry->FileObject = irpStack->FileObject;
  139. InsertHeadList(&PortList, &pPortEntry->Linkage);
  140. DbgPrint("Successfully inserted %d\n", Port);
  141. } else {
  142. DbgPrint("Couldn't allocate memory\n");
  143. }
  144. NdisReleaseSpinLock(&PortSpinLock);
  145. break;
  146. case IOCTL_TIMESTMP_DEREGISTER_PORT:
  147. DbgPrint("DERegister\n");
  148. //
  149. // Grab the PortList lock and REMOVE the new port.
  150. //
  151. NdisAcquireSpinLock(&PortSpinLock);
  152. pPortEntry = CheckInPortList(Port);
  153. if (pPortEntry) {
  154. RemoveEntryList(&pPortEntry->Linkage);
  155. ExFreePool(pPortEntry);
  156. DbgPrint("Successfully removed/freed %d\n", Port);
  157. } else {
  158. DbgPrint("Couldn't find port %d\n", Port);
  159. }
  160. NdisReleaseSpinLock(&PortSpinLock);
  161. break;
  162. } // switch (ioControlCode)
  163. break;
  164. default:
  165. DbgPrint("GPCIoctl: Unknown IRP major function = %08X\n", irpStack->MajorFunction);
  166. Status = STATUS_UNSUCCESSFUL;
  167. break;
  168. }
  169. DbgPrint("GPCIoctl: Status=0x%X, IRP=0x%X, outSize=%d\n", Status, (ULONG_PTR)Irp, outputBufferLength);
  170. if (Status != STATUS_PENDING) {
  171. //
  172. // IRP completed and it's not Pending, we need to restore the Control flags,
  173. // since it might have been marked as Pending before...
  174. //
  175. irpStack->Control = saveControlFlags;
  176. Irp->IoStatus.Status = Status;
  177. Irp->IoStatus.Information = outputBufferLength;
  178. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  179. }
  180. return Status;
  181. } // GPCIoctl
  182. VOID
  183. IoctlCleanup(
  184. )
  185. /*++
  186. Routine Description:
  187. Cleanup code for Initialize
  188. Arguments:
  189. ShutdownMask - mask indicating which functions need to be cleaned up
  190. Return Value:
  191. None
  192. --*/
  193. {
  194. IoDeleteDevice( TimestmpDeviceObject );
  195. }
  196. VOID
  197. RemoveAllPortsForFileObject(
  198. PFILE_OBJECT FileObject
  199. )
  200. {
  201. PLIST_ENTRY ListEntry;
  202. PPORT_ENTRY pPortEntry;
  203. NdisAcquireSpinLock(&PortSpinLock);
  204. ListEntry = PortList.Flink;
  205. while (ListEntry != &PortList) {
  206. pPortEntry = CONTAINING_RECORD(ListEntry, PORT_ENTRY, Linkage);
  207. ListEntry = ListEntry->Flink;
  208. if (FileObject == pPortEntry->FileObject) {
  209. DbgPrint("Deleting Port%d for FileObject0x%X\n", pPortEntry->Port, pPortEntry->FileObject);
  210. RemoveEntryList(&pPortEntry->Linkage);
  211. ExFreePool(pPortEntry);
  212. }
  213. }
  214. NdisReleaseSpinLock(&PortSpinLock);
  215. }