added support for template directories (copy ntfs extended attributes) to CreateDirectoryEx()
Modified: trunk/reactos/lib/kernel32/file/create.c
Modified: trunk/reactos/lib/kernel32/file/dir.c

Modified: trunk/reactos/lib/kernel32/file/create.c
--- trunk/reactos/lib/kernel32/file/create.c	2005-03-20 19:11:52 UTC (rev 14232)
+++ trunk/reactos/lib/kernel32/file/create.c	2005-03-20 20:27:56 UTC (rev 14233)
@@ -34,15 +34,26 @@
 			    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 @@
 			     dwFlagsAndAttributes,
 			     hTemplateFile);
    
+   RtlFreeHeap (RtlGetProcessHeap (),
+		0,
+		FileNameU.Buffer);
+   
    return FileHandle;
 }
 
@@ -254,6 +269,7 @@
             {
                /* we successfully read the extended attributes, break the loop
                   and continue */
+               EaLength = EaInformation.EaSize;
                break;
             }
             else

Modified: trunk/reactos/lib/kernel32/file/dir.c
--- trunk/reactos/lib/kernel32/file/dir.c	2005-03-20 19:11:52 UTC (rev 14232)
+++ trunk/reactos/lib/kernel32/file/dir.c	2005-03-20 20:27:56 UTC (rev 14233)
@@ -34,9 +34,13 @@
         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 @@
         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 @@
         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,55 +156,179 @@
 {
         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);
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &NtPathU,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
 
-        ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
-        ObjectAttributes.RootDirectory = NULL;
-        ObjectAttributes.ObjectName = &NtPathU;
-        ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
-        ObjectAttributes.SecurityDescriptor = NULL;
-        ObjectAttributes.SecurityQualityOfService = 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,
                      NtPathU.Buffer);
@@ -212,12 +389,11 @@
                                            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,22 +427,14 @@
                                        &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;
-        }
-
         return TRUE;
 }