update for HEAD-2003091401
[reactos.git] / lib / kernel32 / file / create.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/file/create.c
6  * PURPOSE:         Directory functions
7  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
8  *                  GetTempFileName is modified from WINE [ Alexandre Juiliard ]
9  * UPDATE HISTORY:
10  *                  Created 01/11/98
11  *                  Removed use of SearchPath (not used by Windows)
12  *                  18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion)
13  *                  24/08/2002: removed superfluous DPRINTs (KJK::Hyperion)
14  */
15
16 /* INCLUDES *****************************************************************/
17
18 #include <k32.h>
19
20 #define NDEBUG
21 #include <kernel32/kernel32.h>
22
23
24 /* FUNCTIONS ****************************************************************/
25
26 /*
27  * @implemented
28  */
29 HANDLE STDCALL CreateFileA (LPCSTR                      lpFileName,
30                             DWORD                       dwDesiredAccess,
31                             DWORD                       dwShareMode,
32                             LPSECURITY_ATTRIBUTES       lpSecurityAttributes,
33                             DWORD                       dwCreationDisposition,
34                             DWORD                       dwFlagsAndAttributes,
35                             HANDLE                      hTemplateFile)
36 {
37    UNICODE_STRING FileNameU;
38    ANSI_STRING FileName;
39    HANDLE FileHandle;
40    
41    DPRINT("CreateFileA(lpFileName %s)\n",lpFileName);
42    
43    RtlInitAnsiString (&FileName,
44                       (LPSTR)lpFileName);
45    
46    /* convert ansi (or oem) string to unicode */
47    if (bIsFileApiAnsi)
48      RtlAnsiStringToUnicodeString (&FileNameU,
49                                    &FileName,
50                                    TRUE);
51    else
52      RtlOemStringToUnicodeString (&FileNameU,
53                                   &FileName,
54                                   TRUE);
55
56    FileHandle = CreateFileW (FileNameU.Buffer,
57                              dwDesiredAccess,
58                              dwShareMode,
59                              lpSecurityAttributes,
60                              dwCreationDisposition,
61                              dwFlagsAndAttributes,
62                              hTemplateFile);
63    
64    RtlFreeHeap (RtlGetProcessHeap (),
65                 0,
66                 FileNameU.Buffer);
67    
68    return FileHandle;
69 }
70
71
72 /*
73  * @implemented
74  */
75 HANDLE STDCALL CreateFileW (LPCWSTR                     lpFileName,
76                             DWORD                       dwDesiredAccess,
77                             DWORD                       dwShareMode,
78                             LPSECURITY_ATTRIBUTES       lpSecurityAttributes,
79                             DWORD                       dwCreationDisposition,
80                             DWORD                       dwFlagsAndAttributes,
81                             HANDLE                      hTemplateFile)
82 {
83    OBJECT_ATTRIBUTES ObjectAttributes;
84    IO_STATUS_BLOCK IoStatusBlock;
85    UNICODE_STRING NtPathU;
86    HANDLE FileHandle;
87    NTSTATUS Status;
88    ULONG Flags = 0;
89    CSRSS_API_REQUEST Request;
90    CSRSS_API_REPLY Reply;
91
92    DPRINT("CreateFileW(lpFileName %S)\n",lpFileName);
93
94    if(hTemplateFile != NULL)
95    {
96     /* FIXME */
97     DPRINT("Template file feature not supported yet\n");
98     SetLastError(ERROR_NOT_SUPPORTED);
99     return INVALID_HANDLE_VALUE;
100    }
101
102    /* validate & translate the creation disposition */
103    switch (dwCreationDisposition)
104      {
105       case CREATE_NEW:
106         dwCreationDisposition = FILE_CREATE;
107         break;
108         
109       case CREATE_ALWAYS:
110         dwCreationDisposition = FILE_OVERWRITE_IF;
111         break;
112         
113       case OPEN_EXISTING:
114         dwCreationDisposition = FILE_OPEN;
115         break;
116         
117       case OPEN_ALWAYS:
118         dwCreationDisposition = FILE_OPEN_IF;
119         break;
120
121       case TRUNCATE_EXISTING:
122         dwCreationDisposition = FILE_OVERWRITE;
123         break;
124       
125       default:
126         SetLastError(ERROR_INVALID_PARAMETER);
127         return (INVALID_HANDLE_VALUE);
128      }
129
130    /* validate & translate the flags */
131    if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
132    {
133     DPRINT("Overlapped I/O not supported\n");
134     SetLastError(ERROR_NOT_SUPPORTED);
135     return INVALID_HANDLE_VALUE;
136    }
137    else
138      Flags |= FILE_SYNCHRONOUS_IO_ALERT;
139    
140    /* validate & translate the filename */
141    if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
142                                       &NtPathU,
143                                       NULL,
144                                       NULL))
145    {
146      DPRINT("Invalid path\n");
147      SetLastError(ERROR_BAD_PATHNAME);
148      return INVALID_HANDLE_VALUE;
149    }
150    
151    DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
152
153    /* translate the flags that need no validation */
154    if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
155     Flags |= FILE_WRITE_THROUGH;
156
157    if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
158     Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
159
160    if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
161     Flags |= FILE_RANDOM_ACCESS;
162    
163    if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
164     Flags |= FILE_SEQUENTIAL_ONLY;
165    
166    if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
167     Flags |= FILE_DELETE_ON_CLOSE;
168    
169    if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
170    {
171     if(dwDesiredAccess & GENERIC_ALL)
172       Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
173     else
174     {
175       if(dwDesiredAccess & GENERIC_READ)
176         Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
177       
178       if(dwDesiredAccess & GENERIC_WRITE)
179         Flags |= FILE_OPEN_FOR_RECOVERY;
180     }
181    }
182    else
183     Flags |= FILE_NON_DIRECTORY_FILE;
184
185    /* FILE_FLAG_POSIX_SEMANTICS is handled later */
186
187 #if 0
188    /* FIXME: Win32 constants to be defined */
189    if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
190     Flags |= FILE_OPEN_REPARSE_POINT;
191    
192    if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
193     Flags |= FILE_OPEN_NO_RECALL;
194 #endif
195
196    /* translate the desired access */
197    if (dwDesiredAccess & GENERIC_ALL)
198      dwDesiredAccess |= FILE_ALL_ACCESS;
199    else
200    {
201      if (dwDesiredAccess & GENERIC_READ)
202        dwDesiredAccess |= FILE_GENERIC_READ;
203      
204      if (dwDesiredAccess & GENERIC_WRITE)
205        dwDesiredAccess |= FILE_GENERIC_WRITE;
206      
207      if (dwDesiredAccess & GENERIC_EXECUTE)
208        dwDesiredAccess |= FILE_GENERIC_EXECUTE;
209    }
210
211    /* check for console output */
212    if (0 == _wcsicmp(L"CONOUT$", lpFileName))
213    {
214       /* FIXME: Send required access rights to Csrss */
215       Request.Type = CSRSS_GET_OUTPUT_HANDLE;
216       Status = CsrClientCallServer(&Request,
217                                    &Reply,
218                                    sizeof(CSRSS_API_REQUEST),
219                                    sizeof(CSRSS_API_REPLY));
220       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
221       {
222          SetLastErrorByStatus(Status);
223          return INVALID_HANDLE_VALUE;
224       }
225       else
226       {
227          return Reply.Data.GetOutputHandleReply.OutputHandle;
228       }
229    }
230
231    /* check for console input */
232    if (0 == _wcsicmp(L"CONIN$", lpFileName))
233    {
234       /* FIXME: Send required access rights to Csrss */
235       Request.Type = CSRSS_GET_INPUT_HANDLE;
236       Status = CsrClientCallServer(&Request,
237                                    &Reply,
238                                    sizeof(CSRSS_API_REQUEST),
239                                    sizeof(CSRSS_API_REPLY));
240       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
241       {
242          SetLastErrorByStatus(Status);
243          return INVALID_HANDLE_VALUE;
244       }
245       else
246       {
247          return Reply.Data.GetInputHandleReply.InputHandle;
248       }
249    }
250
251    /* build the object attributes */
252    InitializeObjectAttributes(
253     &ObjectAttributes,
254     &NtPathU,
255     0,
256     NULL,
257     NULL
258    );
259
260    if (lpSecurityAttributes)
261    {
262       if(lpSecurityAttributes->bInheritHandle)
263          ObjectAttributes.Attributes |= OBJ_INHERIT;
264
265       ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
266    }
267    
268    if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
269     ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
270
271    /* perform the call */
272    Status = NtCreateFile (&FileHandle,
273                           dwDesiredAccess,
274                           &ObjectAttributes,
275                           &IoStatusBlock,
276                           NULL,
277                           dwFlagsAndAttributes,
278                           dwShareMode,
279                           dwCreationDisposition,
280                           Flags,
281                           NULL,
282                           0);
283
284    RtlFreeUnicodeString(&NtPathU);
285
286    /* error */
287    if (!NT_SUCCESS(Status))
288      {
289         SetLastErrorByStatus (Status);
290         return INVALID_HANDLE_VALUE;
291      }
292    
293    switch(IoStatusBlock.Information)
294    {
295     case FILE_OPENED:
296     case FILE_CREATED:
297      SetLastError(ERROR_ALREADY_EXISTS);
298      break;
299     
300     default:
301      break;
302    }
303    
304    return FileHandle;
305 }
306
307 /* EOF */