UINT64 GetDirectorySizeInternal(OBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return 0; UINT64 Space = 0; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) continue; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; Space += GetDirectorySizeInternal(ObjectAttributes); } else { Space += FileInfo.AllocationSize.QuadPart; } } NtClose(hFile); return Space; }
NTSTATUS GetNextReparseVolumePath( IN HANDLE Handle, OUT PUNICODE_STRING Path ) /*++ Routine Description: This routine queries the reparse index for the next volume mount point. Arguments: Handle - Supplies the handle. Path - Returns the path. Return Value: NTSTATUS --*/ { NTSTATUS status; IO_STATUS_BLOCK ioStatus; FILE_REPARSE_POINT_INFORMATION reparseInfo; UNICODE_STRING fileId; OBJECT_ATTRIBUTES oa; HANDLE h; PREPARSE_DATA_BUFFER reparse; UNICODE_STRING volumeName; ULONG nameInfoSize; PFILE_NAME_INFORMATION nameInfo; for (;;) { status = ZwQueryDirectoryFile(Handle, NULL, NULL, NULL, &ioStatus, &reparseInfo, sizeof(reparseInfo), FileReparsePointInformation, TRUE, NULL, FALSE); if (!NT_SUCCESS(status)) { return status; } if (reparseInfo.Tag != IO_REPARSE_TAG_MOUNT_POINT) { continue; } fileId.Length = sizeof(reparseInfo.FileReference); fileId.MaximumLength = fileId.Length; fileId.Buffer = (PWSTR) &reparseInfo.FileReference; InitializeObjectAttributes(&oa, &fileId, 0, Handle, NULL); status = ZwOpenFile(&h, SYNCHRONIZE | FILE_GENERIC_READ, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(status)) { continue; } reparse = ExAllocatePool(PagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!reparse) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwFsControlFile(h, NULL, NULL, NULL, &ioStatus, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!NT_SUCCESS(status)) { ExFreePool(reparse); ZwClose(h); continue; } volumeName.Length = reparse->MountPointReparseBuffer.SubstituteNameLength - sizeof(WCHAR); volumeName.MaximumLength = volumeName.Length + sizeof(WCHAR); volumeName.Buffer = (PWCHAR) ((PCHAR) reparse->MountPointReparseBuffer.PathBuffer + reparse->MountPointReparseBuffer.SubstituteNameOffset); volumeName.Buffer[volumeName.Length/sizeof(WCHAR)] = 0; if (!IsVolumeName(&volumeName)) { ExFreePool(reparse); ZwClose(h); continue; } ExFreePool(reparse); nameInfoSize = 1024; nameInfo = ExAllocatePool(PagedPool, nameInfoSize); if (!nameInfo) { ZwClose(h); continue; } status = ZwQueryInformationFile(h, &ioStatus, nameInfo, nameInfoSize, FileNameInformation); ZwClose(h); if (!NT_SUCCESS(status)) { continue; } Path->Length = (USHORT) nameInfo->FileNameLength; Path->MaximumLength = Path->Length + sizeof(WCHAR); Path->Buffer = ExAllocatePool(PagedPool, Path->MaximumLength); if (!Path->Buffer) { ExFreePool(nameInfo); continue; } RtlCopyMemory(Path->Buffer, nameInfo->FileName, Path->Length); Path->Buffer[Path->Length/sizeof(WCHAR)] = 0; ExFreePool(nameInfo); break; } return status; }
/*++ * @name RtlCliListDirectory * * The RtlCliListDirectory routine lists the current directory contents. * * @param None. * * @return NTSTATUS * * @remarks Documentation for this routine needs to be completed. * *--*/ NTSTATUS RtlCliListDirectory(VOID) { UNICODE_STRING DirectoryString; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE DirectoryHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; BOOLEAN FirstQuery = TRUE; WCHAR CurrentDirectory[MAX_PATH]; PFILE_BOTH_DIR_INFORMATION DirectoryInfo, Entry; HANDLE EventHandle; CHAR i, c; // // For now, we only support the current directory (ie: you can't dir e:\ // without CDing into it first // RtlCliGetCurrentDirectory(CurrentDirectory); // // Convert it to NT Format // if (!RtlDosPathNameToNtPathName_U(CurrentDirectory, &DirectoryString, NULL, NULL)) { // // Fail // return STATUS_UNSUCCESSFUL; } // // Initialize the object attributes // RtlCliDisplayString(" Directory of %S\n\n", CurrentDirectory); InitializeObjectAttributes(&ObjectAttributes, &DirectoryString, OBJ_CASE_INSENSITIVE, NULL, NULL); // // Open the directory // Status = ZwCreateFile(&DirectoryHandle, FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0); if (!NT_SUCCESS(Status)) { return Status; } // // Allocate space for directory entry information // DirectoryInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, 4096); if (!DirectoryInfo) { return STATUS_INSUFFICIENT_RESOURCES; } // // Create the event to wait on // InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); Status = NtCreateEvent(&EventHandle, EVENT_ALL_ACCESS, &ObjectAttributes, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { return Status; } // // Start loop // i = 0; for (;;) { // // Get the contents of the directory, adding up the size as we go // Status = ZwQueryDirectoryFile(DirectoryHandle, EventHandle, NULL, 0, &IoStatusBlock, DirectoryInfo, 4096, FileBothDirectoryInformation, FALSE, NULL, FirstQuery); if (Status == STATUS_PENDING) { // // Wait on the event // NtWaitForSingleObject(EventHandle, FALSE, NULL); Status = IoStatusBlock.Status; } // // Check for success // if (!NT_SUCCESS(Status)) { // // Nothing left to enumerate. Close handles and free memory // ZwClose(DirectoryHandle); RtlFreeHeap(RtlGetProcessHeap(), 0, DirectoryInfo); return STATUS_SUCCESS; } // // Loop every directory // Entry = DirectoryInfo; while(Entry) { // // List the file // RtlCliDumpFileInfo(Entry); if (++i > 20) { i = 0; RtlCliDisplayString("Continue listing (Y/N):"); while (TRUE) { c = RtlCliGetChar(hKeyboard); if (c == 'n' || c == 'N') { RtlCliDisplayString("\n"); return STATUS_SUCCESS; } if (c == 'y' || c == 'Y') { break; } } RtlCliDisplayString("\n"); } // // Make sure we still have a file // if (!Entry->NextEntryOffset) break; // // Move to the next one // Entry = (PFILE_BOTH_DIR_INFORMATION)((ULONG_PTR)Entry + Entry->NextEntryOffset); } // // This isn't the first scan anymore // FirstQuery = FALSE; } }
UINT64 GetDirectoryAllocationSizeInternal(OBJECT_ATTRIBUTES ObjectAttributes, std::map<UINT64, DWORD>& FileMap) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return 0; UINT64 Space = 0; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; Status = -1; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; FILE_STANDARD_INFORMATION FileStandardInfo; FILE_INTERNAL_INFORMATION FileInternalInfo; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) continue; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } Space += GetDirectoryAllocationSizeInternal(ObjectAttributes, FileMap); } else { if (NtGetFileId(&ObjectAttributes, &FileStandardInfo, &FileInternalInfo)) continue; if (FileStandardInfo.NumberOfLinks != 1) { auto T = FileMap.insert(std::pair<UINT64, DWORD>(FileInternalInfo.IndexNumber.QuadPart, FileStandardInfo.NumberOfLinks)).first; if (--(T->second)) continue; } Space += FileInfo.AllocationSize.QuadPart; } } NtClose(hFile); return Space; }
NTSTATUS DeleteDirectoryInternal(OBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return Status; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; NTSTATUS Error = 0; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if ((FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) goto StartDelete; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } if (Error = DeleteDirectoryInternal(ObjectAttributes)) { goto OnError; } } StartDelete: if (FileInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { //取消只读属性 if (Error = NtSetFileAttributes(&ObjectAttributes, FileInfo.FileAttributes^FILE_ATTRIBUTE_READONLY)) { goto OnError; } } if (Error = NtDeleteFile2(&ObjectAttributes)) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { //删除失败恢复只读属性 NtSetFileAttributes(&ObjectAttributes, FileInfo.FileAttributes); } OnError: Status = Error; } } //End: NtClose(hFile); return Status; }
NTSTATUS NtCopyDirectory(OBJECT_ATTRIBUTES ExistingDirectoryPath, OBJECT_ATTRIBUTES NewDirectoryPath) { HANDLE hExistingFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hExistingFile, SYNCHRONIZE | FILE_LIST_DIRECTORY| FILE_READ_ATTRIBUTES, &ExistingDirectoryPath, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return Status; HANDLE hNewFile; Status = NtCreateFile(&hNewFile, SYNCHRONIZE | FILE_LIST_DIRECTORY| FILE_WRITE_ATTRIBUTES, &NewDirectoryPath, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, NULL); if (Status == 0) { byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; NewDirectoryPath.RootDirectory = hNewFile; ExistingDirectoryPath.RootDirectory = hExistingFile; ExistingDirectoryPath.ObjectName = NewDirectoryPath.ObjectName = &TempFileName; byte FileBuffer[1024]; FILE_BASIC_INFORMATION BaseInfo; while (ZwQueryDirectoryFile(hExistingFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; Status = NtCopyDirectory(ExistingDirectoryPath, NewDirectoryPath); } else { HANDLE hExistingFile; Status = NtOpenFile(&hExistingFile, FILE_GENERIC_READ, &ExistingDirectoryPath, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) break; HANDLE hNewFile; Status = NtCreateFile(&hNewFile, SYNCHRONIZE | FILE_GENERIC_WRITE, &NewDirectoryPath, &IoStatusBlock, NULL, FileInfo.FileAttributes, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, NULL); if (Status) { NtClose(hExistingFile); break; } DWORD cbData; while (true) { if (!ReadFile(hExistingFile, FileBuffer, sizeof(FileBuffer), &cbData, NULL)) { Status = GetLastError_s(); break; } if (!cbData) break; WriteFile(hNewFile, FileBuffer, cbData, &cbData, NULL); } if (NtQueryInformationFile(hExistingFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation)==0) { NtSetInformationFile(hNewFile,&IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation); } NtClose(hNewFile); NtClose(hExistingFile); } } if (NtQueryInformationFile(hExistingFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation) == 0) { NtSetInformationFile(hNewFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation); } NtClose(hNewFile); } NtClose(hExistingFile); return Status; }
co_rc_t co_os_file_getdir(char *dirname, co_filesystem_dir_names_t *names) { UNICODE_STRING dirname_unicode; OBJECT_ATTRIBUTES attributes; NTSTATUS status; HANDLE handle; FILE_DIRECTORY_INFORMATION *dir_entries_buffer, *entry; unsigned long dir_entries_buffer_size = 0x1000; IO_STATUS_BLOCK io_status; BOOLEAN first_iteration = TRUE; co_filesystem_name_t *new_name; co_rc_t rc; co_list_init(&names->list); co_debug_lvl(filesystem, 10, "listing of '%s'", dirname); rc = co_winnt_utf8_to_unicode(dirname, &dirname_unicode); if (!CO_OK(rc)) return rc; InitializeObjectAttributes(&attributes, &dirname_unicode, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwCreateFile(&handle, FILE_LIST_DIRECTORY, &attributes, &io_status, NULL, 0, FILE_SHARE_DIRECTORY, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, NULL, 0); if (!NT_SUCCESS(status)) { co_debug_lvl(filesystem, 5, "error %x ZwCreateFile('%s')", (int)status, dirname); rc = co_status_convert(status); goto error; } dir_entries_buffer = co_os_malloc(dir_entries_buffer_size); if (!dir_entries_buffer) { rc = CO_RC(OUT_OF_MEMORY); goto error_1; } for (;;) { status = ZwQueryDirectoryFile(handle, NULL, NULL, 0, &io_status, dir_entries_buffer, dir_entries_buffer_size, FileDirectoryInformation, FALSE, NULL, first_iteration); if (!NT_SUCCESS(status)) break; entry = dir_entries_buffer; for (;;) { int filename_utf8_length; filename_utf8_length = co_utf8_wctowbstrlen(entry->FileName, entry->FileNameLength/sizeof(WCHAR)); new_name = co_os_malloc(filename_utf8_length + sizeof(co_filesystem_name_t) + 2); if (!new_name) { rc = CO_RC(OUT_OF_MEMORY); goto error_2; } if (entry->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) new_name->type = FUSE_DT_DIR; else new_name->type = FUSE_DT_REG; rc = co_utf8_wcstombs(new_name->name, entry->FileName, filename_utf8_length + 1); if (!CO_OK(rc)) { co_os_free(new_name); goto error_2; } co_list_add_tail(&new_name->node, &names->list); if (entry->NextEntryOffset == 0) break; entry = (FILE_DIRECTORY_INFORMATION *)(((char *)entry) + entry->NextEntryOffset); } first_iteration = FALSE; } rc = CO_RC(OK); error_2: if (!CO_OK(rc)) co_filesystem_getdir_free(names); co_os_free(dir_entries_buffer); error_1: ZwClose(handle); error: co_winnt_free_unicode(&dirname_unicode); return rc; }
co_rc_t co_os_file_get_attr(char *fullname, struct fuse_attr *attr) { char * dirname; char * filename; UNICODE_STRING dirname_unicode; UNICODE_STRING filename_unicode; OBJECT_ATTRIBUTES attributes; NTSTATUS status; HANDLE handle; struct { union { FILE_FULL_DIRECTORY_INFORMATION entry; FILE_BOTH_DIRECTORY_INFORMATION entry2; }; WCHAR name_filler[sizeof(co_pathname_t)]; } entry_buffer; IO_STATUS_BLOCK io_status; co_rc_t rc; int len, len1; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; ULONG FileAttributes; attr->uid = 0; attr->gid = 0; attr->rdev = 0; attr->_dummy = 0; attr->nlink = 1; len = co_strlen(fullname); len1 = len; /* Hack: WinNT detects "C:\" not as directory! */ if (len >= 3 && fullname[len-1] == ':') { co_debug_lvl(filesystem, 10, "Root dir: '%s'", fullname); attr->atime = \ attr->mtime = \ attr->ctime = co_os_get_time(); attr->mode = FUSE_S_IFDIR | 0777; attr->size = 0; attr->blocks = 0; return CO_RC(OK); } while (len > 0 && fullname[len-1] != '\\') { if (fullname[len-1] == '?' || fullname[len-1] == '*') { co_debug_lvl(filesystem, 5, "error: Wildcard in filename ('%s')", fullname); return CO_RC(NOT_FOUND); } len--; } dirname = co_os_malloc(len+1); if (!dirname) { co_debug_lvl(filesystem, 5, "no memory"); return CO_RC(OUT_OF_MEMORY); } memcpy(dirname, fullname, len); dirname[len] = 0; filename = &fullname[len]; rc = co_winnt_utf8_to_unicode(dirname, &dirname_unicode); if (!CO_OK(rc)) goto error_0; rc = co_winnt_utf8_to_unicode(filename, &filename_unicode); if (!CO_OK(rc)) goto error_1; InitializeObjectAttributes(&attributes, &dirname_unicode, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwCreateFile(&handle, FILE_LIST_DIRECTORY, &attributes, &io_status, NULL, 0, FILE_SHARE_DIRECTORY, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, NULL, 0); if (!NT_SUCCESS(status)) { co_debug_lvl(filesystem, 5, "error %x ZwCreateFile('%s')", (int)status, dirname); rc = co_status_convert(status); goto error_2; } status = ZwQueryDirectoryFile(handle, NULL, NULL, 0, &io_status, &entry_buffer, sizeof(entry_buffer), FileFullDirectoryInformation, PTRUE, &filename_unicode, PTRUE); if (!NT_SUCCESS(status)) { if (status == STATUS_UNMAPPABLE_CHARACTER) { status = ZwQueryDirectoryFile(handle, NULL, NULL, 0, &io_status, &entry_buffer, sizeof(entry_buffer), FileBothDirectoryInformation, PTRUE, &filename_unicode, PTRUE); if (!NT_SUCCESS(status)) { co_debug_lvl(filesystem, 5, "error %x ZwQueryDirectoryFile('%s')", (int)status, filename); rc = co_status_convert(status); goto error_3; } else { LastAccessTime = entry_buffer.entry2.LastAccessTime; LastWriteTime = entry_buffer.entry2.LastWriteTime; ChangeTime = entry_buffer.entry2.ChangeTime; EndOfFile = entry_buffer.entry2.EndOfFile; FileAttributes = entry_buffer.entry2.FileAttributes; } } else { co_debug_lvl(filesystem, 5, "error %x ZwQueryDirectoryFile('%s')", (int)status, filename); rc = co_status_convert(status); goto error_3; } } else { LastAccessTime = entry_buffer.entry.LastAccessTime; LastWriteTime = entry_buffer.entry.LastWriteTime; ChangeTime = entry_buffer.entry.ChangeTime; EndOfFile = entry_buffer.entry.EndOfFile; FileAttributes = entry_buffer.entry.FileAttributes; } attr->atime = windows_time_to_unix_time(LastAccessTime); attr->mtime = windows_time_to_unix_time(LastWriteTime); attr->ctime = windows_time_to_unix_time(ChangeTime); #define FUSE_S_IR (FUSE_S_IRUSR | FUSE_S_IRGRP | FUSE_S_IROTH) #define FUSE_S_IW (FUSE_S_IWUSR | FUSE_S_IWGRP | FUSE_S_IWOTH) #define FUSE_S_IX (FUSE_S_IXUSR | FUSE_S_IXGRP | FUSE_S_IXOTH) if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) attr->mode = FUSE_S_IFDIR | ((FileAttributes & FILE_ATTRIBUTE_HIDDEN) ? 0 : FUSE_S_IR) | ((FileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : FUSE_S_IW) | ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) ? 0 : FUSE_S_IX); else attr->mode = FUSE_S_IFREG | ((FileAttributes & FILE_ATTRIBUTE_HIDDEN) ? 0 : FUSE_S_IR) | ((FileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : FUSE_S_IW) | ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) ? FUSE_S_IX : 0); attr->size = EndOfFile.QuadPart; attr->blocks = (EndOfFile.QuadPart + ((1<<10)-1)) >> 10; rc = CO_RC(OK); error_3: ZwClose(handle); error_2: co_winnt_free_unicode(&filename_unicode); error_1: co_winnt_free_unicode(&dirname_unicode); error_0: co_os_free(dirname); return rc; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Searches for files according to specified Mask starting from specified Path. Links all found into the FileListHead. // Returns number of files found. // ULONG FilesFind( PWCHAR Directory, // directory name to search in PWCHAR Mask, // search mask ULONG Flags, // variouse flags PLIST_ENTRY FileListHead // result list of file descriptors ) { ULONG bSize, Found = 0; HANDLE hDir; NTSTATUS ntStatus; UNICODE_STRING uDirectory; OBJECT_ATTRIBUTES oa = {0}; IO_STATUS_BLOCK IoStatus = {0}; PFILE_DIRECTORY_INFORMATION FileInfo, CurInfo; PFILE_DIRECTORY_ENTRY DirEntry; ULONG DirLenBytes = wcslen(Directory) * sizeof(WCHAR); RtlInitUnicodeString(&uDirectory, Directory); InitializeObjectAttributes(&oa, &uDirectory, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL); ntStatus = ZwCreateFile(&hDir, GENERIC_READ, &oa, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (NT_SUCCESS(ntStatus)) { if (FileInfo = MyAllocatePool(PagedPool, PAGE_SIZE)) { do { ntStatus = ZwQueryDirectoryFile(hDir, NULL, NULL, 0, &IoStatus, FileInfo, PAGE_SIZE - sizeof(WCHAR), FileDirectoryInformation, FALSE, NULL, FALSE); if (NT_SUCCESS(ntStatus)) { CurInfo = FileInfo; do { if (CurInfo->FileName[0] != '.') { if (!(CurInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (Flags & FILES_FIND_DIRECTORIES)) { ULONG NameLen = CurInfo->FileNameLength >> 1; WCHAR z = CurInfo->FileName[NameLen]; CurInfo->FileName[NameLen] = 0; if (__wcswicmp(Mask, (PWCHAR)&CurInfo->FileName)) { if (DirEntry = FilesAlocateDirEntry(DirLenBytes + CurInfo->FileNameLength)) { RtlCopyMemory(&DirEntry->FileInfo, CurInfo, sizeof(FILE_DIRECTORY_INFORMATION)); RtlCopyMemory(&DirEntry->FileInfo.FileName, Directory, DirLenBytes); RtlCopyMemory(&DirEntry->FileInfo.FileName[DirLenBytes >> 1], &CurInfo->FileName, CurInfo->FileNameLength); InsertTailList(FileListHead, &DirEntry->Entry); Found += 1; } } // if (__wcswicmp(Mask, (PWCHAR)&CurInfo->FileName)) CurInfo->FileName[NameLen] = z; } // if (!(CurInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (Flags & FILES_FIND_DIRECTORIES)) if ((CurInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (Flags & FILES_SCAN_SUBDIRECTORIES)) { PWCHAR NewDir = MyAllocatePool(PagedPool, DirLenBytes + CurInfo->FileNameLength + 2*sizeof(WCHAR)); if (NewDir) { RtlCopyMemory(NewDir, Directory, DirLenBytes); RtlCopyMemory((PCHAR)NewDir + DirLenBytes, CurInfo->FileName, CurInfo->FileNameLength); NewDir[(DirLenBytes + CurInfo->FileNameLength) >> 1] = '\\'; NewDir[(DirLenBytes + CurInfo->FileNameLength + sizeof(WCHAR)) >> 1] = 0; Found += FilesFind(NewDir, Mask, Flags, FileListHead); MyFreePool(NewDir); } } // if ((CurInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (Flags & FILES_SCAN_SUBDIRECTORIES)) } // if (CurInfo->FileName[0] != '.') if (CurInfo->NextEntryOffset == 0) break; CurInfo = (PFILE_DIRECTORY_INFORMATION)((PCHAR)CurInfo + CurInfo->NextEntryOffset); } while(TRUE); } // if (NT_SUCCESS(ntStatus)) } while(NT_SUCCESS(ntStatus));
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; }