2b79c3aae8fe7bcc5070c49840fd881215750dcf
[reactos.git] / lib / ntdll / rtl / path.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/ntdll/rtl/path.c
6  * PURPOSE:         Path and current directory functions
7  * UPDATE HISTORY:
8  *                  Created 03/02/00
9  */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <ntdll/rtl.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <ctype.h>
18 #include <ddk/obfuncs.h>
19
20 #define NDEBUG
21 #include <ntdll/ntdll.h>
22
23 /* DEFINITONS and MACROS ******************************************************/
24
25 #define MAX_PFX_SIZE       16
26
27 #define IS_PATH_SEPARATOR(x) (((x)==L'\\')||((x)==L'/'))
28
29
30 /* FUNCTIONS *****************************************************************/
31
32 static ULONG RtlpGetDotSequence (PWSTR p)
33 {
34    ULONG Count = 0;
35    
36    for (;;)
37      {
38         if (*p == '.')
39           Count++;
40         else if ((*p == '\\' || *p == '\0') && Count)
41           return Count;
42         else
43           return 0;
44         p++;
45      }
46    return 0;
47 }
48
49
50 static VOID RtlpEatPath (PWSTR Path)
51 {
52    PWSTR p, prev;
53    
54    p = Path + 2;
55    prev = p;
56    
57    while ((*p) != 0 || ((*p) == L'\\' && (*(p+1)) == 0))
58      {
59         ULONG DotLen;
60         
61         DotLen = RtlpGetDotSequence (p+1);
62         DPRINT("DotSequenceLength %u\n", DotLen);
63         DPRINT("prev %S p %S\n",prev,p);
64         
65         if (DotLen == 0)
66           {
67              prev = p;
68              do
69                {
70                   p++;
71                }
72              while ((*p) != 0 && (*p) != L'\\');
73           }
74         else if (DotLen == 1)
75           {
76              wcscpy (p, p+2);
77           }
78         else
79           {
80              if (DotLen > 2)
81                {
82                   int n = DotLen - 2;
83                   
84                   while (n > 0 && prev > (Path + 2))
85                     {
86                        prev--;
87                        if ((*prev) == L'\\')
88                          n--;
89                     }
90                }
91              
92              if (*(p + DotLen + 1) == 0)
93                *(prev + 1) = 0;
94                         else
95                wcscpy (prev, p + DotLen + 1);
96              p = prev;
97              if (prev > (Path + 2))
98                {
99                   prev--;
100                   while ((*prev) != L'\\')
101                     {
102                        prev--;
103                     }
104                }
105           }
106      }
107      if (Path[2] == 0)
108      {
109         Path[2] = L'\\';
110         Path[3] = 0;
111      }
112 }
113
114
115 ULONG STDCALL RtlGetLongestNtPathLength (VOID)
116 {
117    return (MAX_PATH + 9);
118 }
119
120
121 ULONG STDCALL
122 RtlDetermineDosPathNameType_U(PWSTR Path)
123 {
124    DPRINT("RtlDetermineDosPathNameType_U %S\n", Path);
125
126    if (Path == NULL)
127      {
128         return 0;
129      }
130
131    if (IS_PATH_SEPARATOR(Path[0]))
132      {
133         if (!IS_PATH_SEPARATOR(Path[1]))
134           {
135              return 4;                  /* \xxx   */
136           }
137
138         if (Path[2] != L'.')
139           return 1;                     /* \\xxx   */
140
141         if (IS_PATH_SEPARATOR(Path[3]))
142           return 6;                     /* \\.\xxx */
143
144         if (Path[3])
145           return 1;                     /* \\.xxxx */
146
147         return 7;                               /* \\.     */
148      }
149    else
150      {
151         if (Path[1] != L':')
152                 return 5;                       /* xxx     */
153
154         if (IS_PATH_SEPARATOR(Path[2]))
155                 return 2;                       /* x:\xxx  */
156
157         return 3;                               /* x:xxx   */
158    }
159 }
160
161
162 /* returns 0 if name is not valid DOS device name, or DWORD with
163  * offset in bytes to DOS device name from beginning of buffer in high word
164  * and size in bytes of DOS device name in low word */
165
166 ULONG STDCALL
167 RtlIsDosDeviceName_U(PWSTR DeviceName)
168 {
169    ULONG Type;
170    ULONG Length = 0;
171    ULONG Offset;
172    PWCHAR wc;
173
174    if (DeviceName == NULL)
175      {
176         return 0;
177      }
178
179    while (DeviceName[Length])
180      {
181         Length++;
182      }
183
184    Type = RtlDetermineDosPathNameType_U(DeviceName);
185    if (Type <= 1)
186      {
187         return 0;
188      }
189
190    if (Type == 6)
191      {
192         if (Length == 7 &&
193             !_wcsnicmp (DeviceName, L"\\\\.\\CON", 7))
194                 return 0x00080006;
195         return 0;
196      }
197
198    /* name can end with ':' */
199    if (Length && DeviceName[Length - 1 ] == L':')
200      {
201         Length--;
202      }
203
204    /* there can be spaces or points at the end of name */
205    wc = DeviceName + Length - 1;
206    while (Length && (*wc == L'.' || *wc == L' '))
207      {
208         Length--;
209         wc--;
210      }
211
212    /* let's find a beginning of name */
213    wc = DeviceName + Length - 1;
214    while (wc > DeviceName && !IS_PATH_SEPARATOR(*(wc - 1)))
215      {
216         wc--;
217      }
218    Offset = wc - DeviceName;
219    Length -= Offset;
220    
221    /* check for LPTx or COMx */
222    if (Length == 4 && wc[3] >= L'0' && wc[3] <= L'9')
223      {
224         if (wc[3] == L'0')
225           {
226              return 0;
227           }
228    
229         if (!_wcsnicmp (wc, L"LPT", 3) ||
230             !_wcsnicmp (wc, L"COM", 3))
231           {
232              return ((Offset * 2) << 16 ) | 8;
233           }
234         return 0;
235      }
236    
237    /* check for PRN,AUX,NUL or CON */
238    if (Length == 3 &&
239        (!_wcsnicmp (wc, L"PRN", 3) ||
240         !_wcsnicmp (wc, L"AUX", 3) ||
241         !_wcsnicmp (wc, L"NUL", 3) ||
242         !_wcsnicmp (wc, L"CON", 3)))
243      {
244         return ((Offset * 2) << 16) | 6;
245      }
246    
247    return 0;
248 }
249
250
251 ULONG STDCALL
252 RtlGetCurrentDirectory_U(ULONG MaximumLength,
253                          PWSTR Buffer)
254 {
255         ULONG Length;
256         PCURDIR cd;
257
258         DPRINT ("RtlGetCurrentDirectory %lu %p\n", MaximumLength, Buffer);
259
260         RtlAcquirePebLock();
261
262         cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName);
263         Length = cd->DosPath.Length / sizeof(WCHAR);
264         if (cd->DosPath.Buffer[Length - 1] == L'\\' &&
265             cd->DosPath.Buffer[Length - 2] != L':')
266                 Length--;
267
268         DPRINT ("cd->DosPath.Buffer %S Length %d\n",
269                 cd->DosPath.Buffer, Length);
270
271         if (MaximumLength / sizeof(WCHAR) > Length)
272         {
273                 memcpy (Buffer,
274                         cd->DosPath.Buffer,
275                         Length * sizeof(WCHAR));
276                 Buffer[Length] = 0;
277         }
278         else
279         {
280                 Length++;
281         }
282
283         RtlReleasePebLock ();
284
285         DPRINT ("CurrentDirectory %S\n", Buffer);
286
287         return (Length * sizeof(WCHAR));
288 }
289
290
291 NTSTATUS STDCALL
292 RtlSetCurrentDirectory_U(PUNICODE_STRING name)
293 {
294    UNICODE_STRING full;
295    UNICODE_STRING envvar;
296    OBJECT_ATTRIBUTES Attr;
297    IO_STATUS_BLOCK iosb;
298    PCURDIR cd;
299    NTSTATUS Status;
300    ULONG size;
301    HANDLE handle = NULL;
302    PWSTR wcs;
303    PWSTR buf = 0;
304    PFILE_NAME_INFORMATION filenameinfo;
305    ULONG backslashcount = 0;
306    PWSTR cntr;
307    WCHAR var[4];
308    
309    DPRINT ("RtlSetCurrentDirectory %wZ\n", name);
310    
311    RtlAcquirePebLock ();
312    cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName;
313    size = cd->DosPath.MaximumLength;
314    
315    buf = RtlAllocateHeap (RtlGetProcessHeap(),
316                           0,
317                           size);
318    if (buf == NULL)
319      {
320         RtlReleasePebLock ();
321         return STATUS_NO_MEMORY;
322      }
323    
324    size = RtlGetFullPathName_U (name->Buffer, size, buf, 0);
325    if (!size)
326      {
327         RtlFreeHeap (RtlGetProcessHeap (),
328                      0,
329                      buf);
330         RtlReleasePebLock ();
331         return STATUS_OBJECT_NAME_INVALID;
332      }
333    
334    if (!RtlDosPathNameToNtPathName_U (buf, &full, 0, 0))
335      {
336         RtlFreeHeap (RtlGetProcessHeap (),
337                      0,
338                      buf);
339         RtlFreeHeap (RtlGetProcessHeap (),
340                      0,
341                      full.Buffer);
342         RtlReleasePebLock ();
343         return STATUS_OBJECT_NAME_INVALID;
344      }
345    
346    InitializeObjectAttributes (&Attr,
347                                &full,
348                                OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
349                                NULL,
350                                NULL);
351    
352    Status = NtOpenFile (&handle,
353                         SYNCHRONIZE | FILE_TRAVERSE,
354                         &Attr,
355                         &iosb,
356                         FILE_SHARE_READ | FILE_SHARE_WRITE,
357                         FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
358    if (!NT_SUCCESS(Status))
359      {
360         RtlFreeHeap (RtlGetProcessHeap (),
361                      0,
362                      buf);
363         RtlFreeHeap (RtlGetProcessHeap (),
364                      0,
365                      full.Buffer);
366         RtlReleasePebLock ();
367         return Status;
368      }
369    
370    filenameinfo = RtlAllocateHeap(RtlGetProcessHeap(),
371                                   0,
372                                   MAX_PATH*sizeof(WCHAR)+sizeof(ULONG));
373    
374    Status = NtQueryInformationFile(handle,
375                                    &iosb,
376                                    filenameinfo,
377                                    MAX_PATH*sizeof(WCHAR)+sizeof(ULONG),
378                                    FileNameInformation);
379    if (!NT_SUCCESS(Status))
380      {
381         RtlFreeHeap(RtlGetProcessHeap(),
382                     0,
383                     filenameinfo);
384         RtlFreeHeap(RtlGetProcessHeap(),
385                     0,
386                     buf);
387         RtlFreeHeap(RtlGetProcessHeap(),
388                     0,
389                     full.Buffer);
390         RtlReleasePebLock();
391         return(Status);
392      }
393    
394    if (filenameinfo->FileName[1]) // If it's just "\", we need special handling
395      {
396         wcs = buf + size / sizeof(WCHAR) - 1;
397         if (*wcs == L'\\')
398           {
399             *(wcs) = 0;
400             wcs--;
401             size -= sizeof(WCHAR);
402           }
403
404         for (cntr=filenameinfo->FileName;*cntr!=0;cntr++)
405           {
406              if (*cntr=='\\') backslashcount++;
407           }
408
409         DPRINT("%d \n",backslashcount);
410         for (;backslashcount;wcs--)
411           {
412              if (*wcs=='\\') backslashcount--;
413           }
414         wcs++;
415
416         wcscpy(wcs,filenameinfo->FileName);
417
418         size=((wcs-buf)+wcslen(filenameinfo->FileName))*sizeof(WCHAR);
419      }
420    
421    RtlFreeHeap (RtlGetProcessHeap (),
422                 0,
423                 filenameinfo);
424    
425    /* append backslash if missing */
426    wcs = buf + size / sizeof(WCHAR) - 1;
427    if (*wcs != L'\\')
428      {
429         *(++wcs) = L'\\';
430         *(++wcs) = 0;
431         size += sizeof(WCHAR);
432      }
433    
434    memmove(cd->DosPath.Buffer,
435            buf,
436            size + sizeof(WCHAR));
437    cd->DosPath.Length = size;
438    
439    if (cd->Handle)
440      NtClose(cd->Handle);
441    cd->Handle = handle;
442
443    if (cd->DosPath.Buffer[1]==':')
444      {
445         envvar.Length = 2 * swprintf (var, L"=%c:", cd->DosPath.Buffer[0]);
446         envvar.MaximumLength = 8;
447         envvar.Buffer = var;
448    
449         RtlSetEnvironmentVariable(NULL,
450                                   &envvar,
451                                   &cd->DosPath);
452    }
453    
454    RtlFreeHeap (RtlGetProcessHeap (),
455                 0,
456                 buf);
457    
458    RtlFreeHeap (RtlGetProcessHeap (),
459                 0,
460                 full.Buffer);
461    
462    RtlReleasePebLock();
463    
464    return STATUS_SUCCESS;
465 }
466
467
468 ULONG STDCALL
469 RtlGetFullPathName_U(PWSTR DosName,
470                      ULONG size,
471                      PWSTR buf,
472                      PWSTR *FilePart)
473 {
474         WCHAR           *wcs, var[4], drive;
475         int             len;
476         int             reallen;
477         DWORD           offs, sz, type;
478         UNICODE_STRING  usvar, pfx;
479         PCURDIR cd;
480         NTSTATUS Status;
481
482         DPRINT("RtlGetFullPathName_U %S %ld %p %p\n",
483                DosName, size, buf, FilePart);
484
485         if (!DosName || !*DosName)
486                 return 0;
487
488         len = wcslen (DosName);
489
490         /* strip trailing spaces */
491         while (len && DosName[len - 1] == L' ')
492                 len--;
493         if (!len)
494                 return 0;
495         
496         reallen=len;
497         /* strip trailing path separator (but don't change '\') */
498         if ((len > 1) &&
499             IS_PATH_SEPARATOR(DosName[len - 1]))
500                 len--;
501         if (FilePart)
502                 *FilePart = L'\0';
503         memset (buf, 0, size);
504
505 CHECKPOINT;
506         /* check for DOS device name */
507         sz = RtlIsDosDeviceName_U (DosName);
508         if (sz)
509         {
510                 offs = sz >> 17;
511                 sz &= 0x0000FFFF;
512                 if (sz + 8 >= size)
513                 return sz + 10;
514                 wcscpy (buf, L"\\\\.\\");
515                 wcsncat (buf, DosName + offs, sz / sizeof(WCHAR));
516                 return sz + 8;
517         }
518
519 CHECKPOINT;
520         type = RtlDetermineDosPathNameType_U (DosName);
521
522         RtlAcquirePebLock();
523
524         cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName);
525 DPRINT("type %ld\n", type);
526         switch (type)
527         {
528                 case 1:         /* \\xxx or \\.xxx */
529                 case 6:         /* \\.\xxx */
530                         break;
531
532                 case 2:         /* x:\xxx  */
533                         *DosName = towupper (*DosName);
534                         break;
535
536                 case 3:         /* x:xxx   */
537                         drive = towupper (*DosName);
538                         DosName += 2;
539                         len     -= 2;
540 CHECKPOINT;
541                         if (drive == towupper (cd->DosPath.Buffer[0]))
542                         {
543 CHECKPOINT;
544                                 wcscpy (buf, cd->DosPath.Buffer);
545                         }
546                         else
547                         {
548 CHECKPOINT;
549                                 usvar.Length = 2 * swprintf (var, L"=%c:", drive);
550                                 usvar.MaximumLength = 8;
551                                 usvar.Buffer = var;
552                                 pfx.Length = 0;
553                                 pfx.MaximumLength = size;
554                                 pfx.Buffer = buf;
555                                 Status = RtlQueryEnvironmentVariable_U (NULL,
556                                                                         &usvar,
557                                                                         &pfx);
558 CHECKPOINT;
559                                 if (!NT_SUCCESS(Status))
560                                 {
561 CHECKPOINT;
562                                         if (Status == STATUS_BUFFER_TOO_SMALL)
563                                                 return pfx.Length + len * 2 + 2;
564                                         swprintf (buf, L"%c:\\", drive);
565                                 }
566                         }
567                         break;
568
569                 case 4:         /* \xxx    */
570                         wcsncpy (buf, cd->DosPath.Buffer, 2);
571                         break;
572
573                 case 5:         /* xxx     */
574                         wcscpy (buf, cd->DosPath.Buffer);
575                         break;
576
577                 case 7:         /* \\.     */
578                         wcscpy (buf, L"\\\\.\\");
579                         len = 0;
580                         break;
581
582                 default:
583                         return 0;
584         }
585
586         DPRINT("buf \'%S\' DosName \'%S\' len %ld\n", buf, DosName, len);
587         /* add dosname to prefix */
588         wcsncat (buf, DosName, len);
589
590         CHECKPOINT;
591         /* replace slashes */
592         for (wcs = buf; *wcs; wcs++)
593                 if (*wcs == L'/')
594                         *wcs = L'\\';
595
596         len = wcslen (buf);
597         if (len < 3 && buf[len-1] == L':')
598                 wcscat (buf, L"\\");
599
600         DPRINT("buf \'%S\'\n", buf);
601         RtlpEatPath (buf);
602         DPRINT("buf \'%S\'\n", buf);
603
604         len = wcslen (buf);
605
606         /* find file part */
607         if (FilePart)
608         {
609                 for (wcs = buf + len - 1; wcs >= buf; wcs--)
610                 {
611                         if (*wcs == L'\\')
612                         {
613                                 *FilePart = wcs + 1;
614                                 break;
615                         }
616                 }
617         }
618
619         RtlReleasePebLock();
620
621         return len * sizeof(WCHAR);
622 }
623
624
625 BOOLEAN STDCALL
626 RtlDosPathNameToNtPathName_U(PWSTR dosname,
627                              PUNICODE_STRING ntname,
628                              PWSTR *FilePart,
629                              PCURDIR nah)
630 {
631         UNICODE_STRING  us;
632         PCURDIR cd;
633         ULONG Type;
634         ULONG Size;
635         ULONG Length;
636         ULONG Offset;
637         WCHAR fullname[2*MAX_PATH];
638         PWSTR Buffer = NULL;
639
640         RtlAcquirePebLock ();
641
642         RtlInitUnicodeString (&us, dosname);
643         if (us.Length > 8)
644         {
645                 Buffer = us.Buffer;
646                 /* check for "\\?\" - allows to use very long filenames ( up to 32k ) */
647                 if (Buffer[0] == L'\\' && Buffer[1] == L'\\' &&
648                     Buffer[2] == L'?' && Buffer[3] == L'\\')
649                 {
650 //                      if( f_77F68606( &us, ntname, shortname, nah ) )
651 //                      {
652 //                              RtlReleasePebLock ();
653 //                              return TRUE;
654 //                      }
655                         Buffer = NULL;
656                         RtlReleasePebLock ();
657                         return FALSE;
658                 }
659         }
660
661         Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
662                                   0,
663                                   sizeof( fullname ) + MAX_PFX_SIZE);
664         if (Buffer == NULL)
665         {
666                 RtlReleasePebLock ();
667                 return FALSE;
668         }
669
670         Size = RtlGetFullPathName_U (dosname,
671                                      sizeof(fullname),
672                                      fullname,
673                                      FilePart);
674         if (Size == 0 || Size > MAX_PATH * sizeof(WCHAR))
675         {
676                 RtlFreeHeap (RtlGetProcessHeap (),
677                              0,
678                              Buffer);
679                 RtlReleasePebLock ();
680                 return FALSE;
681         }
682
683         /* Set NT prefix */
684         Offset = 0;
685         wcscpy (Buffer, L"\\??\\");
686
687         Type = RtlDetermineDosPathNameType_U (fullname);
688         switch (Type)
689         {
690                 case 1:
691                         wcscat (Buffer, L"UNC\\");
692                         Offset = 2;
693                         break; /* \\xxx   */
694
695                 case 6:
696                         Offset = 4;
697                         break; /* \\.\xxx */
698         }
699         wcscat (Buffer, fullname + Offset);
700         Length = wcslen (Buffer);
701
702         /* set NT filename */
703         ntname->Length        = Length * sizeof(WCHAR);
704         ntname->MaximumLength = sizeof(fullname) + MAX_PFX_SIZE;
705         ntname->Buffer        = Buffer;
706
707         /* set pointer to file part if possible */
708         if (FilePart && *FilePart)
709                 *FilePart = Buffer + Length - wcslen (*FilePart);
710
711         /* Set name and handle structure if possible */
712         if (nah)
713         {
714                 memset (nah, 0, sizeof(CURDIR));
715                 cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName);
716                 if (Type == 5 && cd->Handle &&
717                     !_wcsnicmp (cd->DosPath.Buffer, fullname, cd->DosPath.Length / 2))
718                 {
719                         Length = ((cd->DosPath.Length / sizeof(WCHAR)) - Offset) + ((Type == 1) ? 8 : 4);
720                         nah->DosPath.Buffer = Buffer + Length;
721                         nah->DosPath.Length = ntname->Length - (Length * sizeof(WCHAR));
722                         nah->DosPath.MaximumLength = nah->DosPath.Length;
723                         nah->Handle = cd->Handle;
724                 }
725         }
726
727         RtlReleasePebLock();
728
729         return TRUE;
730 }
731
732
733 ULONG
734 STDCALL
735 RtlDosSearchPath_U (
736         WCHAR *sp,
737         WCHAR *name,
738         WCHAR *ext,
739         ULONG buf_sz,
740         WCHAR *buffer,
741         PWSTR *FilePart
742         )
743 {
744         ULONG Type;
745         ULONG Length = 0;
746         PWSTR full_name;
747         PWSTR wcs;
748         PWSTR path;
749
750         Type = RtlDetermineDosPathNameType_U (name);
751
752         if (Type == 5)
753         {
754                 Length = wcslen (sp);
755                 Length += wcslen (name);
756                 if (wcschr (name, L'.'))
757                         ext = NULL;
758                 if (ext != NULL)
759                         Length += wcslen (ext);
760
761                 full_name = (WCHAR*)RtlAllocateHeap (RtlGetProcessHeap (),
762                                                      0,
763                                                      (Length + 1) * sizeof(WCHAR));
764                 Length = 0;
765                 if (full_name != NULL)
766                 {
767                         path = sp;
768                         while (*path)
769                         {
770                                 wcs = full_name;
771                                 while (*path && *path != L';')
772                                         *wcs++ = *path++;
773                                 if (*path)
774                                         path++;
775                                 if (wcs != full_name && *(wcs - 1) != L'\\')
776                                         *wcs++ = L'\\';
777                                 wcscpy (wcs, name);
778                                 if (ext)
779                                         wcscat (wcs, ext);
780                                 if (RtlDoesFileExists_U (full_name))
781                                 {
782                                         Length = RtlGetFullPathName_U (full_name,
783                                                                        buf_sz,
784                                                                        buffer,
785                                                                        FilePart);
786                                         break;
787                                 }
788                         }
789
790                         RtlFreeHeap (RtlGetProcessHeap (),
791                                      0,
792                                      full_name);
793                 }
794         }
795         else if (RtlDoesFileExists_U (name))
796         {
797                 Length = RtlGetFullPathName_U (name,
798                                                buf_sz,
799                                                buffer,
800                                                FilePart);
801         }
802
803         return Length;
804 }
805
806
807 BOOLEAN STDCALL
808 RtlDoesFileExists_U(IN PWSTR FileName)
809 {
810         UNICODE_STRING NtFileName;
811         OBJECT_ATTRIBUTES Attr;
812         NTSTATUS Status;
813         CURDIR CurDir;
814         PWSTR Buffer;
815
816         /* only used by replacement code */
817         HANDLE FileHandle;
818         IO_STATUS_BLOCK StatusBlock;
819
820         if (!RtlDosPathNameToNtPathName_U (FileName,
821                                            &NtFileName,
822                                            NULL,
823                                            &CurDir))
824                 return FALSE;
825
826         /* don't forget to free it! */
827         Buffer = NtFileName.Buffer;
828
829         if (CurDir.DosPath.Length)
830                 NtFileName = CurDir.DosPath;
831         else
832                 CurDir.Handle = 0;
833
834         InitializeObjectAttributes (&Attr,
835                                     &NtFileName,
836                                     OBJ_CASE_INSENSITIVE,
837                                     CurDir.Handle,
838                                     NULL);
839
840         /* FIXME: not implemented yet */
841 //      Status = NtQueryAttributesFile (&Attr, NULL);
842
843         /* REPLACEMENT start */
844         Status = NtOpenFile (&FileHandle,
845                              0x10001,
846                              &Attr,
847                              &StatusBlock,
848                              1,
849                              FILE_SYNCHRONOUS_IO_NONALERT);
850         if (NT_SUCCESS(Status))
851                 NtClose (FileHandle);
852         /* REPLACEMENT end */
853
854         RtlFreeHeap (RtlGetProcessHeap (),
855                      0,
856                      Buffer);
857
858         if (NT_SUCCESS(Status) ||
859             Status == STATUS_SHARING_VIOLATION ||
860             Status == STATUS_ACCESS_DENIED)
861                 return TRUE;
862
863         return FALSE;
864 }
865
866 /* EOF */