mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 17:44:45 +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,
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue