int lkl_env_init(unsigned long mem_size) { HANDLE init_thread_handle, timer_thread_handle; NTSTATUS status; nops.phys_mem_size=mem_size; KeInitializeTimerEx(&timer, SynchronizationTimer); KeInitializeSemaphore(&init_sem, 0, 100); KeInitializeSemaphore(&timer_killer_sem, 0, 100); /* create the initial thread */ status = PsCreateSystemThread(&init_thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, init_thread, NULL); if (status != STATUS_SUCCESS) goto err; /* wait for the initial thread to complete initialization to * be able to interact with it */ status = KeWaitForSingleObject(&init_sem, Executive, KernelMode, FALSE, NULL); if (status != STATUS_SUCCESS) goto close_init_thread; /* create the timer thread responsible with delivering timer interrupts */ status = PsCreateSystemThread(&timer_thread_handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, timer_thread, NULL); if (status != STATUS_SUCCESS) goto close_init_thread; /* get references to the init and timer threads to be able to wait on them */ status = ObReferenceObjectByHandle(init_thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &init_thread_obj, NULL); if (!NT_SUCCESS(status)) goto close_timer_thread; status = ObReferenceObjectByHandle(timer_thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &timer_thread_obj, NULL); if (!NT_SUCCESS(status)) goto deref_init_thread_obj; /* we don't need the handles, we have access to the objects */ ZwClose(timer_thread_handle); ZwClose(init_thread_handle); return STATUS_SUCCESS; deref_init_thread_obj: ObDereferenceObject(init_thread_obj); close_timer_thread: ZwClose(timer_thread_handle); close_init_thread: ZwClose(init_thread_handle); err: return status; }
int sema_init( struct semaphore *sem, int value) { int limit = value ? value : 1; sem->sem = ( struct kerenl_sem*)ddk_mem_alloc( sizeof( KSEMAPHORE), 0); KeInitializeSemaphore( ( KSEMAPHORE*)sem->sem, value, limit); return 0; }
static void* sem_alloc(int count) { KSEMAPHORE *sem=ExAllocatePoolWithTag(NonPagedPool, sizeof(*sem), 'LKLS'); if (!sem) return NULL; KeInitializeSemaphore(sem, count, 100); return sem; }
PGPdiskSemaphore::PGPdiskSemaphore(PGPUInt32 count, PGPUInt32 limit) { mSemPointer = new KSEMAPHORE; if (NULL==(int)(mSemPointer)) mInitErr = DualErr(kPGDMinorError_OutOfMemory); if (mInitErr.IsntError()) { KeInitializeSemaphore(mSemPointer, count, limit); } }
BOOL ShareLockKImp::InitializeShareSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName) { UninitializeShareLock(); m_LockType = LockTypeSemaphore; KeInitializeSemaphore(&m_LockObject.m_Semaphore.m_Semaphore, lInitialCount, lMaximumCount); return TRUE; }
// UsbDev Constructor UsbDev::UsbDev() :m_UsbConfigurationNo(0), m_hConfigureation(NULL), m_NumberOfInterfaces(0), m_SuspendIrp(NULL) { DBGU_TRACE("@@UsbDev::UsbDev()\n"); RtlZeroMemory(&m_DevDesc, sizeof(USB_DEVICE_DESCRIPTOR)); for(int i=0;i<MAX_CONFIGURATION_NO;i++) m_pConfigDesc[i] = NULL; //2010/3/9 11:20上午 KeInitializeSpinLock(&IdleReqStateLock); //2010/8/17 03:50下午 //KeInitializeSpinLock(&SetConfigSpinLock); KeInitializeSemaphore(&CallUSBSemaphore, 1, 1); //KeInitializeSpinLock(&m_IdleReqStateLock); }
void _rtw_init_sema(_sema *sema, int init_val) { #ifdef PLATFORM_LINUX sema_init(sema, init_val); #endif #ifdef PLATFORM_OS_XP KeInitializeSemaphore(sema, init_val, SEMA_UPBND); // count=0; #endif #ifdef PLATFORM_OS_CE if(*sema == NULL) *sema = CreateSemaphore(NULL, init_val, SEMA_UPBND, NULL); #endif }
BOOLEAN InitEventHandler() /*++ Routine Description: 初始化工作 Arguments: None. Return Value: TRUE if successful, and FALSE if not. Author: Fypher --*/ { PAGED_CODE(); KeInitializeSemaphore(&g_EventDataSemaphore, 0 , MAXLONG); KeInitializeSpinLock(&g_EventDataLock); InitializeListHead(&g_EventDataLinkListHead); ExInitializeNPagedLookasideList(&g_EventDataPageList, NULL, NULL, 0, sizeof(EVENTDATA), ALLOC_TAG, 0); g_ulEventDataCount = 0; g_ulMajorProtectedMask = 0; SetMajorProtectedType(CRIME_MAJOR_ALL, TRUE); return TRUE; }
NTSTATUS MobiUsb_AddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Description: Arguments: DriverObject - Store the pointer to the object representing us. PhysicalDeviceObject - Pointer to the device object created by the undelying bus driver. Return: STATUS_SUCCESS - if successful STATUS_UNSUCCESSFUL - otherwise --*/ { NTSTATUS ntStatus; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; POWER_STATE state; KIRQL oldIrql; MobiUsb_DbgPrint(3, ("file mobiusb: MobiUsb_AddDevice - begins\n")); deviceObject = NULL; ntStatus = IoCreateDevice( DriverObject, // our driver object sizeof(DEVICE_EXTENSION), // extension size for us NULL, // name for this device FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics FALSE, // Not exclusive &deviceObject); // Our device object if(!NT_SUCCESS(ntStatus)) { // // returning failure here prevents the entire stack from functioning, // but most likely the rest of the stack will not be able to create // device objects either, so it is still OK. // MobiUsb_DbgPrint(1, ("file mobiusb: Failed to create device object\n")); return ntStatus; } // // Initialize the device extension // deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; deviceExtension->FunctionalDeviceObject = deviceObject; deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; #ifdef MOBI_DIRECT_IO deviceObject->Flags |= DO_DIRECT_IO; #else deviceObject->Flags |= DO_BUFFERED_IO; #endif // // initialize the device state lock and set the device state // KeInitializeSpinLock(&deviceExtension->DevStateLock); INITIALIZE_PNP_STATE(deviceExtension); // //initialize OpenHandleCount // deviceExtension->OpenHandleCount = 0; // // Initialize the selective suspend variables // KeInitializeSpinLock(&deviceExtension->IdleReqStateLock); deviceExtension->IdleReqPend = 0; deviceExtension->PendingIdleIrp = NULL; // // Initialize the vendor command semaphore // KeInitializeSemaphore(&deviceExtension->CallUSBSemaphore, 1, 1); // // Hold requests until the device is started // deviceExtension->QueueState = HoldRequests; // // Initialize the queue and the queue spin lock // InitializeListHead(&deviceExtension->NewRequestsQueue); KeInitializeSpinLock(&deviceExtension->QueueLock); // // Initialize the remove event to not-signaled. // KeInitializeEvent(&deviceExtension->RemoveEvent, SynchronizationEvent, FALSE); // // Initialize the stop event to signaled. // This event is signaled when the OutstandingIO becomes 1 // KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, TRUE); // // OutstandingIo count biased to 1. // Transition to 0 during remove device means IO is finished. // Transition to 1 means the device can be stopped // deviceExtension->OutStandingIO = 1; KeInitializeSpinLock(&deviceExtension->IOCountLock); // // Delegating to WMILIB // ntStatus = MobiUsb_WmiRegistration(deviceExtension); if(!NT_SUCCESS(ntStatus)) { MobiUsb_DbgPrint(1, ("file mobiusb: MobiUsb_WmiRegistration failed with %X\n", ntStatus)); IoDeleteDevice(deviceObject); return ntStatus; } // // set the flags as underlying PDO // if(PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) { deviceObject->Flags |= DO_POWER_PAGABLE; } // // Typically, the function driver for a device is its // power policy owner, although for some devices another // driver or system component may assume this role. // Set the initial power state of the device, if known, by calling // PoSetPowerState. // deviceExtension->DevPower = PowerDeviceD0; deviceExtension->SysPower = PowerSystemWorking; state.DeviceState = PowerDeviceD0; PoSetPowerState(deviceObject, DevicePowerState, state); // // attach our driver to device stack // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. // deviceExtension->TopOfStackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); if(NULL == deviceExtension->TopOfStackDeviceObject) { MobiUsb_WmiDeRegistration(deviceExtension); IoDeleteDevice(deviceObject); return STATUS_NO_SUCH_DEVICE; } // // Register device interfaces // ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject, &GUID_CLASS_VCMOBI_MOBI, NULL, &deviceExtension->InterfaceName); if(!NT_SUCCESS(ntStatus)) { MobiUsb_WmiDeRegistration(deviceExtension); IoDetachDevice(deviceExtension->TopOfStackDeviceObject); IoDeleteDevice(deviceObject); return ntStatus; } //MobiUsb_DbgPrint(3, ("file mobiusb: interfacename: Filename = %ws nameLength = %d\n", deviceExtension->InterfaceName.Buffer, deviceExtension->InterfaceName.Length / sizeof(WCHAR))); if(IoIsWdmVersionAvailable(1, 0x20)) { deviceExtension->WdmVersion = WinXpOrBetter; } else if(IoIsWdmVersionAvailable(1, 0x10)) { deviceExtension->WdmVersion = Win2kOrBetter; } else if(IoIsWdmVersionAvailable(1, 0x5)) { deviceExtension->WdmVersion = WinMeOrBetter; } else if(IoIsWdmVersionAvailable(1, 0x0)) { deviceExtension->WdmVersion = Win98OrBetter; } MobiUsb_DbgPrint(3, ("file mobiusb: WdmVersion = %d\n", deviceExtension->WdmVersion)); deviceExtension->SSRegistryEnable = 0; deviceExtension->SSEnable = 0; // // WinXP only // check the registry flag - // whether the device should selectively // suspend when idle // if(WinXpOrBetter == deviceExtension->WdmVersion) { MobiUsb_GetRegistryDword(MOBIUSB_REGISTRY_PARAMETERS_PATH, L"VCMobiEnable", &deviceExtension->SSRegistryEnable); if(deviceExtension->SSRegistryEnable) { // // initialize DPC // KeInitializeDpc(&deviceExtension->DeferredProcCall, DpcRoutine, deviceObject); // // initialize the timer. // the DPC and the timer in conjunction, // monitor the state of the device to // selectively suspend the device. // KeInitializeTimerEx(&deviceExtension->Timer, NotificationTimer); // // Initialize the NoDpcWorkItemPendingEvent to signaled state. // This event is cleared when a Dpc is fired and signaled // on completion of the work-item. // KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent, NotificationEvent, TRUE); // // Initialize the NoIdleReqPendEvent to ensure that the idle request // is indeed complete before we unload the drivers. // KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent, NotificationEvent, TRUE); } } // // Clear the DO_DEVICE_INITIALIZING flag. // Note: Do not clear this flag until the driver has set the // device power state and the power DO flags. // deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; MobiUsb_DbgPrint(3, ("file mobiusb: MobiUsb_AddDevice - ends\n")); return ntStatus; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: DriverObject - pointer to the driver object registryPath - pointer to a unicode string representing the path, to driver-specific key in the registry. Return Value: STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise --*/ { NTSTATUS status = STATUS_SUCCESS; NTSTATUS cleanupStatus; UNICODE_STRING unicodeDeviceName; UNICODE_STRING unicodeDosDeviceName; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; HANDLE threadHandle; UNICODE_STRING sddlString; ULONG devExtensionSize; UNREFERENCED_PARAMETER (RegistryPath); LSP_KDPRINT(("DriverEntry Enter \n")); (void) RtlInitUnicodeString(&unicodeDeviceName, LSP_DEVICE_NAME_U); (void) RtlInitUnicodeString( &sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)"); // // We will create a secure deviceobject so that only processes running // in admin and local system account can access the device. Refer // "Security Descriptor String Format" section in the platform // SDK documentation to understand the format of the sddl string. // We need to do because this is a legacy driver and there is no INF // involved in installing the driver. For PNP drivers, security descriptor // is typically specified for the FDO in the INF file. // /* includes LSP Session Buffer Size */ devExtensionSize = sizeof(DEVICE_EXTENSION) + LSP_SESSION_BUFFER_SIZE - 1; status = IoCreateDevice( DriverObject, devExtensionSize, &unicodeDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject); //status = IoCreateDeviceSecure( // DriverObject, // devExtensionSize, // &unicodeDeviceName, // FILE_DEVICE_UNKNOWN, // 0, // (BOOLEAN) FALSE, //&SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R_RES_R, /* &sddlString, */ // (LPCGUID)&GUID_DEVCLASS_LSP, // &deviceObject); if (!NT_SUCCESS(status)) { return status; } DbgPrint("DeviceObject %p\n", deviceObject); // // Allocate and initialize a Unicode String containing the Win32 name // for our device. // (void)RtlInitUnicodeString( &unicodeDosDeviceName, LSP_DOS_DEVICE_NAME_U ); IoDeleteSymbolicLink(&unicodeDosDeviceName); status = IoCreateSymbolicLink( (PUNICODE_STRING) &unicodeDosDeviceName, (PUNICODE_STRING) &unicodeDeviceName ); if (!NT_SUCCESS(status)) { IoDeleteDevice(deviceObject); return status; } deviceExtension = deviceObject->DeviceExtension; RtlZeroMemory(deviceExtension, sizeof(deviceExtension)); KeInitializeSpinLock(&deviceExtension->LspLock); #if 1 { // 2.0 TDI_ADDRESS_LPX deviceAddress = {0x1027, 0x00, 0x0d, 0x0b, 0x5d, 0x80, 0x03}; // PALE TDI_ADDRESS_LPX localAddress = {0x0000, 0x00, 0x03, 0xff, 0x5d, 0xac, 0xb8}; RtlCopyMemory( &deviceExtension->DeviceAddress, &deviceAddress, sizeof(TDI_ADDRESS_LPX)); RtlCopyMemory( &deviceExtension->LocalAddress, &localAddress, sizeof(TDI_ADDRESS_LPX)); } #endif deviceExtension->CloseWorkItem = IoAllocateWorkItem(deviceObject); if (NULL == deviceExtension->CloseWorkItem) { IoDeleteDevice(deviceObject); return STATUS_INSUFFICIENT_RESOURCES; } DriverObject->MajorFunction[IRP_MJ_CREATE]= LspDispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = LspDispatchClose; DriverObject->MajorFunction[IRP_MJ_READ] = LspDispatchRead; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = LspDispatchCleanup; DriverObject->DriverStartIo = LspStartIo; DriverObject->DriverUnload = LspUnload; // deviceObject->Flags |= DO_BUFFERED_IO; deviceObject->Flags |= DO_DIRECT_IO; // // This is used to serialize access to the queue. // KeInitializeSpinLock(&deviceExtension->QueueLock); KeInitializeSemaphore(&deviceExtension->IrpQueueSemaphore, 0, MAXLONG ); // // Initialize the pending Irp device queue // InitializeListHead( &deviceExtension->PendingIrpQueue ); KeInitializeEvent( &deviceExtension->LspCompletionEvent, NotificationEvent, FALSE); // // Initialize the cancel safe queue // IoCsqInitialize( &deviceExtension->CancelSafeQueue, LspInsertIrp, LspRemoveIrp, LspPeekNextIrp, LspAcquireLock, LspReleaseLock, LspCompleteCanceledIrp ); // // 10 is multiplied because system time is specified in 100ns units // deviceExtension->PollingInterval.QuadPart = Int32x32To64( LSP_RETRY_INTERVAL, -10); // // Note down system time // KeQuerySystemTime (&deviceExtension->LastPollTime); // // Start the polling thread. // deviceExtension->ThreadShouldStop = FALSE; status = PsCreateSystemThread(&threadHandle, (ACCESS_MASK)0, NULL, (HANDLE) 0, NULL, LspPollingThread, deviceObject ); if( !NT_SUCCESS( status )) { IoDeleteSymbolicLink( &unicodeDosDeviceName ); IoDeleteDevice( deviceObject ); return status; } // // Convert the Thread object handle into a pointer to the Thread object // itself. Then close the handle. // ObReferenceObjectByHandle( threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &deviceExtension->ThreadObject, NULL ); ZwClose(threadHandle); // // Finish initialization // deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; LSP_KDPRINT(("DriverEntry Exit = %x\n", status)); return status; }
NTSTATUS DriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: DriverObject - pointer to the driver object registryPath - pointer to a unicode string representing the path, to driver-specific key in the registry. Return Value: STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise --*/ { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING unicodeDeviceName; UNICODE_STRING unicodeDosDeviceName; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION devExtension; HANDLE threadHandle; UNICODE_STRING sddlString; UNREFERENCED_PARAMETER (RegistryPath); CSAMP_KDPRINT(("DriverEntry Enter \n")); (void) RtlInitUnicodeString(&unicodeDeviceName, CSAMP_DEVICE_NAME_U); (void) RtlInitUnicodeString( &sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)"); // // We will create a secure deviceobject so that only processes running // in admin and local system account can access the device. Refer // "Security Descriptor String Format" section in the platform // SDK documentation to understand the format of the sddl string. // We need to do because this is a legacy driver and there is no INF // involved in installing the driver. For PNP drivers, security descriptor // is typically specified for the FDO in the INF file. // status = IoCreateDeviceSecure( DriverObject, sizeof(DEVICE_EXTENSION), &unicodeDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, (BOOLEAN) FALSE, &sddlString, (LPCGUID)&GUID_DEVCLASS_CANCEL_SAMPLE, &deviceObject ); if (!NT_SUCCESS(status)) { return status; } DbgPrint("DeviceObject %p\n", deviceObject); // // Allocate and initialize a Unicode String containing the Win32 name // for our device. // (void)RtlInitUnicodeString( &unicodeDosDeviceName, CSAMP_DOS_DEVICE_NAME_U ); status = IoCreateSymbolicLink( (PUNICODE_STRING) &unicodeDosDeviceName, (PUNICODE_STRING) &unicodeDeviceName ); if (!NT_SUCCESS(status)) { IoDeleteDevice(deviceObject); return status; } devExtension = deviceObject->DeviceExtension; DriverObject->MajorFunction[IRP_MJ_CREATE]= DriverObject->MajorFunction[IRP_MJ_CLOSE] = CsampCreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = CsampRead; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CsampCleanup; DriverObject->DriverUnload = CsampUnload; // // Set the flag signifying that we will do buffered I/O. This causes NT // to allocate a buffer on a ReadFile operation which will then be copied // back to the calling application by the I/O subsystem // deviceObject->Flags |= DO_BUFFERED_IO; // // This is used to serailize access to the queue. // KeInitializeSpinLock(&devExtension->QueueLock); KeInitializeSemaphore(&devExtension->IrpQueueSemaphore, 0, MAXLONG ); // // Initialize the pending Irp devicequeue // InitializeListHead( &devExtension->PendingIrpQueue ); // // Initialize the cancel safe queue // IoCsqInitialize( &devExtension->CancelSafeQueue, CsampInsertIrp, CsampRemoveIrp, CsampPeekNextIrp, CsampAcquireLock, CsampReleaseLock, CsampCompleteCanceledIrp ); // // 10 is multiplied because system time is specified in 100ns units // devExtension->PollingInterval.QuadPart = Int32x32To64( CSAMP_RETRY_INTERVAL, -10); // // Note down system time // KeQuerySystemTime (&devExtension->LastPollTime); // // Start the polling thread. // devExtension->ThreadShouldStop = FALSE; status = PsCreateSystemThread(&threadHandle, (ACCESS_MASK)0, NULL, (HANDLE) 0, NULL, CsampPollingThread, deviceObject ); if ( !NT_SUCCESS( status )) { IoDeleteSymbolicLink( &unicodeDosDeviceName ); IoDeleteDevice( deviceObject ); return status; } // // Convert the Thread object handle into a pointer to the Thread object // itself. Then close the handle. // ObReferenceObjectByHandle(threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &devExtension->ThreadObject, NULL ); ZwClose(threadHandle); CSAMP_KDPRINT(("DriverEntry Exit = %x\n", status)); ASSERT(NT_SUCCESS(status)); return status; }
BOOLEAN FsRtlInitSystem ( ) { ULONG i; ULONG Value; UNICODE_STRING ValueName; extern KSEMAPHORE FsRtlpUncSemaphore; PAGED_CODE(); // // Allocate and initialize all the paging Io resources // FsRtlPagingIoResources = FsRtlAllocatePool( NonPagedPool, FSRTL_NUMBER_OF_RESOURCES * sizeof(ERESOURCE) ); for (i=0; i < FSRTL_NUMBER_OF_RESOURCES; i++) { ExInitializeResource( &FsRtlPagingIoResources[i] ); } // // Initialize the global tunneling structures. // FsRtlInitializeTunnels(); // // Initialize the global filelock structures. // FsRtlInitializeFileLocks(); // // Initialize the global largemcb structures. // FsRtlInitializeLargeMcbs(); // // Initialize the semaphore used to guard loading of the MUP // KeInitializeSemaphore( &FsRtlpUncSemaphore, 1, MAXLONG ); // // Pull the bit from the registry telling us whether to do a safe // or dangerous extension truncation. // ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME; ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR); ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME); if (NT_SUCCESS(FsRtlGetCompatibilityModeValue( &ValueName, &Value )) && (Value != 0)) { FsRtlSafeExtensions = FALSE; } // // Initialize the FsRtl stack overflow work QueueObject and thread. // if (!NT_SUCCESS(FsRtlInitializeWorkerThread())) { return FALSE; } return TRUE; }
NTSTATUS Serenum_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT BusPhysicalDeviceObject) /*++ Routine Description. A bus has been found. Attach our FDO to it. Allocate any required resources. Set things up. And be prepared for the first ``start device.'' Arguments: BusPhysicalDeviceObject - Device object representing the bus. That to which we attach a new FDO. DriverObject - This very self referenced driver. --*/ { NTSTATUS status; PDEVICE_OBJECT deviceObject; PFDO_DEVICE_DATA pDeviceData; HANDLE keyHandle; ULONG actualLength; PAGED_CODE(); Serenum_KdPrint_Def(SER_DBG_PNP_TRACE, ("Add Device: 0x%x\n", BusPhysicalDeviceObject)); // // Create our FDO // status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, 0, TRUE, &deviceObject); if (NT_SUCCESS(status)) { pDeviceData = (PFDO_DEVICE_DATA)deviceObject->DeviceExtension; RtlFillMemory (pDeviceData, sizeof (FDO_DEVICE_DATA), 0); pDeviceData->IsFDO = TRUE; pDeviceData->DebugLevel = SER_DEFAULT_DEBUG_OUTPUT_LEVEL; pDeviceData->Self = deviceObject; pDeviceData->AttachedPDO = NULL; pDeviceData->NumPDOs = 0; pDeviceData->DeviceState = PowerDeviceD0; pDeviceData->SystemState = PowerSystemWorking; pDeviceData->PDOForcedRemove = FALSE; pDeviceData->SystemWake=PowerSystemUnspecified; pDeviceData->DeviceWake=PowerDeviceUnspecified; pDeviceData->Removed = FALSE; // // Set the PDO for use with PlugPlay functions // pDeviceData->UnderlyingPDO = BusPhysicalDeviceObject; // // Attach our filter driver to the device stack. // the return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. // // Our filter will send IRPs to the top of the stack and use the PDO // for all PlugPlay functions. // pDeviceData->TopOfStack = IoAttachDeviceToDeviceStack(deviceObject, BusPhysicalDeviceObject); if (!pDeviceData->TopOfStack) { Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR, ("AddDevice: IoAttach failed (%x)", status)); IoDeleteDevice(deviceObject); return STATUS_UNSUCCESSFUL; } // // Set the type of IO we do // if (pDeviceData->TopOfStack->Flags & DO_BUFFERED_IO) { deviceObject->Flags |= DO_BUFFERED_IO; } else if (pDeviceData->TopOfStack->Flags & DO_DIRECT_IO) { deviceObject->Flags |= DO_DIRECT_IO; } // // Bias outstanding request to 1 so that we can look for a // transition to zero when processing the remove device PlugPlay IRP. // pDeviceData->OutstandingIO = 1; KeInitializeEvent(&pDeviceData->RemoveEvent, SynchronizationEvent, FALSE); KeInitializeSemaphore(&pDeviceData->CreateSemaphore, 1, 1); KeInitializeSpinLock(&pDeviceData->EnumerationLock); // // Tell the PlugPlay system that this device will need an interface // device class shingle. // // It may be that the driver cannot hang the shingle until it starts // the device itself, so that it can query some of its properties. // (Aka the shingles guid (or ref string) is based on the properties // of the device.) // status = IoRegisterDeviceInterface(BusPhysicalDeviceObject, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR, NULL, &pDeviceData->DevClassAssocName); if (!NT_SUCCESS(status)) { Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR, ("AddDevice: IoRegisterDCA failed (%x)", status)); IoDetachDevice(pDeviceData->TopOfStack); IoDeleteDevice(deviceObject); return status; } // // If for any reason you need to save values in a safe location that // clients of this DeviceClassAssociate might be interested in reading // here is the time to do so, with the function // IoOpenDeviceClassRegistryKey // the symbolic link name used is was returned in // pDeviceData->DevClassAssocName (the same name which is returned by // IoGetDeviceClassAssociations and the SetupAPI equivs. // #if DBG { PWCHAR deviceName = NULL; ULONG nameLength = 0; status = IoGetDeviceProperty(BusPhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &nameLength); if ((nameLength != 0) && (status == STATUS_BUFFER_TOO_SMALL)) { deviceName = ExAllocatePool(NonPagedPool, nameLength); if (NULL == deviceName) { goto someDebugStuffExit; } IoGetDeviceProperty(BusPhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, nameLength, deviceName, &nameLength); Serenum_KdPrint(pDeviceData, SER_DBG_PNP_TRACE, ("AddDevice: %x to %x->%x (%ws) \n", deviceObject, pDeviceData->TopOfStack, BusPhysicalDeviceObject, deviceName)); } someDebugStuffExit: ; if (deviceName != NULL) { ExFreePool(deviceName); } } #endif // DBG // // Turn on the shingle and point it to the given device object. // status = IoSetDeviceInterfaceState(&pDeviceData->DevClassAssocName, TRUE); if (!NT_SUCCESS(status)) { Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR, ("AddDevice: IoSetDeviceClass failed (%x)", status)); return status; } // // Open the registry and read in our settings // status = IoOpenDeviceRegistryKey(pDeviceData->UnderlyingPDO, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_READ, &keyHandle); if (status == STATUS_SUCCESS) { status = Serenum_GetRegistryKeyValue(keyHandle, L"SkipEnumerations", sizeof(L"SkipEnumerations"), &pDeviceData->SkipEnumerations, sizeof(pDeviceData->SkipEnumerations), &actualLength); if ((status != STATUS_SUCCESS) || (actualLength != sizeof(pDeviceData->SkipEnumerations))) { pDeviceData->SkipEnumerations = 0; status = STATUS_SUCCESS; } ZwClose(keyHandle); } } if (NT_SUCCESS(status)) { deviceObject->Flags |= DO_POWER_PAGABLE; deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; } return status; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING ntDeviceName; UNICODE_STRING dosDeviceName; PDEVICE_EXTENSION deviceExtension; PDEVICE_OBJECT deviceObject = NULL; kprintf(" DriverEntry: %wZ\n", RegistryPath); GetProcessNameOffset(); RtlInitUnicodeString(&ntDeviceName, TEST_KIDISPAT_DEVICE_NAME_W); //initialize InitializeListHead(&g_HookInfoListHead); g_Ksmp= (KSEMAPHORE*)kmalloc(sizeof(KSEMAPHORE)); // save old system call locations KeInitializeSemaphore(g_Ksmp, SemaphoreCount, SemaphoreCount); Status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), // DeviceExtensionSize &ntDeviceName, // DeviceName FILE_DEVICE_TEST_KIDISPAT, // DeviceType 0, // DeviceCharacteristics TRUE, // Exclusive &deviceObject // [OUT] ); if(!NT_SUCCESS(Status)) { kprintf(" IoCreateDevice Error Code = 0x%X\n", Status); return Status; } deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; // // Set up synchronization objects, state info,, etc. // // // Create a symbolic link that Win32 apps can specify to gain access // to this driver/device // RtlInitUnicodeString(&dosDeviceName, TEST_KIDISPAT_DOS_DEVICE_NAME_W); Status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName); if(!NT_SUCCESS(Status)) { kprintf(" IoCreateSymbolicLink Error Code = 0x%X\n", Status); // // Delete Object // IoDeleteDevice(deviceObject); return Status; } // // Create dispatch points for device control, create, close. // DriverObject->MajorFunction[IRP_MJ_CREATE] = Test_kidispatDispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = Test_kidispatDispatchClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Test_kidispatDispatchDeviceControl; DriverObject->DriverUnload = Test_kidispatUnload; return Status; }
NTSTATUS ExInitializeResource ( IN PNTDDK_ERESOURCE Resource ) /*++ Routine Description: This routine initializes the input resource variable Arguments: Resource - Supplies the resource variable being initialized Return Value: Status of the operation. --*/ { ULONG i; ASSERTMSG("A resource cannot be in paged pool ", MmDeterminePoolType(Resource) == NonPagedPool); // // Initialize the shared and exclusive waiting counters and semaphore. // The counters indicate how many are waiting for access to the resource // and the semaphores are used to wait on the resource. Note that // the semaphores can also indicate the number waiting for a resource // however there is a race condition in the algorithm on the acquire // side if count if not updated before the critical section is exited. // So we need to have an outside counter. // Resource->NumberOfSharedWaiters = 0; Resource->NumberOfExclusiveWaiters = 0; KeInitializeSemaphore ( &Resource->SharedWaiters, 0, MAXLONG ); KeInitializeEvent ( &Resource->ExclusiveWaiters, SynchronizationEvent, FALSE ); KeInitializeSpinLock ( &Resource->SpinLock ); Resource->OwnerThreads = Resource->InitialOwnerThreads; Resource->OwnerCounts = Resource->InitialOwnerCounts; Resource->TableSize = INITIAL_TABLE_SIZE; Resource->ActiveCount = 0; Resource->TableRover = 1; Resource->Flag = 0; for(i=0; i < INITIAL_TABLE_SIZE; i++) { Resource->OwnerThreads[i] = 0; Resource->OwnerCounts[i] = 0; } Resource->ContentionCount = 0; InitializeListHead( &Resource->SystemResourcesList ); #if defined(_X86_) && !FPO if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) { Resource->CreatorBackTraceIndex = RtlLogStackBackTrace(); } else { Resource->CreatorBackTraceIndex = 0; } #endif // _X86_ && !FPO if (Resource >= (PNTDDK_ERESOURCE)MM_USER_PROBE_ADDRESS) { ExInterlockedInsertTailList ( &ExpSystemResourcesList, &Resource->SystemResourcesList, &ExpResourceSpinLock ); } return STATUS_SUCCESS; }
//@@@@@@@@@@@@@@@@@@@@@@@@ // IRQL = passive level //@@@@@@@@@@@@@@@@@@@@@@@@@ extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS Status = {0}; DbgPrint("Keyboard Filter Driver - DriverEntry\nCompiled at " __TIME__ " on " __DATE__ "\n"); ///////////////////////////////////////////////////////////////////////////////////////// // Fill in IRP dispatch table in the DriverObject to handle I/O Request Packets (IRPs) ///////////////////////////////////////////////////////////////////////////////////////// // For a filter driver, we want pass down ALL IRP_MJ_XX requests to the driver which // we are hooking except for those we are interested in modifying. for(int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) pDriverObject->MajorFunction[i] = DispatchPassDown; DbgPrint("Filled dispatch table with generic pass down routine...\n"); //Explicitly fill in the IRP's we want to hook pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; //Go ahead and hook the keyboard now HookKeyboard(pDriverObject); DbgPrint("Hooked IRP_MJ_READ routine...\n"); //Set up our worker thread to handle file writes of the scan codes extracted from the //read IRPs InitThreadKeyLogger(pDriverObject); //Initialize the linked list that will serve as a queue to hold the captured keyboard scan codes PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDriverObject->DeviceObject->DeviceExtension; InitializeListHead(&pKeyboardDeviceExtension->QueueListHead); //Initialize the lock for the linked list queue KeInitializeSpinLock(&pKeyboardDeviceExtension->lockQueue); //Initialize the work queue semaphore KeInitializeSemaphore(&pKeyboardDeviceExtension->semQueue, 0 , MAXLONG); //Create the log file IO_STATUS_BLOCK file_status; OBJECT_ATTRIBUTES obj_attrib; CCHAR ntNameFile[64] = "\\DosDevices\\c:\\klog.txt"; STRING ntNameString; UNICODE_STRING uFileName; RtlInitAnsiString( &ntNameString, ntNameFile); RtlAnsiStringToUnicodeString(&uFileName, &ntNameString, TRUE ); InitializeObjectAttributes(&obj_attrib, &uFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwCreateFile(&pKeyboardDeviceExtension->hLogFile,GENERIC_WRITE,&obj_attrib,&file_status, NULL,FILE_ATTRIBUTE_NORMAL,0,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0); RtlFreeUnicodeString(&uFileName); if (Status != STATUS_SUCCESS) { DbgPrint("Failed to create log file...\n"); DbgPrint("File Status = %x\n",file_status); } else { DbgPrint("Successfully created log file...\n"); DbgPrint("File Handle = %x\n",pKeyboardDeviceExtension->hLogFile); } // Set the DriverUnload procedure pDriverObject->DriverUnload = Unload; DbgPrint("Set DriverUnload function pointer...\n"); DbgPrint("Exiting Driver Entry......\n"); return STATUS_SUCCESS; }
// but this still gives a PFD warning?! NTSTATUS CreateDevice ( IN PDRIVER_OBJECT DriverObject, OUT PDEVICE_OBJECT *DeviceObject ) { NTSTATUS status; UNICODE_STRING devName; PDEVICE_EXTENSION devExtension; HANDLE threadHandle; PDEVICE_OBJECT devObj; ANSI_STRING tmpANSIName; GUID driverGUID; HASH_DRIVER_INFO tmpDevExt; DEBUGOUTHASHDRV(DEBUGLEV_ENTER, ("CreateDevice\n")); ASSERT(DriverObject != NULL); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Building device name...\n")); // We subtrace a sizeof(WCHAR) to discount the #NULL - required // since although the UNICODE_STRING string doesn't require it, swprintf // adds one on anyway // This is a bit of a hack to get the driver's GUID ImpHashDriverExtDetailsInit(&tmpDevExt); driverGUID = tmpDevExt.DriverGUID; ImpHashDriverExtDetailsCleardown(&tmpDevExt); devName.MaximumLength = sizeof(DEVICE_HASH_DIR_NAME) // ^^ dir name + sizeof(WCHAR) // ^^ slash + GUID_STRING_REP_UNICODE_BYTE_LENGTH // ^^ GUID length + sizeof(WCHAR); // ^^ terminating NULL devName.Buffer = FREEOTFE_MEMALLOC(devName.MaximumLength); RtlZeroMemory(devName.Buffer, devName.MaximumLength); // Note the "/" in the format string devName.Length = (USHORT)FREEOTFE_SWPRINTF( devName.Buffer, (devName.MaximumLength / sizeof(*(devName.Buffer))), L"%s\\", DEVICE_HASH_DIR_NAME ); // swprintf returns the number of WCHARs, not the length in bytes devName.Length = devName.Length * sizeof(WCHAR); status = AppendGUIDToUnicodeString(driverGUID, &devName); if (!NT_SUCCESS(status)) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("AppendGUIDToUnicodeString NOT OK\n")); SecZeroAndFreeMemory( devName.Buffer, devName.MaximumLength ); return status; } DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("xdevNameLength: %d\n", devName.Length)); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("xdevNameMaximumLength: %d\n", devName.MaximumLength)); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("About to create device: %ls\n", devName.Buffer)); // Hmmm... I'd prefer to use FILE_DEVICE_UNKNOWN, but since // IOCTL control codes pass through the device type, and we just // pass then through... // (See other call to IoCreateDevice in this file for details why we don't // use FILE_DEVICE_VIRTUAL_DISK) status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &devObj ); if (!NT_SUCCESS(status)) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Status NOT OK\n")); SecZeroAndFreeMemory( devName.Buffer, devName.MaximumLength ); return status; } devExtension = (PDEVICE_EXTENSION)devObj->DeviceExtension; devExtension->zzDeviceName = devName; devExtension->ThreadObject = NULL; devExtension->zzSymbolicLinkName.Buffer = NULL; status = ImpHashDriverExtDetailsInit(&(devExtension->DriverInfo)); if (!NT_SUCCESS(status)) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Failed to ImpHashDriverExtDetailsInit.\n")); DestroyDevice(devObj); return status; } // Create symlink; his allows user applications to CreateFile with // "SymbolicName" DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Building symlink name...\n")); // We add on sizeof(WCHAR) to include the terminating #NULL - required // since although the UNICODE_STRING string doesn't require it, swprintf // adds one on anyway devExtension->zzSymbolicLinkName.MaximumLength = sizeof(DEVICE_HASH_SYMLINK_PREFIX) // ^^ dir name + sizeof(WCHAR) // ^^ slash + GUID_STRING_REP_UNICODE_BYTE_LENGTH // ^^ GUID length + sizeof(WCHAR); // ^^ terminating NULL devExtension->zzSymbolicLinkName.Buffer = FREEOTFE_MEMALLOC(devExtension->zzSymbolicLinkName.MaximumLength); RtlZeroMemory(devExtension->zzSymbolicLinkName.Buffer, devExtension->zzSymbolicLinkName.MaximumLength); devExtension->zzSymbolicLinkName.Length = (USHORT)FREEOTFE_SWPRINTF( devExtension->zzSymbolicLinkName.Buffer, (devExtension->zzSymbolicLinkName.MaximumLength / sizeof(*(devExtension->zzSymbolicLinkName.Buffer))), L"%s", DEVICE_HASH_SYMLINK_PREFIX ); // swprintf returns the number of WCHARs, not the length in bytes devExtension->zzSymbolicLinkName.Length = devExtension->zzSymbolicLinkName.Length * sizeof(WCHAR); status = AppendGUIDToUnicodeString(driverGUID, &devExtension->zzSymbolicLinkName); if (!NT_SUCCESS(status)) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("AppendGUIDToUnicodeString NOT OK\n")); DestroyDevice(devObj); return status; } DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Unicoded symlink name: %ls\n", devExtension->zzSymbolicLinkName.Buffer)); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Length: %d\n", devExtension->zzSymbolicLinkName.Length)); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("MaximumLength: %d\n", devExtension->zzSymbolicLinkName.MaximumLength)); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("About to create dosdevice symlink: %ls -> %ls\n", devExtension->zzSymbolicLinkName.Buffer, devExtension->zzDeviceName.Buffer)); status = IoCreateSymbolicLink(&devExtension->zzSymbolicLinkName, &devExtension->zzDeviceName); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Done, checking status...\n")); if (!NT_SUCCESS(status)) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Status NOT OK\n")); DestroyDevice(devObj); return status; } DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("OK\n")); devObj->Flags |= DO_DIRECT_IO; devObj->Characteristics |= FILE_READ_ONLY_DEVICE; // (Some of the bits following are taken from the DDK src/general/cancel example) // This is used to serialize access to the queue. KeInitializeSpinLock(&devExtension->IRPQueueLock); KeInitializeSemaphore(&devExtension->IRPQueueSemaphore, 0, MAXLONG ); // Initialize the pending Irp devicequeue InitializeListHead(&devExtension->PendingIRPQueue); // Initialize the cancel safe queue IoCsqInitialize(&devExtension->CancelSafeQueue, CSQInsertIrp, CSQRemoveIrp, CSQPeekNextIrp, CSQAcquireLock, CSQReleaseLock, CSQCompleteCanceledIrp); // Create a thread for the device object devExtension->TerminateThread = FALSE; status = PsCreateSystemThread( &threadHandle, (ACCESS_MASK)0, NULL, (HANDLE)0L, // )0L because it's a // driver-created thread NULL, FreeOTFEThread, devObj ); if (!(NT_SUCCESS(status))) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Create thread FAILED.\n")); DestroyDevice(devObj); return status; } DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("OK\n")); // Convert the Thread object handle into a pointer to the Thread object // itself. Then close the handle. status = ObReferenceObjectByHandle( threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &devExtension->ThreadObject, NULL ); DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("Done processing thread; checking status.\n")); if (!NT_SUCCESS(status)) { DEBUGOUTHASHDRV(DEBUGLEV_ERROR, ("Status FAILED.\n")); ZwClose(threadHandle); DestroyDevice(devObj); return status; } DEBUGOUTHASHDRV(DEBUGLEV_INFO, ("OK\n")); // Close the thread handle ZwClose(threadHandle); // This is an easy thing to overlook - we do *not* have to unset the // device's DO_DEVICE_INITIALIZING "Flags" as this function is carried out // undef DriverEntry, and not something like AddDevice *DeviceObject = devObj; DEBUGOUTHASHDRV(DEBUGLEV_EXIT, ("CreateDevice\n")); return STATUS_SUCCESS; }
NTSTATUS NtCreateSemaphore ( __out PHANDLE SemaphoreHandle, __in ACCESS_MASK DesiredAccess, __in_opt POBJECT_ATTRIBUTES ObjectAttributes, __in LONG InitialCount, __in LONG MaximumCount ) /*++ Routine Description: This function creates a semaphore object, sets its initial count to the specified value, sets its maximum count to the specified value, and opens a handle to the object with the specified desired access. Arguments: SemaphoreHandle - Supplies a pointer to a variable that will receive the semaphore object handle. DesiredAccess - Supplies the desired types of access for the semaphore object. ObjectAttributes - Supplies a pointer to an object attributes structure. InitialCount - Supplies the initial count of the semaphore object. MaximumCount - Supplies the maximum count of the semaphore object. Return Value: NTSTATUS. --*/ { HANDLE Handle; KPROCESSOR_MODE PreviousMode; PVOID Semaphore; NTSTATUS Status; // // Get previous processor mode and probe output handle address if // necessary. // PreviousMode = KeGetPreviousMode(); if (PreviousMode != KernelMode) { try { ProbeForWriteHandle(SemaphoreHandle); } except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } } // // Check argument validity. // if ((MaximumCount <= 0) || (InitialCount < 0) || (InitialCount > MaximumCount)) { return STATUS_INVALID_PARAMETER; } // // Allocate semaphore object. // Status = ObCreateObject(PreviousMode, ExSemaphoreObjectType, ObjectAttributes, PreviousMode, NULL, sizeof(KSEMAPHORE), 0, 0, &Semaphore); // // If the semaphore object was successfully allocated, then initialize // the semaphore object and attempt to insert the semaphore object in // the current process' handle table. // if (NT_SUCCESS(Status)) { KeInitializeSemaphore((PKSEMAPHORE)Semaphore, InitialCount, MaximumCount); Status = ObInsertObject(Semaphore, NULL, DesiredAccess, 0, NULL, &Handle); // // If the semaphore object was successfully inserted in the current // process' handle table, then attempt to write the semaphore handle // value. If the write attempt fails, then do not report an error. // When the caller attempts to access the handle value, an access // violation will occur. // if (NT_SUCCESS(Status)) { if (PreviousMode != KernelMode) { try { *SemaphoreHandle = Handle; } except(EXCEPTION_EXECUTE_HANDLER) { NOTHING; } } else { *SemaphoreHandle = Handle; } } }
VOID DLDAcquireShared(PERESOURCE Resource, ULONG BugCheckId, ULONG Line, BOOLEAN WaitForExclusive) { KIRQL oldIrql; ERESOURCE_THREAD Thread = (ERESOURCE_THREAD)PsGetCurrentThread(); POWNER_ENTRY pOwnerEntry; KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); if (!Resource->ActiveCount) { Resource->Flag &= ~ResourceOwnedExclusive; Resource->ActiveCount = 1; Resource->OwnerThreads[1].OwnerThread = Thread; Resource->OwnerThreads[1].OwnerCount = 1; KeReleaseSpinLock(&Resource->SpinLock, oldIrql); return; } if (Resource->Flag & ResourceOwnedExclusive ) { if (Resource->OwnerThreads[0].OwnerThread == Thread) { Resource->OwnerThreads[0].OwnerCount++; KeReleaseSpinLock(&Resource->SpinLock, oldIrql); return; } pOwnerEntry = DLDpFindCurrentThread(Resource, 0); } else { // owned shared by some thread(s) pOwnerEntry = DLDpFindCurrentThread(Resource, Thread); if (!WaitForExclusive && pOwnerEntry->OwnerThread == Thread) { pOwnerEntry->OwnerCount++; KeReleaseSpinLock(&Resource->SpinLock, oldIrql); return; } if (!(Resource->NumberOfExclusiveWaiters)) { pOwnerEntry->OwnerThread = Thread; pOwnerEntry->OwnerCount = 1; Resource->ActiveCount++; KeReleaseSpinLock(&Resource->SpinLock, oldIrql); return; } } if (!(Resource->SharedWaiters)) { Resource->SharedWaiters = (PKSEMAPHORE)ExAllocatePoolWithTag(NonPagedPool, sizeof(KSEMAPHORE),RESOURCE_SEMAFORE_TAG); KeInitializeSemaphore(Resource->SharedWaiters,0,0x7fffffff); } Resource->NumberOfSharedWaiters++; PTHREAD_STRUCT ThrdStruct = DLDAllocFindThread(Thread); // Set WaitingResource for current thread ThrdStruct->WaitingResource = Resource; ThrdStruct->BugCheckId = BugCheckId; ThrdStruct->Line = Line; KeReleaseSpinLock(&Resource->SpinLock, oldIrql); DLDpWaitForResource(Resource,&(Resource->SharedWaiters->Header),ThrdStruct); KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); pOwnerEntry = DLDpFindCurrentThread(Resource, Thread); pOwnerEntry->OwnerThread = Thread; pOwnerEntry->OwnerCount = 1; ThrdStruct->WaitingResource = NULL; ThrdStruct->ThreadId = 0; ThrdStruct->BugCheckId = 0; ThrdStruct->Line = 0; KeReleaseSpinLock(&Resource->SpinLock, oldIrql); return; }
NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* * FUNCTION: Entry-point for the driver * ARGUMENTS: * DriverObject: Our driver object * RegistryPath: Unused * RETURNS: * STATUS_SUCCESS on successful initialization of at least one drive * STATUS_NO_SUCH_DEVICE if we didn't find even one drive * STATUS_UNSUCCESSFUL otherwise */ { HANDLE ThreadHandle; UNREFERENCED_PARAMETER(RegistryPath); /* * Set up dispatch routines */ DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)CreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)CreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)ReadWrite; DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)ReadWrite; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DeviceIoctl; DriverObject->DriverUnload = Unload; /* * We depend on some zeroes in these structures. I know this is supposed to be * initialized to 0 by the complier but this makes me feel beter. */ memset(&gControllerInfo, 0, sizeof(gControllerInfo)); /* * Set up queue. This routine cannot fail (trust me, I wrote it). */ IoCsqInitialize(&Csq, CsqInsertIrp, CsqRemoveIrp, CsqPeekNextIrp, CsqAcquireLock, CsqReleaseLock, CsqCompleteCanceledIrp); /* * ...and its lock */ KeInitializeSpinLock(&IrpQueueLock); /* * ...and the queue list itself */ InitializeListHead(&IrpQueue); /* * The queue is counted by a semaphore. The queue management thread * blocks on this semaphore, so if requests come in faster than the queue * thread can handle them, the semaphore count goes up. */ KeInitializeSemaphore(&QueueSemaphore, 0, 0x7fffffff); /* * Event to terminate that thread */ KeInitializeEvent(&QueueThreadTerminate, NotificationEvent, FALSE); /* * Create the queue processing thread. Save its handle in the global variable * ThreadHandle so we can wait on its termination during Unload. */ if(PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, QueueThread, 0) != STATUS_SUCCESS) { WARN_(FLOPPY, "Unable to create system thread; failing init\n"); return STATUS_INSUFFICIENT_RESOURCES; } if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, PsThreadType, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS) { WARN_(FLOPPY, "Unable to reference returned thread handle; failing init\n"); return STATUS_UNSUCCESSFUL; } /* * Close the handle, now that we have the object pointer and a reference of our own. * The handle will certainly not be valid in the context of the caller next time we * need it, as handles are process-specific. */ ZwClose(ThreadHandle); /* * Start the device discovery proces. Returns STATUS_SUCCESS if * it finds even one drive attached to one controller. */ if(!AddControllers(DriverObject)) return STATUS_NO_SUCH_DEVICE; return STATUS_SUCCESS; }
NTSTATUS NTAPI PspCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, IN PEPROCESS TargetProcess, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PINITIAL_TEB InitialTeb, IN BOOLEAN CreateSuspended, IN PKSTART_ROUTINE StartRoutine OPTIONAL, IN PVOID StartContext OPTIONAL) { HANDLE hThread; PEPROCESS Process; PETHREAD Thread; PTEB TebBase = NULL; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status, AccessStatus; HANDLE_TABLE_ENTRY CidEntry; ACCESS_STATE LocalAccessState; PACCESS_STATE AccessState = &LocalAccessState; AUX_ACCESS_DATA AuxData; BOOLEAN Result, SdAllocated; PSECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_SUBJECT_CONTEXT SubjectContext; PAGED_CODE(); PSTRACE(PS_THREAD_DEBUG, "ThreadContext: %p TargetProcess: %p ProcessHandle: %p\n", ThreadContext, TargetProcess, ProcessHandle); /* If we were called from PsCreateSystemThread, then we're kernel mode */ if (StartRoutine) PreviousMode = KernelMode; /* Reference the Process by handle or pointer, depending on what we got */ if (ProcessHandle) { /* Normal thread or System Thread */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_CREATE_THREAD, PsProcessType, PreviousMode, (PVOID*)&Process, NULL); PSREFTRACE(Process); } else { /* System thread inside System Process, or Normal Thread with a bug */ if (StartRoutine) { /* Reference the Process by Pointer */ ObReferenceObject(TargetProcess); Process = TargetProcess; Status = STATUS_SUCCESS; } else { /* Fake ObReference returning this */ Status = STATUS_INVALID_HANDLE; } } /* Check for success */ if (!NT_SUCCESS(Status)) return Status; /* Also make sure that User-Mode isn't trying to create a system thread */ if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess)) { /* Fail */ ObDereferenceObject(Process); return STATUS_INVALID_HANDLE; } /* Create Thread Object */ Status = ObCreateObject(PreviousMode, PsThreadType, ObjectAttributes, PreviousMode, NULL, sizeof(ETHREAD), 0, 0, (PVOID*)&Thread); if (!NT_SUCCESS(Status)) { /* We failed; dereference the process and exit */ ObDereferenceObject(Process); return Status; } /* Zero the Object entirely */ RtlZeroMemory(Thread, sizeof(ETHREAD)); /* Initialize rundown protection */ ExInitializeRundownProtection(&Thread->RundownProtect); /* Initialize exit code */ Thread->ExitStatus = STATUS_PENDING; /* Set the Process CID */ Thread->ThreadsProcess = Process; Thread->Cid.UniqueProcess = Process->UniqueProcessId; /* Create Cid Handle */ CidEntry.Object = Thread; CidEntry.GrantedAccess = 0; Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry); if (!Thread->Cid.UniqueThread) { /* We couldn't create the CID, dereference the thread and fail */ ObDereferenceObject(Thread); return STATUS_INSUFFICIENT_RESOURCES; } /* Save the read cluster size */ Thread->ReadClusterSize = MmReadClusterSize; /* Initialize the LPC Reply Semaphore */ KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1); /* Initialize the list heads and locks */ InitializeListHead(&Thread->LpcReplyChain); InitializeListHead(&Thread->IrpList); InitializeListHead(&Thread->PostBlockList); InitializeListHead(&Thread->ActiveTimerListHead); KeInitializeSpinLock(&Thread->ActiveTimerListLock); /* Acquire rundown protection */ if (!ExAcquireRundownProtection (&Process->RundownProtect)) { /* Fail */ ObDereferenceObject(Thread); return STATUS_PROCESS_IS_TERMINATING; } /* Now let the kernel initialize the context */ if (ThreadContext) { /* User-mode Thread, create Teb */ Status = MmCreateTeb(Process, &Thread->Cid, InitialTeb, &TebBase); if (!NT_SUCCESS(Status)) { /* Failed to create the TEB. Release rundown and dereference */ ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Thread); return Status; } /* Set the Start Addresses */ Thread->StartAddress = (PVOID)KeGetContextPc(ThreadContext); Thread->Win32StartAddress = (PVOID)KeGetContextReturnRegister(ThreadContext); /* Let the kernel intialize the Thread */ Status = KeInitThread(&Thread->Tcb, NULL, PspUserThreadStartup, NULL, Thread->StartAddress, ThreadContext, TebBase, &Process->Pcb); } else { /* System Thread */ Thread->StartAddress = StartRoutine; PspSetCrossThreadFlag(Thread, CT_SYSTEM_THREAD_BIT); /* Let the kernel intialize the Thread */ Status = KeInitThread(&Thread->Tcb, NULL, PspSystemThreadStartup, StartRoutine, StartContext, NULL, NULL, &Process->Pcb); } /* Check if we failed */ if (!NT_SUCCESS(Status)) { /* Delete the TEB if we had done */ if (TebBase) MmDeleteTeb(Process, TebBase); /* Release rundown and dereference */ ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Thread); return Status; } /* Lock the process */ KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&Process->ProcessLock); /* Make sure the proces didn't just die on us */ if (Process->ProcessDelete) goto Quickie; /* Check if the thread was ours, terminated and it was user mode */ if ((Thread->Terminated) && (ThreadContext) && (Thread->ThreadsProcess == Process)) { /* Cleanup, we don't want to start it up and context switch */ goto Quickie; } /* * Insert the Thread into the Process's Thread List * Note, this is the ETHREAD Thread List. It is removed in * ps/kill.c!PspExitThread. */ InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry); Process->ActiveThreads++; /* Start the thread */ KeStartThread(&Thread->Tcb); /* Release the process lock */ ExReleasePushLockExclusive(&Process->ProcessLock); KeLeaveCriticalRegion(); /* Release rundown */ ExReleaseRundownProtection(&Process->RundownProtect); /* Notify WMI */ //WmiTraceProcess(Process, TRUE); //WmiTraceThread(Thread, InitialTeb, TRUE); /* Notify Thread Creation */ PspRunCreateThreadNotifyRoutines(Thread, TRUE); /* Reference ourselves as a keep-alive */ ObReferenceObjectEx(Thread, 2); /* Suspend the Thread if we have to */ if (CreateSuspended) KeSuspendThread(&Thread->Tcb); /* Check if we were already terminated */ if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb); /* Create an access state */ Status = SeCreateAccessStateEx(NULL, ThreadContext ? PsGetCurrentProcess() : Process, &LocalAccessState, &AuxData, DesiredAccess, &PsThreadType->TypeInfo.GenericMapping); if (!NT_SUCCESS(Status)) { /* Access state failed, thread is dead */ PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT); /* If we were suspended, wake it up */ if (CreateSuspended) KeResumeThread(&Thread->Tcb); /* Dispatch thread */ KeReadyThread(&Thread->Tcb); /* Dereference completely to kill it */ ObDereferenceObjectEx(Thread, 2); return Status; } /* Insert the Thread into the Object Manager */ Status = ObInsertObject(Thread, AccessState, DesiredAccess, 0, NULL, &hThread); /* Delete the access state if we had one */ if (AccessState) SeDeleteAccessState(AccessState); /* Check for success */ if (NT_SUCCESS(Status)) { /* Wrap in SEH to protect against bad user-mode pointers */ _SEH2_TRY { /* Return Cid and Handle */ if (ClientId) *ClientId = Thread->Cid; *ThreadHandle = hThread; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Thread insertion failed, thread is dead */ PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT); /* If we were suspended, wake it up */ if (CreateSuspended) KeResumeThread(&Thread->Tcb); /* Dispatch thread */ KeReadyThread(&Thread->Tcb); /* Dereference it, leaving only the keep-alive */ ObDereferenceObject(Thread); /* Close its handle, killing it */ ObCloseHandle(ThreadHandle, PreviousMode); /* Return the exception code */ _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } else {
static void stop(void) { KSEMAPHORE stopme; KeInitializeSemaphore(&stopme, 0, 10); KeWaitForSingleObject(&stopme, Executive, KernelMode, FALSE, NULL); }
NTSTATUS NTAPI PspCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, IN PEPROCESS TargetProcess, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PINITIAL_TEB InitialTeb, IN BOOLEAN CreateSuspended, IN PKSTART_ROUTINE StartRoutine OPTIONAL, IN PVOID StartContext OPTIONAL) { HANDLE hThread; PEPROCESS Process; PETHREAD Thread; PTEB TebBase = NULL; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status, AccessStatus; HANDLE_TABLE_ENTRY CidEntry; ACCESS_STATE LocalAccessState; PACCESS_STATE AccessState = &LocalAccessState; AUX_ACCESS_DATA AuxData; BOOLEAN Result, SdAllocated; PSECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_SUBJECT_CONTEXT SubjectContext; PAGED_CODE(); PSTRACE(PS_THREAD_DEBUG, "ThreadContext: %p TargetProcess: %p ProcessHandle: %p\n", ThreadContext, TargetProcess, ProcessHandle); /* If we were called from PsCreateSystemThread, then we're kernel mode */ if (StartRoutine) PreviousMode = KernelMode; /* Reference the Process by handle or pointer, depending on what we got */ if (ProcessHandle) { /* Normal thread or System Thread */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_CREATE_THREAD, PsProcessType, PreviousMode, (PVOID*)&Process, NULL); PSREFTRACE(Process); } else { /* System thread inside System Process, or Normal Thread with a bug */ if (StartRoutine) { /* Reference the Process by Pointer */ ObReferenceObject(TargetProcess); Process = TargetProcess; Status = STATUS_SUCCESS; } else { /* Fake ObReference returning this */ Status = STATUS_INVALID_HANDLE; } } /* Check for success */ if (!NT_SUCCESS(Status)) return Status; /* Also make sure that User-Mode isn't trying to create a system thread */ if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess)) { /* Fail */ ObDereferenceObject(Process); return STATUS_INVALID_HANDLE; } /* Create Thread Object */ Status = ObCreateObject(PreviousMode, PsThreadType, ObjectAttributes, PreviousMode, NULL, sizeof(ETHREAD), 0, 0, (PVOID*)&Thread); if (!NT_SUCCESS(Status)) { /* We failed; dereference the process and exit */ ObDereferenceObject(Process); return Status; } /* Zero the Object entirely */ RtlZeroMemory(Thread, sizeof(ETHREAD)); /* Initialize rundown protection */ ExInitializeRundownProtection(&Thread->RundownProtect); /* Initialize exit code */ Thread->ExitStatus = STATUS_PENDING; /* Set the Process CID */ Thread->ThreadsProcess = Process; Thread->Cid.UniqueProcess = Process->UniqueProcessId; /* Create Cid Handle */ CidEntry.Object = Thread; CidEntry.GrantedAccess = 0; Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry); if (!Thread->Cid.UniqueThread) { /* We couldn't create the CID, dereference the thread and fail */ ObDereferenceObject(Thread); return STATUS_INSUFFICIENT_RESOURCES; } /* Save the read cluster size */ Thread->ReadClusterSize = MmReadClusterSize; /* Initialize the LPC Reply Semaphore */ KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1); /* Initialize the list heads and locks */ InitializeListHead(&Thread->LpcReplyChain); InitializeListHead(&Thread->IrpList); InitializeListHead(&Thread->PostBlockList); InitializeListHead(&Thread->ActiveTimerListHead); KeInitializeSpinLock(&Thread->ActiveTimerListLock); /* Acquire rundown protection */ if (!ExAcquireRundownProtection (&Process->RundownProtect)) { /* Fail */ ObDereferenceObject(Thread); return STATUS_PROCESS_IS_TERMINATING; } /* Now let the kernel initialize the context */ if (ThreadContext) { /* User-mode Thread, create Teb */ Status = MmCreateTeb(Process, &Thread->Cid, InitialTeb, &TebBase); if (!NT_SUCCESS(Status)) { /* Failed to create the TEB. Release rundown and dereference */ ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Thread); return Status; } /* Set the Start Addresses from the untrusted ThreadContext */ _SEH2_TRY { Thread->StartAddress = (PVOID)KeGetContextPc(ThreadContext); Thread->Win32StartAddress = (PVOID)KeGetContextReturnRegister(ThreadContext); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; /* Let the kernel intialize the Thread */ if (NT_SUCCESS(Status)) { Status = KeInitThread(&Thread->Tcb, NULL, PspUserThreadStartup, NULL, Thread->StartAddress, ThreadContext, TebBase, &Process->Pcb); } } else {
BOOLEAN obtest( void ) { ULONG i; HANDLE Handles[ 2 ]; NTSTATUS Status; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectTypeAName, "ObjectTypeA" ); RtlInitString( &ObjectTypeBName, "ObjectTypeB" ); RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) ); ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer ); ObjectTypeInitializer.ValidAccessMask = -1; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.MaintainHandleCount = TRUE; ObjectTypeInitializer.DumpProcedure = DumpAProc; ObjectTypeInitializer.OpenProcedure = OpenAProc; ObjectTypeInitializer.CloseProcedure = CloseAProc; ObjectTypeInitializer.DeleteProcedure = DeleteAProc; ObjectTypeInitializer.ParseProcedure = ParseAProc; ObCreateObjectType( &ObjectTypeAName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObjectTypeA ); ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.MaintainHandleCount = FALSE; ObjectTypeInitializer.GenericMapping = MyGenericMapping; ObjectTypeInitializer.DumpProcedure = DumpBProc; ObjectTypeInitializer.OpenProcedure = NULL; ObjectTypeInitializer.CloseProcedure = NULL; ObjectTypeInitializer.DeleteProcedure = DeleteBProc; ObjectTypeInitializer.ParseProcedure = NULL; ObCreateObjectType( &ObjectTypeBName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObjectTypeB ); ObpDumpTypes( NULL ); RtlInitString( &DirectoryName, "\\MyObjects" ); InitializeObjectAttributes( &DirectoryObjA, &DirectoryName, OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, NULL ); NtCreateDirectoryObject( &DirectoryHandle, 0, &DirectoryObjA ); NtClose( DirectoryHandle ); RtlInitString( &ObjectAName, "\\myobjects\\ObjectA" ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAName, OBJ_CASE_INSENSITIVE, NULL, NULL ); RtlInitString( &ObjectBName, "\\myobjects\\ObjectB" ); InitializeObjectAttributes( &ObjectBObjA, &ObjectBName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ObCreateObject( KernelMode, ObjectTypeA, &ObjectAObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEA ), 0L, 0L, (PVOID *)&ObjectBodyA ); ObjectA = (POBJECTTYPEA)ObjectBodyA; ObjectA->TypeALength = sizeof( *ObjectA ); for (i=0; i<4; i++) { ObjectA->Stuff[i] = i+1; } KeInitializeEvent( &ObjectA->Event, NotificationEvent, TRUE ); Status = ObCreateObject( KernelMode, ObjectTypeB, &ObjectBObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEB ), 0L, 0L, (PVOID *)&ObjectBodyB ); ObjectB = (POBJECTTYPEB)ObjectBodyB; ObjectB->TypeBLength = sizeof( *ObjectB ); for (i=0; i<16; i++) { ObjectB->Stuff[i] = i+1; } KeInitializeSemaphore ( &ObjectB->Semaphore, 2L, 2L ); Status = ObInsertObject( ObjectBodyA, SYNCHRONIZE | 0x3, NULL, 1, &ObjectBodyA, &ObjectHandleA1 ); DbgPrint( "Status: %lx ObjectBodyA: %lx ObjectHandleA1: %lx\n", Status, ObjectBodyA, ObjectHandleA1 ); Status = ObInsertObject( ObjectBodyB, SYNCHRONIZE | 0x1, NULL, 1, &ObjectBodyB, &ObjectHandleB1 ); DbgPrint( "Status: %lx ObjectBodyB: %lx ObjectHandleB1: %lx\n", Status, ObjectBodyB, ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectAName, "\\MyObjects\\ObjectA" ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAName, OBJ_OPENIF, NULL, NULL ); Status = ObCreateObject( KernelMode, ObjectTypeA, &ObjectAObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEA ), 0L, 0L, (PVOID *)&ObjectBodyA1 ); Status = ObInsertObject( ObjectBodyA1, SYNCHRONIZE | 0x3, NULL, 1, &ObjectBodyA2, &ObjectHandleA2 ); DbgPrint( "Status: %lx ObjectBodyA1: %lx ObjectBodyA2: %lx ObjectHandleA2: %lx\n", Status, ObjectBodyA1, ObjectBodyA2, ObjectHandleA2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); NtClose( ObjectHandleA2 ); ObDereferenceObject( ObjectBodyA2 ); // ObInsertObject,ObjectPointerBias NtWaitForSingleObject( ObjectHandleB1, TRUE, NULL ); Handles[ 0 ] = ObjectHandleA1; Handles[ 1 ] = ObjectHandleB1; NtWaitForMultipleObjects( 2, Handles, WaitAny, TRUE, NULL ); ObReferenceObjectByHandle( ObjectHandleA1, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB1, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA1, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB1, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByPointer( ObjectBodyA, 0L, ObjectTypeA, KernelMode ); ObReferenceObjectByPointer( ObjectBodyB, 0L, ObjectTypeB, KernelMode ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectAPathName, "\\MyObjects\\ObjectA" ); RtlInitString( &ObjectBPathName, "\\MyObjects\\ObjectB" ); ObReferenceObjectByName( &ObjectAPathName, OBJ_CASE_INSENSITIVE, 0L, ObjectTypeA, KernelMode, NULL, &ObjectBodyA ); ObReferenceObjectByName( &ObjectBPathName, OBJ_CASE_INSENSITIVE, 0L, ObjectTypeB, KernelMode, NULL, &ObjectBodyB ); DbgPrint( "Reference Name %s = %lx\n", ObjectAPathName.Buffer, ObjectBodyA ); DbgPrint( "Reference Name %s = %lx\n", ObjectBPathName.Buffer, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObDereferenceObject( ObjectBodyA ); // ObInsertObject,ObjectPointerBias ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByPointer ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByName ObDereferenceObject( ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObOpenObjectByName( &ObjectAObjA, 0L, NULL, ObjectTypeA, KernelMode, NULL, &ObjectHandleA2 ); InitializeObjectAttributes( &ObjectBObjA, &ObjectBPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObOpenObjectByName( &ObjectBObjA, 0L, NULL, ObjectTypeB, KernelMode, NULL, &ObjectHandleB2 ); DbgPrint( "Open Object Name %s = %lx\n", ObjectAPathName.Buffer, ObjectHandleA2 ); DbgPrint( "Open Object Name %s = %lx\n", ObjectBPathName.Buffer, ObjectHandleB2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); NtClose( ObjectHandleA1 ); NtClose( ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByHandle( ObjectHandleA2, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB2, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA2, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB2, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObOpenObjectByPointer( ObjectBodyA, OBJ_CASE_INSENSITIVE, 0L, NULL, ObjectTypeA, KernelMode, &ObjectHandleA1 ); ObOpenObjectByPointer( ObjectBodyB, OBJ_CASE_INSENSITIVE, 0L, NULL, ObjectTypeB, KernelMode, &ObjectHandleB1 ); DbgPrint( "Open Object Pointer %lx = %lx\n", ObjectBodyA, ObjectHandleA1 ); DbgPrint( "Open Object Pointer %lx = %lx\n", ObjectBodyB, ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByHandle( ObjectHandleA1, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB1, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA1, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB1, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); NtClose( ObjectHandleA1 ); NtClose( ObjectHandleB1 ); NtClose( ObjectHandleA2 ); NtClose( ObjectHandleB2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); TestFunction = NULL; return( TRUE ); }
NTSTATUS DfsDriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS Status; UNICODE_STRING UnicodeString; PDEVICE_OBJECT DeviceObject; OBJECT_ATTRIBUTES ObjectAttributes; PWSTR p; int i; HANDLE hTemp; HANDLE DirHandle; IO_STATUS_BLOCK iosb; // // See if someone else has already created a File System Device object // with the name we intend to use. If so, we bail. // RtlInitUnicodeString( &UnicodeString, DFS_DRIVER_NAME ); InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, 0, NULL); Status = ZwCreateFile( &hTemp, SYNCHRONIZE, &ObjectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0); if (NT_SUCCESS(Status)) { ZwClose( hTemp ); DfsDbgTrace(0, Dbg, "Dfs driver already loaded!\n", 0); return( STATUS_UNSUCCESSFUL ); } // // Create the filesystem device object. // Status = IoCreateDevice( DriverObject, 0, &UnicodeString, FILE_DEVICE_DFS_FILE_SYSTEM, FILE_REMOTE_DEVICE, FALSE, &DeviceObject ); if ( !NT_SUCCESS( Status ) ) { return Status; } // // Create a permanent object directory in which the logical root // device objects will reside. Make the directory temporary, so // we can just close the handle to make it go away. // UnicodeString.Buffer = p = LogicalRootDevPath; UnicodeString.Length = 0; UnicodeString.MaximumLength = MAX_LOGICAL_ROOT_LEN; while (*p++ != UNICODE_NULL) UnicodeString.Length += sizeof (WCHAR); InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_PERMANENT, NULL, NULL ); Status = ZwCreateDirectoryObject( &DirHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes); if ( !NT_SUCCESS( Status ) ) { return Status; } ZwMakeTemporaryObject(DirHandle); p[-1] = UNICODE_PATH_SEP; UnicodeString.Length += sizeof (WCHAR); // // Initialize the driver object with this driver's entry points. // Most are simply passed through to some other device driver. // for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = DfsVolumePassThrough; } DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)DfsFsdCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)DfsFsdClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)DfsFsdCleanup; DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdQueryInformation; DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)DfsFsdSetInformation; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)DfsFsdFileSystemControl; DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdQueryVolumeInformation; DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]= (PDRIVER_DISPATCH)DfsFsdSetVolumeInformation; DriverObject->FastIoDispatch = &FastIoDispatch; // // Initialize the global data structures // RtlZeroMemory(&DfsData, sizeof (DFS_DATA)); DfsData.NodeTypeCode = DSFS_NTC_DATA_HEADER; DfsData.NodeByteSize = sizeof( DFS_DATA ); InitializeListHead( &DfsData.VcbQueue ); InitializeListHead( &DfsData.DeletedVcbQueue ); InitializeListHead( &DfsData.Credentials ); InitializeListHead( &DfsData.DeletedCredentials ); DfsData.DriverObject = DriverObject; DfsData.FileSysDeviceObject = DeviceObject; DfsData.LogRootDevName = UnicodeString; ExInitializeResource( &DfsData.Resource ); KeInitializeEvent( &DfsData.PktWritePending, NotificationEvent, TRUE ); KeInitializeSemaphore( &DfsData.PktReferralRequests, 1, 1 ); DfsData.MachineState = DFS_CLIENT; // // Allocate Provider structures. // DfsData.pProvider = ExAllocatePool( PagedPool, sizeof ( PROVIDER_DEF ) * MAX_PROVIDERS); for (i = 0; i < MAX_PROVIDERS; i++) { DfsData.pProvider[i].NodeTypeCode = DSFS_NTC_PROVIDER; DfsData.pProvider[i].NodeByteSize = sizeof ( PROVIDER_DEF ); } DfsData.cProvider = 0; DfsData.maxProvider = MAX_PROVIDERS; // // Initialize the system wide PKT // PktInitialize(&DfsData.Pkt); { ULONG SystemSizeMultiplier; ULONG ZoneSegmentSize; switch (MmQuerySystemSize()) { default: case MmSmallSystem: SystemSizeMultiplier = 4; break; case MmMediumSystem: SystemSizeMultiplier = 8; break; case MmLargeSystem: SystemSizeMultiplier = 16; break; } // // Allocate the DFS_FCB hash table structure. The number of hash buckets // will depend upon the memory size of the system. // Status = DfsInitFcbs(SystemSizeMultiplier * 2); // // Now initialize the zone structures for allocating IRP context // records. The size of the zone will depend upon the memory // available in the system. // KeInitializeSpinLock( &DfsData.IrpContextSpinLock ); ZoneSegmentSize = (SystemSizeMultiplier * QuadAlign(sizeof(IRP_CONTEXT))) + sizeof(ZONE_SEGMENT_HEADER); (VOID) ExInitializeZone( &DfsData.IrpContextZone, QuadAlign(sizeof(IRP_CONTEXT)), FsRtlAllocatePool( NonPagedPool, ZoneSegmentSize ), ZoneSegmentSize ); } // // Set up global pointer to the system process. // DfsData.OurProcess = PsGetCurrentProcess(); // // Register the file system with the I/O system // IoRegisterFileSystem( DeviceObject ); // // Initialize the provider definitions from the registry. // if (!NT_SUCCESS( ProviderInit() )) { DfsDbgTrace(0,DEBUG_TRACE_ERROR, "Could not initialize some or all providers!\n", 0); } // // Initialize the logical roots device objects. These are what form the // link between the outside world and the Dfs driver. // Status = DfsInitializeLogicalRoot( DD_DFS_DEVICE_NAME, NULL, NULL, 0); if (!NT_SUCCESS(Status)) { DfsDbgTrace(-1, DEBUG_TRACE_ERROR, "Failed creation of root logical root %08lx\n", Status); return(Status); } // // Let us start off the Timer Routine. // RtlZeroMemory(&DfsTimerContext, sizeof(DFS_TIMER_CONTEXT)); DfsTimerContext.InUse = FALSE; DfsTimerContext.TickCount = 0; IoInitializeTimer(DeviceObject, DfsIoTimerRoutine, &DfsTimerContext); DfsDbgTrace(0, Dbg, "Initialized the Timer routine\n", 0); // // Let us start the timer now. // IoStartTimer(DeviceObject); return STATUS_SUCCESS; }
DLC_STATUS LlcInitialize( VOID ) /*++ Routine Description: The routines initializes the protocol module and does the minimal stuff, that must be done in the serialized initialization routine. Arguments: None. Return Value: NDIS_STATUS --*/ { NDIS_STATUS Status; ASSUME_IRQL(PASSIVE_LEVEL); // // We must build a MDL for the XID information used // when the link level takes care of XID handling. // pXidMdl = IoAllocateMdl(&Ieee802Xid, sizeof(Ieee802Xid), FALSE, FALSE, NULL ); if (pXidMdl == NULL) { return DLC_STATUS_NO_MEMORY; } #if LLC_DBG ALLOCATE_SPIN_LOCK(&MemCheckLock); #endif MmBuildMdlForNonPagedPool(pXidMdl); LlcInitializeTimerSystem(); NdisRegisterProtocol(&Status, &LlcProtocolHandle, &LlcCharacteristics, sizeof(LlcCharacteristics) ); KeInitializeSpinLock(&LlcSpinLock); ASSUME_IRQL(PASSIVE_LEVEL); KeInitializeMutex(&NdisAccessMutex, 1); // // We use the OpenAdapterSemaphore in the LlcOpenAdapter function. We really // want a mutex, but a mutex causes us problems on a checked build if we // make a call into NTOS. In either case, we just need a mechanism to ensure // only one thread is creating the ADAPTER_CONTEXT & opening the adapter at // NDIS level // KeInitializeSemaphore(&OpenAdapterSemaphore, 1, 1); if (Status != STATUS_SUCCESS) { IoFreeMdl(pXidMdl); } return Status; }