:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / lib / kernel32 / file / dir.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/file/dir.c
6  * PURPOSE:         Directory functions
7  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
8  * UPDATE HISTORY:
9  *                  Created 01/11/98
10  */
11
12 /*
13  * NOTES: Changed to using ZwCreateFile
14  */
15
16 /* INCLUDES ******************************************************************/
17
18 #include <ddk/ntddk.h>
19 #include <ntdll/rtl.h>
20 #include <windows.h>
21 #include <string.h>
22 #include <wchar.h>
23
24 #define NDEBUG
25 #include <kernel32/kernel32.h>
26 #include <kernel32/error.h>
27
28
29 /* FUNCTIONS *****************************************************************/
30
31 WINBOOL
32 STDCALL
33 CreateDirectoryA (
34         LPCSTR                  lpPathName,
35         LPSECURITY_ATTRIBUTES   lpSecurityAttributes
36         )
37 {
38         return CreateDirectoryExA (NULL,
39                                    lpPathName,
40                                    lpSecurityAttributes);
41 }
42
43 WINBOOL
44 STDCALL
45 CreateDirectoryExA (
46         LPCSTR                  lpTemplateDirectory,
47         LPCSTR                  lpNewDirectory,
48         LPSECURITY_ATTRIBUTES   lpSecurityAttributes)
49 {
50         UNICODE_STRING TmplDirU;
51         UNICODE_STRING NewDirU;
52         ANSI_STRING TmplDir;
53         ANSI_STRING NewDir;
54         WINBOOL Result;
55
56         RtlInitUnicodeString (&TmplDirU,
57                               NULL);
58
59         RtlInitUnicodeString (&NewDirU,
60                               NULL);
61
62         if (lpTemplateDirectory != NULL)
63         {
64                 RtlInitAnsiString (&TmplDir,
65                                    (LPSTR)lpTemplateDirectory);
66
67                 /* convert ansi (or oem) string to unicode */
68                 if (bIsFileApiAnsi)
69                         RtlAnsiStringToUnicodeString (&TmplDirU,
70                                                       &TmplDir,
71                                                       TRUE);
72                 else
73                         RtlOemStringToUnicodeString (&TmplDirU,
74                                                      &TmplDir,
75                                                      TRUE);
76         }
77
78         if (lpNewDirectory != NULL)
79         {
80                 RtlInitAnsiString (&NewDir,
81                                    (LPSTR)lpNewDirectory);
82
83                 /* convert ansi (or oem) string to unicode */
84                 if (bIsFileApiAnsi)
85                         RtlAnsiStringToUnicodeString (&NewDirU,
86                                                       &NewDir,
87                                                       TRUE);
88                 else
89                         RtlOemStringToUnicodeString (&NewDirU,
90                                                      &NewDir,
91                                                      TRUE);
92         }
93
94         Result = CreateDirectoryExW (TmplDirU.Buffer,
95                                      NewDirU.Buffer,
96                                      lpSecurityAttributes);
97
98         if (lpTemplateDirectory != NULL)
99                 RtlFreeHeap (RtlGetProcessHeap (),
100                              0,
101                              TmplDirU.Buffer);
102
103         if (lpNewDirectory != NULL)
104                 RtlFreeHeap (RtlGetProcessHeap (),
105                              0,
106                              NewDirU.Buffer);
107
108         return Result;
109 }
110
111
112 WINBOOL
113 STDCALL
114 CreateDirectoryW (
115         LPCWSTR                 lpPathName,
116         LPSECURITY_ATTRIBUTES   lpSecurityAttributes
117         )
118 {
119         return CreateDirectoryExW (NULL,
120                                    lpPathName,
121                                    lpSecurityAttributes);
122 }
123
124
125 WINBOOL
126 STDCALL
127 CreateDirectoryExW (
128         LPCWSTR                 lpTemplateDirectory,
129         LPCWSTR                 lpNewDirectory,
130         LPSECURITY_ATTRIBUTES   lpSecurityAttributes
131         )
132 {
133         OBJECT_ATTRIBUTES ObjectAttributes;
134         IO_STATUS_BLOCK IoStatusBlock;
135         UNICODE_STRING NtPathU;
136         HANDLE DirectoryHandle;
137         NTSTATUS Status;
138
139         DPRINT ("lpTemplateDirectory %S lpNewDirectory %S lpSecurityAttributes %p\n",
140                 lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes);
141
142         if (lpTemplateDirectory != NULL && *lpTemplateDirectory != 0)
143         {
144                 // get object attributes from template directory
145                 DPRINT("KERNEL32:FIXME:%s:%d\n",__FILE__,__LINE__);
146                 return FALSE;
147         }
148
149         if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewDirectory,
150                                            &NtPathU,
151                                            NULL,
152                                            NULL))
153                 return FALSE;
154
155         DPRINT1 ("NtPathU \'%wZ\'\n", &NtPathU);
156
157         ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
158         ObjectAttributes.RootDirectory = NULL;
159         ObjectAttributes.ObjectName = &NtPathU;
160         ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT;
161         ObjectAttributes.SecurityDescriptor = NULL;
162         ObjectAttributes.SecurityQualityOfService = NULL;
163
164         Status = NtCreateFile (&DirectoryHandle,
165                                DIRECTORY_ALL_ACCESS,
166                                &ObjectAttributes,
167                                &IoStatusBlock,
168                                NULL,
169                                FILE_ATTRIBUTE_DIRECTORY,
170                                0,
171                                FILE_CREATE,
172                                FILE_DIRECTORY_FILE,
173                                NULL,
174                                0);
175         DPRINT("Status: %lx\n", Status);
176
177         RtlFreeHeap (RtlGetProcessHeap (),
178                      0,
179                      NtPathU.Buffer);
180
181         if (!NT_SUCCESS(Status))
182         {
183                 SetLastErrorByStatus(Status);
184                 return FALSE;
185         }
186
187         NtClose (DirectoryHandle);
188
189         return TRUE;
190 }
191
192
193 WINBOOL
194 STDCALL
195 RemoveDirectoryA (
196         LPCSTR  lpPathName
197         )
198 {
199         UNICODE_STRING PathNameU;
200         ANSI_STRING PathName;
201         WINBOOL Result;
202
203         RtlInitAnsiString (&PathName,
204                            (LPSTR)lpPathName);
205
206         /* convert ansi (or oem) string to unicode */
207         if (bIsFileApiAnsi)
208                 RtlAnsiStringToUnicodeString (&PathNameU,
209                                               &PathName,
210                                               TRUE);
211         else
212                 RtlOemStringToUnicodeString (&PathNameU,
213                                              &PathName,
214                                              TRUE);
215
216         Result = RemoveDirectoryW (PathNameU.Buffer);
217
218         RtlFreeHeap (RtlGetProcessHeap (),
219                      0,
220                      PathNameU.Buffer);
221
222         return Result;
223 }
224
225
226 WINBOOL
227 STDCALL
228 RemoveDirectoryW (
229         LPCWSTR lpPathName
230         )
231 {
232         FILE_DISPOSITION_INFORMATION FileDispInfo;
233         OBJECT_ATTRIBUTES ObjectAttributes;
234         IO_STATUS_BLOCK IoStatusBlock;
235         UNICODE_STRING NtPathU;
236         HANDLE DirectoryHandle;
237         NTSTATUS Status;
238
239         DPRINT("lpPathName %S\n", lpPathName);
240
241         if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpPathName,
242                                            &NtPathU,
243                                            NULL,
244                                            NULL))
245                 return FALSE;
246
247         ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
248         ObjectAttributes.RootDirectory = NULL;
249         ObjectAttributes.ObjectName = &NtPathU;
250         ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
251         ObjectAttributes.SecurityDescriptor = NULL;
252         ObjectAttributes.SecurityQualityOfService = NULL;
253
254         DPRINT("NtPathU '%S'\n", NtPathU.Buffer);
255
256         Status = NtCreateFile (&DirectoryHandle,
257                                FILE_WRITE_ATTRIBUTES,    /* 0x110080 */
258                                &ObjectAttributes,
259                                &IoStatusBlock,
260                                NULL,
261                                FILE_ATTRIBUTE_DIRECTORY, /* 0x7 */
262                                0,
263                                FILE_OPEN,
264                                FILE_DIRECTORY_FILE,      /* 0x204021 */
265                                NULL,
266                                0);
267
268         RtlFreeHeap (RtlGetProcessHeap (),
269                      0,
270                      NtPathU.Buffer);
271
272         if (!NT_SUCCESS(Status))
273         {
274                 CHECKPOINT;
275                 SetLastErrorByStatus (Status);
276                 return FALSE;
277         }
278
279         FileDispInfo.DoDeleteFile = TRUE;
280
281         Status = NtSetInformationFile (DirectoryHandle,
282                                        &IoStatusBlock,
283                                        &FileDispInfo,
284                                        sizeof(FILE_DISPOSITION_INFORMATION),
285                                        FileDispositionInformation);
286         if (!NT_SUCCESS(Status))
287         {
288                 CHECKPOINT;
289                 NtClose(DirectoryHandle);
290                 SetLastErrorByStatus (Status);
291                 return FALSE;
292         }
293
294         Status = NtClose (DirectoryHandle);
295         if (!NT_SUCCESS(Status))
296         {
297                 CHECKPOINT;
298                 SetLastErrorByStatus (Status);
299                 return FALSE;
300         }
301
302         return TRUE;
303 }
304
305
306 DWORD
307 STDCALL
308 GetFullPathNameA (
309         LPCSTR  lpFileName,
310         DWORD   nBufferLength,
311         LPSTR   lpBuffer,
312         LPSTR   *lpFilePart
313         )
314 {
315         UNICODE_STRING FileNameU;
316         UNICODE_STRING FullNameU;
317         ANSI_STRING FileName;
318         ANSI_STRING FullName;
319         PWSTR FilePartU;
320         ULONG BufferLength;
321         ULONG Offset;
322
323         DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
324                "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
325
326         RtlInitAnsiString (&FileName,
327                            (LPSTR)lpFileName);
328
329         RtlAnsiStringToUnicodeString (&FileNameU,
330                                       &FileName,
331                                       TRUE);
332
333         BufferLength = nBufferLength * sizeof(WCHAR);
334
335         FullNameU.MaximumLength = BufferLength;
336         FullNameU.Length = 0;
337         FullNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
338                                             0,
339                                             BufferLength);
340
341         FullNameU.Length = RtlGetFullPathName_U (FileNameU.Buffer,
342                                                  BufferLength,
343                                                  FullNameU.Buffer,
344                                                  &FilePartU);
345
346         RtlFreeUnicodeString (&FileNameU);
347
348         FullName.MaximumLength = nBufferLength;
349         FullName.Length = 0;
350         FullName.Buffer = lpBuffer;
351
352         RtlUnicodeStringToAnsiString (&FullName,
353                                       &FullNameU,
354                                       FALSE);
355
356         if (lpFilePart != NULL)
357         {
358                 Offset = (ULONG)(FilePartU - FullNameU.Buffer);
359                 *lpFilePart = FullName.Buffer + Offset;
360         }
361
362         RtlFreeHeap (RtlGetProcessHeap (),
363                      0,
364                      FullNameU.Buffer);
365
366         DPRINT("lpBuffer %s lpFilePart %s Length %ld\n",
367                lpBuffer, lpFilePart, FullName.Length);
368
369         return FullName.Length;
370 }
371
372
373 DWORD
374 STDCALL
375 GetFullPathNameW (
376         LPCWSTR lpFileName,
377         DWORD   nBufferLength,
378         LPWSTR  lpBuffer,
379         LPWSTR  *lpFilePart
380         )
381 {
382         ULONG Length;
383
384         DPRINT("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, "
385                "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
386
387         Length = RtlGetFullPathName_U ((LPWSTR)lpFileName,
388                                        nBufferLength * sizeof(WCHAR),
389                                        lpBuffer,
390                                        lpFilePart);
391
392         DPRINT("lpBuffer %S lpFilePart %S Length %ld\n",
393                lpBuffer, lpFilePart, Length / sizeof(WCHAR));
394
395         return (Length / sizeof(WCHAR));
396 }
397
398
399 DWORD
400 STDCALL
401 GetShortPathNameA (
402         LPCSTR  lpszLongPath,
403         LPSTR   lpszShortPath,
404         DWORD   cchBuffer
405         )
406 {
407         //1 remove unicode chars and spaces
408         //2 remove preceding and trailing periods.
409         //3 remove embedded periods except the last one
410         
411         //4 Split the string in two parts before and after the period
412         //      truncate the part before the period to 6 chars and add ~1
413         //      truncate the part after the period to 3 chars
414         //3 Put the new name in uppercase
415         
416         //4 Increment the ~1 string if the resulting name allready exists
417
418         return 0;
419 }
420
421
422 DWORD
423 STDCALL
424 GetShortPathNameW (
425         LPCWSTR lpszLongPath,
426         LPWSTR  lpszShortPath,
427         DWORD   cchBuffer
428         )
429 {
430         return 0;
431 }
432
433
434 DWORD
435 STDCALL
436 SearchPathA (
437         LPCSTR  lpPath,
438         LPCSTR  lpFileName,
439         LPCSTR  lpExtension,
440         DWORD   nBufferLength,
441         LPSTR   lpBuffer,
442         LPSTR   *lpFilePart
443         )
444 {
445         UNICODE_STRING PathU;
446         UNICODE_STRING FileNameU;
447         UNICODE_STRING ExtensionU;
448         UNICODE_STRING BufferU;
449         ANSI_STRING Path;
450         ANSI_STRING FileName;
451         ANSI_STRING Extension;
452         ANSI_STRING Buffer;
453         PWCHAR FilePartW;
454         DWORD RetValue;
455
456         RtlInitAnsiString (&Path,
457                            (LPSTR)lpPath);
458         RtlInitAnsiString (&FileName,
459                            (LPSTR)lpFileName);
460         RtlInitAnsiString (&Extension,
461                            (LPSTR)lpExtension);
462
463         /* convert ansi (or oem) strings to unicode */
464         if (bIsFileApiAnsi)
465         {
466                 RtlAnsiStringToUnicodeString (&PathU,
467                                               &Path,
468                                               TRUE);
469                 RtlAnsiStringToUnicodeString (&FileNameU,
470                                               &FileName,
471                                               TRUE);
472                 RtlAnsiStringToUnicodeString (&ExtensionU,
473                                               &Extension,
474                                               TRUE);
475         }
476         else
477         {
478                 RtlOemStringToUnicodeString (&PathU,
479                                              &Path,
480                                              TRUE);
481                 RtlOemStringToUnicodeString (&FileNameU,
482                                              &FileName,
483                                              TRUE);
484                 RtlOemStringToUnicodeString (&ExtensionU,
485                                              &Extension,
486                                              TRUE);
487         }
488
489         BufferU.Length = 0;
490         BufferU.MaximumLength = nBufferLength * sizeof(WCHAR);
491         BufferU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
492                                           0,
493                                           BufferU.MaximumLength);
494
495         Buffer.Length = 0;
496         Buffer.MaximumLength = nBufferLength;
497         Buffer.Buffer = lpBuffer;
498
499         RetValue = SearchPathW (PathU.Buffer,
500                                 FileNameU.Buffer,
501                                 ExtensionU.Buffer,
502                                 nBufferLength,
503                                 BufferU.Buffer,
504                                 &FilePartW);
505
506         RtlFreeHeap (RtlGetProcessHeap (),
507                      0,
508                      PathU.Buffer);
509         RtlFreeHeap (RtlGetProcessHeap (),
510                      0,
511                      FileNameU.Buffer);
512         RtlFreeHeap (RtlGetProcessHeap (),
513                      0,
514                      ExtensionU.Buffer);
515
516         /* convert ansi (or oem) string to unicode */
517         if (bIsFileApiAnsi)
518                 RtlUnicodeStringToAnsiString (&Buffer,
519                                               &BufferU,
520                                               FALSE);
521         else
522                 RtlUnicodeStringToOemString (&Buffer,
523                                              &BufferU,
524                                              FALSE);
525
526         RtlFreeHeap (RtlGetProcessHeap (),
527                      0,
528                      BufferU.Buffer);
529
530         *lpFilePart = strrchr (lpBuffer, '\\') + 1;
531
532         return RetValue;
533 }
534
535
536 DWORD
537 STDCALL
538 SearchPathW (
539         LPCWSTR lpPath,
540         LPCWSTR lpFileName,
541         LPCWSTR lpExtension,
542         DWORD   nBufferLength,
543         LPWSTR  lpBuffer,
544         LPWSTR  *lpFilePart
545         )
546 /*
547  * FUNCTION: Searches for the specified file
548  * ARGUMENTS:
549  *       lpPath = Points to a null-terminated string that specified the
550  *                path to be searched. If this parameters is NULL then
551  *                the following directories are searched
552  *                          The directory from which the application loaded
553  *                          The current directory
554  *                          The system directory
555  *                          The 16-bit system directory
556  *                          The windows directory
557  *                          The directories listed in the PATH environment
558  *                          variable
559  *        lpFileName = Specifies the filename to search for
560  *        lpExtension = Points to the null-terminated string that specifies
561  *                      an extension to be added to the filename when
562  *                      searching for the file. The first character of the
563  *                      filename extension must be a period (.). The
564  *                      extension is only added if the specified filename
565  *                      doesn't end with an extension
566  *                      
567  *                      If the filename extension is not required or if the
568  *                      filename contains an extension, this parameters can be
569  *                      NULL
570  *        nBufferLength = The length in characters of the buffer for output
571  *        lpBuffer = Points to the buffer for the valid path and filename of
572  *                   file found
573  *        lpFilePart = Points to the last component of the valid path and
574  *                     filename 
575  * RETURNS: On success, the length, in characters, of the string copied to the
576  *          buffer
577  *          On failure, zero.
578  */
579 {
580         DWORD retCode = 0;
581         ULONG pos, len;
582         PWCHAR EnvironmentBufferW = NULL;
583         WCHAR Buffer;
584
585         DPRINT("SearchPath\n");
586
587         if (lpPath == NULL)
588         {
589                 len = GetEnvironmentVariableW(L"PATH", &Buffer, 0);
590                 len += 1 + GetCurrentDirectoryW(0, &Buffer);
591                 len += 1 + GetSystemDirectoryW(&Buffer, 0);
592                 len += 1 + GetWindowsDirectoryW(&Buffer, 0);
593
594                 EnvironmentBufferW = (PWCHAR) RtlAllocateHeap(GetProcessHeap(), 
595                                                 HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, 
596                                                 len * sizeof(WCHAR));
597                 if (EnvironmentBufferW == NULL)
598                 {
599                         return 0;
600                 }
601
602                 pos = GetCurrentDirectoryW(len, EnvironmentBufferW);
603                 EnvironmentBufferW[pos++] = L';';
604                 EnvironmentBufferW[pos] = 0;
605                 pos += GetSystemDirectoryW(&EnvironmentBufferW[pos], len - pos);
606                 EnvironmentBufferW[pos++] = L';';
607                 EnvironmentBufferW[pos] = 0;
608                 pos += GetWindowsDirectoryW(&EnvironmentBufferW[pos], len - pos);
609                 EnvironmentBufferW[pos++] = L';';
610                 EnvironmentBufferW[pos] = 0;
611                 pos += GetEnvironmentVariableW(L"PATH", &EnvironmentBufferW[pos], len - pos);
612                 lpPath = EnvironmentBufferW;
613         }
614
615         retCode = RtlDosSearchPath_U ((PWCHAR)lpPath, (PWCHAR)lpFileName, (PWCHAR)lpExtension, nBufferLength, lpBuffer, lpFilePart);
616
617         if (EnvironmentBufferW != NULL)
618         {
619                 RtlFreeHeap(GetProcessHeap(), 0, EnvironmentBufferW);
620         }
621         return retCode;
622 }
623
624 /* EOF */