- added support for template files (copy ntfs extended attributes) to CreateFile()
- mask out file flags from dwFlagsAndAttributes before passing them to NtCreateFile as file attributes
Modified: trunk/reactos/lib/kernel32/file/create.c

Modified: trunk/reactos/lib/kernel32/file/create.c
--- trunk/reactos/lib/kernel32/file/create.c	2005-03-20 18:40:57 UTC (rev 14230)
+++ trunk/reactos/lib/kernel32/file/create.c	2005-03-20 18:55:54 UTC (rev 14231)
@@ -70,20 +70,14 @@
    UNICODE_STRING NtPathU;
    HANDLE FileHandle;
    NTSTATUS Status;
-   ULONG Flags = 0;
+   ULONG FileAttributes, Flags = 0;
    CSRSS_API_REQUEST Request;
    CSRSS_API_REPLY Reply;
+   PVOID EaBuffer = NULL;
+   ULONG EaLength = 0;
 
    DPRINT("CreateFileW(lpFileName %S)\n",lpFileName);
 
-   if(hTemplateFile != NULL && hTemplateFile != INVALID_HANDLE_VALUE)
-   {
-    /* FIXME */
-    DPRINT1("Template file feature not supported yet\n");
-    SetLastError(ERROR_NOT_SUPPORTED);
-    return INVALID_HANDLE_VALUE;
-   }
-
    /* validate & translate the creation disposition */
    switch (dwCreationDisposition)
      {
@@ -128,58 +122,57 @@
   /* validate & translate the flags */
 
    /* translate the flags that need no validation */
-  if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)){
-    /* yes, nonalert is correct! apc's are not delivered
-    while waiting for file io to complete */
-    Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
-  }
+   if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
+   {
+      /* yes, nonalert is correct! apc's are not delivered
+      while waiting for file io to complete */
+      Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
+   }
    
    if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
-    Flags |= FILE_WRITE_THROUGH;
+      Flags |= FILE_WRITE_THROUGH;
 
    if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
-    Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
+      Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
 
    if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
-    Flags |= FILE_RANDOM_ACCESS;
+      Flags |= FILE_RANDOM_ACCESS;
    
    if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
-    Flags |= FILE_SEQUENTIAL_ONLY;
+      Flags |= FILE_SEQUENTIAL_ONLY;
    
    if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
-    Flags |= FILE_DELETE_ON_CLOSE;
+      Flags |= FILE_DELETE_ON_CLOSE;
    
    if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
    {
-    if(dwDesiredAccess & GENERIC_ALL)
-      Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
-    else
-    {
-      if(dwDesiredAccess & GENERIC_READ)
-        Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
-      
-      if(dwDesiredAccess & GENERIC_WRITE)
-        Flags |= FILE_OPEN_FOR_RECOVERY;
-    }
+      if(dwDesiredAccess & GENERIC_ALL)
+         Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
+      else
+      {
+         if(dwDesiredAccess & GENERIC_READ)
+            Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
+
+         if(dwDesiredAccess & GENERIC_WRITE)
+            Flags |= FILE_OPEN_FOR_RECOVERY;
+      }
    }
    else
-    Flags |= FILE_NON_DIRECTORY_FILE;
+      Flags |= FILE_NON_DIRECTORY_FILE;
+
+   if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
+      Flags |= FILE_OPEN_REPARSE_POINT;
+
+   if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
+      Flags |= FILE_OPEN_NO_RECALL;
+
+   FileAttributes = (dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY));
     
-    
-  /* handle may allways be waited on and querying attributes are allways allowed */
-  dwDesiredAccess |= SYNCHRONIZE|FILE_READ_ATTRIBUTES; 
+   /* handle may allways be waited on and querying attributes are allways allowed */
+   dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES;
 
    /* FILE_FLAG_POSIX_SEMANTICS is handled later */
 
-#if 0
-   /* FIXME: Win32 constants to be defined */
-   if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
-    Flags |= FILE_OPEN_REPARSE_POINT;
-   
-   if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
-    Flags |= FILE_OPEN_NO_RECALL;
-#endif
-
    /* check for console output */
    if (0 == _wcsicmp(L"CONOUT$", lpFileName))
    {
@@ -219,15 +212,81 @@
          return Reply.Data.GetInputHandleReply.InputHandle;
       }
    }
+   
+   if (hTemplateFile != NULL)
+   {
+      FILE_EA_INFORMATION EaInformation;
 
+      for (;;)
+      {
+         /* try to get the size of the extended attributes, if we fail just continue
+            creating the file without copying the attributes! */
+         Status = NtQueryInformationFile(hTemplateFile,
+                                         &IoStatusBlock,
+                                         &EaInformation,
+                                         sizeof(FILE_EA_INFORMATION),
+                                         FileEaInformation);
+         if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0))
+         {
+            /* there's extended attributes to read, let's give it a try */
+            EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                       0,
+                                       EaInformation.EaSize);
+            if (EaBuffer == NULL)
+            {
+               /* the template file handle is valid and has extended attributes,
+                  however we seem to lack some memory here. We should fail here! */
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+               return INVALID_HANDLE_VALUE;
+            }
+            
+            Status = NtQueryEaFile(hTemplateFile,
+                                   &IoStatusBlock,
+                                   EaBuffer,
+                                   EaInformation.EaSize,
+                                   FALSE,
+                                   NULL,
+                                   0,
+                                   NULL,
+                                   TRUE);
+            
+            if (NT_SUCCESS(Status))
+            {
+               /* we successfully read the extended attributes, break the loop
+                  and continue */
+               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
+         {
+            /* we either failed to get the size of the extended attributes or
+               they're empty, just continue as there's no need to copy
+               attributes */
+            break;
+         }
+      }
+   }
+
    /* build the object attributes */
-   InitializeObjectAttributes(
-    &ObjectAttributes,
-    &NtPathU,
-    0,
-    NULL,
-    NULL
-   );
+   InitializeObjectAttributes(&ObjectAttributes,
+                              &NtPathU,
+                              0,
+                              NULL,
+                              NULL);
 
    if (lpSecurityAttributes)
    {
@@ -246,14 +305,22 @@
 			  &ObjectAttributes,
 			  &IoStatusBlock,
 			  NULL,
-			  dwFlagsAndAttributes,
+			  FileAttributes,
 			  dwShareMode,
 			  dwCreationDisposition,
 			  Flags,
-			  NULL,
-			  0);
+			  EaBuffer,
+			  EaLength);
 
    RtlFreeUnicodeString(&NtPathU);
+   
+   /* free the extended attributes buffer if allocated */
+   if (EaBuffer != NULL)
+   {
+      RtlFreeHeap(RtlGetProcessHeap(),
+                  0,
+                  EaBuffer);
+   }
 
    /* error */
    if (!NT_SUCCESS(Status))