2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
5 * PURPOSE: Path and current directory functions
9 /* INCLUDES *****************************************************************/
16 /* DEFINITONS and MACROS ******************************************************/
18 #define MAX_PFX_SIZE 16
20 #define IS_PATH_SEPARATOR(x) (((x)==L'\\')||((x)==L'/'))
23 /* GLOBALS ********************************************************************/
25 static const WCHAR DeviceRootW
[] = L
"\\\\.\\";
27 static const UNICODE_STRING _condev
= RTL_CONSTANT_STRING(L
"\\\\.\\CON");
29 static const UNICODE_STRING _lpt
= RTL_CONSTANT_STRING(L
"LPT");
31 static const UNICODE_STRING _com
= RTL_CONSTANT_STRING(L
"COM");
33 static const UNICODE_STRING _prn
= RTL_CONSTANT_STRING(L
"PRN");
35 static const UNICODE_STRING _aux
= RTL_CONSTANT_STRING(L
"AUX");
37 static const UNICODE_STRING _con
= RTL_CONSTANT_STRING(L
"CON");
39 static const UNICODE_STRING _nul
= RTL_CONSTANT_STRING(L
"NUL");
41 /* FUNCTIONS *****************************************************************/
47 ULONG STDCALL
RtlGetLongestNtPathLength (VOID
)
49 return (MAX_PATH
+ 9);
58 RtlDetermineDosPathNameType_U(PCWSTR Path
)
60 DPRINT("RtlDetermineDosPathNameType_U %S\n", Path
);
67 if (IS_PATH_SEPARATOR(Path
[0]))
69 if (!IS_PATH_SEPARATOR(Path
[1])) return ABSOLUTE_PATH
; /* \xxx */
70 if (Path
[2] != L
'.') return UNC_PATH
; /* \\xxx */
71 if (IS_PATH_SEPARATOR(Path
[3])) return DEVICE_PATH
; /* \\.\xxx */
72 if (Path
[3]) return UNC_PATH
; /* \\.xxxx */
74 return UNC_DOT_PATH
; /* \\. */
78 /* FIXME: the Wine version of this line reads:
79 * if (!Path[1] || Path[1] != L':') return RELATIVE_PATH
80 * Should we do this too?
83 if (Path
[1] != L
':') return RELATIVE_PATH
; /* xxx */
84 if (IS_PATH_SEPARATOR(Path
[2])) return ABSOLUTE_DRIVE_PATH
; /* x:\xxx */
86 return RELATIVE_DRIVE_PATH
; /* x:xxx */
91 /* returns 0 if name is not valid DOS device name, or DWORD with
92 * offset in bytes to DOS device name from beginning of buffer in high word
93 * and size in bytes of DOS device name in low word */
99 RtlIsDosDeviceName_U(PWSTR DeviceName
)
105 UNICODE_STRING DeviceNameU
;
107 if (DeviceName
== NULL
)
112 while (DeviceName
[Length
])
117 Type
= RtlDetermineDosPathNameType_U(DeviceName
);
125 DeviceNameU
.Length
= DeviceNameU
.MaximumLength
= Length
* sizeof(WCHAR
);
126 DeviceNameU
.Buffer
= DeviceName
;
128 RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_condev
, TRUE
))
133 /* name can end with ':' */
134 if (Length
&& DeviceName
[Length
- 1 ] == L
':')
139 /* there can be spaces or points at the end of name */
140 wc
= DeviceName
+ Length
- 1;
141 while (Length
&& (*wc
== L
'.' || *wc
== L
' '))
147 /* let's find a beginning of name */
148 wc
= DeviceName
+ Length
- 1;
149 while (wc
> DeviceName
&& !IS_PATH_SEPARATOR(*(wc
- 1)))
153 Offset
= wc
- DeviceName
;
155 DeviceNameU
.Length
= DeviceNameU
.MaximumLength
= 3 * sizeof(WCHAR
);
156 DeviceNameU
.Buffer
= wc
;
158 /* check for LPTx or COMx */
159 if (Length
== 4 && wc
[3] >= L
'0' && wc
[3] <= L
'9')
166 if (RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_lpt
, TRUE
) ||
167 RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_com
, TRUE
))
169 return ((Offset
* 2) << 16 ) | 8;
174 /* check for PRN,AUX,NUL or CON */
176 (RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_prn
, TRUE
) ||
177 RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_aux
, TRUE
) ||
178 RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_nul
, TRUE
) ||
179 RtlEqualUnicodeString(&DeviceNameU
, (PUNICODE_STRING
)&_con
, TRUE
)))
181 return ((Offset
* 2) << 16) | 6;
192 RtlGetCurrentDirectory_U(ULONG MaximumLength
,
198 DPRINT ("RtlGetCurrentDirectory %lu %p\n", MaximumLength
, Buffer
);
202 cd
= (PCURDIR
)&(NtCurrentPeb ()->ProcessParameters
->CurrentDirectory
.DosPath
);
203 Length
= cd
->DosPath
.Length
/ sizeof(WCHAR
);
204 if (cd
->DosPath
.Buffer
[Length
- 1] == L
'\\' &&
205 cd
->DosPath
.Buffer
[Length
- 2] != L
':')
208 DPRINT ("cd->DosPath.Buffer %S Length %d\n",
209 cd
->DosPath
.Buffer
, Length
);
211 if (MaximumLength
/ sizeof(WCHAR
) > Length
)
215 Length
* sizeof(WCHAR
));
223 RtlReleasePebLock ();
225 DPRINT ("CurrentDirectory %S\n", Buffer
);
227 return (Length
* sizeof(WCHAR
));
235 RtlSetCurrentDirectory_U(PUNICODE_STRING dir
)
238 UNICODE_STRING envvar
;
239 FILE_FS_DEVICE_INFORMATION device_info
;
240 OBJECT_ATTRIBUTES Attr
;
241 IO_STATUS_BLOCK iosb
;
245 HANDLE handle
= NULL
;
249 DPRINT("RtlSetCurrentDirectory %wZ\n", dir
);
251 RtlAcquirePebLock ();
253 cd
= (PCURDIR
)&NtCurrentPeb ()->ProcessParameters
->CurrentDirectory
.DosPath
;
255 if (!RtlDosPathNameToNtPathName_U (dir
->Buffer
, &full
, 0, 0))
257 RtlReleasePebLock ();
258 return STATUS_OBJECT_NAME_INVALID
;
261 DPRINT("RtlSetCurrentDirectory: full %wZ\n",&full
);
263 InitializeObjectAttributes (&Attr
,
265 OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
,
269 Status
= NtOpenFile (&handle
,
270 SYNCHRONIZE
| FILE_TRAVERSE
,
273 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
274 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
276 if (!NT_SUCCESS(Status
))
278 RtlFreeUnicodeString( &full
);
279 RtlReleasePebLock ();
283 /* don't keep the directory handle open on removable media */
284 if (NT_SUCCESS(NtQueryVolumeInformationFile( handle
, &iosb
, &device_info
,
285 sizeof(device_info
), FileFsDeviceInformation
)) &&
286 (device_info
.Characteristics
& FILE_REMOVABLE_MEDIA
))
288 DPRINT1("don't keep the directory handle open on removable media\n");
294 /* What the heck is this all about??? It looks like its getting the long path,
295 * and if does, ITS WRONG! If current directory is set with a short path,
296 * GetCurrentDir should return a short path.
297 * If anyone agrees with me, remove this stuff.
301 filenameinfo
= RtlAllocateHeap(RtlGetProcessHeap(),
303 MAX_PATH
*sizeof(WCHAR
)+sizeof(ULONG
));
305 Status
= NtQueryInformationFile(handle
,
308 MAX_PATH
*sizeof(WCHAR
)+sizeof(ULONG
),
309 FileNameInformation
);
310 if (!NT_SUCCESS(Status
))
312 RtlFreeHeap(RtlGetProcessHeap(),
315 RtlFreeHeap(RtlGetProcessHeap(),
318 RtlFreeHeap(RtlGetProcessHeap(),
325 /* If it's just "\", we need special handling */
326 if (filenameinfo
->FileNameLength
> sizeof(WCHAR
))
328 wcs
= buf
+ size
/ sizeof(WCHAR
) - 1;
333 size
-= sizeof(WCHAR
);
337 Index
< filenameinfo
->FileNameLength
/ sizeof(WCHAR
);
340 if (filenameinfo
->FileName
[Index
] == '\\') backslashcount
++;
343 DPRINT("%d \n",backslashcount
);
344 for (;backslashcount
;wcs
--)
346 if (*wcs
=='\\') backslashcount
--;
350 RtlCopyMemory(wcs
, filenameinfo
->FileName
, filenameinfo
->FileNameLength
);
351 wcs
[filenameinfo
->FileNameLength
/ sizeof(WCHAR
)] = 0;
353 size
= (wcs
- buf
) * sizeof(WCHAR
) + filenameinfo
->FileNameLength
;
363 /* append trailing \ if missing */
364 size
= full
.Length
/ sizeof(WCHAR
);
366 ptr
+= 4; /* skip \??\ prefix */
369 /* This is ok because RtlDosPathNameToNtPathName_U returns a nullterminated string.
370 * So the nullterm is replaced with \
373 if (size
&& ptr
[size
- 1] != '\\') ptr
[size
++] = '\\';
375 memcpy( cd
->DosPath
.Buffer
, ptr
, size
* sizeof(WCHAR
));
376 cd
->DosPath
.Buffer
[size
] = 0;
377 cd
->DosPath
.Length
= size
* sizeof(WCHAR
);
380 /* FIXME: whats this all about??? Wine doesnt have this. -Gunnar */
381 if (cd
->DosPath
.Buffer
[1]==':')
383 envvar
.Length
= 2 * swprintf (var
, L
"=%c:", cd
->DosPath
.Buffer
[0]);
384 envvar
.MaximumLength
= 8;
387 RtlSetEnvironmentVariable(NULL
,
392 RtlFreeUnicodeString( &full
);
395 return STATUS_SUCCESS
;
400 /******************************************************************
403 * Helper for RtlGetFullPathName_U.
404 * 1) Convert slashes into backslashes
405 * 2) Get rid of duplicate backslashes
406 * 3) Get rid of . and .. components in the path.
408 static __inline
void collapse_path( WCHAR
*path
, UINT mark
)
412 /* convert every / into a \ */
413 for (p
= path
; *p
; p
++) if (*p
== '/') *p
= '\\';
415 /* collapse duplicate backslashes */
416 next
= path
+ max( 1, mark
);
417 for (p
= next
; *p
; p
++) if (*p
!= '\\' || next
[-1] != '\\') *next
++ = *p
;
427 case '\\': /* .\ component */
429 memmove( p
, next
, (wcslen(next
) + 1) * sizeof(WCHAR
) );
431 case 0: /* final . */
432 if (p
> path
+ mark
) p
--;
436 if (p
[2] == '\\') /* ..\ component */
442 while (p
> path
+ mark
&& p
[-1] != '\\') p
--;
444 memmove( p
, next
, (wcslen(next
) + 1) * sizeof(WCHAR
) );
447 else if (!p
[2]) /* final .. */
452 while (p
> path
+ mark
&& p
[-1] != '\\') p
--;
453 if (p
> path
+ mark
) p
--;
461 /* skip to the next component */
462 while (*p
&& *p
!= '\\') p
++;
466 /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */
467 while (p
> path
+ mark
&& (p
[-1] == ' ' || p
[-1] == '.')) p
--;
473 /******************************************************************
476 * Skip the \\share\dir\ part of a file name. Helper for RtlGetFullPathName_U.
478 static const WCHAR
*skip_unc_prefix( const WCHAR
*ptr
)
481 while (*ptr
&& !IS_PATH_SEPARATOR(*ptr
)) ptr
++; /* share name */
482 while (IS_PATH_SEPARATOR(*ptr
)) ptr
++;
483 while (*ptr
&& !IS_PATH_SEPARATOR(*ptr
)) ptr
++; /* dir name */
484 while (IS_PATH_SEPARATOR(*ptr
)) ptr
++;
489 /******************************************************************
490 * get_full_path_helper
492 * Helper for RtlGetFullPathName_U
493 * Note: name and buffer are allowed to point to the same memory spot
495 static ULONG
get_full_path_helper(
500 ULONG reqsize
= 0, mark
= 0, dep
= 0, deplen
;
501 DOS_PATHNAME_TYPE type
;
502 LPWSTR ins_str
= NULL
;
504 const UNICODE_STRING
* cd
;
507 /* return error if name only consists of spaces */
508 for (ptr
= name
; *ptr
; ptr
++) if (*ptr
!= ' ') break;
513 cd
= &((PCURDIR
)&NtCurrentTeb()->ProcessEnvironmentBlock
->ProcessParameters
->CurrentDirectory
.DosPath
)->DosPath
;
515 switch (type
= RtlDetermineDosPathNameType_U(name
))
517 case UNC_PATH
: /* \\foo */
518 ptr
= skip_unc_prefix( name
);
522 case DEVICE_PATH
: /* \\.\foo */
526 case ABSOLUTE_DRIVE_PATH
: /* c:\foo */
527 reqsize
= sizeof(WCHAR
);
528 tmp
[0] = towupper(name
[0]);
534 case RELATIVE_DRIVE_PATH
: /* c:foo */
536 if (towupper(name
[0]) != towupper(cd
->Buffer
[0]) || cd
->Buffer
[1] != ':')
538 UNICODE_STRING var
, val
;
544 var
.Length
= 3 * sizeof(WCHAR
);
545 var
.MaximumLength
= 4 * sizeof(WCHAR
);
548 val
.MaximumLength
= size
;
549 val
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, size
);
551 switch (RtlQueryEnvironmentVariable_U(NULL
, &var
, &val
))
554 /* FIXME: Win2k seems to check that the environment variable actually points
555 * to an existing directory. If not, root of the drive is used
556 * (this seems also to be the only spot in RtlGetFullPathName that the
557 * existence of a part of a path is checked)
560 case STATUS_BUFFER_TOO_SMALL
:
561 reqsize
= val
.Length
+ sizeof(WCHAR
); /* append trailing '\\' */
562 val
.Buffer
[val
.Length
/ sizeof(WCHAR
)] = '\\';
563 ins_str
= val
.Buffer
;
565 case STATUS_VARIABLE_NOT_FOUND
:
566 reqsize
= 3 * sizeof(WCHAR
);
573 DPRINT1("Unsupported status code\n");
581 case RELATIVE_PATH
: /* foo */
582 reqsize
= cd
->Length
;
583 ins_str
= cd
->Buffer
;
584 if (cd
->Buffer
[1] != ':')
586 ptr
= skip_unc_prefix( cd
->Buffer
);
587 mark
= ptr
- cd
->Buffer
;
592 case ABSOLUTE_PATH
: /* \xxx */
594 if (name
[0] == '/') /* may be a Unix path */
596 const WCHAR
*ptr
= name
;
597 int drive
= find_drive_root( &ptr
);
600 reqsize
= 3 * sizeof(WCHAR
);
601 tmp
[0] = 'A' + drive
;
611 if (cd
->Buffer
[1] == ':')
613 reqsize
= 2 * sizeof(WCHAR
);
614 tmp
[0] = cd
->Buffer
[0];
621 ptr
= skip_unc_prefix( cd
->Buffer
);
622 reqsize
= (ptr
- cd
->Buffer
) * sizeof(WCHAR
);
623 mark
= reqsize
/ sizeof(WCHAR
);
624 ins_str
= cd
->Buffer
;
628 case UNC_DOT_PATH
: /* \\. */
629 reqsize
= 4 * sizeof(WCHAR
);
644 deplen
= wcslen(name
+ dep
) * sizeof(WCHAR
);
645 if (reqsize
+ deplen
+ sizeof(WCHAR
) > size
)
647 /* not enough space, return need size (including terminating '\0') */
648 reqsize
+= deplen
+ sizeof(WCHAR
);
652 memmove(buffer
+ reqsize
/ sizeof(WCHAR
), name
+ dep
, deplen
+ sizeof(WCHAR
));
653 if (reqsize
) memcpy(buffer
, ins_str
, reqsize
);
656 if (ins_str
&& ins_str
!= tmp
&& ins_str
!= cd
->Buffer
)
657 RtlFreeHeap(RtlGetProcessHeap(), 0, ins_str
);
659 collapse_path( buffer
, mark
);
660 reqsize
= wcslen(buffer
) * sizeof(WCHAR
);
668 /******************************************************************
669 * RtlGetFullPathName_U (NTDLL.@)
671 * Returns the number of bytes written to buffer (not including the
672 * terminating NULL) if the function succeeds, or the required number of bytes
673 * (including the terminating NULL) if the buffer is too small.
675 * file_part will point to the filename part inside buffer (except if we use
676 * DOS device name, in which case file_in_buf is NULL)
680 DWORD STDCALL
RtlGetFullPathName_U(
690 DPRINT("RtlGetFullPathName_U(%S %lu %p %p)\n", name
, size
, buffer
, file_part
);
692 if (!name
|| !*name
) return 0;
694 if (file_part
) *file_part
= NULL
;
696 /* check for DOS device name */
697 dosdev
= RtlIsDosDeviceName_U((WCHAR
*)name
);
700 DWORD offset
= HIWORD(dosdev
) / sizeof(WCHAR
); /* get it in WCHARs, not bytes */
701 DWORD sz
= LOWORD(dosdev
); /* in bytes */
703 if (8 + sz
+ 2 > size
) return sz
+ 10;
704 wcscpy(buffer
, DeviceRootW
);
705 memmove(buffer
+ 4, name
+ offset
, sz
);
706 buffer
[4 + sz
/ sizeof(WCHAR
)] = '\0';
707 /* file_part isn't set in this case */
711 reqsize
= get_full_path_helper(name
, buffer
, size
);
712 if (!reqsize
) return 0;
715 LPWSTR tmp
= RtlAllocateHeap(RtlGetProcessHeap(), 0, reqsize
);
716 reqsize
= get_full_path_helper(name
, tmp
, reqsize
);
717 if (reqsize
> size
) /* it may have worked the second time */
719 RtlFreeHeap(RtlGetProcessHeap(), 0, tmp
);
720 return reqsize
+ sizeof(WCHAR
);
722 memcpy( buffer
, tmp
, reqsize
+ sizeof(WCHAR
) );
723 RtlFreeHeap(RtlGetProcessHeap(), 0, tmp
);
727 if (file_part
&& (ptr
= wcsrchr(buffer
, '\\')) != NULL
&& ptr
>= buffer
+ 2 && *++ptr
)
737 RtlDosPathNameToNtPathName_U(PWSTR dosname
,
738 PUNICODE_STRING ntname
,
749 WCHAR fullname
[MAX_PATH
+ 1];
753 RtlAcquirePebLock ();
755 RtlInitUnicodeString (&us
, dosname
);
759 /* check for "\\?\" - allows to use very long filenames ( up to 32k ) */
760 if (Buffer
[0] == L
'\\' && Buffer
[1] == L
'\\' &&
761 Buffer
[2] == L
'?' && Buffer
[3] == L
'\\')
763 // if( f_77F68606( &us, ntname, shortname, nah ) )
765 // RtlReleasePebLock ();
769 RtlReleasePebLock ();
774 Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
776 sizeof( fullname
) + MAX_PFX_SIZE
);
779 RtlReleasePebLock ();
783 Size
= RtlGetFullPathName_U (dosname
,
787 if (Size
== 0 || Size
> MAX_PATH
* sizeof(WCHAR
))
789 RtlFreeHeap (RtlGetProcessHeap (),
792 RtlReleasePebLock ();
798 memcpy (Buffer
, L
"\\??\\", 4 * sizeof(WCHAR
));
801 Type
= RtlDetermineDosPathNameType_U (fullname
);
805 memcpy (Buffer
+ tmpLength
, L
"UNC\\", 4 * sizeof(WCHAR
));
814 Length
= wcslen(fullname
+ Offset
);
815 memcpy (Buffer
+ tmpLength
, fullname
+ Offset
, (Length
+ 1) * sizeof(WCHAR
));
817 if (Type
== ABSOLUTE_DRIVE_PATH
||
818 Type
== RELATIVE_DRIVE_PATH
)
820 /* make the drive letter to uppercase */
821 Buffer
[tmpLength
] = towupper(Buffer
[tmpLength
]);
824 /* set NT filename */
825 ntname
->Length
= Length
* sizeof(WCHAR
);
826 ntname
->MaximumLength
= sizeof(fullname
) + MAX_PFX_SIZE
;
827 ntname
->Buffer
= Buffer
;
829 /* set pointer to file part if possible */
830 if (FilePart
&& *FilePart
)
831 *FilePart
= Buffer
+ Length
- wcslen (*FilePart
);
833 /* Set name and handle structure if possible */
836 memset (nah
, 0, sizeof(CURDIR
));
837 cd
= (PCURDIR
)&(NtCurrentPeb ()->ProcessParameters
->CurrentDirectory
.DosPath
);
838 if (Type
== 5 && cd
->Handle
)
840 RtlInitUnicodeString(&us
, fullname
);
841 if (RtlEqualUnicodeString(&us
, &cd
->DosPath
, TRUE
))
843 Length
= ((cd
->DosPath
.Length
/ sizeof(WCHAR
)) - Offset
) + ((Type
== 1) ? 8 : 4);
844 nah
->DosPath
.Buffer
= Buffer
+ Length
;
845 nah
->DosPath
.Length
= ntname
->Length
- (Length
* sizeof(WCHAR
));
846 nah
->DosPath
.MaximumLength
= nah
->DosPath
.Length
;
847 nah
->Handle
= cd
->Handle
;
877 Type
= RtlDetermineDosPathNameType_U (name
);
881 Length
= wcslen (sp
);
882 Length
+= wcslen (name
);
883 if (wcschr (name
, L
'.'))
886 Length
+= wcslen (ext
);
888 full_name
= (WCHAR
*)RtlAllocateHeap (RtlGetProcessHeap (),
890 (Length
+ 1) * sizeof(WCHAR
));
892 if (full_name
!= NULL
)
898 while (*path
&& *path
!= L
';')
902 if (wcs
!= full_name
&& *(wcs
- 1) != L
'\\')
907 if (RtlDoesFileExists_U (full_name
))
909 Length
= RtlGetFullPathName_U (full_name
,
917 RtlFreeHeap (RtlGetProcessHeap (),
922 else if (RtlDoesFileExists_U (name
))
924 Length
= RtlGetFullPathName_U (name
,
938 RtlDoesFileExists_U(IN PWSTR FileName
)
940 UNICODE_STRING NtFileName
;
941 OBJECT_ATTRIBUTES Attr
;
942 FILE_BASIC_INFORMATION Info
;
947 if (!RtlDosPathNameToNtPathName_U (FileName
,
953 if (CurDir
.DosPath
.Length
)
954 NtFileName
= CurDir
.DosPath
;
958 InitializeObjectAttributes (&Attr
,
960 OBJ_CASE_INSENSITIVE
,
964 Status
= NtQueryAttributesFile (&Attr
, &Info
);
966 RtlFreeUnicodeString(&NtFileName
);
969 if (NT_SUCCESS(Status
) ||
970 Status
== STATUS_SHARING_VIOLATION
||
971 Status
== STATUS_ACCESS_DENIED
)
982 RtlDosPathNameToRelativeNtPathName_U(PVOID Unknown1
,
987 DPRINT1("RtlDosPathNameToRelativeNtPathName_U(0x%p, 0x%p, 0x%p, 0x%p) UNIMPLEMENTED!\n",
988 Unknown1
, Unknown2
, Unknown3
, Unknown4
);
997 RtlReleaseRelativeName(PVOID Unknown
)
999 DPRINT1("RtlReleaseRelativeName(0x%p) UNIMPLEMENTED\n", Unknown
);
1003 RtlpEnsureBufferSize(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
1005 DPRINT1("RtlpEnsureBufferSize: stub\n");
1006 return STATUS_NOT_IMPLEMENTED
;
1010 RtlNtPathNameToDosPathName(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
, ULONG Unknown4
)
1012 DPRINT1("RtlNtPathNameToDosPathName: stub\n");
1013 return STATUS_NOT_IMPLEMENTED
;