added support for template directories (copy ntfs extended attributes) to CreateDirectoryEx()

svn path=/trunk/; revision=14233
This commit is contained in:
Thomas Bluemel 2005-03-20 20:27:56 +00:00
parent 34484a48d9
commit b407470ef1
2 changed files with 248 additions and 64 deletions

View file

@ -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);
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
return INVALID_HANDLE_VALUE;
RtlInitAnsiString (&FileName,
(LPSTR)lpFileName);
FileHandle = CreateFileW (FileNameW ,
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
else
RtlOemStringToUnicodeString (&FileNameU,
&FileName,
TRUE);
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

View file

@ -34,8 +34,12 @@ CreateDirectoryA (
LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
{
return CreateDirectoryExA (NULL,
lpPathName,
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);
if (lpNewDirectory != NULL)
RtlFreeHeap (RtlGetProcessHeap (),
0,
NewDirectoryW);
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)
/*
* Read the extended attributes from the template directory
*/
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpTemplateDirectory,
&NtTemplatePathU,
NULL,
NULL))
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
if (lpTemplateDirectory != NULL && *lpTemplateDirectory != 0)
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))
{
// get object attributes from template directory
DPRINT("KERNEL32:FIXME:%s:%d\n",__FILE__,__LINE__);
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);
if (!NT_SUCCESS(Status))
{
CHECKPOINT;
NtClose(DirectoryHandle);
SetLastErrorByStatus (Status);
return FALSE;
}
Status = NtClose (DirectoryHandle);
if (!NT_SUCCESS(Status))
{
CHECKPOINT;
SetLastErrorByStatus (Status);
return FALSE;
}