NDIS_STATUS NICRegisterDevice(VOID) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING DeviceLinkUnicodeString; PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; PAGED_CODE(); DEBUGP(MP_TRACE, ("[HT_STARTUP]-->NICRegisterDevice\n")); NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); DispatchTable[IRP_MJ_CREATE] = NICDispatch; DispatchTable[IRP_MJ_CLEANUP] = NICDispatch; DispatchTable[IRP_MJ_CLOSE] = NICDispatch; DispatchTable[IRP_MJ_DEVICE_CONTROL] = NICDispatch; NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING); Status = NdisMRegisterDevice( NdisWrapperHandle, &DeviceName, &DeviceLinkUnicodeString, &DispatchTable[0], &g_ControlDeviceObject, &g_NdisDeviceHandle ); DEBUGP(MP_TRACE, ("[HT_STARTUP]<--NICRegisterDevice: %x\n", Status)); return Status; }
// Initialize the control device void NeoInitControlDevice() { char name_kernel[MAX_SIZE]; char name_win32[MAX_SIZE]; UNICODE *unicode_kernel, *unicode_win32; DEVICE_OBJECT *control_device_object; NDIS_HANDLE ndis_control_handle; if (ctx == NULL) { return; } // Initialize the dispatch table NeoZero(ctx->DispatchTable, sizeof(PDRIVER_DISPATCH) * IRP_MJ_MAXIMUM_FUNCTION); // Register the handler ctx->DispatchTable[IRP_MJ_CREATE] = ctx->DispatchTable[IRP_MJ_CLOSE] = ctx->DispatchTable[IRP_MJ_READ] = ctx->DispatchTable[IRP_MJ_WRITE] = ctx->DispatchTable[IRP_MJ_DEVICE_CONTROL] = NeoNdisDispatch; ctx->Opened = FALSE; // Generate the device name sprintf(name_kernel, NDIS_NEO_DEVICE_NAME, ctx->HardwareID); unicode_kernel = NewUnicode(name_kernel); sprintf(name_win32, NDIS_NEO_DEVICE_NAME_WIN32, ctx->HardwareID); unicode_win32 = NewUnicode(name_win32); // Register the Device NdisMRegisterDevice(ctx->NdisWrapper, GetUnicode(unicode_kernel), GetUnicode(unicode_win32), ctx->DispatchTable, &control_device_object, &ndis_control_handle); ctx->NdisControlDevice = control_device_object; ctx->NdisControl = ndis_control_handle; // Initialize the display name if (strlen(ctx->HardwareID) > 11) { sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw + 11); } else { sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw); } }
NTSTATUS ZlzCreateDevice(PDRIVER_OBJECT driver,NDIS_HANDLE wraphandle) { DbgBreakPoint(); NDIS_STATUS sta; UNICODE_STRING devname; UNICODE_STRING symname; PDRIVER_DISPATCH dispatchfunc[IRP_MJ_MAXIMUM_FUNCTION + 1]; RtlInitUnicodeString(&devname, DEVICE_NAME); RtlInitUnicodeString(&symname, SYM_NAME); dispatchfunc[IRP_MJ_CREATE] = ZlzDeviceCreate; dispatchfunc[IRP_MJ_DEVICE_CONTROL] = ZlzIoControl; dispatchfunc[IRP_MJ_CLOSE] = ZlzDeviceClose; dispatchfunc[IRP_MJ_CLEANUP] = ZlzDeviceCleanUp; sta=NdisMRegisterDevice(wraphandle, &devname, &symname, dispatchfunc, &global.controlobj, &global.controlhand); global.controlobj->Flags |= DO_BUFFERED_IO; global.controlobj->Flags &= ~DO_DEVICE_INITIALIZING; if (sta!=NDIS_STATUS_SUCCESS) { return sta; } sta = IoCreateSymbolicLink(&symname, &devname); return STATUS_SUCCESS; }
Boolean __fastcall ssh_interceptor_iodevice_create_device(SshInterceptorIoDevice io_dev) { SshInterceptor interceptor; PDRIVER_OBJECT driver; PSECURITY_DESCRIPTOR new_sd; PDRIVER_DISPATCH *fn_table; NTSTATUS st; #ifndef SSH_IM_INTERCEPTOR PDEVICE_OBJECT device; #else PDRIVER_DISPATCH major_function[IRP_MJ_MAXIMUM_FUNCTION + 1]; #endif /* SSH_IM_INTERCEPTOR */ SSH_ASSERT(io_dev != NULL); SSH_ASSERT(io_dev->interceptor != NULL); interceptor = io_dev->interceptor; SSH_ASSERT(interceptor->driver_object != NULL); driver = interceptor->driver_object; NdisAcquireSpinLock(&io_dev->output_queue_lock); if (io_dev->destroy_after_close) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Clearing delayed destroy flag...")); io_dev->destroy_after_close = FALSE; } NdisReleaseSpinLock(&io_dev->output_queue_lock); if (InterlockedCompareExchange(&io_dev->io_device_created, 1, 0) != 0) { SSH_DEBUG(SSH_D_HIGHSTART, ("I/O device already exists; ignoring this call")); return TRUE; } SSH_DEBUG(SSH_D_HIGHSTART, ("Creating I/O device and symbolic link...")); #ifndef SSH_IM_INTERCEPTOR #pragma warning(disable : 28175) fn_table = driver->MajorFunction; #pragma warning(default : 28175) #else memset(&major_function, 0, sizeof(major_function)); fn_table = major_function; #endif /* SSH_IM_INTERCEPTOR */ /* Create the I/O device and symbolic link and limit the access permissions of the I/O device. */ /* Initialize dispatch function table */ fn_table[IRP_MJ_CREATE] = ssh_interceptor_iodevice_dispatch_create; fn_table[IRP_MJ_CLOSE] = ssh_interceptor_iodevice_dispatch_close; fn_table[IRP_MJ_CLEANUP] = ssh_interceptor_iodevice_dispatch_cleanup; fn_table[IRP_MJ_READ] = ssh_interceptor_iodevice_dispatch_read; fn_table[IRP_MJ_WRITE] = ssh_interceptor_iodevice_dispatch_write; fn_table[IRP_MJ_DEVICE_CONTROL] = ssh_interceptor_iodevice_dispatch_ioctl; #ifdef SSH_IM_INTERCEPTOR /* Try to register our I/O device with NDIS */ st = NdisMRegisterDevice(io_dev->interceptor->wrapper_handle, &io_dev->device_name, &io_dev->symlink_name, fn_table, &io_dev->device, &io_dev->handle); if (!NT_SUCCESS(st)) { SSH_DEBUG(SSH_D_FAIL, ("NdisMRegisterDevice() failed - %08x", st)); return FALSE; } #else /* not SSH_IM_INTERCEPTOR */ st = IoCreateDevice(driver, sizeof(void *), &io_dev->device_name, FILE_DEVICE_NETWORK, 0, (BOOLEAN)io_dev->exclusive_access, &device); if (!NT_SUCCESS(st)) { SSH_DEBUG(SSH_D_FAIL, ("IoCreateDevice() failed - %08x", st)); return FALSE; } io_dev->device = device; *((SshInterceptorIoDevice *)device->DeviceExtension) = io_dev; #endif /* not SSH_IM_INTERCEPTOR */ io_dev->device->AlignmentRequirement = FILE_QUAD_ALIGNMENT; io_dev->device->Flags |= DO_DIRECT_IO; /* Remove world access to newly created device object */ #pragma warning(disable : 28175) if (ssh_access_permissions_limit(io_dev->device->SecurityDescriptor, &new_sd) != FALSE) { io_dev->orig_sd = io_dev->device->SecurityDescriptor; io_dev->device->SecurityDescriptor = new_sd; } else { SSH_DEBUG(SSH_D_FAIL, ("ssh_access_permissions_limit() failed!")); } #pragma warning(default : 28175) #ifndef SSH_IM_INTERCEPTOR /* Create symbolic link to make device accessible from Win32 */ st = IoCreateSymbolicLink(&io_dev->symlink_name, &io_dev->device_name); if (!NT_SUCCESS(st)) { SSH_DEBUG(SSH_D_FAIL, ("IoCreateSymbolicLink() failed (%08X): %ls -> %ls", st, io_dev->symlink_name.Buffer, io_dev->device_name.Buffer)); IoDeleteDevice(io_dev->device); return FALSE; } #endif /* SSH_IM_INTERCEPTOR */ return TRUE; }
NDIS_STATUS PtRegisterDevice( VOID ) /*++ Routine Description: Register an ioctl interface - a device object to be used for this purpose is created by NDIS when we call NdisMRegisterDevice. This routine is called whenever a new miniport instance is initialized. However, we only create one global device object, when the first miniport instance is initialized. This routine handles potential race conditions with PtDeregisterDevice via the ControlDeviceState and MiniportCount variables. NOTE: do not call this from DriverEntry; it will prevent the driver from being unloaded (e.g. on uninstall). Arguments: None Return Value: NDIS_STATUS_SUCCESS if we successfully register a device object. --*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING DeviceLinkUnicodeString; PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; DBGPRINT(("==>PtRegisterDevice\n")); NdisAcquireSpinLock(&GlobalLock); ++MiniportCount; if (1 == MiniportCount) { ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING); // // Another thread could be running PtDeregisterDevice on // behalf of another miniport instance. If so, wait for // it to exit. // while (ControlDeviceState != PS_DEVICE_STATE_READY) { NdisReleaseSpinLock(&GlobalLock); NdisMSleep(1); NdisAcquireSpinLock(&GlobalLock); } ControlDeviceState = PS_DEVICE_STATE_CREATING; NdisReleaseSpinLock(&GlobalLock); NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); DispatchTable[IRP_MJ_CREATE] = NdisProtOpen; DispatchTable[IRP_MJ_CLEANUP] = NdisProtCleanup; DispatchTable[IRP_MJ_CLOSE] = NdisProtClose; // DispatchTable[IRP_MJ_READ] = NdisProtRead; DispatchTable[IRP_MJ_READ] = divert_read; // DispatchTable[IRP_MJ_WRITE] = PtDispatch; DispatchTable[IRP_MJ_WRITE] = divert_write; // DispatchTable[IRP_MJ_DEVICE_CONTROL] = NdisProtIoControl; DispatchTable[IRP_MJ_DEVICE_CONTROL] = PtDispatch; NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING); // // Create a device object and register our dispatch handlers // Status = NdisMRegisterDevice( NdisWrapperHandle, &DeviceName, &DeviceLinkUnicodeString, &DispatchTable[0], &ControlDeviceObject, &NdisDeviceHandle ); ControlDeviceObject->Flags |= DO_DIRECT_IO; NdisAcquireSpinLock(&GlobalLock); ControlDeviceState = PS_DEVICE_STATE_READY; } NdisReleaseSpinLock(&GlobalLock); DBGPRINT(("<==PtRegisterDevice: %x\n", Status)); return (Status); }
NDIS_STATUS ProtocolRegisterDevice( VOID ) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING DeviceLinkUnicodeString; PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; NdisAcquireSpinLock(&GlobalLock); ++MiniportCount; if (1 == MiniportCount) { ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING); // // Another thread could be running PtDeregisterDevice on // behalf of another miniport instance. If so, wait for // it to exit. // while (ControlDeviceState != PS_DEVICE_STATE_READY) { NdisReleaseSpinLock(&GlobalLock); NdisMSleep(1); NdisAcquireSpinLock(&GlobalLock); } ControlDeviceState = PS_DEVICE_STATE_CREATING; NdisReleaseSpinLock(&GlobalLock); NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); DispatchTable[IRP_MJ_CREATE] = DispatchCreate; DispatchTable[IRP_MJ_CLOSE] = DispatchClose; DispatchTable[IRP_MJ_DEVICE_CONTROL] = DispatchIoCtrl; DispatchTable[IRP_MJ_WRITE] = DispatchWrite; NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING); // // Create a device object and register our dispatch handlers // Status = NdisMRegisterDevice( NdisWrapperHandle, &DeviceName, &DeviceLinkUnicodeString, &DispatchTable[0], &ControlDeviceObject, &NdisDeviceHandle ); NdisAcquireSpinLock(&GlobalLock); ControlDeviceObject->Flags |= DO_BUFFERED_IO; ControlDeviceState = PS_DEVICE_STATE_READY; } NdisReleaseSpinLock(&GlobalLock); return (Status); }