From b407470ef1157e314d8ec5856951261ab0d5e7a6 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sun, 20 Mar 2005 20:27:56 +0000 Subject: [PATCH] added support for template directories (copy ntfs extended attributes) to CreateDirectoryEx() svn path=/trunk/; revision=14233 --- reactos/lib/kernel32/file/create.c | 26 ++- reactos/lib/kernel32/file/dir.c | 286 +++++++++++++++++++++++------ 2 files changed, 248 insertions(+), 64 deletions(-) diff --git a/reactos/lib/kernel32/file/create.c b/reactos/lib/kernel32/file/create.c index bda7135aef0..f9046a35254 100644 --- a/reactos/lib/kernel32/file/create.c +++ b/reactos/lib/kernel32/file/create.c @@ -34,15 +34,26 @@ HANDLE STDCALL CreateFileA (LPCSTR lpFileName, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { - PWCHAR FileNameW; + UNICODE_STRING FileNameU; + ANSI_STRING FileName; HANDLE FileHandle; DPRINT("CreateFileA(lpFileName %s)\n",lpFileName); + + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); - if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) - return INVALID_HANDLE_VALUE; - - FileHandle = CreateFileW (FileNameW , + FileHandle = CreateFileW (FileNameU.Buffer, dwDesiredAccess, dwShareMode, lpSecurityAttributes, @@ -50,6 +61,10 @@ HANDLE STDCALL CreateFileA (LPCSTR lpFileName, dwFlagsAndAttributes, hTemplateFile); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileNameU.Buffer); + return FileHandle; } @@ -254,6 +269,7 @@ HANDLE STDCALL CreateFileW (LPCWSTR lpFileName, { /* we successfully read the extended attributes, break the loop and continue */ + EaLength = EaInformation.EaSize; break; } else diff --git a/reactos/lib/kernel32/file/dir.c b/reactos/lib/kernel32/file/dir.c index 5327fb36470..f7d60b5bbbf 100644 --- a/reactos/lib/kernel32/file/dir.c +++ b/reactos/lib/kernel32/file/dir.c @@ -34,9 +34,13 @@ CreateDirectoryA ( LPSECURITY_ATTRIBUTES lpSecurityAttributes ) { - return CreateDirectoryExA (NULL, - lpPathName, - lpSecurityAttributes); + PWCHAR PathNameW; + + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; + + return CreateDirectoryW (PathNameW, + lpSecurityAttributes); } @@ -50,25 +54,28 @@ CreateDirectoryExA ( LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { - PWCHAR TemplateDirectoryW = NULL; - PWCHAR NewDirectoryW = NULL; + PWCHAR TemplateDirectoryW; + PWCHAR NewDirectoryW; BOOL ret; - if (lpTemplateDirectory != NULL && - !(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, FALSE))) + if (!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, TRUE))) return FALSE; - if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, TRUE))) + if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, FALSE))) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + TemplateDirectoryW); return FALSE; + } ret = CreateDirectoryExW (TemplateDirectoryW, - NewDirectoryW, - lpSecurityAttributes); + NewDirectoryW, + lpSecurityAttributes); - if (lpNewDirectory != NULL) - RtlFreeHeap (RtlGetProcessHeap (), - 0, - NewDirectoryW); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + TemplateDirectoryW); return ret; } @@ -84,9 +91,55 @@ CreateDirectoryW ( LPSECURITY_ATTRIBUTES lpSecurityAttributes ) { - return CreateDirectoryExW (NULL, - lpPathName, - lpSecurityAttributes); + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE DirectoryHandle; + NTSTATUS Status; + + DPRINT ("lpPathName %S lpSecurityAttributes %p\n", + lpPathName, lpSecurityAttributes); + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpPathName, + &NtPathU, + NULL, + NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL)); + + Status = NtCreateFile (&DirectoryHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + NtClose (DirectoryHandle); + + return TRUE; } @@ -103,54 +156,178 @@ CreateDirectoryExW ( { OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING NtPathU; - HANDLE DirectoryHandle; + UNICODE_STRING NtPathU, NtTemplatePathU; + HANDLE DirectoryHandle, TemplateHandle; + FILE_EA_INFORMATION EaInformation; NTSTATUS Status; + PVOID EaBuffer = NULL; + ULONG EaLength = 0; DPRINT ("lpTemplateDirectory %S lpNewDirectory %S lpSecurityAttributes %p\n", lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes); - // Can't create empty directory - if(lpNewDirectory == NULL || *lpNewDirectory == 0) - { - SetLastError(ERROR_PATH_NOT_FOUND); - return FALSE; - } + /* + * Read the extended attributes from the template directory + */ - if (lpTemplateDirectory != NULL && *lpTemplateDirectory != 0) + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpTemplateDirectory, + &NtTemplatePathU, + NULL, + NULL)) { - // get object attributes from template directory - DPRINT("KERNEL32:FIXME:%s:%d\n",__FILE__,__LINE__); + SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } + + InitializeObjectAttributes(&ObjectAttributes, + &NtTemplatePathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtCreateFile (&TemplateHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_DIRECTORY_FILE, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtTemplatePathU.Buffer); + SetLastErrorByStatus (Status); + return FALSE; + } + + for (;;) + { + Status = NtQueryInformationFile(TemplateHandle, + &IoStatusBlock, + &EaInformation, + sizeof(FILE_EA_INFORMATION), + FileEaInformation); + if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0)) + { + EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + EaInformation.EaSize); + if (EaBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + Status = NtQueryEaFile(TemplateHandle, + &IoStatusBlock, + EaBuffer, + EaInformation.EaSize, + FALSE, + NULL, + 0, + NULL, + TRUE); + + if (NT_SUCCESS(Status)) + { + /* we successfully read the extended attributes */ + EaLength = EaInformation.EaSize; + break; + } + else + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + EaBuffer); + EaBuffer = NULL; + + if (Status != STATUS_BUFFER_TOO_SMALL) + { + /* unless we just allocated not enough memory, break the loop + and just continue without copying extended attributes */ + break; + } + } + } + else + { + /* failure or no extended attributes present, break the loop */ + break; + } + } + + NtClose(TemplateHandle); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtTemplatePathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + /* free the he extended attributes buffer */ + if (EaBuffer != NULL) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + EaBuffer); + } + + SetLastErrorByStatus (Status); + return FALSE; + } + + /* + * Create the new directory and copy over the extended attributes if + * needed + */ if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewDirectory, &NtPathU, NULL, NULL)) + { + /* free the he extended attributes buffer */ + if (EaBuffer != NULL) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + EaBuffer); + } + + SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; + } - DPRINT ("NtPathU \'%wZ\'\n", &NtPathU); - - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); - ObjectAttributes.RootDirectory = NULL; - ObjectAttributes.ObjectName = &NtPathU; - ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT; - ObjectAttributes.SecurityDescriptor = NULL; - ObjectAttributes.SecurityQualityOfService = NULL; + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL)); Status = NtCreateFile (&DirectoryHandle, - DIRECTORY_ALL_ACCESS, + GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, - FILE_ATTRIBUTE_DIRECTORY, - 0, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, - FILE_DIRECTORY_FILE, - NULL, - 0); - DPRINT("Status: %lx\n", Status); + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + EaBuffer, + EaLength); + + /* free the he extended attributes buffer */ + if (EaBuffer != NULL) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + EaBuffer); + } RtlFreeHeap (RtlGetProcessHeap (), 0, @@ -212,12 +389,11 @@ RemoveDirectoryW ( NULL)) return FALSE; - ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); - ObjectAttributes.RootDirectory = NULL; - ObjectAttributes.ObjectName = &NtPathU; - ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; - ObjectAttributes.SecurityDescriptor = NULL; - ObjectAttributes.SecurityQualityOfService = NULL; + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); DPRINT("NtPathU '%S'\n", NtPathU.Buffer); @@ -251,18 +427,10 @@ RemoveDirectoryW ( &FileDispInfo, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation); + NtClose(DirectoryHandle); + if (!NT_SUCCESS(Status)) { - CHECKPOINT; - NtClose(DirectoryHandle); - SetLastErrorByStatus (Status); - return FALSE; - } - - Status = NtClose (DirectoryHandle); - if (!NT_SUCCESS(Status)) - { - CHECKPOINT; SetLastErrorByStatus (Status); return FALSE; }