kmem_cache_t * kmem_cache_create (const char *name, size_t size, size_t offset, unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long), void (*dtor)(void*, kmem_cache_t *, unsigned long)) { kmem_cache_t *cachep = NULL; ULONG tag = sadyc_tag(name); if ((!name) || ((strlen(name) >= CACHE_NAMELEN - 1)) || (size < BYTES_PER_WORD) || (offset > size)) BUG(); printk("kmem_cache: %s: created size=%u tag=%u\n", name, (unsigned)size, tag); cachep = kmalloc(sizeof(kmem_cache_t), GFP_KERNEL); memset(cachep, 0, sizeof(kmem_cache_t)); #ifdef USE_NONPAGED_MEMORY ExInitializeNPagedLookasideList(&cachep->lookaside, NULL, NULL, 0, size, tag, 0); #else ExInitializePagedLookasideList(&cachep->lookaside, NULL, NULL, 0, size, tag, 0); #endif cachep->objsize = size; strcpy(cachep->name, name); cachep->ctor = ctor; cachep->dtor = dtor; #if DBG cachep->objects_allocated = 0; #endif return cachep; }
void TestLookaside() { KdPrint(("enter TestLookaside ......\n")); PAGED_LOOKASIDE_LIST tLookaside; ExInitializePagedLookasideList(&tLookaside,NULL,NULL,0,sizeof(MyListNode),'1234',0); MyListNode* MyList[10] = {0}; for(int i=0; i<10; i++) { MyList[i] = (MyListNode*)ExAllocateFromPagedLookasideList(&tLookaside); if(MyList[i] == NULL) { KdPrint(("i f**k ..\n")); continue; } MyList[i]->data = i; } for(int k=0; k<10; k++) { if(MyList[k] == NULL) { KdPrint(("i f**k too \n")); continue; } KdPrint(("%d ",MyList[k]->data)); ExFreeToPagedLookasideList(&tLookaside,MyList[k]); MyList[k] = NULL; } ExDeletePagedLookasideList(&tLookaside); KdPrint(("leave TestLookaside ......\n")); }
NTSTATUS InitializeProctectProcessList() { // 初始化自旋锁 KeInitializeSpinLock(&ProtectProcessList.Lock); // 初始化链表 InitializeListHead(&ProtectProcessList.HeadList); // 初始化LookAside结构 ExInitializePagedLookasideList(&ProtectProcessList.PageList, NULL, NULL, 0, sizeof(PROTECT_PROCESS), 'ppBx', 0); return STATUS_SUCCESS; }
NTSTATUS InitializeMatchExpressionList() { // 初始化自旋锁 KeInitializeSpinLock(&MatchExpressionList.Lock); // 初始化链表 InitializeListHead(&MatchExpressionList.HeadList); // 初始化LookAside结构 ExInitializePagedLookasideList(&MatchExpressionList.PageList, NULL, NULL, 0, sizeof(MATCH_EXPRESSION), 'meBx', 0); return STATUS_SUCCESS; }
BOOLEAN NTAPI INIT_FUNCTION LpcInitSystem(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; UNICODE_STRING Name; /* Setup the LPC Lock */ KeInitializeGuardedMutex(&LpcpLock); /* Create the Port Object Type */ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlInitUnicodeString(&Name, L"Port"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(LPCP_PORT_OBJECT); ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(LPCP_NONPAGED_PORT_QUEUE); ObjectTypeInitializer.GenericMapping = LpcpPortMapping; ObjectTypeInitializer.PoolType = PagedPool; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.CloseProcedure = LpcpClosePort; ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort; ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &LpcPortObjectType); /* Allocate the LPC lookaside list */ LpcpMaxMessageSize = LPCP_MAX_MESSAGE_SIZE; ExInitializePagedLookasideList(&LpcpMessagesLookaside, NULL, NULL, 0, LpcpMaxMessageSize, 'McpL', 32); /* We're done */ return TRUE; }
NTSTATUS RegmonEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { int i; ServiceTable = KeServiceDescriptorTable; RealRegSetValueKey = (fnRealRegSetValueKey) SYSCALL( ZwSetValueKey ); // 更改SSDT表 SETSYSCALL( ZwSetValueKey, RegSetValueKey ); for(i = 0; i < arrayof(CurrentUser); i++) CurrentUser[i].RootNameLen = wcslen(CurrentUser[i].RootName); for(i = 0; i < arrayof(RootKey); i++) RootKey[i].RootNameLen = wcslen(RootKey[i].RootName); for(i = 0; i < arrayof(RegGuardPath); i++) RegGuardPath[i].ulPathHash = GetHashUprPath(RegGuardPath[i].pGuardPath, NULL); // 初始化内存分配器 ExInitializePagedLookasideList(&gRegMonLooaside, NULL, NULL, 0 , MAXPATHLEN * 2 + 2 * sizeof(ULONG), PAGE_DEBUG, 0); return STATUS_SUCCESS; }
/* * @implemented */ VOID NTAPI FsRtlInitializeLargeMcbs(VOID) { /* Initialize the list for the MCB */ ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList, NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, sizeof(LARGE_MCB_MAPPING), IFS_POOL_TAG, 0); /* FIXME: Should be 4 */ /* Initialize the list for the guarded mutex */ ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList, NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, sizeof(KGUARDED_MUTEX), IFS_POOL_TAG, 0); /* FIXME: Should be 32 */ }
/* @implemented */ KSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocatorEx( IN PIRP Irp, IN PVOID InitializeContext OPTIONAL, IN PFNKSDEFAULTALLOCATE DefaultAllocate OPTIONAL, IN PFNKSDEFAULTFREE DefaultFree OPTIONAL, IN PFNKSINITIALIZEALLOCATOR InitializeAllocator OPTIONAL, IN PFNKSDELETEALLOCATOR DeleteAllocator OPTIONAL) { NTSTATUS Status; PKSALLOCATOR_FRAMING AllocatorFraming; PALLOCATOR Allocator; PVOID Ctx; /* first validate connect request */ Status = KsValidateAllocatorCreateRequest(Irp, &AllocatorFraming); if (!NT_SUCCESS(Status)) return STATUS_INVALID_PARAMETER; /* check the valid file alignment */ if (AllocatorFraming->FileAlignment > (PAGE_SIZE-1)) { FreeItem(AllocatorFraming); return STATUS_INVALID_PARAMETER; } /* allocate allocator struct */ Allocator = AllocateItem(NonPagedPool, sizeof(ALLOCATOR)); if (!Allocator) { FreeItem(AllocatorFraming); return STATUS_INSUFFICIENT_RESOURCES; } /* allocate object header */ Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&Allocator->Header, 0, NULL, Irp, &DispatchTable); if (!NT_SUCCESS(Status)) { FreeItem(AllocatorFraming); FreeItem(Allocator); return Status; } /* set allocator type in object header */ Allocator->lpVtbl = &vt_IKsAllocator; Allocator->Header->Unknown = (PUNKNOWN)&Allocator->lpVtbl; Allocator->ref = 1; if (DefaultAllocate) { /* use external allocator */ Allocator->Type = ALLOCATOR_CUSTOM; Allocator->Allocate.DefaultAllocate = DefaultAllocate; Allocator->Free.DefaultFree = DefaultFree; Allocator->Delete.DefaultDelete = DeleteAllocator; Ctx = InitializeAllocator(InitializeContext, AllocatorFraming, &Allocator->u.CustomList); /* check for success */ if (!Ctx) { KsFreeObjectHeader(Allocator->Header); FreeItem(Allocator); return Status; } } else if (AllocatorFraming->PoolType == NonPagedPool) { /* use non-paged pool allocator */ Allocator->Type = ALLOCATOR_NPAGED_LOOKASIDE; Allocator->Allocate.NPagedPool = ExAllocateFromNPagedLookasideList; Allocator->Free.NPagedPool = ExFreeToNPagedLookasideList; Allocator->Delete.NPagedPool = ExDeleteNPagedLookasideList; ExInitializeNPagedLookasideList(&Allocator->u.NPagedList, NULL, NULL, 0, AllocatorFraming->FrameSize, 0, 0); } else if (AllocatorFraming->PoolType == PagedPool) { /* use paged pool allocator */ Allocator->Allocate.PagedPool = ExAllocateFromPagedLookasideList; Allocator->Free.PagedPool = ExFreeToPagedLookasideList; Allocator->Delete.PagedPool = ExDeletePagedLookasideList; Allocator->Type = ALLOCATOR_PAGED_LOOKASIDE; ExInitializePagedLookasideList(&Allocator->u.PagedList, NULL, NULL, 0, AllocatorFraming->FrameSize, 0, 0); } /* backup allocator framing */ RtlMoveMemory(&Allocator->Status.Framing, AllocatorFraming, sizeof(KSALLOCATOR_FRAMING)); FreeItem(AllocatorFraming); return Status; }
// // Функция инициализации драйвера. // NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath) { PDEVICE_OBJECT pDeviceObject; // указатель на объект устройство NTSTATUS status = STATUS_SUCCESS; // статус завершения функции ULONG reg; UNICODE_STRING f1; char* str; char* ptr; int len; //InitProtectedFiles(); //DbgPrint("ProtectedFiles: %wZ, %wZ", &glProtectedFiles[0], &glProtectedFiles[1]); //DbgPrint("Load driver %wZ", &DriverObject->DriverName); //DbgPrint("Registry path %wZ", RegistryPath); pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; //pDriverObject->MajorFunction [IRP_MJ_CREATE_NAMED_PIPE ] = 0; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite; pDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInformation; //pDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = DispatchSetInformation; pDriverObject->DriverUnload = DriverUnload; KdPrint(("Load driver %wZ\n", &pDriverObject->DriverName)); KdPrint(("Registry path %wZ\n", RegistryPath)); RtlInitUnicodeString(&glDeviceName, DEVICE_NAME); RtlInitUnicodeString(&glSymLinkName, SYM_LINK_NAME); // создание устройства status = IoCreateDevice(pDriverObject, // указатель на объект драйвера 0, // размер области дополнительной памяти устройства &glDeviceName, // имя устройства FILE_DEVICE_UNKNOWN, // идентификатор типа устройства 0, // дополнительная информация об устройстве FALSE, // используется системой(для драйверов должно быть FALSE) &pDeviceObject); // адрес для сохранения указателя на объект устройства if (!NT_SUCCESS(status)) { return status; } // буферизованный ввод/вывод для операций чтения/записи pDeviceObject->Flags |= DO_BUFFERED_IO; KdPrint(("Create device %wZ\n", &glDeviceName)); // создание символьной ссылки status = IoCreateSymbolicLink(&glSymLinkName, &glDeviceName); if (!NT_SUCCESS(status)) { IoDeleteDevice(pDeviceObject); return status; } KdPrint(("Create symbolic link %wZ\n", &glSymLinkName)); // создаем резервный список ExInitializePagedLookasideList(&glPagedList, NULL, NULL, 0, sizeof(OpenFileEntry), ' LFO', 0); InitializeListHead(&glOpenFiles); // запоминаем адрес реального обработчика вызова NtCreateFile glRealNtCreateFile = (NT_CREATE_FILE)KeServiceDescriptorTable->Base[NUMBER_NT_CREATE_FILE]; glRealNtOpenFile = (NT_OPEN_FILE)KeServiceDescriptorTable->Base[NUMBER_NT_OPEN_FILE]; //glRealNtOpenFile = KeServiceDescriptorTable->Base[NUMBER_NT_CREATE_FILE]; // подставляем адрес нового обработчика //reg = ClearWP(); KeServiceDescriptorTable->Base[NUMBER_NT_CREATE_FILE] = (ULONG)HookNtCreateFile; KeServiceDescriptorTable->Base[NUMBER_NT_OPEN_FILE] = (ULONG)HookNtOpenFile; //WriteCR0(reg); return status; }
VOID FsRtlInitializeTunnel ( VOID ) /*++ Routine Description: Initializes the global part of the tunneling package. Arguments: None Return Value: None --*/ { UNICODE_STRING ValueName; USHORT LookasideDepth; PAGED_CODE(); if (MmIsThisAnNtAsSystem()) { TunnelMaxEntries = 1024; } else { TunnelMaxEntries = 256; } TunnelMaxAge = 15; // // Query our configurable parameters // // Don't worry about failure in retrieving from the registry. We've gotten // this far so fall back on defaults even if there was a problem with resources. // ValueName.Buffer = TUNNEL_SIZE_VALUE_NAME; ValueName.Length = sizeof(TUNNEL_SIZE_VALUE_NAME) - sizeof(WCHAR); ValueName.MaximumLength = sizeof(TUNNEL_SIZE_VALUE_NAME); (VOID) FsRtlGetTunnelParameterValue(&ValueName, &TunnelMaxEntries); ValueName.Buffer = TUNNEL_AGE_VALUE_NAME; ValueName.Length = sizeof(TUNNEL_AGE_VALUE_NAME) - sizeof(WCHAR); ValueName.MaximumLength = sizeof(TUNNEL_AGE_VALUE_NAME); (VOID) FsRtlGetTunnelParameterValue(&ValueName, &TunnelMaxAge); if (TunnelMaxAge == 0) { // // If the registry has been set so the timeout is zero, we should force // the number of entries to zero also. This preserves expectations and lets // us key off of max entries alone in performing the hard disabling of the // caching code. // TunnelMaxEntries = 0; } // // Convert from seconds to 10ths of msecs, the internal resolution // TunnelMaxAge *= 10000000; // // Build the lookaside list for common node allocation // if (TunnelMaxEntries > MAXUSHORT) { // // User is hinting a big need to us // LookasideDepth = MAX_LOOKASIDE_DEPTH; } else { LookasideDepth = ((USHORT)TunnelMaxEntries)/16; } if (LookasideDepth == 0 && TunnelMaxEntries) { // // Miniscule number of entries allowed. Lookaside 'em all. // LookasideDepth = (USHORT)TunnelMaxEntries + 1; } if (LookasideDepth > MAX_LOOKASIDE_DEPTH) { // // Finally, restrict the depth to something reasonable. // LookasideDepth = MAX_LOOKASIDE_DEPTH; } ExInitializePagedLookasideList( &TunnelLookasideList, NULL, NULL, 0, LOOKASIDE_NODE_SIZE, 'LnuT', LookasideDepth ); return; }
NTSTATUS EnumServices() { //_asm int 3 NTSTATUS status = STATUS_SUCCESS; ULONG SubKeyIndex, ResultLength, ulSize; HANDLE i, HandleRegKey = NULL; UNICODE_STRING RegistryKeyName, KeyValue; UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; PLIST_ENTRY pListHead = NULL, pListCur = NULL; PLDR_DATA_TABLE_ENTRY pLdrDataTable = NULL; PSERVICES_INFO pServicesInfo = NULL,\ pPreServicesInfo = NULL; PKEY_BASIC_INFORMATION pKeyBasicInfo = NULL; PKEY_FULL_INFORMATION pKeyFullInfo = NULL; /************************************************************************/ /* User-mode Handle Corresponding Object Name HKEY_LOCAL_MACHINE \Registry\Machine HKEY_USERS \Registry\User HKEY_CLASSES_ROOT No kernel-mode equivalent HKEY_CURRENT_USER No simple kernel-mode equivalent, but see Registry Run-Time Library Routines */ /************************************************************************/ WCHAR ServiceRegisterPath[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; //pListHead = ((PLIST_ENTRY)pDriverObj->DriverSection)->Flink; //pListCur = pListHead; __try { FreePagedLookasideListForServices(); ExInitializePagedLookasideList(&g_PageListServices, NULL, NULL, 0, sizeof(SERVICES_INFO), NULL, 0); RtlInitUnicodeString(&RegistryKeyName, ServiceRegisterPath); InitializeObjectAttributes(&ObjectAttributes, &RegistryKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, // handle NULL); status = ZwOpenKey(&HandleRegKey, KEY_READ, &ObjectAttributes); // 第一次调用是为了获取需要的长度 ZwQueryKey(HandleRegKey, KeyFullInformation, NULL, 0, &ulSize); pKeyFullInfo = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize); // 第二次调用是为了获取数据 ZwQueryKey(HandleRegKey, KeyFullInformation, pKeyFullInfo, ulSize, &ulSize); //循环遍历各个子项 for (SubKeyIndex = 0; SubKeyIndex <pKeyFullInfo->SubKeys; SubKeyIndex++) { ZwEnumerateKey(HandleRegKey, SubKeyIndex, KeyBasicInformation, NULL, 0, &ulSize); pKeyBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize); //获取第I个子项的数据 ZwEnumerateKey(HandleRegKey, SubKeyIndex, KeyBasicInformation, pKeyBasicInfo, ulSize, &ulSize); pServicesInfo = (PSERVICES_INFO)ExAllocateFromPagedLookasideList(&g_PageListServices); RtlZeroMemory(pServicesInfo, sizeof(SERVICES_INFO)); //服务的名称 RtlCopyMemory(pServicesInfo->lpwzSrvName, pKeyBasicInfo->Name, pKeyBasicInfo->NameLength); KeyName.Buffer = (PWCH)ExAllocatePool(PagedPool, RegistryKeyName.Length + pKeyBasicInfo->NameLength); KeyName.Length = RegistryKeyName.Length + pKeyBasicInfo->NameLength; KeyName.MaximumLength = KeyName.Length; RtlZeroMemory(KeyName.Buffer, KeyName.Length); RtlCopyMemory(KeyName.Buffer, RegistryKeyName.Buffer, RegistryKeyName.Length); RtlCopyMemory((PUCHAR)KeyName.Buffer + RegistryKeyName.Length, pKeyBasicInfo->Name, pKeyBasicInfo->NameLength); if (!QueryServiceRunType(&KeyName, pServicesInfo)) { if (NULL != pServicesInfo) { ExFreeToPagedLookasideList(&g_PageListServices, pServicesInfo); pServicesInfo = NULL; } } else { pServicesInfo->next = NULL; if (g_pServicesInfo == NULL) { g_pServicesInfo = pServicesInfo; pPreServicesInfo = pServicesInfo; } else { pPreServicesInfo->next = pServicesInfo; pPreServicesInfo = pServicesInfo; } } if (KeyName.Buffer != NULL) { ExFreePool(KeyName.Buffer); KeyName.Buffer = NULL; } if (pKeyBasicInfo != NULL) { ExFreePool(pKeyBasicInfo); pKeyBasicInfo = NULL; } } } __except(EXCEPTION_EXECUTE_HANDLER) { FreePagedLookasideListForServices(); KdPrint(("Services:EnumServices failed!")); status = STATUS_UNSUCCESSFUL; } if (NULL != HandleRegKey) { ZwClose(HandleRegKey); HandleRegKey = NULL; } if (pKeyBasicInfo != NULL) { ExFreePool(pKeyBasicInfo); pKeyBasicInfo = NULL; } if (pKeyFullInfo != NULL) { ExFreePool(pKeyFullInfo); pKeyFullInfo = NULL; } 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; }