mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
added support for template directories (copy ntfs extended attributes) to CreateDirectoryEx()
svn path=/trunk/; revision=14233
This commit is contained in:
parent
34484a48d9
commit
b407470ef1
2 changed files with 248 additions and 64 deletions
|
@ -34,15 +34,26 @@ HANDLE STDCALL CreateFileA (LPCSTR lpFileName,
|
||||||
DWORD dwFlagsAndAttributes,
|
DWORD dwFlagsAndAttributes,
|
||||||
HANDLE hTemplateFile)
|
HANDLE hTemplateFile)
|
||||||
{
|
{
|
||||||
PWCHAR FileNameW;
|
UNICODE_STRING FileNameU;
|
||||||
|
ANSI_STRING FileName;
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
|
|
||||||
DPRINT("CreateFileA(lpFileName %s)\n",lpFileName);
|
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)))
|
FileHandle = CreateFileW (FileNameU.Buffer,
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
FileHandle = CreateFileW (FileNameW ,
|
|
||||||
dwDesiredAccess,
|
dwDesiredAccess,
|
||||||
dwShareMode,
|
dwShareMode,
|
||||||
lpSecurityAttributes,
|
lpSecurityAttributes,
|
||||||
|
@ -50,6 +61,10 @@ HANDLE STDCALL CreateFileA (LPCSTR lpFileName,
|
||||||
dwFlagsAndAttributes,
|
dwFlagsAndAttributes,
|
||||||
hTemplateFile);
|
hTemplateFile);
|
||||||
|
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap (),
|
||||||
|
0,
|
||||||
|
FileNameU.Buffer);
|
||||||
|
|
||||||
return FileHandle;
|
return FileHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +269,7 @@ HANDLE STDCALL CreateFileW (LPCWSTR lpFileName,
|
||||||
{
|
{
|
||||||
/* we successfully read the extended attributes, break the loop
|
/* we successfully read the extended attributes, break the loop
|
||||||
and continue */
|
and continue */
|
||||||
|
EaLength = EaInformation.EaSize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -34,9 +34,13 @@ CreateDirectoryA (
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return CreateDirectoryExA (NULL,
|
PWCHAR PathNameW;
|
||||||
lpPathName,
|
|
||||||
lpSecurityAttributes);
|
if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return CreateDirectoryW (PathNameW,
|
||||||
|
lpSecurityAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,25 +54,28 @@ CreateDirectoryExA (
|
||||||
LPCSTR lpNewDirectory,
|
LPCSTR lpNewDirectory,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||||||
{
|
{
|
||||||
PWCHAR TemplateDirectoryW = NULL;
|
PWCHAR TemplateDirectoryW;
|
||||||
PWCHAR NewDirectoryW = NULL;
|
PWCHAR NewDirectoryW;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
if (lpTemplateDirectory != NULL &&
|
if (!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, TRUE)))
|
||||||
!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, FALSE)))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, TRUE)))
|
if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, FALSE)))
|
||||||
|
{
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap (),
|
||||||
|
0,
|
||||||
|
TemplateDirectoryW);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
ret = CreateDirectoryExW (TemplateDirectoryW,
|
ret = CreateDirectoryExW (TemplateDirectoryW,
|
||||||
NewDirectoryW,
|
NewDirectoryW,
|
||||||
lpSecurityAttributes);
|
lpSecurityAttributes);
|
||||||
|
|
||||||
if (lpNewDirectory != NULL)
|
RtlFreeHeap (RtlGetProcessHeap (),
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
0,
|
||||||
0,
|
TemplateDirectoryW);
|
||||||
NewDirectoryW);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -84,9 +91,55 @@ CreateDirectoryW (
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return CreateDirectoryExW (NULL,
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
lpPathName,
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
lpSecurityAttributes);
|
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;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
UNICODE_STRING NtPathU;
|
UNICODE_STRING NtPathU, NtTemplatePathU;
|
||||||
HANDLE DirectoryHandle;
|
HANDLE DirectoryHandle, TemplateHandle;
|
||||||
|
FILE_EA_INFORMATION EaInformation;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PVOID EaBuffer = NULL;
|
||||||
|
ULONG EaLength = 0;
|
||||||
|
|
||||||
DPRINT ("lpTemplateDirectory %S lpNewDirectory %S lpSecurityAttributes %p\n",
|
DPRINT ("lpTemplateDirectory %S lpNewDirectory %S lpSecurityAttributes %p\n",
|
||||||
lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes);
|
lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes);
|
||||||
|
|
||||||
// Can't create empty directory
|
/*
|
||||||
if(lpNewDirectory == NULL || *lpNewDirectory == 0)
|
* Read the extended attributes from the template directory
|
||||||
{
|
*/
|
||||||
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lpTemplateDirectory != NULL && *lpTemplateDirectory != 0)
|
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpTemplateDirectory,
|
||||||
|
&NtTemplatePathU,
|
||||||
|
NULL,
|
||||||
|
NULL))
|
||||||
{
|
{
|
||||||
// get object attributes from template directory
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
DPRINT("KERNEL32:FIXME:%s:%d\n",__FILE__,__LINE__);
|
|
||||||
return FALSE;
|
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,
|
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewDirectory,
|
||||||
&NtPathU,
|
&NtPathU,
|
||||||
NULL,
|
NULL,
|
||||||
NULL))
|
NULL))
|
||||||
|
{
|
||||||
|
/* free the he extended attributes buffer */
|
||||||
|
if (EaBuffer != NULL)
|
||||||
|
{
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap (),
|
||||||
|
0,
|
||||||
|
EaBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT ("NtPathU \'%wZ\'\n", &NtPathU);
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&NtPathU,
|
||||||
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
OBJ_CASE_INSENSITIVE,
|
||||||
ObjectAttributes.RootDirectory = NULL;
|
NULL,
|
||||||
ObjectAttributes.ObjectName = &NtPathU;
|
(lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
|
||||||
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
|
|
||||||
ObjectAttributes.SecurityDescriptor = NULL;
|
|
||||||
ObjectAttributes.SecurityQualityOfService = NULL;
|
|
||||||
|
|
||||||
Status = NtCreateFile (&DirectoryHandle,
|
Status = NtCreateFile (&DirectoryHandle,
|
||||||
DIRECTORY_ALL_ACCESS,
|
GENERIC_READ,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
NULL,
|
NULL,
|
||||||
FILE_ATTRIBUTE_DIRECTORY,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
0,
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
FILE_CREATE,
|
FILE_CREATE,
|
||||||
FILE_DIRECTORY_FILE,
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
||||||
NULL,
|
EaBuffer,
|
||||||
0);
|
EaLength);
|
||||||
DPRINT("Status: %lx\n", Status);
|
|
||||||
|
/* free the he extended attributes buffer */
|
||||||
|
if (EaBuffer != NULL)
|
||||||
|
{
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap (),
|
||||||
|
0,
|
||||||
|
EaBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
RtlFreeHeap (RtlGetProcessHeap (),
|
||||||
0,
|
0,
|
||||||
|
@ -212,12 +389,11 @@ RemoveDirectoryW (
|
||||||
NULL))
|
NULL))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
ObjectAttributes.RootDirectory = NULL;
|
&NtPathU,
|
||||||
ObjectAttributes.ObjectName = &NtPathU;
|
OBJ_CASE_INSENSITIVE,
|
||||||
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
|
NULL,
|
||||||
ObjectAttributes.SecurityDescriptor = NULL;
|
NULL);
|
||||||
ObjectAttributes.SecurityQualityOfService = NULL;
|
|
||||||
|
|
||||||
DPRINT("NtPathU '%S'\n", NtPathU.Buffer);
|
DPRINT("NtPathU '%S'\n", NtPathU.Buffer);
|
||||||
|
|
||||||
|
@ -251,18 +427,10 @@ RemoveDirectoryW (
|
||||||
&FileDispInfo,
|
&FileDispInfo,
|
||||||
sizeof(FILE_DISPOSITION_INFORMATION),
|
sizeof(FILE_DISPOSITION_INFORMATION),
|
||||||
FileDispositionInformation);
|
FileDispositionInformation);
|
||||||
|
NtClose(DirectoryHandle);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
CHECKPOINT;
|
|
||||||
NtClose(DirectoryHandle);
|
|
||||||
SetLastErrorByStatus (Status);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = NtClose (DirectoryHandle);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
CHECKPOINT;
|
|
||||||
SetLastErrorByStatus (Status);
|
SetLastErrorByStatus (Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue