#include "timestmp.h" #define FRIENDLY_NAME L"\\DosDevices\\Timestmp" NTSTATUS IoctlInitialize( PDRIVER_OBJECT DriverObject ) /*++ Routine Description: Perform initialization Arguments: DriverObject - pointer to DriverObject from DriverEntry InitShutdownMask - pointer to mask used to indicate which events have been successfully init'ed Return Value: STATUS_SUCCESS if everything worked ok --*/ { NTSTATUS Status; UINT FuncIndex; // // Initialize the driver object's entry points // DriverObject->FastIoDispatch = NULL; for (FuncIndex = 0; FuncIndex <= IRP_MJ_MAXIMUM_FUNCTION; FuncIndex++) { DriverObject->MajorFunction[FuncIndex] = IoctlHandler; } RtlInitUnicodeString(&TimestmpDriverName, L"\\Device\\Timestmp"); Status = IoCreateDevice(DriverObject, 0, &TimestmpDriverName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &TimestmpDeviceObject); if ( NT_SUCCESS( Status )) { // Now create a symbolic link so that apps can open with createfile. DbgPrint("IoCreateDevice SUCCESS!\n"); RtlInitUnicodeString (&symbolicLinkName, FRIENDLY_NAME); DbgPrint("The DeviceName(%ws) and FriendlyName(%ws) are OK\n", TimestmpDriverName, symbolicLinkName); Status = IoCreateSymbolicLink(&symbolicLinkName, &TimestmpDriverName); if (!NT_SUCCESS (Status)) { DbgPrint("Failed to create symbolic link: %lx\n", Status); //IoDeleteDevice(TimestmpDeviceObject); return STATUS_UNSUCCESSFUL; } TimestmpDeviceObject->Flags |= DO_BUFFERED_IO; } else { DbgPrint("IoCreateDevice failed. Status = %x\n", Status); TimestmpDeviceObject = NULL; } return Status; } NTSTATUS IoctlHandler( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Process the IRPs sent to this device. Arguments: DeviceObject - pointer to a device object Irp - pointer to an I/O Request Packet Return Value: None --*/ { PIO_STACK_LOCATION irpStack; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG ioControlCode; UCHAR saveControlFlags; NTSTATUS Status = STATUS_SUCCESS; PPORT_ENTRY pPortEntry; PLIST_ENTRY ListEntry; USHORT Port = 0; PAGED_CODE(); // // Init to default settings- we only expect 1 type of // IOCTL to roll through here, all others an error. // Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; // // Get a pointer to the current location in the Irp. This is where // the function codes and parameters are located. // irpStack = IoGetCurrentIrpStackLocation(Irp); // // Get the pointer to the input/output buffer and it's length // ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; saveControlFlags = irpStack->Control; switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: DbgPrint("CREATE\n"); break; case IRP_MJ_READ: DbgPrint("READ\n"); break; case IRP_MJ_CLOSE: DbgPrint("CLOSE\n"); DbgPrint("FileObject %X\n", irpStack->FileObject); RemoveAllPortsForFileObject(irpStack->FileObject); // // make sure we clean all the objects for this particular // file object, since it's closing right now. // break; case IRP_MJ_CLEANUP: DbgPrint("CLEANUP\n"); break; case IRP_MJ_SHUTDOWN: DbgPrint("Shutdown\n"); break; case IRP_MJ_DEVICE_CONTROL: DbgPrint("The ioBuffer is %X and the contents are %d\n", ioBuffer, Port); Port = *(USHORT *)ioBuffer; DbgPrint("The Port number being added is %d\n", Port); switch (ioControlCode) { case IOCTL_TIMESTMP_REGISTER_PORT: DbgPrint("Register\n"); // // Grab the PortList lock and Insert the new port. // NdisAcquireSpinLock(&PortSpinLock); pPortEntry = ExAllocatePool( NonPagedPool, sizeof(PORT_ENTRY)); if (pPortEntry) { InitializeListHead(&pPortEntry->Linkage); pPortEntry->Port = Port; pPortEntry->FileObject = irpStack->FileObject; InsertHeadList(&PortList, &pPortEntry->Linkage); DbgPrint("Successfully inserted %d\n", Port); } else { DbgPrint("Couldn't allocate memory\n"); } NdisReleaseSpinLock(&PortSpinLock); break; case IOCTL_TIMESTMP_DEREGISTER_PORT: DbgPrint("DERegister\n"); // // Grab the PortList lock and REMOVE the new port. // NdisAcquireSpinLock(&PortSpinLock); pPortEntry = CheckInPortList(Port); if (pPortEntry) { RemoveEntryList(&pPortEntry->Linkage); ExFreePool(pPortEntry); DbgPrint("Successfully removed/freed %d\n", Port); } else { DbgPrint("Couldn't find port %d\n", Port); } NdisReleaseSpinLock(&PortSpinLock); break; } // switch (ioControlCode) break; default: DbgPrint("GPCIoctl: Unknown IRP major function = %08X\n", irpStack->MajorFunction); Status = STATUS_UNSUCCESSFUL; break; } DbgPrint("GPCIoctl: Status=0x%X, IRP=0x%X, outSize=%d\n", Status, (ULONG_PTR)Irp, outputBufferLength); if (Status != STATUS_PENDING) { // // IRP completed and it's not Pending, we need to restore the Control flags, // since it might have been marked as Pending before... // irpStack->Control = saveControlFlags; Irp->IoStatus.Status = Status; Irp->IoStatus.Information = outputBufferLength; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } return Status; } // GPCIoctl VOID IoctlCleanup( ) /*++ Routine Description: Cleanup code for Initialize Arguments: ShutdownMask - mask indicating which functions need to be cleaned up Return Value: None --*/ { IoDeleteDevice( TimestmpDeviceObject ); } VOID RemoveAllPortsForFileObject( PFILE_OBJECT FileObject ) { PLIST_ENTRY ListEntry; PPORT_ENTRY pPortEntry; NdisAcquireSpinLock(&PortSpinLock); ListEntry = PortList.Flink; while (ListEntry != &PortList) { pPortEntry = CONTAINING_RECORD(ListEntry, PORT_ENTRY, Linkage); ListEntry = ListEntry->Flink; if (FileObject == pPortEntry->FileObject) { DbgPrint("Deleting Port%d for FileObject0x%X\n", pPortEntry->Port, pPortEntry->FileObject); RemoveEntryList(&pPortEntry->Linkage); ExFreePool(pPortEntry); } } NdisReleaseSpinLock(&PortSpinLock); }