ReactOS 0.4.17-dev-966-gf06eace
path.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/client/path.c
5 * PURPOSE: Handles path APIs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <k32.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS ********************************************************************/
17
19
22
25
26/* This is bitmask for each illegal filename character */
27/* If someone has time, please feel free to use 0b notation */
29{
30 0xFFFFFFFF, // None allowed (00 to 1F)
31 0xFC009C05, // 20, 22, 2A, 2B, 2C, 2F, 3A, 3B, 3C, 3D, 3E, 3F not allowed
32 0x38000000, // 5B, 5C, 5D not allowed
33 0x10000000 // 7C not allowed
34};
35
37{
38 {
44 },
45 {
51 }
52};
53
55{
61};
62
64{
70};
71
73{
79};
80
82
84
86
87/* PRIVATE FUNCTIONS **********************************************************/
88
92{
93 PWCHAR FileNameEnd, FileNameSeparator;
94
95 /* Find the first slash */
96 FileNameSeparator = wcschr(FileName, OBJ_NAME_PATH_SEPARATOR);
97 if (FileNameSeparator)
98 {
99 /* Find the last one */
100 FileNameEnd = wcsrchr(FileNameSeparator, OBJ_NAME_PATH_SEPARATOR);
101 ASSERT(FileNameEnd);
102
103 /* Handle the case where they are one and the same */
104 if (FileNameEnd == FileNameSeparator) FileNameEnd++;
105 }
106 else
107 {
108 /* No directory was specified */
109 FileNameEnd = NULL;
110 }
111
112 /* Return where the directory ends and the filename starts */
113 return FileNameEnd;
114}
115
116LPWSTR
117WINAPI
121{
122 PWCHAR PathBuffer, Buffer, AppNameEnd, PathCurrent;
123 SIZE_T PathLengthInBytes;
125 UNICODE_STRING EnvPath;
127
128 /* Initialize state */
129 AppNameEnd = Buffer = PathBuffer = NULL;
131 PathLengthInBytes = 0;
132
133 /* Loop the ordering array */
134 for (Order = PathOrder; *Order != BaseSearchPathInvalid; Order++) {
135 switch (*Order)
136 {
137 /* Compute the size of the DLL path */
139
140 /* This path only gets called if SetDllDirectory was called */
142
143 /* Make sure there's a DLL directory size */
145 {
146 /* Add it, plus the separator */
147 PathLengthInBytes += BaseDllDirectory.Length + sizeof(L';');
148 }
149 break;
150
151 /* Compute the size of the current path */
153
154 /* Add ".;" */
155 PathLengthInBytes += (2 * sizeof(WCHAR));
156 break;
157
158 /* Compute the size of the "PATH" environment variable */
160
161 /* Grab PEB lock if one wasn't passed in */
163
164 /* Query the size first */
165 EnvPath.MaximumLength = 0;
168 &EnvPath);
170 {
171 /* Compute the size we'll need for the environment */
172 EnvPath.MaximumLength = EnvPath.Length + sizeof(WCHAR);
173 if ((EnvPath.Length + sizeof(WCHAR)) > UNICODE_STRING_MAX_BYTES)
174 {
175 /* Don't let it overflow */
176 EnvPath.MaximumLength = EnvPath.Length;
177 }
178
179 /* Allocate the environment buffer */
180 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
181 0,
182 EnvPath.MaximumLength);
183 if (Buffer)
184 {
185 /* Now query the PATH environment variable */
186 EnvPath.Buffer = Buffer;
189 &EnvPath);
190 }
191 else
192 {
193 /* Failure case */
195 }
196 }
197
198 /* Release the PEB lock from above */
200
201 /* There might not be a PATH */
203 {
204 /* In this case, skip this PathOrder */
205 EnvPath.Length = EnvPath.MaximumLength = 0;
207 }
208 else if (!NT_SUCCESS(Status))
209 {
210 /* An early failure, go to exit code */
211 goto Quickie;
212 }
213 else
214 {
215 /* Add the length of the PATH variable unless it's empty */
216 ASSERT(!(EnvPath.Length & 1));
217 if (EnvPath.Length)
218 {
219 /* Reserve space for the variable and a semicolon */
220 PathLengthInBytes += (EnvPath.Length + sizeof(L';'));
221 }
222 }
223 break;
224
225 /* Compute the size of the default search path */
227
228 /* Just add it... it already has a ';' at the end */
230 PathLengthInBytes += BaseDefaultPath.Length;
231 break;
232
233 /* Compute the size of the current app directory */
235 /* Find out where the app name ends, to get only the directory */
236 if (AppName) AppNameEnd = BasepEndOfDirName(AppName);
237
238 /* Check if there was no application name passed in */
239 if (!(AppName) || !(AppNameEnd))
240 {
241 /* Do we have a per-thread CURDIR to use? */
242 if (NtCurrentTeb()->NtTib.SubSystemTib)
243 {
244 /* This means someone added RTL_PERTHREAD_CURDIR */
246 }
247
248 /* We do not. Do we have the LDR_ENTRY for the executable? */
249 if (!BasepExeLdrEntry)
250 {
251 /* We do not. Grab it */
254 NtCurrentPeb()->ImageBaseAddress);
255 }
256
257 /* Now do we have it? */
259 {
260 /* Yes, so read the name out of it */
262 }
263
264 /* Find out where the app name ends, to get only the directory */
265 if (AppName) AppNameEnd = BasepEndOfDirName(AppName);
266 }
267
268 /* So, do we have an application name and its directory? */
269 if ((AppName) && (AppNameEnd))
270 {
271 /* Add the size of the app's directory, plus the separator */
272 PathLengthInBytes += ((AppNameEnd - AppName) * sizeof(WCHAR)) + sizeof(L';');
273 }
274 break;
275
276 default:
277 break;
278 }
279 }
280
281 /* Bam, all done, we now have the final path size */
282 ASSERT(PathLengthInBytes > 0);
283 ASSERT(!(PathLengthInBytes & 1));
284
285 /* Allocate the buffer to hold it */
286 PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLengthInBytes);
287 if (!PathBuffer)
288 {
289 /* Failure path */
291 goto Quickie;
292 }
293
294 /* Now we loop again, this time to copy the data */
295 PathCurrent = PathBuffer;
296 for (Order = PathOrder; *Order != BaseSearchPathInvalid; Order++) {
297 switch (*Order)
298 {
299 /* Add the DLL path */
302 {
303 /* Copy it in the buffer, ASSERT there's enough space */
304 ASSERT((((PathCurrent - PathBuffer + 1) * sizeof(WCHAR)) + BaseDllDirectory.Length) <= PathLengthInBytes);
305 RtlCopyMemory(PathCurrent,
308
309 /* Update the current pointer, add a separator */
310 PathCurrent += (BaseDllDirectory.Length / sizeof(WCHAR));
311 *PathCurrent++ = ';';
312 }
313 break;
314
315 /* Add the current application path */
317 if ((AppName) && (AppNameEnd))
318 {
319 /* Copy it in the buffer, ASSERT there's enough space */
320 ASSERT(((PathCurrent - PathBuffer + 1 + (AppNameEnd - AppName)) * sizeof(WCHAR)) <= PathLengthInBytes);
321 RtlCopyMemory(PathCurrent,
322 AppName,
323 (AppNameEnd - AppName) * sizeof(WCHAR));
324
325 /* Update the current pointer, add a separator */
326 PathCurrent += AppNameEnd - AppName;
327 *PathCurrent++ = ';';
328 }
329 break;
330
331 /* Add the default search path */
333 /* Copy it in the buffer, ASSERT there's enough space */
334 ASSERT((((PathCurrent - PathBuffer) * sizeof(WCHAR)) + BaseDefaultPath.Length) <= PathLengthInBytes);
336
337 /* Update the current pointer. The default path already has a ";" */
338 PathCurrent += (BaseDefaultPath.Length / sizeof(WCHAR));
339 break;
340
341 /* Add the path in the PATH environment variable */
343 if (EnvPath.Length)
344 {
345 /* Copy it in the buffer, ASSERT there's enough space */
346 ASSERT((((PathCurrent - PathBuffer + 1) * sizeof(WCHAR)) + EnvPath.Length) <= PathLengthInBytes);
347 RtlCopyMemory(PathCurrent, EnvPath.Buffer, EnvPath.Length);
348
349 /* Update the current pointer, add a separator */
350 PathCurrent += (EnvPath.Length / sizeof(WCHAR));
351 *PathCurrent++ = ';';
352 }
353 break;
354
355 /* Add the current directory */
357
358 /* Copy it in the buffer, ASSERT there's enough space */
359 ASSERT(((PathCurrent - PathBuffer + 2) * sizeof(WCHAR)) <= PathLengthInBytes);
360 *PathCurrent++ = '.';
361
362 /* Add the path separator */
363 *PathCurrent++ = ';';
364 break;
365
366 default:
367 break;
368 }
369 }
370
371 /* Everything should've perfectly fit in there */
372 ASSERT((PathCurrent - PathBuffer) * sizeof(WCHAR) == PathLengthInBytes);
373 ASSERT(PathCurrent > PathBuffer);
374
375 /* Terminate the whole thing */
376 PathCurrent[-1] = UNICODE_NULL;
377
378Quickie:
379 /* Exit path: free our buffers */
380 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
381 if (PathBuffer)
382 {
383 /* This only gets freed in the failure path, since caller wants it */
384 if (!NT_SUCCESS(Status))
385 {
386 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
387 PathBuffer = NULL;
388 }
389 }
390
391 /* Return the path! */
392 return PathBuffer;
393}
394
395LPWSTR
396WINAPI
398{
399 BASE_CURRENT_DIR_PLACEMENT CurDirPlacement;
400 DWORD CurrentModeFlags, OldCurrentModeFlags;
401 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager");
402 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SafeProcessSearchMode");
404 CHAR PartialInfoBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(DWORD)];
408
409 DPRINT("Computing Process Search path\n");
410
411 CurrentModeFlags = BasepSearchPathModeFlags;
412 /* No flag is set, read from registry */
413 if (CurrentModeFlags == BASE_SEARCH_PATH_INVALID_FLAGS)
414 {
415 /* Open the configuration key */
417 if (NT_SUCCESS(Status))
418 {
419 /* Query if safe search is enabled */
421 &ValueName,
423 PartialInfoBuffer,
424 sizeof(PartialInfoBuffer),
425 &ResultLength);
426 if (NT_SUCCESS(Status))
427 {
428 /* Read the value if the size is OK */
429 if (ResultLength == sizeof(PartialInfoBuffer))
430 {
431 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)PartialInfoBuffer;
432 /* 0 means disabled and 1 means enabled */
433 CurrentModeFlags = *(PDWORD)PartialInfo->Data == 1
436 }
437 }
438 /* Close the handle */
440 }
441
442 /* Fallback to default value if couldn't read from registry */
443 if (CurrentModeFlags == BASE_SEARCH_PATH_INVALID_FLAGS)
445
446 /* Update the flag and read the old one */
448 CurrentModeFlags,
450 if (OldCurrentModeFlags != BASE_SEARCH_PATH_INVALID_FLAGS)
451 CurrentModeFlags = OldCurrentModeFlags;
452 }
453
454 CurDirPlacement = CurrentModeFlags & BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE ?
456
457 /* Compute the path using default process order */
458 return BasepComputeProcessPath(BaseDllOrderCurrent[CurDirPlacement], NULL, NULL);
459}
460
461LPWSTR
462WINAPI
464{
465 PBASE_SEARCH_PATH_TYPE PathOrder;
466 DPRINT("Computing EXE path: %S\n", FullPath);
467
468 /* Check if we should use the current directory */
469 PathOrder = NeedCurrentDirectoryForExePathW(FullPath) ?
471
472 /* And now compute the path */
473 return BasepComputeProcessPath(PathOrder, NULL, NULL);
474}
475
476LPWSTR
477WINAPI
480{
481 LPWSTR DllPath = NULL;
482 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager");
483 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SafeDllSearchMode");
485 CHAR PartialInfoBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
489 BASE_CURRENT_DIR_PLACEMENT CurrentDirPlacement, OldCurrentDirPlacement;
490
491 /* Acquire DLL directory lock */
493
494 /* Check if we have a base dll directory */
496 {
497 /* Then compute the process path using DLL order (without curdir) */
499
500 /* Release DLL directory lock */
502
503 /* Return dll path */
504 return DllPath;
505 }
506
507 /* Release DLL directory lock */
509
510 /* Read the current placement */
511 CurrentDirPlacement = BasepDllCurrentDirPlacement;
512 if (CurrentDirPlacement == BaseCurrentDirPlacementInvalid)
513 {
514 /* Open the configuration key */
516 if (NT_SUCCESS(Status))
517 {
518 /* Query if safe search is enabled */
520 &ValueName,
522 PartialInfoBuffer,
523 sizeof(PartialInfoBuffer),
524 &ResultLength);
525 if (NT_SUCCESS(Status))
526 {
527 /* Read the value if the size is OK */
528 if (ResultLength == sizeof(PartialInfoBuffer))
529 {
530 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)PartialInfoBuffer;
531 CurrentDirPlacement = *(PULONG)PartialInfo->Data;
532 }
533 }
534
535 /* Close the handle */
537
538 /* Validate the registry value */
539 if ((CurrentDirPlacement <= BaseCurrentDirPlacementInvalid) ||
540 (CurrentDirPlacement >= BaseCurrentDirPlacementMax))
541 {
542 /* Default to safe search */
543 CurrentDirPlacement = BaseCurrentDirPlacementSafe;
544 }
545 }
546
547 /* Update the placement and read the old one */
549 CurrentDirPlacement,
551 if (OldCurrentDirPlacement != BaseCurrentDirPlacementInvalid)
552 {
553 /* If there already was a placement, use it */
554 CurrentDirPlacement = OldCurrentDirPlacement;
555 }
556 }
557
558 /* Check if the placement is invalid or not set */
559 if ((CurrentDirPlacement <= BaseCurrentDirPlacementInvalid) ||
560 (CurrentDirPlacement >= BaseCurrentDirPlacementMax))
561 {
562 /* Default to safe search */
563 CurrentDirPlacement = BaseCurrentDirPlacementSafe;
564 }
565
566 /* Compute the process path using either normal or safe search */
567 DllPath = BasepComputeProcessPath(BaseDllOrderCurrent[CurrentDirPlacement],
568 FullPath,
570
571 /* Return dll path */
572 return DllPath;
573}
574
576WINAPI
578{
579 PUNICODE_STRING CurDir;
580 USHORT CurLength;
582 UNICODE_STRING CurDirCopy;
583
584 CurDir = &NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath;
585
586 CurLength = CurDir->Length;
587 if (CurDir->Length <= 6)
588 {
589 if (CurLength != DirName->Length) return FALSE;
590 }
591 else
592 {
593 if ((CurLength - 2) != DirName->Length) return FALSE;
594 }
595
597
598 CurDirCopy = *CurDir;
599 if (CurDirCopy.Length > 6) CurDirCopy.Length -= 2;
600
601 Result = 0;
602
603 if (RtlEqualUnicodeString(&CurDirCopy, DirName, TRUE)) Result = TRUE;
604
606
607 return Result;
608}
609
610/*
611 * Why not use RtlIsNameLegalDOS8Dot3? In fact the actual algorithm body is
612 * identical (other than the Rtl can optionally check for spaces), however the
613 * Rtl will always convert to OEM, while kernel32 has two possible file modes
614 * (ANSI or OEM). Therefore we must duplicate the algorithm body to get
615 * the correct compatible results
616 */
617BOOL
618WINAPI
621{
622 BOOLEAN HasExtension;
623 UCHAR c;
626 ANSI_STRING AnsiName;
627 ULONG i, Dots;
628 CHAR AnsiBuffer[MAX_PATH];
629 ASSERT(Name);
630
631 /* What do you think 8.3 means? */
632 if (Length > 12) return FALSE;
633
634 /* Sure, any empty name is a short name */
635 if (!Length) return TRUE;
636
637 /* This could be . or .. or something else */
638 if (*Name == L'.')
639 {
640 /* Which one is it */
641 if ((Length == 1) || ((Length == 2) && *(Name + 1) == L'.'))
642 {
643 /* . or .., this is good */
644 return TRUE;
645 }
646
647 /* Some other bizare dot-based name, not good */
648 return FALSE;
649 }
650
651 /* Initialize our two strings */
652 RtlInitEmptyAnsiString(&AnsiName, AnsiBuffer, MAX_PATH);
653 RtlInitEmptyUnicodeString(&UnicodeName, Name, (USHORT)Length * sizeof(WCHAR));
654 UnicodeName.Length = UnicodeName.MaximumLength;
655
656 /* Now do the conversion */
658 if (!NT_SUCCESS(Status)) return FALSE;
659
660 /* Now we loop the name */
661 HasExtension = FALSE;
662 for (i = 0, Dots = Length - 1; i < AnsiName.Length; i++, Dots--)
663 {
664 /* Read the current byte */
665 c = AnsiName.Buffer[i];
666
667 /* Is it DBCS? */
668 if (IsDBCSLeadByte(c))
669 {
670 /* If we're near the end of the string, we can't allow a DBCS */
671 if ((!(HasExtension) && (i >= 7)) || (i == AnsiName.Length - 1))
672 {
673 return FALSE;
674 }
675
676 /* Otherwise we skip over it */
677 continue;
678 }
679
680 /* Check for illegal characters */
681 if ((c > 0x7F) || (IllegalMask[c / 32] & (1 << (c % 32))))
682 {
683 return FALSE;
684 }
685
686 /* Check if this is perhaps an extension? */
687 if (c == '.')
688 {
689 /* Unless the extension is too large or there's more than one */
690 if ((HasExtension) || (Dots > 3)) return FALSE;
691
692 /* This looks like an extension */
693 HasExtension = TRUE;
694 }
695
696 /* 8.3 length was validated, but now we must guard against 9.2 or similar */
697 if ((i >= 8) && !(HasExtension)) return FALSE;
698 }
699
700 /* You survived the loop, this is a good short name */
701 return TRUE;
702}
703
704BOOL
705WINAPI
708{
709 BOOLEAN HasExtension;
710 ULONG i, Dots;
711
712 /* More than 8.3, any combination of dots, and NULL names are all long */
713 if (!(Length) || (Length > 12) || (*FileName == L'.')) return TRUE;
714
715 /* Otherwise, initialize our scanning loop */
716 HasExtension = FALSE;
717 for (i = 0, Dots = Length - 1; i < Length; i++, Dots--)
718 {
719 /* Check if this could be an extension */
720 if (FileName[i] == L'.')
721 {
722 /* Unlike the short case, we WANT more than one extension, or a long one */
723 if ((HasExtension) || (Dots > 3))
724 {
725 return TRUE;
726 }
727 HasExtension = TRUE;
728 }
729
730 /* Check if this would violate the "8" in 8.3, ie. 9.2 */
731 if ((i >= 8) && (!HasExtension)) return TRUE;
732 }
733
734 /* The name *seems* to conform to 8.3 */
735 return FALSE;
736}
737
738BOOL
739WINAPI
742 OUT PWCHAR *Last,
743 IN BOOL UseShort)
744{
745 PWCHAR p;
747 BOOL Found = 0;
748 ASSERT(Path);
749
750 /* Loop while there is something in the path */
751 while (TRUE)
752 {
753 /* Loop within the path skipping slashes */
754 while ((*Path == L'\\') || (*Path == L'/')) Path++;
755
756 /* Make sure there's something after the slashes too! */
757 if (*Path == UNICODE_NULL) break;
758
759 /* Now skip past the file name until we get to the first slash */
760 p = Path + 1;
761 while ((*p) && ((*p != L'\\') && (*p != L'/'))) p++;
762
763 /* Whatever is in between those two is now the file name length */
764 Length = p - Path;
765
766 /*
767 * Check if it is valid
768 * Note that !IsShortName != IsLongName, these two functions simply help
769 * us determine if a conversion is necessary or not.
770 * "Found" really means: "Is a conversion necessary?", hence the "!"
771 */
773 if (Found)
774 {
775 /* It is! did the caller request to know the markers? */
776 if ((First) && (Last))
777 {
778 /* Return them */
779 *First = Path;
780 *Last = p;
781 }
782 break;
783 }
784
785 /* Is there anything else following this sub-path/filename? */
786 if (*p == UNICODE_NULL) break;
787
788 /* Yes, keep going */
789 Path = p + 1;
790 }
791
792 /* Return if anything was found and valid */
793 return Found;
794}
795
796PWCHAR
797WINAPI
799{
800 PWCHAR ReturnPath;
801 ULONG i;
802
803 /* Check what kind of path this is and how many slashes to skip */
805 {
808 {
809 /* Keep going until we bypass the path indicators */
810 for (ReturnPath = Path + 2, i = 2; (i > 0) && (*ReturnPath); ReturnPath++)
811 {
812 /* We look for 2 slashes, so keep at it until we find them */
813 if ((*ReturnPath == L'\\') || (*ReturnPath == L'/')) i--;
814 }
815
816 return ReturnPath;
817 }
818
820 return Path + 3;
821
823 return Path + 2;
824
826 return Path + 1;
827
829 return Path;
830
832 default:
833 return NULL;
834 }
835}
836
837BOOL
838WINAPI
840{
842 UNICODE_STRING EmptyString;
843
844 RtlInitEmptyUnicodeString(&EmptyString, NULL, 0);
847 &EmptyString);
849}
850
851/* PUBLIC FUNCTIONS ***********************************************************/
852
853/*
854 * @implemented
855 */
856BOOL
857WINAPI
859{
860 UNICODE_STRING OldDirectory, DllDirectory;
861
862 if (lpPathName)
863 {
864 if (wcschr(lpPathName, L';'))
865 {
867 return FALSE;
868 }
869 if (!RtlCreateUnicodeString(&DllDirectory, lpPathName))
870 {
872 return FALSE;
873 }
874 }
875 else
876 {
877 RtlInitUnicodeString(&DllDirectory, NULL);
878 }
879
881
882 OldDirectory = BaseDllDirectory;
883 BaseDllDirectory = DllDirectory;
884
886
887 RtlFreeUnicodeString(&OldDirectory);
888 return TRUE;
889}
890
891/*
892 * @implemented
893 */
894BOOL
895WINAPI
897{
898 ANSI_STRING AnsiDllDirectory;
899 UNICODE_STRING OldDirectory, DllDirectory;
901
902 if (lpPathName)
903 {
904 if (strchr(lpPathName, ';'))
905 {
907 return FALSE;
908 }
909
910 Status = RtlInitAnsiStringEx(&AnsiDllDirectory, lpPathName);
911 if (NT_SUCCESS(Status))
912 {
914 &AnsiDllDirectory,
915 TRUE);
916 }
917
918 if (!NT_SUCCESS(Status))
919 {
921 return FALSE;
922 }
923 }
924 else
925 {
926 RtlInitUnicodeString(&DllDirectory, NULL);
927 }
928
930
931 OldDirectory = BaseDllDirectory;
932 BaseDllDirectory = DllDirectory;
933
935
936 RtlFreeUnicodeString(&OldDirectory);
937 return TRUE;
938}
939
940/*
941 * @implemented
942 */
943DWORD
944WINAPI
947{
949
951
952 if ((nBufferLength * sizeof(WCHAR)) > BaseDllDirectory.Length)
953 {
957 }
958 else
959 {
960 Length = (BaseDllDirectory.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
962 }
963
965 return Length;
966}
967
968/*
969 * @implemented
970 */
971DWORD
972WINAPI
975{
977 ANSI_STRING AnsiDllDirectory;
979
980 RtlInitEmptyAnsiString(&AnsiDllDirectory, lpBuffer, (USHORT)nBufferLength);
981
983
985 if (Length > nBufferLength)
986 {
989 }
990 else
991 {
992 --Length;
993 Status = BasepUnicodeStringTo8BitString(&AnsiDllDirectory,
995 FALSE);
996 }
997
999
1000 if (!NT_SUCCESS(Status))
1001 {
1003 Length = 0;
1004 if (lpBuffer) *lpBuffer = ANSI_NULL;
1005 }
1006
1007 return Length;
1008}
1009
1010/*
1011 * @implemented
1012 */
1013BOOL
1014WINAPI
1016{
1017 if (wcschr(ExeName, L'\\')) return TRUE;
1018
1020}
1021
1022/*
1023 * @implemented
1024 */
1025BOOL
1026WINAPI
1028{
1029 if (strchr(ExeName, '\\')) return TRUE;
1030
1032}
1033
1034/*
1035 * @implemented
1036 *
1037 * NOTE: Many of these A functions may seem to do rather complex A<->W mapping
1038 * beyond what you would usually expect. There are two main reasons:
1039 *
1040 * First, these APIs are subject to the ANSI/OEM File API selection status that
1041 * the caller has chosen, so we must use the "8BitString" internal Base APIs.
1042 *
1043 * Secondly, the Wide APIs (coming from the 9x world) are coded to return the
1044 * length of the paths in "ANSI" by dividing their internal Wide character count
1045 * by two... this is usually correct when dealing with pure-ASCII codepages but
1046 * not necessarily when dealing with MBCS pre-Unicode sets, which NT supports
1047 * for CJK, for example.
1048 */
1049DWORD
1050WINAPI
1055{
1057 PWCHAR Buffer = NULL;
1058 ULONG PathSize, FilePartSize;
1060 UNICODE_STRING FileNameString, UniString;
1061 PWCHAR LocalFilePart;
1062 PWCHAR* FilePart;
1063
1064 /* If the caller wants filepart, use a local wide buffer since this is A */
1065 FilePart = lpFilePart != NULL ? &LocalFilePart : NULL;
1066
1067 /* Initialize for Quickie */
1068 FilePartSize = PathSize = 0;
1069 FileNameString.Buffer = NULL;
1070
1071 /* First get our string in Unicode */
1073 if (!NT_SUCCESS(Status)) goto Quickie;
1074
1075 /* Allocate a buffer to hold teh path name */
1076 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
1077 0,
1078 MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1079 if (!Buffer)
1080 {
1082 goto Quickie;
1083 }
1084
1085 /* Call into RTL to get the full Unicode path name */
1086 PathSize = RtlGetFullPathName_U(FileNameString.Buffer,
1087 MAX_PATH * sizeof(WCHAR),
1088 Buffer,
1089 FilePart);
1090 if (PathSize <= (MAX_PATH * sizeof(WCHAR)))
1091 {
1092 /* The buffer will fit, get the real ANSI string size now */
1093 Status = RtlUnicodeToMultiByteSize(&PathSize, Buffer, PathSize);
1094 if (NT_SUCCESS(Status))
1095 {
1096 /* Now check if the user wanted file part size as well */
1097 if ((PathSize) && (lpFilePart) && (LocalFilePart))
1098 {
1099 /* Yep, so in this case get the length of the file part too */
1100 Status = RtlUnicodeToMultiByteSize(&FilePartSize,
1101 Buffer,
1102 (ULONG)(LocalFilePart - Buffer) *
1103 sizeof(WCHAR));
1104 if (!NT_SUCCESS(Status))
1105 {
1106 /* We failed to do that, so fail the whole call */
1108 PathSize = 0;
1109 }
1110 }
1111 }
1112 }
1113 else
1114 {
1115 /* Reset the path size since the buffer is not large enough */
1116 PathSize = 0;
1117 }
1118
1119 /* Either no path, or local buffer was too small, enter failure code */
1120 if (!PathSize) goto Quickie;
1121
1122 /* If the *caller's* buffer was too small, fail, but add in space for NULL */
1123 if (PathSize >= nBufferLength)
1124 {
1125 PathSize++;
1126 goto Quickie;
1127 }
1128
1129 /* So far so good, initialize a unicode string to convert back to ANSI/OEM */
1130 RtlInitUnicodeString(&UniString, Buffer);
1132 if (!NT_SUCCESS(Status))
1133 {
1134 /* Final conversion failed, fail the call */
1136 PathSize = 0;
1137 }
1138 else
1139 {
1140 /* Conversion worked, now copy the ANSI/OEM buffer into the buffer */
1141 RtlCopyMemory(lpBuffer, AnsiString.Buffer, PathSize + 1);
1143
1144 /* And finally, did the caller request file part information? */
1145 if (lpFilePart)
1146 {
1147 /* Use the size we computed earlier and add it to the buffer */
1148 *lpFilePart = LocalFilePart ? &lpBuffer[FilePartSize] : 0;
1149 }
1150 }
1151
1152Quickie:
1153 /* Cleanup and return the path size */
1154 if (FileNameString.Buffer) RtlFreeUnicodeString(&FileNameString);
1155 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1156 return PathSize;
1157}
1158
1159/*
1160 * @implemented
1161 */
1162DWORD
1163WINAPI
1168{
1169 /* Call Rtl to do the work */
1171 nBufferLength * sizeof(WCHAR),
1172 lpBuffer,
1173 lpFilePart) / sizeof(WCHAR);
1174}
1175
1176/*
1177 * @implemented
1178 */
1179BOOL
1180WINAPI
1183{
1184 LONG OldFlags, CurrentFlags;
1185
1186 switch (dwFlags)
1187 {
1188 /* There are only 3 valid parameters */
1193 do
1194 {
1195 if ((CurrentFlags & BASE_SEARCH_PATH_PERMANENT) &&
1196 dwFlags != CurrentFlags)
1197 {
1198 /* Return with ERROR_ACCESS_DENIED if permanent flag is set */
1200 return FALSE;
1201 }
1202
1203 OldFlags = CurrentFlags;
1205 (LONG)dwFlags,
1206 OldFlags);
1207 } while (CurrentFlags != OldFlags);
1208
1209 return TRUE;
1210
1211 default:
1213 return FALSE;
1214 }
1215}
1216
1217/*
1218 * @implemented
1219 */
1220DWORD
1221WINAPI
1228{
1229 PUNICODE_STRING FileNameString;
1230 UNICODE_STRING PathString, ExtensionString;
1232 ULONG PathSize, FilePartSize, AnsiLength;
1233 PWCHAR LocalFilePart, Buffer;
1234 PWCHAR* FilePart;
1235
1236 /* If the caller wants filepart, use a local wide buffer since this is A */
1237 FilePart = lpFilePart != NULL ? &LocalFilePart : NULL;
1238
1239 /* Initialize stuff for Quickie */
1240 PathSize = 0;
1241 Buffer = NULL;
1242 ExtensionString.Buffer = PathString.Buffer = NULL;
1243
1244 /* Get the UNICODE_STRING file name */
1246 if (!FileNameString) return 0;
1247
1248 /* Did the caller specify an extension */
1249 if (lpExtension)
1250 {
1251 /* Yup, convert it into UNICODE_STRING */
1253 lpExtension);
1254 if (!NT_SUCCESS(Status)) goto Quickie;
1255 }
1256
1257 /* Did the caller specify a path */
1258 if (lpPath)
1259 {
1260 /* Yup, convert it into UNICODE_STRING */
1261 Status = Basep8BitStringToDynamicUnicodeString(&PathString, lpPath);
1262 if (!NT_SUCCESS(Status)) goto Quickie;
1263 }
1264
1265 /* Allocate our output buffer */
1266 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nBufferLength * sizeof(WCHAR));
1267 if (!Buffer)
1268 {
1269 /* It failed, bail out */
1271 goto Quickie;
1272 }
1273
1274 /* Now run the Wide search with the input buffer lengths */
1275 PathSize = SearchPathW(PathString.Buffer,
1276 FileNameString->Buffer,
1277 ExtensionString.Buffer,
1279 Buffer,
1280 FilePart);
1281 if (PathSize <= nBufferLength)
1282 {
1283 /* It fits, but is it empty? If so, bail out */
1284 if (!PathSize) goto Quickie;
1285
1286 /* The length above is inexact, we need it in ANSI */
1287 Status = RtlUnicodeToMultiByteSize(&AnsiLength, Buffer, PathSize * sizeof(WCHAR));
1288 if (!NT_SUCCESS(Status))
1289 {
1290 /* Conversion failed, fail the call */
1291 PathSize = 0;
1293 goto Quickie;
1294 }
1295
1296 /* If the correct ANSI size is too big, return required length plus a NULL */
1297 if (AnsiLength >= nBufferLength)
1298 {
1299 PathSize = AnsiLength + 1;
1300 goto Quickie;
1301 }
1302
1303 /* Now apply the final conversion to ANSI */
1305 nBufferLength - 1,
1306 &AnsiLength,
1307 Buffer,
1308 PathSize * sizeof(WCHAR));
1309 if (!NT_SUCCESS(Status))
1310 {
1311 /* Conversion failed, fail the whole call */
1312 PathSize = 0;
1314 goto Quickie;
1315 }
1316
1317 /* NULL-terminate and return the real ANSI length */
1318 lpBuffer[AnsiLength] = ANSI_NULL;
1319 PathSize = AnsiLength;
1320
1321 /* Now check if the user wanted file part size as well */
1322 if (lpFilePart)
1323 {
1324 /* If we didn't get a file part, clear the caller's */
1325 if (!LocalFilePart)
1326 {
1327 *lpFilePart = NULL;
1328 }
1329 else
1330 {
1331 /* Yep, so in this case get the length of the file part too */
1332 Status = RtlUnicodeToMultiByteSize(&FilePartSize,
1333 Buffer,
1334 (ULONG)(LocalFilePart - Buffer) *
1335 sizeof(WCHAR));
1336 if (!NT_SUCCESS(Status))
1337 {
1338 /* We failed to do that, so fail the whole call */
1340 PathSize = 0;
1341 }
1342
1343 /* Return the file part buffer */
1344 *lpFilePart = lpBuffer + FilePartSize;
1345 }
1346 }
1347 }
1348 else
1349 {
1350 /* Our initial buffer guess was too small, allocate a bigger one */
1351 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1352 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize * sizeof(WCHAR));
1353 if (!Buffer)
1354 {
1355 /* Out of memory, fail everything */
1357 goto Quickie;
1358 }
1359
1360 /* Do the search again -- it will fail, we just want the path size */
1361 PathSize = SearchPathW(PathString.Buffer,
1362 FileNameString->Buffer,
1363 ExtensionString.Buffer,
1364 PathSize,
1365 Buffer,
1366 FilePart);
1367 if (!PathSize) goto Quickie;
1368
1369 /* Convert it to a correct size */
1370 Status = RtlUnicodeToMultiByteSize(&PathSize, Buffer, PathSize * sizeof(WCHAR));
1371 if (NT_SUCCESS(Status))
1372 {
1373 /* Make space for the NULL-char */
1374 PathSize++;
1375 }
1376 else
1377 {
1378 /* Conversion failed for some reason, fail the call */
1380 PathSize = 0;
1381 }
1382 }
1383
1384Quickie:
1385 /* Cleanup/complete path */
1386 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1387 if (ExtensionString.Buffer) RtlFreeUnicodeString(&ExtensionString);
1388 if (PathString.Buffer) RtlFreeUnicodeString(&PathString);
1389 return PathSize;
1390}
1391
1392/*
1393 * @implemented
1394 */
1395DWORD
1396WINAPI
1403{
1404 UNICODE_STRING FileNameString, ExtensionString, PathString, CallerBuffer;
1405 ULONG Flags;
1406 SIZE_T LengthNeeded, FilePartSize;
1408 DWORD Result = 0;
1409
1410 /* Default flags for RtlDosSearchPath_Ustr */
1411 Flags = 6;
1412
1413 /* Clear file part in case we fail */
1414 if (lpFilePart) *lpFilePart = NULL;
1415
1416 /* Initialize path buffer for free later */
1417 PathString.Buffer = NULL;
1418
1419 /* Convert filename to a unicode string and eliminate trailing spaces */
1420 RtlInitUnicodeString(&FileNameString, lpFileName);
1421 while ((FileNameString.Length >= sizeof(WCHAR)) &&
1422 (FileNameString.Buffer[(FileNameString.Length / sizeof(WCHAR)) - 1] == L' '))
1423 {
1424 FileNameString.Length -= sizeof(WCHAR);
1425 }
1426
1427 /* Was it all just spaces? */
1428 if (!FileNameString.Length)
1429 {
1430 /* Fail out */
1432 goto Quickie;
1433 }
1434
1435 /* Convert extension to a unicode string */
1436 RtlInitUnicodeString(&ExtensionString, lpExtension);
1437
1438 /* Check if the user sent a path */
1439 if (lpPath)
1440 {
1441 /* Convert it to a unicode string too */
1442 Status = RtlInitUnicodeStringEx(&PathString, lpPath);
1443 if (NT_ERROR(Status))
1444 {
1445 /* Fail if it was too long */
1447 goto Quickie;
1448 }
1449 }
1450 else
1451 {
1452 /* A path wasn't sent, so compute it ourselves */
1453 PathString.Buffer = BaseComputeProcessSearchPath();
1454 if (!PathString.Buffer)
1455 {
1456 /* Fail if we couldn't compute it */
1458 goto Quickie;
1459 }
1460
1461 /* See how big the computed path is */
1462 LengthNeeded = lstrlenW(PathString.Buffer);
1464 {
1465 /* Fail if it's too long */
1467 goto Quickie;
1468 }
1469
1470 /* Set the path size now that we have it */
1471 PathString.MaximumLength = PathString.Length = (USHORT)LengthNeeded * sizeof(WCHAR);
1472
1473 /* Request SxS isolation from RtlDosSearchPath_Ustr */
1474 Flags |= 1;
1475 }
1476
1477 /* Create the string that describes the output buffer from the caller */
1478 CallerBuffer.Length = 0;
1479 CallerBuffer.Buffer = lpBuffer;
1480
1481 /* How much space does the caller have? */
1483 {
1484 /* Add it into the string */
1485 CallerBuffer.MaximumLength = (USHORT)nBufferLength * sizeof(WCHAR);
1486 }
1487 else
1488 {
1489 /* Caller wants too much, limit it to the maximum length of a string */
1491 }
1492
1493 /* Call Rtl to do the work */
1495 &PathString,
1496 &FileNameString,
1497 &ExtensionString,
1498 &CallerBuffer,
1499 NULL,
1500 NULL,
1501 &FilePartSize,
1502 &LengthNeeded);
1503 if (NT_ERROR(Status))
1504 {
1505 /* Check for unusual status codes */
1507 {
1508 /* Print them out since maybe an app needs fixing */
1509 DbgPrint("%s on file %wZ failed; NTSTATUS = %08lx\n",
1511 &FileNameString,
1512 Status);
1513 DbgPrint(" Path = %wZ\n", &PathString);
1514 }
1515
1516 /* Check if the failure was due to a small buffer */
1518 {
1519 /* Check if the length was actually too big for Rtl to work with */
1520 Result = LengthNeeded / sizeof(WCHAR);
1522 }
1523 else
1524 {
1525 /* Some other error, set the error code */
1527 }
1528 }
1529 else
1530 {
1531 /* It worked! Write the file part now */
1532 if (lpFilePart) *lpFilePart = &lpBuffer[FilePartSize];
1533
1534 /* Convert the final result length */
1535 Result = CallerBuffer.Length / sizeof(WCHAR);
1536 }
1537
1538Quickie:
1539 /* Check if there was a dynamic path string to free */
1540 if ((PathString.Buffer != lpPath) && (PathString.Buffer))
1541 {
1542 /* And free it */
1543 RtlFreeHeap(RtlGetProcessHeap(), 0, PathString.Buffer);
1544 }
1545
1546 /* Return the final result length */
1547 return Result;
1548}
1549
1550/*
1551 * @implemented
1552 */
1553DWORD
1554WINAPI
1556 OUT LPWSTR lpszLongPath,
1558{
1559 PWCHAR Path, Original, First, Last, Buffer, Src, Dst;
1561 WCHAR LastChar;
1562 HANDLE FindHandle;
1563 ULONG ErrorMode;
1565 WIN32_FIND_DATAW FindFileData;
1566
1567 /* Initialize so Quickie knows there's nothing to do */
1568 Buffer = Original = NULL;
1569 ReturnLength = 0;
1570
1571 /* First check if the input path was obviously NULL */
1572 if (!lpszShortPath)
1573 {
1574 /* Fail the request */
1576 return 0;
1577 }
1578
1579 /* We will be touching removed, removable drives -- don't warn the user */
1581
1582 /* Do a simple check to see if the path exists */
1583 if (GetFileAttributesW(lpszShortPath) == INVALID_FILE_ATTRIBUTES)
1584 {
1585 /* It doesn't, so fail */
1586 ReturnLength = 0;
1587 goto Quickie;
1588 }
1589
1590 /* Now get a pointer to the actual path, skipping indicators */
1591 Path = SkipPathTypeIndicator_U((LPWSTR)lpszShortPath);
1592
1593 /* Is there any path or filename in there? */
1594 if (!(Path) ||
1595 (*Path == UNICODE_NULL) ||
1596 !(FindLFNorSFN_U(Path, &First, &Last, FALSE)))
1597 {
1598 /* There isn't, so the long path is simply the short path */
1599 ReturnLength = wcslen(lpszShortPath);
1600
1601 /* Is there space for it? */
1602 if ((cchBuffer > ReturnLength) && (lpszLongPath))
1603 {
1604 /* Make sure the pointers aren't already the same */
1605 if (lpszLongPath != lpszShortPath)
1606 {
1607 /* They're not -- copy the short path into the long path */
1608 RtlMoveMemory(lpszLongPath,
1609 lpszShortPath,
1610 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1611 }
1612 }
1613 else
1614 {
1615 /* Otherwise, let caller know we need a bigger buffer, include NULL */
1616 ReturnLength++;
1617 }
1618 goto Quickie;
1619 }
1620
1621 /* We are still in the game -- compute the current size */
1622 Length = wcslen(lpszShortPath) + sizeof(ANSI_NULL);
1623 Original = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1624 if (!Original) goto ErrorQuickie;
1625
1626 /* Make a copy of it */
1627 RtlMoveMemory(Original, lpszShortPath, Length * sizeof(WCHAR));
1628
1629 /* Compute the new first and last markers */
1630 First = &Original[First - lpszShortPath];
1631 Last = &Original[Last - lpszShortPath];
1632
1633 /* Set the current destination pointer for a copy */
1634 Dst = lpszLongPath;
1635
1636 /*
1637 * Windows allows the paths to overlap -- we have to be careful with this and
1638 * see if it's same to do so, and if not, allocate our own internal buffer
1639 * that we'll return at the end.
1640 *
1641 * This is also why we use RtlMoveMemory everywhere. Don't use RtlCopyMemory!
1642 */
1643 if ((cchBuffer) && (lpszLongPath) &&
1644 (((lpszLongPath >= lpszShortPath) && (lpszLongPath < &lpszShortPath[Length])) ||
1645 ((lpszLongPath < lpszShortPath) && (&lpszLongPath[cchBuffer] >= lpszShortPath))))
1646 {
1647 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchBuffer * sizeof(WCHAR));
1648 if (!Buffer) goto ErrorQuickie;
1649
1650 /* New destination */
1651 Dst = Buffer;
1652 }
1653
1654 /* Prepare for the loop */
1655 Src = Original;
1656 ReturnLength = 0;
1657 while (TRUE)
1658 {
1659 /* Current delta in the loop */
1660 Length = First - Src;
1661
1662 /* Update the return length by it */
1664
1665 /* Is there a delta? If so, is there space and buffer for it? */
1666 if ((Length) && (cchBuffer > ReturnLength) && (lpszLongPath))
1667 {
1668 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR));
1669 Dst += Length;
1670 }
1671
1672 /* "Terminate" this portion of the path's substring so we can do a find */
1673 LastChar = *Last;
1674 *Last = UNICODE_NULL;
1675 FindHandle = FindFirstFileW(Original, &FindFileData);
1676 *Last = LastChar;
1677
1678 /* This portion wasn't found, so fail */
1679 if (FindHandle == INVALID_HANDLE_VALUE)
1680 {
1681 ReturnLength = 0;
1682 break;
1683 }
1684
1685 /* Close the find handle */
1686 FindClose(FindHandle);
1687
1688 /* Now check the length of the long name */
1689 Length = wcslen(FindFileData.cFileName);
1690 if (Length)
1691 {
1692 /* This is our new first marker */
1693 First = FindFileData.cFileName;
1694 }
1695 else
1696 {
1697 /* Otherwise, the name is the delta between our current markers */
1698 Length = Last - First;
1699 }
1700
1701 /* Update the return length with the short name length, if any */
1703
1704 /* Once again check for appropriate space and buffer */
1705 if ((cchBuffer > ReturnLength) && (lpszLongPath))
1706 {
1707 /* And do the copy if there is */
1708 RtlMoveMemory(Dst, First, Length * sizeof(WCHAR));
1709 Dst += Length;
1710 }
1711
1712 /* Now update the source pointer */
1713 Src = Last;
1714 if (*Src == UNICODE_NULL) break;
1715
1716 /* Are there more names in there? */
1717 Found = FindLFNorSFN_U(Src, &First, &Last, FALSE);
1718 if (!Found) break;
1719 }
1720
1721 /* The loop is done, is there anything left? */
1722 if (ReturnLength)
1723 {
1724 /* Get the length of the straggling path */
1725 Length = wcslen(Src);
1727
1728 /* Once again check for appropriate space and buffer */
1729 if ((cchBuffer > ReturnLength) && (lpszLongPath))
1730 {
1731 /* And do the copy if there is -- accounting for NULL here */
1732 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1733
1734 /* What about our buffer? */
1735 if (Buffer)
1736 {
1737 /* Copy it into the caller's long path */
1738 RtlMoveMemory(lpszLongPath,
1739 Buffer,
1740 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1741 }
1742 }
1743 else
1744 {
1745 /* Buffer is too small, let the caller know, making space for NULL */
1746 ReturnLength++;
1747 }
1748 }
1749
1750 /* We're all done */
1751 goto Quickie;
1752
1753ErrorQuickie:
1754 /* This is the goto for memory failures */
1756
1757Quickie:
1758 /* General function end: free memory, restore error mode, return length */
1759 if (Original) RtlFreeHeap(RtlGetProcessHeap(), 0, Original);
1760 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1761 SetErrorMode(ErrorMode);
1762 return ReturnLength;
1763}
1764
1765/*
1766 * @implemented
1767 */
1768DWORD
1769WINAPI
1771 OUT LPSTR lpszLongPath,
1773{
1775 PWCHAR LongPath;
1777 UNICODE_STRING LongPathUni, ShortPathUni;
1778 ANSI_STRING LongPathAnsi;
1779 WCHAR LongPathBuffer[MAX_PATH];
1780
1781 LongPath = NULL;
1782 LongPathAnsi.Buffer = NULL;
1783 ShortPathUni.Buffer = NULL;
1784 Result = 0;
1785
1786 if (!lpszShortPath)
1787 {
1789 return 0;
1790 }
1791
1792 Status = Basep8BitStringToDynamicUnicodeString(&ShortPathUni, lpszShortPath);
1793 if (!NT_SUCCESS(Status)) goto Quickie;
1794
1795 LongPath = LongPathBuffer;
1796
1797 PathLength = GetLongPathNameW(ShortPathUni.Buffer, LongPathBuffer, MAX_PATH);
1798 if (PathLength >= MAX_PATH)
1799 {
1800 LongPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLength * sizeof(WCHAR));
1801 if (!LongPath)
1802 {
1803 PathLength = 0;
1805 }
1806 else
1807 {
1808 PathLength = GetLongPathNameW(ShortPathUni.Buffer, LongPath, PathLength);
1809 }
1810 }
1811
1812 if (!PathLength) goto Quickie;
1813
1814 ShortPathUni.MaximumLength = (USHORT)PathLength * sizeof(WCHAR) + sizeof(UNICODE_NULL);
1815 LongPathUni.Buffer = LongPath;
1816 LongPathUni.Length = (USHORT)PathLength * sizeof(WCHAR);
1817
1818 Status = BasepUnicodeStringTo8BitString(&LongPathAnsi, &LongPathUni, TRUE);
1819 if (!NT_SUCCESS(Status))
1820 {
1822 Result = 0;
1823 }
1824
1825 Result = LongPathAnsi.Length;
1826 if ((lpszLongPath) && (cchBuffer > LongPathAnsi.Length))
1827 {
1828 RtlMoveMemory(lpszLongPath, LongPathAnsi.Buffer, LongPathAnsi.Length);
1829 lpszLongPath[Result] = ANSI_NULL;
1830 }
1831 else
1832 {
1833 Result = LongPathAnsi.Length + sizeof(ANSI_NULL);
1834 }
1835
1836Quickie:
1837 if (ShortPathUni.Buffer) RtlFreeUnicodeString(&ShortPathUni);
1838 if (LongPathAnsi.Buffer) RtlFreeAnsiString(&LongPathAnsi);
1839 if ((LongPath) && (LongPath != LongPathBuffer))
1840 {
1841 RtlFreeHeap(RtlGetProcessHeap(), 0, LongPath);
1842 }
1843 return Result;
1844}
1845
1846/*
1847 * @implemented
1848 */
1849DWORD
1850WINAPI
1852 OUT LPWSTR lpszShortPath,
1854{
1855 PWCHAR Path, Original, First, Last, Buffer, Src, Dst;
1857 WCHAR LastChar;
1858 HANDLE FindHandle;
1859 ULONG ErrorMode;
1861 WIN32_FIND_DATAW FindFileData;
1862
1863 /* Initialize so Quickie knows there's nothing to do */
1864 Buffer = Original = NULL;
1865 ReturnLength = 0;
1866
1867 /* First check if the input path was obviously NULL */
1868 if (!lpszLongPath)
1869 {
1870 /* Fail the request */
1872 return 0;
1873 }
1874
1875 /* We will be touching removed, removable drives -- don't warn the user */
1877
1878 /* Do a simple check to see if the path exists */
1879 if (GetFileAttributesW(lpszLongPath) == INVALID_FILE_ATTRIBUTES)
1880 {
1881 /* Windows checks for an application compatibility flag to allow this */
1882 if (!(NtCurrentPeb()) || !(NtCurrentPeb()->AppCompatFlags.LowPart & GetShortPathNameNT4))
1883 {
1884 /* It doesn't, so fail */
1885 ReturnLength = 0;
1886 goto Quickie;
1887 }
1888 }
1889
1890 /* Now get a pointer to the actual path, skipping indicators */
1891 Path = SkipPathTypeIndicator_U((LPWSTR)lpszLongPath);
1892
1893 /* Is there any path or filename in there? */
1894 if (!(Path) ||
1895 (*Path == UNICODE_NULL) ||
1896 !(FindLFNorSFN_U(Path, &First, &Last, TRUE)))
1897 {
1898 /* There isn't, so the long path is simply the short path */
1899 ReturnLength = wcslen(lpszLongPath);
1900
1901 /* Is there space for it? */
1902 if ((cchBuffer > ReturnLength) && (lpszShortPath))
1903 {
1904 /* Make sure the pointers aren't already the same */
1905 if (lpszLongPath != lpszShortPath)
1906 {
1907 /* They're not -- copy the short path into the long path */
1908 RtlMoveMemory(lpszShortPath,
1909 lpszLongPath,
1910 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1911 }
1912 }
1913 else
1914 {
1915 /* Otherwise, let caller know we need a bigger buffer, include NULL */
1916 ReturnLength++;
1917 }
1918 goto Quickie;
1919 }
1920
1921 /* We are still in the game -- compute the current size */
1922 Length = wcslen(lpszLongPath) + sizeof(ANSI_NULL);
1923 Original = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1924 if (!Original) goto ErrorQuickie;
1925
1926 /* Make a copy of it */
1927 wcsncpy(Original, lpszLongPath, Length);
1928
1929 /* Compute the new first and last markers */
1930 First = &Original[First - lpszLongPath];
1931 Last = &Original[Last - lpszLongPath];
1932
1933 /* Set the current destination pointer for a copy */
1934 Dst = lpszShortPath;
1935
1936 /*
1937 * Windows allows the paths to overlap -- we have to be careful with this and
1938 * see if it's same to do so, and if not, allocate our own internal buffer
1939 * that we'll return at the end.
1940 *
1941 * This is also why we use RtlMoveMemory everywhere. Don't use RtlCopyMemory!
1942 */
1943 if ((cchBuffer) && (lpszShortPath) &&
1944 (((lpszShortPath >= lpszLongPath) && (lpszShortPath < &lpszLongPath[Length])) ||
1945 ((lpszShortPath < lpszLongPath) && (&lpszShortPath[cchBuffer] >= lpszLongPath))))
1946 {
1947 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchBuffer * sizeof(WCHAR));
1948 if (!Buffer) goto ErrorQuickie;
1949
1950 /* New destination */
1951 Dst = Buffer;
1952 }
1953
1954 /* Prepare for the loop */
1955 Src = Original;
1956 ReturnLength = 0;
1957 while (TRUE)
1958 {
1959 /* Current delta in the loop */
1960 Length = First - Src;
1961
1962 /* Update the return length by it */
1964
1965 /* Is there a delta? If so, is there space and buffer for it? */
1966 if ((Length) && (cchBuffer > ReturnLength) && (lpszShortPath))
1967 {
1968 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR));
1969 Dst += Length;
1970 }
1971
1972 /* "Terminate" this portion of the path's substring so we can do a find */
1973 LastChar = *Last;
1974 *Last = UNICODE_NULL;
1975 FindHandle = FindFirstFileW(Original, &FindFileData);
1976 *Last = LastChar;
1977
1978 /* This portion wasn't found, so fail */
1979 if (FindHandle == INVALID_HANDLE_VALUE)
1980 {
1981 ReturnLength = 0;
1982 break;
1983 }
1984
1985 /* Close the find handle */
1986 FindClose(FindHandle);
1987
1988 /* Now check the length of the short name */
1989 Length = wcslen(FindFileData.cAlternateFileName);
1990 if (Length)
1991 {
1992 /* This is our new first marker */
1993 First = FindFileData.cAlternateFileName;
1994 }
1995 else
1996 {
1997 /* Otherwise, the name is the delta between our current markers */
1998 Length = Last - First;
1999 }
2000
2001 /* Update the return length with the short name length, if any */
2003
2004 /* Once again check for appropriate space and buffer */
2005 if ((cchBuffer > ReturnLength) && (lpszShortPath))
2006 {
2007 /* And do the copy if there is */
2008 RtlMoveMemory(Dst, First, Length * sizeof(WCHAR));
2009 Dst += Length;
2010 }
2011
2012 /* Now update the source pointer */
2013 Src = Last;
2014 if (*Src == UNICODE_NULL) break;
2015
2016 /* Are there more names in there? */
2017 Found = FindLFNorSFN_U(Src, &First, &Last, TRUE);
2018 if (!Found) break;
2019 }
2020
2021 /* The loop is done, is there anything left? */
2022 if (ReturnLength)
2023 {
2024 /* Get the length of the straggling path */
2025 Length = wcslen(Src);
2027
2028 /* Once again check for appropriate space and buffer */
2029 if ((cchBuffer > ReturnLength) && (lpszShortPath))
2030 {
2031 /* And do the copy if there is -- accounting for NULL here */
2032 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR) + sizeof(UNICODE_NULL));
2033
2034 /* What about our buffer? */
2035 if (Buffer)
2036 {
2037 /* Copy it into the caller's long path */
2038 RtlMoveMemory(lpszShortPath,
2039 Buffer,
2040 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
2041 }
2042 }
2043 else
2044 {
2045 /* Buffer is too small, let the caller know, making space for NULL */
2046 ReturnLength++;
2047 }
2048 }
2049
2050 /* We're all done */
2051 goto Quickie;
2052
2053ErrorQuickie:
2054 /* This is the goto for memory failures */
2056
2057Quickie:
2058 /* General function end: free memory, restore error mode, return length */
2059 if (Original) RtlFreeHeap(RtlGetProcessHeap(), 0, Original);
2060 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
2061 SetErrorMode(ErrorMode);
2062 return ReturnLength;
2063}
2064
2065/*
2066 * @implemented
2067 *
2068 * NOTE: Windows returns a dos/short (8.3) path
2069 */
2070DWORD
2071WINAPI
2074{
2075 WCHAR BufferW[MAX_PATH];
2076 DWORD ret;
2077
2078 ret = GetTempPathW(MAX_PATH, BufferW);
2079
2080 if (!ret) return 0;
2081
2082 if (ret > MAX_PATH)
2083 {
2085 return 0;
2086 }
2087
2088 return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
2089}
2090
2091/*
2092 * @implemented
2093 *
2094 * ripped from wine
2095 */
2096DWORD
2097WINAPI
2099 OUT LPWSTR path)
2100{
2101 static const WCHAR tmp[] = { 'T', 'M', 'P', 0 };
2102 static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 };
2103 static const WCHAR userprofile[] = { 'U','S','E','R','P','R','O','F','I','L','E',0 };
2104 WCHAR tmp_path[MAX_PATH];
2105 WCHAR full_tmp_path[MAX_PATH];
2106 UINT ret;
2107
2108 DPRINT("%u,%p\n", count, path);
2109
2110 if (!(ret = GetEnvironmentVariableW( tmp, tmp_path, MAX_PATH )) &&
2111 !(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )) &&
2112 !(ret = GetEnvironmentVariableW( userprofile, tmp_path, MAX_PATH )) &&
2113 !(ret = GetWindowsDirectoryW( tmp_path, MAX_PATH )))
2114 {
2115 return 0;
2116 }
2117
2118 if (ret > MAX_PATH)
2119 {
2121 return 0;
2122 }
2123
2124 ret = GetFullPathNameW(tmp_path, MAX_PATH, full_tmp_path, NULL);
2125 if (!ret) return 0;
2126
2127 if (ret > MAX_PATH - 2)
2128 {
2130 return 0;
2131 }
2132
2133 if (full_tmp_path[ret-1] != '\\')
2134 {
2135 full_tmp_path[ret++] = '\\';
2136 full_tmp_path[ret] = '\0';
2137 }
2138
2139 ret++; /* add space for terminating 0 */
2140
2141 if (count >= ret)
2142 {
2143 lstrcpynW(path, full_tmp_path, count);
2144 /* the remaining buffer must be zeroed up to 32766 bytes in XP or 32767
2145 * bytes after it, we will assume the > XP behavior for now */
2146 memset(path + ret, 0, (min(count, 32767) - ret) * sizeof(WCHAR));
2147 ret--; /* return length without 0 */
2148 }
2149 else if (count)
2150 {
2151 /* the buffer must be cleared if contents will not fit */
2152 memset(path, 0, count * sizeof(WCHAR));
2153 }
2154
2155 DPRINT("GetTempPathW returning %u, %S\n", ret, path);
2156 return ret;
2157}
2158
2159/*
2160 * @implemented
2161 */
2162DWORD
2163WINAPI
2166{
2170 ULONG MaxLength;
2171
2172 StaticString = &NtCurrentTeb()->StaticUnicodeString;
2173
2174 MaxLength = nBufferLength;
2176 {
2177 MaxLength = UNICODE_STRING_MAX_BYTES - 1;
2178 }
2179
2185 if (!NT_SUCCESS(Status))
2186 {
2188 return 0;
2189 }
2190
2191 if (MaxLength <= nBufferLength)
2192 {
2193 return nBufferLength + 1;
2194 }
2195
2196 AnsiString.Buffer = lpBuffer;
2197 AnsiString.MaximumLength = (USHORT)MaxLength;
2199 if (!NT_SUCCESS(Status))
2200 {
2202 return 0;
2203 }
2204
2205 return AnsiString.Length;
2206}
2207
2208/*
2209 * @implemented
2210 */
2211DWORD
2212WINAPI
2215{
2216 return RtlGetCurrentDirectory_U(nBufferLength * sizeof(WCHAR), lpBuffer) / sizeof(WCHAR);
2217}
2218
2219/*
2220 * @implemented
2221 */
2222BOOL
2223WINAPI
2225{
2228
2229 if (!lpPathName)
2230 {
2232 return FALSE;
2233 }
2234
2236 if (!DirName) return FALSE;
2237
2238 if (CheckForSameCurdir(DirName)) return TRUE;
2239
2241 if (NT_SUCCESS(Status)) return TRUE;
2242
2243 if ((*DirName->Buffer != L'"') || (DirName->Length <= 2))
2244 {
2246 return 0;
2247 }
2248
2250 if (!DirName) return FALSE;
2251
2253 if (!NT_SUCCESS(Status))
2254 {
2256 return FALSE;
2257 }
2258
2259 return TRUE;
2260}
2261
2262/*
2263 * @implemented
2264 */
2265BOOL
2266WINAPI
2268{
2271
2272 if (!lpPathName)
2273 {
2275 return FALSE;
2276 }
2277
2279 if (NT_SUCCESS(Status))
2280 {
2282 {
2284 }
2285 }
2286
2287 if (!NT_SUCCESS(Status))
2288 {
2290 return FALSE;
2291 }
2292
2293 return TRUE;
2294}
2295
2296/*
2297 * @implemented
2298 */
2299UINT
2300WINAPI
2302 IN UINT uSize)
2303{
2306 ULONG AnsiLength;
2307
2308 /* Get the correct size of the Unicode Base directory */
2309 Status = RtlUnicodeToMultiByteSize(&AnsiLength,
2312 if (!NT_SUCCESS(Status)) return 0;
2313
2314 if (uSize < AnsiLength) return AnsiLength;
2315
2316 RtlInitEmptyAnsiString(&AnsiString, lpBuffer, uSize);
2317
2320 FALSE);
2321 if (!NT_SUCCESS(Status)) return 0;
2322
2323 return AnsiString.Length;
2324}
2325
2326/*
2327 * @implemented
2328 */
2329UINT
2330WINAPI
2332 IN UINT uSize)
2333{
2335
2337 if ((uSize * sizeof(WCHAR)) >= ReturnLength)
2338 {
2343
2345 }
2346
2347 return ReturnLength / sizeof(WCHAR);
2348}
2349
2350/*
2351 * @implemented
2352 */
2353UINT
2354WINAPI
2356 IN UINT uSize)
2357{
2358 /* Is this a TS installation? */
2360
2361 /* Otherwise, call the System API */
2362 return GetSystemWindowsDirectoryA(lpBuffer, uSize);
2363}
2364
2365/*
2366 * @implemented
2367 */
2368UINT
2369WINAPI
2371 IN UINT uSize)
2372{
2373 /* Is this a TS installation? */
2375
2376 /* Otherwise, call the System API */
2377 return GetSystemWindowsDirectoryW(lpBuffer, uSize);
2378}
2379
2380/*
2381 * @implemented
2382 */
2383UINT
2384WINAPI
2386 IN UINT uSize)
2387{
2390 ULONG AnsiLength;
2391
2392 /* Get the correct size of the Unicode Base directory */
2393 Status = RtlUnicodeToMultiByteSize(&AnsiLength,
2396 if (!NT_SUCCESS(Status)) return 0;
2397
2398 if (uSize < AnsiLength) return AnsiLength;
2399
2400 RtlInitEmptyAnsiString(&AnsiString, lpBuffer, uSize);
2401
2404 FALSE);
2405 if (!NT_SUCCESS(Status)) return 0;
2406
2407 return AnsiString.Length;
2408}
2409
2410/*
2411 * @implemented
2412 */
2413UINT
2414WINAPI
2416 IN UINT uSize)
2417{
2419
2421 if ((uSize * sizeof(WCHAR)) >= ReturnLength)
2422 {
2427
2429 }
2430
2431 return ReturnLength / sizeof(WCHAR);
2432}
2433
2434/*
2435 * @unimplemented
2436 */
2437UINT
2438WINAPI
2440 IN UINT uSize)
2441{
2442#ifdef _WIN64
2444 return 0;
2445#else
2447 return 0;
2448#endif
2449}
2450
2451/*
2452 * @unimplemented
2453 */
2454UINT
2455WINAPI
2457 IN UINT uSize)
2458{
2459#ifdef _WIN64
2461 return 0;
2462#else
2464 return 0;
2465#endif
2466}
2467
2468/* EOF */
#define NtCurrentPeb()
Definition: FLS.c:22
WCHAR First[]
Definition: FormatMessage.c:11
static USHORT PathLength
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
IN PUNICODE_STRING StaticString
PRTL_UNICODE_STRING_BUFFER Path
unsigned char BOOLEAN
Definition: actypes.h:127
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
return Found
Definition: dirsup.c:1270
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:737
Definition: bufpool.h:45
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
LPWSTR Name
Definition: desk.c:124
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define wcschr
Definition: compat.h:17
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define wcsrchr
Definition: compat.h:16
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static DWORD cchBuffer
Definition: fusion.c:85
RTL_CRITICAL_SECTION BaseDllDirectoryLock
Definition: dllmain.c:32
UINT WINAPI SetErrorMode(IN UINT uMode)
Definition: except.c:751
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:636
DWORD FilenameW2A_FitOrFail(LPSTR DestA, INT destLen, LPCWSTR SourceW, INT sourceLen)
Definition: fileutils.c:98
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
UINT WINAPI GetSystemWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2385
DWORD WINAPI GetDllDirectoryW(IN DWORD nBufferLength, OUT LPWSTR lpBuffer)
Definition: path.c:945
BOOLEAN WINAPI CheckForSameCurdir(IN PUNICODE_STRING DirName)
Definition: path.c:577
UNICODE_STRING BaseWindowsDirectory
Definition: path.c:20
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2164
LPWSTR WINAPI BaseComputeProcessSearchPath(VOID)
Definition: path.c:397
BASE_SEARCH_PATH_TYPE BaseDllOrderNoCurrent[BaseSearchPathMax]
Definition: path.c:63
BASE_CURRENT_DIR_PLACEMENT BasepDllCurrentDirPlacement
Definition: path.c:81
UINT WINAPI GetSystemWow64DirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2456
PVOID gpTermsrvGetWindowsDirectoryW
Definition: path.c:24
DWORD IllegalMask[4]
Definition: path.c:28
UNICODE_STRING BasePathVariableName
Definition: proc.c:22
DWORD WINAPI SearchPathA(IN LPCSTR lpPath OPTIONAL, IN LPCSTR lpFileName, IN LPCSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart OPTIONAL)
Definition: path.c:1222
BOOL WINAPI SetDllDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:858
BOOL WINAPI NeedCurrentDirectoryForExePathA(IN LPCSTR ExeName)
Definition: path.c:1027
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2098
BOOL WINAPI SetDllDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:896
UNICODE_STRING BaseDefaultPathAppend
Definition: path.c:21
LPWSTR WINAPI BaseComputeProcessDllPath(IN LPWSTR FullPath, IN PVOID Environment)
Definition: path.c:478
PVOID gpTermsrvGetWindowsDirectoryA
Definition: path.c:23
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2355
UINT WINAPI GetSystemWow64DirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2439
DWORD WINAPI GetLongPathNameA(IN LPCSTR lpszShortPath, OUT LPSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1770
LPWSTR WINAPI BaseComputeProcessExePath(IN LPWSTR FullPath)
Definition: path.c:463
LPWSTR WINAPI BasepComputeProcessPath(IN PBASE_SEARCH_PATH_TYPE PathOrder, IN LPWSTR AppName, IN LPVOID Environment)
Definition: path.c:118
BOOL WINAPI SetSearchPathMode(_In_ DWORD dwFlags)
Definition: path.c:1181
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2267
DWORD WINAPI SearchPathW(IN LPCWSTR lpPath OPTIONAL, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart OPTIONAL)
Definition: path.c:1397
BASE_SEARCH_PATH_TYPE BaseProcessOrder[BaseSearchPathMax]
Definition: path.c:72
BOOL WINAPI BasepIsCurDirAllowedForPlainExeNames(VOID)
Definition: path.c:839
BOOL WINAPI FindLFNorSFN_U(IN PWCHAR Path, OUT PWCHAR *First, OUT PWCHAR *Last, IN BOOL UseShort)
Definition: path.c:740
BOOL WINAPI IsLongName_U(IN PWCHAR FileName, IN ULONG Length)
Definition: path.c:706
UNICODE_STRING BaseWindowsSystemDirectory
Definition: path.c:20
PWCHAR WINAPI SkipPathTypeIndicator_U(IN LPWSTR Path)
Definition: path.c:798
DWORD WINAPI GetDllDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:973
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:1051
UNICODE_STRING BaseDefaultPath
Definition: path.c:21
DWORD BasepSearchPathModeFlags
Definition: path.c:83
PWCHAR WINAPI BasepEndOfDirName(IN PWCHAR FileName)
Definition: path.c:91
UNICODE_STRING NoDefaultCurrentDirectoryInExePath
Definition: path.c:18
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2331
DWORD WINAPI GetLongPathNameW(IN LPCWSTR lpszShortPath, OUT LPWSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1555
BOOL WINAPI IsShortName_U(IN PWCHAR Name, IN ULONG Length)
Definition: path.c:619
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1851
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2224
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2415
BASE_SEARCH_PATH_TYPE BaseProcessOrderNoCurrent[BaseSearchPathMax]
Definition: path.c:54
UNICODE_STRING BaseDllDirectory
Definition: path.c:21
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1164
BOOL WINAPI NeedCurrentDirectoryForExePathW(IN LPCWSTR ExeName)
Definition: path.c:1015
BASE_SEARCH_PATH_TYPE BaseDllOrderCurrent[BaseCurrentDirPlacementMax][BaseSearchPathMax]
Definition: path.c:36
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2370
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2072
UINT WINAPI GetSystemDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2301
PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry
Definition: proc.c:23
PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString
Definition: utils.c:28
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:226
VOID NTAPI BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry, IN PVOID Context, OUT BOOLEAN *StopEnumeration)
Definition: utils.c:157
PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
Definition: utils.c:27
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:189
PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize
Definition: utils.c:29
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2126
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3291
@ AnsiString
Definition: dnslib.h:19
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
#define __FUNCTION__
Definition: types.h:116
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
IN PDCB IN POEM_STRING IN PUNICODE_STRING UnicodeName
Definition: fatprocs.h:1306
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION _In_ ULONG _Out_opt_ PULONG LengthNeeded
Definition: fltkernel.h:1343
SHORT OldFlags
Definition: fxioqueue.cpp:1325
Status
Definition: gdiplustypes.h:24
GLuint GLuint GLsizei count
Definition: gl.h:1545
const GLubyte * c
Definition: glext.h:8905
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
unsigned int UINT
Definition: sysinfo.c:13
@ GetShortPathNameNT4
Definition: pstypes.h:822
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define NtCurrentTeb
#define c
Definition: ke_i.h:80
enum _BASE_SEARCH_PATH_TYPE BASE_SEARCH_PATH_TYPE
enum _BASE_SEARCH_PATH_TYPE * PBASE_SEARCH_PATH_TYPE
@ BaseCurrentDirPlacementSafe
Definition: kernel32.h:92
@ BaseCurrentDirPlacementMax
Definition: kernel32.h:93
@ BaseCurrentDirPlacementInvalid
Definition: kernel32.h:90
@ BaseCurrentDirPlacementDefault
Definition: kernel32.h:91
@ BaseSearchPathMax
Definition: kernel32.h:85
@ BaseSearchPathDll
Definition: kernel32.h:80
@ BaseSearchPathInvalid
Definition: kernel32.h:79
@ BaseSearchPathApp
Definition: kernel32.h:81
@ BaseSearchPathDefault
Definition: kernel32.h:82
@ BaseSearchPathCurrent
Definition: kernel32.h:84
@ BaseSearchPathEnv
Definition: kernel32.h:83
enum _BASE_CURRENT_DIR_PLACEMENT BASE_CURRENT_DIR_PLACEMENT
NTSTATUS NTAPI LdrEnumerateLoadedModules(_Reserved_ ULONG ReservedFlag, _In_ PLDR_ENUM_CALLBACK EnumProc, _In_opt_ PVOID Context)
Definition: ldrapi.c:1104
#define Dst
Definition: mesh.h:153
#define ASSERT(a)
Definition: mode.c:44
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define min(a, b)
Definition: monoChain.cc:55
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
NTSYSAPI NTSTATUS NTAPI RtlDosSearchPath_Ustr(_In_ ULONG Flags, _In_ PUNICODE_STRING PathString, _In_ PUNICODE_STRING FileNameString, _In_ PUNICODE_STRING ExtensionString, _In_ PUNICODE_STRING CallerBuffer, _Inout_opt_ PUNICODE_STRING DynamicString, _Out_opt_ PUNICODE_STRING *FullNameOut, _Out_opt_ PSIZE_T FilePartSize, _Out_opt_ PSIZE_T LengthNeeded)
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)
NTSYSAPI NTSTATUS NTAPI RtlSetCurrentDirectory_U(_In_ PUNICODE_STRING name)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI ULONG NTAPI RtlGetFullPathName_U(_In_ PCWSTR FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PWSTR *ShortName)
Definition: path.c:1987
NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(_In_opt_ PWSTR Environment, _In_ PCUNICODE_STRING Name, _Out_ PUNICODE_STRING Value)
Definition: env.c:659
NTSYSAPI ULONG NTAPI RtlGetCurrentDirectory_U(_In_ ULONG MaximumLength, _Out_bytecap_(MaximumLength) PWSTR Buffer)
Definition: path.c:1661
#define SEM_FAILCRITICALERRORS
Definition: rtltypes.h:69
@ RtlPathTypeRootLocalDevice
Definition: rtltypes.h:483
@ RtlPathTypeDriveRelative
Definition: rtltypes.h:479
@ RtlPathTypeRelative
Definition: rtltypes.h:481
@ RtlPathTypeUncAbsolute
Definition: rtltypes.h:477
@ RtlPathTypeRooted
Definition: rtltypes.h:480
@ RtlPathTypeLocalDevice
Definition: rtltypes.h:482
@ RtlPathTypeDriveAbsolute
Definition: rtltypes.h:478
#define SEM_NOOPENFILEERRORBOX
Definition: rtltypes.h:72
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
_Out_ LPWSTR lpBuffer
Definition: netsh.h:68
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteN(_Out_ PCHAR MbString, _In_ ULONG MbSize, _Out_opt_ PULONG ResultSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:108
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:146
#define _In_
Definition: no_sal2.h:158
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
@ KeyValuePartialInformation
Definition: nt_native.h:1185
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3429
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define DWORD
Definition: nt_native.h:44
#define UNICODE_NULL
#define UNICODE_STRING_MAX_CHARS
#define UNICODE_STRING_MAX_BYTES
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
#define STATUS_VARIABLE_NOT_FOUND
Definition: ntstatus.h:586
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:592
short WCHAR
Definition: pedump.c:58
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
static calc_node_t temp
Definition: rpn_ieee.c:38
wcsncpy
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1882
USHORT MaximumLength
Definition: env_spec_w32.h:370
_Field_z_ WCHAR cAlternateFileName[14]
Definition: minwinbase.h:292
_Field_z_ WCHAR cFileName[MAX_PATH]
Definition: minwinbase.h:291
const char * LPCSTR
Definition: typedefs.h:52
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * LPCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint16_t * LPWSTR
Definition: typedefs.h:56
ULONG_PTR SIZE_T
Definition: typedefs.h:80
char * LPSTR
Definition: typedefs.h:51
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define NT_ERROR(Status)
Definition: umtypes.h:106
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3782
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2705
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_opt_ PCUNICODE_STRING UnicodeString
Definition: wdfstring.h:64
_In_ LPCSTR _In_opt_ LPCSTR lpExtension
Definition: winbase.h:2801
_In_ LPCSTR lpFileName
Definition: winbase.h:2800
#define BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE
Definition: winbase.h:587
#define BASE_SEARCH_PATH_INVALID_FLAGS
Definition: winbase.h:589
#define BASE_SEARCH_PATH_PERMANENT
Definition: winbase.h:588
#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
Definition: winbase.h:586
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD _Out_opt_ LPSTR * lpFilePart
Definition: winbase.h:2804
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD nBufferLength
Definition: winbase.h:2802
#define WINAPI
Definition: msvc.h:6
NTSYSAPI void WINAPI RtlReleasePebLock(void)
Definition: libsupp.c:84
NTSYSAPI NTSTATUS WINAPI RtlInitAnsiStringEx(PANSI_STRING, PCSZ)
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
Definition: libsupp.c:74
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:385
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409