// // Plug in a device on NDAS bus in KernelMode. // NTSTATUS LSBus_PlugInLSBUSDevice( PFDO_DEVICE_DATA FdoData, PBUSENUM_PLUGIN_HARDWARE_EX2 PlugIn ){ HANDLE DisconEvent; HANDLE AlarmEvent; NTSTATUS status; // // Create events // status = ZwCreateEvent( &DisconEvent, GENERIC_READ, NULL, NotificationEvent, FALSE ); if(!NT_SUCCESS(status)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ZwCreateEvent() failed. Disconnection event.\n")); return status; } status = ZwCreateEvent( &AlarmEvent, GENERIC_READ, NULL, NotificationEvent, FALSE ); if(!NT_SUCCESS(status)) { ZwClose(DisconEvent); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed. AlarmEvent\n")); return status; } // // Set up BUSENUM_PLUGIN_HARDWARE_EX2 structure. // PlugIn->phAlarmEvent = &AlarmEvent; PlugIn->phEvent = &DisconEvent; status = Bus_PlugInDeviceEx2(PlugIn, PlugIn->Size, FdoData, KernelMode, TRUE); // // Close handle to decrease one reference from events. // ZwClose(AlarmEvent); ZwClose(DisconEvent); return status; }
NTSTATUS NTAPI CmpCreateEvent(IN EVENT_TYPE EventType, OUT PHANDLE EventHandle, OUT PKEVENT *Event) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; /* Create the event */ InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateEvent(EventHandle, EVENT_ALL_ACCESS, &ObjectAttributes, EventType, FALSE); if (!NT_SUCCESS(Status)) return Status; /* Get a pointer to the object itself */ Status = ObReferenceObjectByHandle(*EventHandle, EVENT_ALL_ACCESS, NULL, KernelMode, (PVOID*)Event, NULL); if (!NT_SUCCESS(Status)) ZwClose(*EventHandle); /* Return status */ return Status; }
PKEVENT NTAPI IopCreateEvent(IN PUNICODE_STRING EventName, IN PHANDLE EventHandle, IN EVENT_TYPE Type) { OBJECT_ATTRIBUTES ObjectAttributes; PKEVENT Event; HANDLE Handle; NTSTATUS Status; PAGED_CODE(); /* Initialize the object attributes */ InitializeObjectAttributes(&ObjectAttributes, EventName, OBJ_OPENIF | OBJ_KERNEL_HANDLE, NULL, NULL); /* Create the event */ Status = ZwCreateEvent(&Handle, EVENT_ALL_ACCESS, &ObjectAttributes, Type, TRUE); if (!NT_SUCCESS(Status)) return NULL; /* Get a handle to it */ ObReferenceObjectByHandle(Handle, 0, ExEventObjectType, KernelMode, (PVOID*)&Event, NULL); /* Dereference the extra count, and return the handle */ ObDereferenceObject(Event); *EventHandle = Handle; return Event; }
NTSTATUS CmpCreateEvent( IN EVENT_TYPE eventType, OUT PHANDLE eventHandle, OUT PKEVENT *event ) { NTSTATUS status; OBJECT_ATTRIBUTES obja; InitializeObjectAttributes( &obja, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); status = ZwCreateEvent( eventHandle, EVENT_ALL_ACCESS, &obja, eventType, FALSE); if (!NT_SUCCESS(status)) { return status; } status = ObReferenceObjectByHandle( *eventHandle, EVENT_ALL_ACCESS, NULL, KernelMode, event, NULL); if (!NT_SUCCESS(status)) { ZwClose(*eventHandle); return status; } return status; }
/* Create an event */ HANDLE NTAPI CreateEvent( ULONG AccessMask, PWSTR wEventName OPTIONAL, EVENT_TYPE EventType, BOOLEAN InitialState ) { NTSTATUS Status; OBJECT_ATTRIBUTES Oa; UNICODE_STRING EventName, *pEventName = NULL; HANDLE EventHandle; if (ARGUMENT_PRESENT(wEventName)) { RtlInitUnicodeString (&EventName, wEventName); pEventName = &EventName; } InitializeObjectAttributes (&Oa, pEventName, 0, 0, 0); Status = ZwCreateEvent ( &EventHandle, AccessMask, &Oa, EventType, InitialState); if (!NT_SUCCESS(Status)) { EventHandle = NULL; } return EventHandle; }
// // Plug in a device on LanscsiBus in KernelMode. // NTSTATUS LSBus_PlugInLSBUSDevice( PFDO_DEVICE_DATA FdoData, ULONG SlotNo, PWCHAR HardwareIDs, LONG HardwareIDLen, ULONG MaxBlocksPerRequest ){ PBUSENUM_PLUGIN_HARDWARE_EX BusDevice; ULONG Length; HANDLE DisconEvent; HANDLE AlarmEvent; NTSTATUS status; // // Create events // status = ZwCreateEvent( &DisconEvent, GENERIC_READ, NULL, NotificationEvent, FALSE ); if(!NT_SUCCESS(status)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ZwCreateEvent() failed. Disconnection event.\n")); return status; } status = ZwCreateEvent( &AlarmEvent, GENERIC_READ, NULL, NotificationEvent, FALSE ); if(!NT_SUCCESS(status)) { ZwClose(DisconEvent); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed. AlarmEvent\n")); return status; } // // Build BUSENUM_PLUGIN_HARDWARE_EX structure. // Length = sizeof(BUSENUM_PLUGIN_HARDWARE_EX) + HardwareIDLen; BusDevice = ExAllocatePoolWithTag( PagedPool, Length, LSBUS_POOTAG_PLUGIN ); if(!BusDevice) { ZwClose(DisconEvent); ZwClose(AlarmEvent); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed.\n")); return STATUS_INSUFFICIENT_RESOURCES; } BusDevice->Size = Length; BusDevice->SlotNo = SlotNo; RtlCopyMemory(BusDevice->HardwareIDs, HardwareIDs, HardwareIDLen); BusDevice->MaxRequestBlocks = MaxBlocksPerRequest; BusDevice->phAlarmEvent = &AlarmEvent; BusDevice->phEvent = &DisconEvent; status = Bus_PlugInDeviceEx(BusDevice, Length, FdoData, KernelMode); // // Close handle to decrease one reference from events. // ZwClose(AlarmEvent); ZwClose(DisconEvent); ExFreePool(BusDevice); return status; }
BOOLEAN SeRmInitPhase1( ) /*++ Routine Description: This function is called by Phase 1 System Initialization to initialize the Security Reference Monitor. Note that initialization of the Reference Monitor Global State has already been performed in Phase 0 initialization to allow access validation routines to operate without having to check that Reference Monitor Initialization is complete. The steps listed below are performed in this routine. The remainder of Reference Monitor initialization requires the LSA subsystem to have run, so that initialization is performed in a separate thread (the RM Command Server Thread, see below), so that the present thread can create the Session Manager which execs the LSA. o Create the Reference Monitor Command LPC port. The LSA subsystem sends commands (e.g. turn on auditing) which change the Reference Monitor Global State. o Create an Event for use in synchronizing with the LSA subsystem. The LSA will signal the event when the portion of LSA initialization upon with the Reference Monitor depends is complete. The Reference Monitor uses another LPC port, called the LSA Command Port to send commands to the LSA, so the RM must know that this port has been created before trying to connect to it. o Create the Reference Monitor Command Server Thread. This thread is a permanent thread of the System Init process that fields the Reference Monitor State Change commands described above. Arguments: None. Return Value: BOOLEAN - TRUE if Rm Initialization (Phase 1) succeeded, else FALSE --*/ { NTSTATUS Status; STRING RmCommandPortName; UNICODE_STRING UnicodeRmCommandPortName; OBJECT_ATTRIBUTES ObjectAttributes; STRING LsaInitEventName; UNICODE_STRING UnicodeLsaInitEventName; OBJECT_ATTRIBUTES LsaInitEventObjectAttributes; SECURITY_DESCRIPTOR LsaInitEventSecurityDescriptor; ULONG AclSize; PAGED_CODE(); // // Create an LPC port called the Reference Monitor Command Port. // This will be used by the LSA to send commands to the Reference // Monitor to update its state data. // RtlInitString( &RmCommandPortName, "\\SeRmCommandPort" ); Status = RtlAnsiStringToUnicodeString( &UnicodeRmCommandPortName, &RmCommandPortName, TRUE ); ASSERT( NT_SUCCESS(Status) ); InitializeObjectAttributes( &ObjectAttributes, &UnicodeRmCommandPortName, 0, NULL, NULL ); Status = ZwCreatePort( &SepRmState.RmCommandPortHandle, &ObjectAttributes, sizeof(SEP_RM_CONNECT_INFO), sizeof(RM_COMMAND_MESSAGE), sizeof(RM_COMMAND_MESSAGE) * 32 ); RtlFreeUnicodeString( &UnicodeRmCommandPortName ); if( !NT_SUCCESS(Status) ) { KdPrint(("Security: Rm Create Command Port failed 0x%lx\n", Status)); return FALSE; } // // Prepare to create an event for synchronizing with the LSA. // First, build the Security Descriptor for the Init Event Object // Status = RtlCreateSecurityDescriptor( &LsaInitEventSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); if (!NT_SUCCESS(Status)) { KdPrint(("Security: Creating Lsa Init Event Desc failed 0x%lx\n", Status)); return FALSE; } // // Allocate a temporary buffer from the paged pool. It is a fatal // system error if the allocation fails since security cannot be // enabled. // AclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + SeLengthSid(SeLocalSystemSid); LsaInitEventSecurityDescriptor.Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'cAeS'); if (LsaInitEventSecurityDescriptor.Dacl == NULL) { KdPrint(("Security LSA: Insufficient resources to initialize\n")); return FALSE; } // // Now create the Discretionary ACL within the Security Descriptor // Status = RtlCreateAcl( LsaInitEventSecurityDescriptor.Dacl, AclSize, ACL_REVISION2 ); if (!NT_SUCCESS(Status)) { KdPrint(("Security: Creating Lsa Init Event Dacl failed 0x%lx\n", Status)); return FALSE; } // // Now add an ACE giving GENERIC_ALL access to the User ID // Status = RtlAddAccessAllowedAce( LsaInitEventSecurityDescriptor.Dacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); if (!NT_SUCCESS(Status)) { KdPrint(("Security: Adding Lsa Init Event ACE failed 0x%lx\n", Status)); return FALSE; } // // Set up the Object Attributes for the Lsa Initialization Event // RtlInitString( &LsaInitEventName, "\\SeLsaInitEvent" ); Status = RtlAnsiStringToUnicodeString( &UnicodeLsaInitEventName, &LsaInitEventName, TRUE ); ASSERT( NT_SUCCESS(Status) ); InitializeObjectAttributes( &LsaInitEventObjectAttributes, &UnicodeLsaInitEventName, 0, NULL, &LsaInitEventSecurityDescriptor ); // // Create an event for use in synchronizing with the LSA. The LSA will // signal this event when LSA initialization has reached the point // where the LSA's Reference Monitor Server Port has been created. // Status = ZwCreateEvent( &(SepRmState.LsaInitEventHandle), EVENT_MODIFY_STATE, &LsaInitEventObjectAttributes, NotificationEvent, FALSE); RtlFreeUnicodeString( &UnicodeLsaInitEventName ); if (!NT_SUCCESS(Status)) { KdPrint(("Security: LSA init event creation failed.0x%xl\n", Status)); return FALSE; } // // Deallocate the pool memory used for the Init Event DACL // ExFreePool( LsaInitEventSecurityDescriptor.Dacl ); // // Create a permanent thread of the Sysinit Process, called the // Reference Monitor Server Thread. This thread is dedicated to // receiving Reference Monitor commands and dispatching them. // Status = PsCreateSystemThread( &SepRmState.SepRmThreadHandle, THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SET_INFORMATION, NULL, NULL, NULL, SepRmCommandServerThread, NULL ); if (!NT_SUCCESS(Status)) { KdPrint(("Security: Rm Server Thread creation failed 0x%lx\n", Status)); return FALSE; } // // Initialize data from the registry. This must go here because all other // Se initialization takes place before the registry is initialized. // SepAdtInitializeCrashOnFail(); SepAdtInitializePrivilegeAuditing(); SepAdtInitializeAuditingOptions(); // // Reference Monitor initialization is successful if we get to here. // ZwClose( SepRmState.SepRmThreadHandle ); SepRmState.SepRmThreadHandle = NULL; return TRUE; }
VOID VolDoThreadProc ( IN PVOLUME_DEVICE_OBJECT VolDo ) { BOOLEAN volDoThreadTerminate = FALSE; DebugTrace( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) ); VolDo_Reference( VolDo ); VolDo->Thread.Flags = VOLDO_THREAD_FLAG_INITIALIZING; ExAcquireFastMutex( &VolDo->FastMutex ); ClearFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_INITIALIZING ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_START ); ExReleaseFastMutex( &VolDo->FastMutex ); KeSetEvent( &VolDo->ReadyEvent, IO_DISK_INCREMENT, FALSE ); volDoThreadTerminate = FALSE; while (volDoThreadTerminate == FALSE) { PKEVENT events[2]; LONG eventCount; NTSTATUS eventStatus; LARGE_INTEGER timeOut; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); eventCount = 0; events[eventCount++] = &VolDo->RequestEvent; timeOut.QuadPart = -NDNTFS_VOLDO_THREAD_FLAG_TIME_OUT; eventStatus = KeWaitForMultipleObjects( eventCount, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, NULL ); if (eventStatus == STATUS_TIMEOUT) { LARGE_INTEGER currentTime; KeQuerySystemTime( ¤tTime ); if (FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN) || !(FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_MOUNTED) /*&& !FlagOn(LfsDeviceExt->Flags, LFS_DEVICE_STOP)*/)) { continue; } if ((VolDo->NetdiskEnableMode == NETDISK_READ_ONLY && (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_PURGE_DURATION)) || (VolDo->ReceiveWriteCommand == TRUE && (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_FLUSH_DURATION))) { if (VolDo->NetdiskEnableMode != NETDISK_READ_ONLY && (currentTime.QuadPart - VolDo->CommandReceiveTime.QuadPart) <= NDNTFS_TRY_FLUSH_DURATION /*&& (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) <= (100*NDNTFS_TRY_FLUSH_OR_PURGE_DURATION)*/) { continue; } do { HANDLE eventHandle = NULL; HANDLE fileHandle = NULL; ACCESS_MASK desiredAccess; ULONG attributes; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER allocationSize; ULONG fileAttributes; ULONG shareAccess; ULONG createDisposition; ULONG createOptions; PVOID eaBuffer; ULONG eaLength; NTSTATUS createStatus; NTSTATUS fileSystemControlStatus; PIRP topLevelIrp; PRIMARY_REQUEST_INFO primaryRequestInfo; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); if (VolDo->NetdiskEnableMode == NETDISK_SECONDARY) { break; } DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, VolDo->NetdiskPartitionInformation.VolumeName = %wZ\n", VolDo, &VolDo->NetdiskPartitionInformation.VolumeName) ); desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &VolDo->NetdiskPartitionInformation.VolumeName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); createStatus = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, &allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, eaBuffer, eaLength ); if (createStatus != STATUS_SUCCESS) break; ASSERT( ioStatusBlock.Information == FILE_OPENED); createStatus = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (createStatus != STATUS_SUCCESS) { ASSERT( NDASNTFS_UNEXPECTED ); ZwClose( fileHandle ); break; } primaryRequestInfo.PrimaryTag = 0xe2027482; primaryRequestInfo.PrimarySessionId = NDASNTFS_LOCAL_PRMARY_SESSION_ID; primaryRequestInfo.PrimarySession = NULL; primaryRequestInfo.NdfsWinxpRequestHeader = NULL; topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); IoSetTopLevelIrp( (PIRP)&primaryRequestInfo ); RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); fileSystemControlStatus = ZwFsControlFile( fileHandle, NULL, //&eventHandle, NULL, NULL, &ioStatusBlock, (VolDo->NetdiskEnableMode == NETDISK_READ_ONLY) ? FSCTL_NDAS_FS_PURGE : FSCTL_NDAS_FS_FLUSH, NULL, 0, NULL, 0 ); DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, createStatus = %x, ioStatusBlock = %x\n", VolDo, fileSystemControlStatus, ioStatusBlock.Information) ); if (fileSystemControlStatus == STATUS_PENDING) { LARGE_INTEGER timeOut; timeOut.QuadPart = -3*NANO100_PER_SEC; ASSERT( FALSE ); //fileSystemControlStatus = ZwWaitForSingleObject( eventHandle, TRUE,NULL /*, &timeOut*/ ); } IoSetTopLevelIrp( topLevelIrp ); if (fileSystemControlStatus != STATUS_SUCCESS) DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, fileSystemControlStatus = %x, ioStatusBlock = %x\n", VolDo, fileSystemControlStatus, ioStatusBlock.Information) ); ZwClose( eventHandle ); ZwClose( fileHandle ); break; } while (0); KeQuerySystemTime( &VolDo->TryFlushOrPurgeTime ); VolDo->ReceiveWriteCommand = FALSE; } continue; } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ASSERT( eventCount < THREAD_WAIT_OBJECTS ); if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) { ASSERT( NDASNTFS_UNEXPECTED ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_ERROR ); volDoThreadTerminate = TRUE; continue; } KeClearEvent( events[eventStatus] ); if (eventStatus == 0) { volDoThreadTerminate = TRUE; break; } else { NDAS_ASSERT( NDASNTFS_BUG ); } } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ExAcquireFastMutex( &VolDo->FastMutex ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_STOPED ); ExReleaseFastMutex( &VolDo->FastMutex ); DebugTrace( 0, Dbg2, ("VolDoThreadProc: PsTerminateSystemThread VolDo = %p\n", VolDo) ); ExAcquireFastMutex( &VolDo->FastMutex ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_TERMINATED ); ExReleaseFastMutex( &VolDo->FastMutex ); VolDo_Dereference( VolDo ); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); PsTerminateSystemThread( STATUS_SUCCESS ); }
NTSTATUS ReadonlyDismountVolume ( IN PLFS_DEVICE_EXTENSION LfsDeviceExt ) { NTSTATUS status; HANDLE eventHandle; HANDLE fileHandle = NULL; ACCESS_MASK desiredAccess; ULONG attributes; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER allocationSize; ULONG fileAttributes; ULONG shareAccess; ULONG createDisposition; ULONG createOptions; PVOID eaBuffer; ULONG eaLength; PIRP topLevelIrp; READONLY_REDIRECT_REQUEST readonlyRedirectRequest; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p, LfsDeviceExt->FileSystemType = %d LfsDeviceExt->Vpb->ReferenceCount = %d\n", LfsDeviceExt, LfsDeviceExt->FileSystemType, LfsDeviceExt->Vpb->ReferenceCount) ); desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES; desiredAccess |= FILE_WRITE_EA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &LfsDeviceExt->NetdiskPartitionInformation.VolumeName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); readonlyRedirectRequest.Tag = READONLY_REDIRECT_REQUEST_TAG; #if DBG readonlyRedirectRequest.DebugTag = READONLY_REDIRECT_REQUEST_TAG; #endif readonlyRedirectRequest.DevExt = CONTAINING_RECORD( LfsDeviceExt, FILESPY_DEVICE_EXTENSION, LfsDeviceExt ); readonlyRedirectRequest.OriginalTopLevelIrp = topLevelIrp; readonlyRedirectRequest.ReadonlyDismount = 1; IoSetTopLevelIrp( (PIRP)&readonlyRedirectRequest ); status = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, &allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, eaBuffer, eaLength ); ASSERT( readonlyRedirectRequest.DebugTag == (READONLY_REDIRECT_REQUEST_TAG - 4) ); IoSetTopLevelIrp( topLevelIrp ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwCreateFile fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); if (status != STATUS_SUCCESS) { return status; } else { ASSERT( ioStatusBlock.Information == FILE_OPENED ); } do { status = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (status != STATUS_SUCCESS) { ASSERT( LFS_UNEXPECTED ); break; } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); readonlyRedirectRequest.Tag = READONLY_REDIRECT_REQUEST_TAG; #if DBG readonlyRedirectRequest.DebugTag = READONLY_REDIRECT_REQUEST_TAG; #endif readonlyRedirectRequest.DevExt = CONTAINING_RECORD( LfsDeviceExt, FILESPY_DEVICE_EXTENSION, LfsDeviceExt ); readonlyRedirectRequest.OriginalTopLevelIrp = topLevelIrp; readonlyRedirectRequest.ReadonlyDismount = 1; IoSetTopLevelIrp( (PIRP)&readonlyRedirectRequest ); status = ZwFsControlFile( fileHandle, eventHandle, NULL, NULL, &ioStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = ZwWaitForSingleObject( eventHandle, TRUE, NULL ); if (status != STATUS_SUCCESS) { NDAS_ASSERT( FALSE ); } else { status = ioStatusBlock.Status; } } ASSERT( readonlyRedirectRequest.DebugTag == (READONLY_REDIRECT_REQUEST_TAG - 4) ); IoSetTopLevelIrp( topLevelIrp ); ZwClose( eventHandle ); if (status != STATUS_SUCCESS) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwFsControlFile FSCTL_LOCK_VOLUME fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); #if 0 status = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (status != STATUS_SUCCESS) { ASSERT( LFS_UNEXPECTED ); break; } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); status = ZwFsControlFile( fileHandle, eventHandle, NULL, NULL, &ioStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = ZwWaitForSingleObject( eventHandle, TRUE, NULL ); if (status != STATUS_SUCCESS) NDAS_ASSERT( FALSE ); else status = ioStatusBlock.Status; } ZwClose( eventHandle ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwFsControlFile FSCTL_DISMOUNT_VOLUME fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); if (status != STATUS_SUCCESS) { break; } break; #endif break; } status = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (status != STATUS_SUCCESS) { ASSERT( LFS_UNEXPECTED ); break; } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); readonlyRedirectRequest.Tag = READONLY_REDIRECT_REQUEST_TAG; #if DBG readonlyRedirectRequest.DebugTag = READONLY_REDIRECT_REQUEST_TAG; #endif readonlyRedirectRequest.DevExt = CONTAINING_RECORD( LfsDeviceExt, FILESPY_DEVICE_EXTENSION, LfsDeviceExt ); readonlyRedirectRequest.OriginalTopLevelIrp = topLevelIrp; readonlyRedirectRequest.ReadonlyDismount = 1; IoSetTopLevelIrp( (PIRP)&readonlyRedirectRequest ); status = ZwFsControlFile( fileHandle, eventHandle, NULL, NULL, &ioStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = ZwWaitForSingleObject( eventHandle, TRUE, NULL ); if (status != STATUS_SUCCESS) { NDAS_ASSERT( FALSE ); break; } status = ioStatusBlock.Status; } ASSERT( readonlyRedirectRequest.DebugTag == (READONLY_REDIRECT_REQUEST_TAG - 4) ); IoSetTopLevelIrp( topLevelIrp ); ZwClose( eventHandle ); if (status != STATUS_SUCCESS) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwFsControlFile FSCTL_UNLOCK_VOLUME fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); break; } } while(0); ZwClose( fileHandle ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p status = %X\n", LfsDeviceExt, status) ); if (status != STATUS_SUCCESS) return status; #if 0 do { UNICODE_STRING fileName; PWCHAR fileNameBuffer; fileNameBuffer = ExAllocatePool(PagedPool,NDFS_MAX_PATH); if(GlobalLfs.ShutdownOccured == TRUE) break; RtlInitEmptyUnicodeString( &fileName, fileNameBuffer, NDFS_MAX_PATH ); RtlCopyUnicodeString( &fileName, &LfsDeviceExt->NetdiskPartitionInformation.VolumeName ); ioStatusBlock.Information = 0; status = RtlAppendUnicodeToString( &fileName, REMOUNT_VOLUME_FILE_NAME ); if (status != STATUS_SUCCESS) { ExFreePool( fileNameBuffer ); ASSERT( LFS_UNEXPECTED ); status = STATUS_SUCCESS; break; } desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA; desiredAccess |= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &fileName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; status = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, NULL, fileAttributes, shareAccess, createDisposition, createOptions, NULL, 0 ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyDismountVolume: New Volume Create %p %wZ, status = %x, ioStatusBlock.Information = %d\n", LfsDeviceExt, &LfsDeviceExt->NetdiskPartitionInformation.VolumeName, status, ioStatusBlock.Information) ); if (status == STATUS_SUCCESS) { ASSERT( ioStatusBlock.Information == FILE_OPENED ); ZwClose( fileHandle ); } else { NDAS_ASSERT( FALSE ); } status = STATUS_SUCCESS; ExFreePool( fileNameBuffer ); } while(0); #endif return status; }
VOID MyThreadStart(__in PVOID StartContext){ HANDLE handle;//Create File handle NTSTATUS ntstatus; NTSTATUS timerStatus; //IO_STATUS_BLOCK ioStatusBlock; //OBJECT_ATTRIBUTES ObjAttr; //UNICODE_STRING path; LARGE_INTEGER timeout; //#define BUFFER_SIZE 30 // CHAR buffer[BUFFER_SIZE]; //size_t cb; NTSTATUS Status; HANDLE hEvent; //OBJECT_ATTRIBUTES oa; //UNICODE_STRING us; int counter=20; SIZE_T BytesNUM; char* dataPtr; __debugbreak(); dataPtr="123"; BytesNUM=strlen(dataPtr)*sizeof(char); WriteToRingBuffer(&dataPtr, BytesNUM); FlushRingBuffre(); RtlInitUnicodeString( &path, L"\\DosDevices\\C:\\MyLogger.txt"); InitializeObjectAttributes( &ObjAttr, &path, //ObjectName OBJ_CASE_INSENSITIVE, //Attributes NULL, //RootDirectory NULL); //SecurityDescriptor // Do not try to perform any file operations at higher IRQL levels. // Instead, you may use a work item or a system worker thread to perform file operations. if(KeGetCurrentIrql() != PASSIVE_LEVEL) // return STATUS_INVALID_DEVICE_STATE; DbgPrint("STATUS_INVALID_DEVICE_STATE\n"); ntstatus = ZwCreateFile(&handle, GENERIC_WRITE, &ObjAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); timeout.QuadPart = -5 * 1000000; RtlInitUnicodeString( &us, L"\\BaseNamedObjects\\TestEvent"); InitializeObjectAttributes( &oa, &us, //ObjectName OBJ_CASE_INSENSITIVE, //Attributes NULL, //RootDirectory NULL); //SecurityDescriptor Status = ZwCreateEvent(&hEvent, EVENT_ALL_ACCESS, &oa, NotificationEvent, FALSE); if(NT_SUCCESS(Status)){ DbgPrint("Event created"); } else { DbgPrint("Event Not created"); } Status = ObReferenceObjectByHandle( hEvent, //Handle EVENT_ALL_ACCESS, //DesiredAccess NULL, //ObjectType KernelMode, //AccessMode &pEvent, //Object NULL); //HandleInformation if (!NT_SUCCESS(Status)) { ZwClose(hEvent); DbgPrint("Failed to reference event \n"); //return Status; }; while(counter!=0){ timerStatus = KeWaitForSingleObject( pEvent, Executive, KernelMode, FALSE, &timeout ); if(timerStatus == STATUS_TIMEOUT){ if(NT_SUCCESS(ntstatus)) { ntstatus = RtlStringCbPrintfA(buffer, sizeof(buffer), "This is %d test\r\n", counter); if(NT_SUCCESS(ntstatus)) { ntstatus = RtlStringCbLengthA(buffer, sizeof(buffer), &cb); if(NT_SUCCESS(ntstatus)) { ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock, buffer, cb, NULL, NULL); } } //ZwClose(handle); } } counter--; } ZwClose(handle); }
NTSTATUS NTAPI UserCreateThreadInfo(struct _ETHREAD *Thread) { struct _EPROCESS *Process; PCLIENTINFO pci; PTHREADINFO ptiCurrent; int i; NTSTATUS Status = STATUS_SUCCESS; PTEB pTeb; LARGE_INTEGER LargeTickCount; Process = Thread->ThreadsProcess; pTeb = NtCurrentTeb(); ASSERT(pTeb); ptiCurrent = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_THREADINFO); if (ptiCurrent == NULL) { ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread); return STATUS_NO_MEMORY; } TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); RtlZeroMemory(ptiCurrent, sizeof(THREADINFO)); /* Initialize the THREADINFO */ PsSetThreadWin32Thread(Thread, ptiCurrent, NULL); IntReferenceThreadInfo(ptiCurrent); ptiCurrent->pEThread = Thread; ptiCurrent->ppi = PsGetCurrentProcessWin32Process(); pTeb->Win32ThreadInfo = ptiCurrent; ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); InitializeListHead(&ptiCurrent->WindowListHead); InitializeListHead(&ptiCurrent->W32CallbackListHead); InitializeListHead(&ptiCurrent->PostedMessagesListHead); InitializeListHead(&ptiCurrent->SentMessagesListHead); InitializeListHead(&ptiCurrent->DispatchingMessagesHead); InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead); InitializeListHead(&ptiCurrent->PtiLink); for (i = 0; i < NB_HOOKS; i++) { InitializeListHead(&ptiCurrent->aphkStart[i]); } ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList; ptiCurrent->ppi->ptiList = ptiCurrent; ptiCurrent->ppi->cThreads++; ptiCurrent->hEventQueueClient = NULL; Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { goto error; } Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, *ExEventObjectType, KernelMode, (PVOID*)&ptiCurrent->pEventQueueServer, NULL); if (!NT_SUCCESS(Status)) { ZwClose(ptiCurrent->hEventQueueClient); ptiCurrent->hEventQueueClient = NULL; goto error; } KeQueryTickCount(&LargeTickCount); ptiCurrent->timeLast = LargeTickCount.u.LowPart; ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent); if(ptiCurrent->MessageQueue == NULL) { ERR_CH(UserThread,"Failed to allocate message loop\n"); Status = STATUS_NO_MEMORY; goto error; } ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout(); if (ptiCurrent->KeyboardLayout) UserReferenceObject(ptiCurrent->KeyboardLayout); ptiCurrent->TIF_flags &= ~TIF_INCLEANUP; if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */ ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD; ptiCurrent->pcti = &ptiCurrent->cti; /* Initialize the CLIENTINFO */ pci = (PCLIENTINFO)pTeb->Win32ClientInfo; RtlZeroMemory(pci, sizeof(CLIENTINFO)); pci->ppi = ptiCurrent->ppi; pci->fsHooks = ptiCurrent->fsHooks; pci->dwTIFlags = ptiCurrent->TIF_flags; if (ptiCurrent->KeyboardLayout) { pci->hKL = ptiCurrent->KeyboardLayout->hkl; pci->CodePage = ptiCurrent->KeyboardLayout->CodePage; } /* Assign a default window station and desktop to the process */ /* Do not try to open a desktop or window station before winlogon initializes */ if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL) { HWINSTA hWinSta = NULL; HDESK hDesk = NULL; UNICODE_STRING DesktopPath; PDESKTOP pdesk; PRTL_USER_PROCESS_PARAMETERS ProcessParams; /* * inherit the thread desktop and process window station (if not yet inherited) from the process startup * info structure. See documentation of CreateProcess() */ ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters; Status = STATUS_UNSUCCESSFUL; if(ProcessParams && ProcessParams->DesktopInfo.Length > 0) { Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo); } if(!NT_SUCCESS(Status)) { RtlInitUnicodeString(&DesktopPath, NULL); } Status = IntParseDesktopPath(Process, &DesktopPath, &hWinSta, &hDesk); if (DesktopPath.Buffer) ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING); if(!NT_SUCCESS(Status)) { ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n"); goto error; } if(!UserSetProcessWindowStation(hWinSta)) { Status = STATUS_UNSUCCESSFUL; ERR_CH(UserThread,"Failed to set initial process winsta\n"); goto error; } /* Validate the new desktop. */ Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk); if(!NT_SUCCESS(Status)) { ERR_CH(UserThread,"Failed to validate initial desktop handle\n"); goto error; } /* Store the parsed desktop as the initial desktop */ ptiCurrent->ppi->hdeskStartup = hDesk; ptiCurrent->ppi->rpdeskStartup = pdesk; } if (ptiCurrent->ppi->hdeskStartup != NULL) { if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE)) { ERR_CH(UserThread,"Failed to set thread desktop\n"); Status = STATUS_UNSUCCESSFUL; goto error; } } /* mark the thread as fully initialized */ ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) && (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi )) { ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; } ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; TRACE_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent); return STATUS_SUCCESS; error: ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); UserDestroyThreadInfo(Thread); return Status; }
EXTERN_C NTSTATUS EnumDirectory( char *lpDirName ) { NTSTATUS status, fStatus; ULONG dwBytesReturned; OBJECT_ATTRIBUTES objectAttributes; PDEVICE_OBJECT lpDeviceObject; IO_STACK_LOCATION iost; PIO_STACK_LOCATION lpsp; IO_STATUS_BLOCK IoStatus; HANDLE hFile = NULL; PFILE_DIRECTORY_INFORMATION lpInformation; PDIRECTORY_INFO lpDirInfo = NULL, lpPreDirInfo = NULL; PFILE_OBJECT lpFileObject = NULL; UNICODE_STRING unFileName; ANSI_STRING anFileName; HANDLE eventHandle = NULL; CHAR buffer[1024]; PUCHAR lpNext; dwBytesReturned = 0; status = STATUS_UNSUCCESSFUL; RtlZeroMemory(buffer,1024); strcpy(buffer,"\\DosDevices\\"); strcat(buffer,lpDirName); RtlInitAnsiString(&anFileName,buffer); RtlAnsiStringToUnicodeString(&unFileName,&anFileName,TRUE); InitializeObjectAttributes(&objectAttributes,&unFileName,OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE,NULL,NULL); __try { //打开文件 fStatus = ZwOpenFile(&hFile,\ FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_ANY_ACCESS,\ &objectAttributes,\ &IoStatus,\ FILE_SHARE_READ | FILE_SHARE_WRITE| FILE_SHARE_DELETE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ObReferenceObjectByHandle(hFile, FILE_LIST_DIRECTORY | SYNCHRONIZE, 0, KernelMode, (PVOID *)&lpFileObject, NULL); status = ZwCreateEvent(&eventHandle, GENERIC_ALL, 0, NotificationEvent, FALSE); lpInformation = (PFILE_DIRECTORY_INFORMATION)ExAllocatePool(PagedPool, 655350); status = ZwQueryDirectoryFile(hFile, eventHandle,0, 0, &IoStatus, lpInformation, 655350, FileDirectoryInformation, FALSE, NULL, FALSE ); if (!NT_SUCCESS(status) && status != STATUS_PENDING) { goto LeaveBefore; } if (status == STATUS_PENDING) { KeWaitForSingleObject(eventHandle, Executive, KernelMode, TRUE, 0); } FreePagedLookasideListForDirectory(); g_pPageListDirectory = (PPAGED_LOOKASIDE_LIST)ExAllocatePool(PagedPool, sizeof(PAGED_LOOKASIDE_LIST)); ExInitializePagedLookasideList(g_pPageListDirectory, NULL, NULL, 0, sizeof(DIRECTORY_INFO), NULL, 0); while(1) { lpDirInfo = (PDIRECTORY_INFO)ExAllocateFromPagedLookasideList(g_pPageListDirectory); RtlZeroMemory(lpDirInfo, sizeof(DIRECTORY_INFO)); RtlCopyMemory(lpDirInfo->FileName, lpInformation->FileName, lpInformation->FileNameLength); lpDirInfo->AllocationSize = lpInformation->AllocationSize; lpDirInfo->FileAttributes = lpInformation->FileAttributes; RtlTimeToTimeFields(&(lpInformation->CreationTime), &(lpDirInfo->CreationTime)); RtlTimeToTimeFields(&(lpInformation->LastAccessTime), &(lpDirInfo->LastAccessTime)); RtlTimeToTimeFields(&(lpInformation->LastWriteTime), &(lpDirInfo->LastWriteTime)); RtlTimeToTimeFields(&(lpInformation->ChangeTime), &(lpDirInfo->ChangeTime)); lpDirInfo->next = NULL; if (NULL == g_pDirectoryInfo) { g_pDirectoryInfo = lpDirInfo; lpPreDirInfo = lpDirInfo; } else { lpPreDirInfo->next = lpDirInfo; lpPreDirInfo = lpDirInfo; } if(!lpInformation->NextEntryOffset) { break; } lpInformation = (PFILE_DIRECTORY_INFORMATION)((PUCHAR)lpInformation + lpInformation->NextEntryOffset); } LeaveBefore: ; } __finally { if (NT_SUCCESS(fStatus)) { ZwClose(hFile); } if (NULL != lpFileObject) { ObDereferenceObject(lpFileObject); lpFileObject = NULL; } if (NULL != eventHandle) { ZwClose(eventHandle); eventHandle = NULL; } } return status; }