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