ReactOS 0.4.15-dev-5666-gc548b97
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
85/* PRIVATE FUNCTIONS **********************************************************/
86
90{
91 PWCHAR FileNameEnd, FileNameSeparator;
92
93 /* Find the first slash */
94 FileNameSeparator = wcschr(FileName, OBJ_NAME_PATH_SEPARATOR);
95 if (FileNameSeparator)
96 {
97 /* Find the last one */
98 FileNameEnd = wcsrchr(FileNameSeparator, OBJ_NAME_PATH_SEPARATOR);
99 ASSERT(FileNameEnd);
100
101 /* Handle the case where they are one and the same */
102 if (FileNameEnd == FileNameSeparator) FileNameEnd++;
103 }
104 else
105 {
106 /* No directory was specified */
107 FileNameEnd = NULL;
108 }
109
110 /* Return where the directory ends and the filename starts */
111 return FileNameEnd;
112}
113
114LPWSTR
115WINAPI
119{
120 PWCHAR PathBuffer, Buffer, AppNameEnd, PathCurrent;
121 SIZE_T PathLengthInBytes;
123 UNICODE_STRING EnvPath;
125
126 /* Initialize state */
127 AppNameEnd = Buffer = PathBuffer = NULL;
129 PathLengthInBytes = 0;
130
131 /* Loop the ordering array */
132 for (Order = PathOrder; *Order != BaseSearchPathInvalid; Order++) {
133 switch (*Order)
134 {
135 /* Compute the size of the DLL path */
137
138 /* This path only gets called if SetDllDirectory was called */
140
141 /* Make sure there's a DLL directory size */
143 {
144 /* Add it, plus the separator */
145 PathLengthInBytes += BaseDllDirectory.Length + sizeof(L';');
146 }
147 break;
148
149 /* Compute the size of the current path */
151
152 /* Add ".;" */
153 PathLengthInBytes += (2 * sizeof(WCHAR));
154 break;
155
156 /* Compute the size of the "PATH" environment variable */
158
159 /* Grab PEB lock if one wasn't passed in */
161
162 /* Query the size first */
163 EnvPath.MaximumLength = 0;
166 &EnvPath);
168 {
169 /* Compute the size we'll need for the environment */
170 EnvPath.MaximumLength = EnvPath.Length + sizeof(WCHAR);
171 if ((EnvPath.Length + sizeof(WCHAR)) > UNICODE_STRING_MAX_BYTES)
172 {
173 /* Don't let it overflow */
174 EnvPath.MaximumLength = EnvPath.Length;
175 }
176
177 /* Allocate the environment buffer */
178 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
179 0,
180 EnvPath.MaximumLength);
181 if (Buffer)
182 {
183 /* Now query the PATH environment variable */
184 EnvPath.Buffer = Buffer;
187 &EnvPath);
188 }
189 else
190 {
191 /* Failure case */
193 }
194 }
195
196 /* Release the PEB lock from above */
198
199 /* There might not be a PATH */
201 {
202 /* In this case, skip this PathOrder */
203 EnvPath.Length = EnvPath.MaximumLength = 0;
205 }
206 else if (!NT_SUCCESS(Status))
207 {
208 /* An early failure, go to exit code */
209 goto Quickie;
210 }
211 else
212 {
213 /* Add the length of the PATH variable unless it's empty */
214 ASSERT(!(EnvPath.Length & 1));
215 if (EnvPath.Length)
216 {
217 /* Reserve space for the variable and a semicolon */
218 PathLengthInBytes += (EnvPath.Length + sizeof(L';'));
219 }
220 }
221 break;
222
223 /* Compute the size of the default search path */
225
226 /* Just add it... it already has a ';' at the end */
228 PathLengthInBytes += BaseDefaultPath.Length;
229 break;
230
231 /* Compute the size of the current app directory */
233 /* Find out where the app name ends, to get only the directory */
234 if (AppName) AppNameEnd = BasepEndOfDirName(AppName);
235
236 /* Check if there was no application name passed in */
237 if (!(AppName) || !(AppNameEnd))
238 {
239 /* Do we have a per-thread CURDIR to use? */
240 if (NtCurrentTeb()->NtTib.SubSystemTib)
241 {
242 /* This means someone added RTL_PERTHREAD_CURDIR */
244 }
245
246 /* We do not. Do we have the LDR_ENTRY for the executable? */
247 if (!BasepExeLdrEntry)
248 {
249 /* We do not. Grab it */
252 NtCurrentPeb()->ImageBaseAddress);
253 }
254
255 /* Now do we have it? */
257 {
258 /* Yes, so read the name out of it */
260 }
261
262 /* Find out where the app name ends, to get only the directory */
263 if (AppName) AppNameEnd = BasepEndOfDirName(AppName);
264 }
265
266 /* So, do we have an application name and its directory? */
267 if ((AppName) && (AppNameEnd))
268 {
269 /* Add the size of the app's directory, plus the separator */
270 PathLengthInBytes += ((AppNameEnd - AppName) * sizeof(WCHAR)) + sizeof(L';');
271 }
272 break;
273
274 default:
275 break;
276 }
277 }
278
279 /* Bam, all done, we now have the final path size */
280 ASSERT(PathLengthInBytes > 0);
281 ASSERT(!(PathLengthInBytes & 1));
282
283 /* Allocate the buffer to hold it */
284 PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLengthInBytes);
285 if (!PathBuffer)
286 {
287 /* Failure path */
289 goto Quickie;
290 }
291
292 /* Now we loop again, this time to copy the data */
293 PathCurrent = PathBuffer;
294 for (Order = PathOrder; *Order != BaseSearchPathInvalid; Order++) {
295 switch (*Order)
296 {
297 /* Add the DLL path */
300 {
301 /* Copy it in the buffer, ASSERT there's enough space */
302 ASSERT((((PathCurrent - PathBuffer + 1) * sizeof(WCHAR)) + BaseDllDirectory.Length) <= PathLengthInBytes);
303 RtlCopyMemory(PathCurrent,
306
307 /* Update the current pointer, add a separator */
308 PathCurrent += (BaseDllDirectory.Length / sizeof(WCHAR));
309 *PathCurrent++ = ';';
310 }
311 break;
312
313 /* Add the current application path */
315 if ((AppName) && (AppNameEnd))
316 {
317 /* Copy it in the buffer, ASSERT there's enough space */
318 ASSERT(((PathCurrent - PathBuffer + 1 + (AppNameEnd - AppName)) * sizeof(WCHAR)) <= PathLengthInBytes);
319 RtlCopyMemory(PathCurrent,
320 AppName,
321 (AppNameEnd - AppName) * sizeof(WCHAR));
322
323 /* Update the current pointer, add a separator */
324 PathCurrent += AppNameEnd - AppName;
325 *PathCurrent++ = ';';
326 }
327 break;
328
329 /* Add the default search path */
331 /* Copy it in the buffer, ASSERT there's enough space */
332 ASSERT((((PathCurrent - PathBuffer) * sizeof(WCHAR)) + BaseDefaultPath.Length) <= PathLengthInBytes);
334
335 /* Update the current pointer. The default path already has a ";" */
336 PathCurrent += (BaseDefaultPath.Length / sizeof(WCHAR));
337 break;
338
339 /* Add the path in the PATH environment variable */
341 if (EnvPath.Length)
342 {
343 /* Copy it in the buffer, ASSERT there's enough space */
344 ASSERT((((PathCurrent - PathBuffer + 1) * sizeof(WCHAR)) + EnvPath.Length) <= PathLengthInBytes);
345 RtlCopyMemory(PathCurrent, EnvPath.Buffer, EnvPath.Length);
346
347 /* Update the current pointer, add a separator */
348 PathCurrent += (EnvPath.Length / sizeof(WCHAR));
349 *PathCurrent++ = ';';
350 }
351 break;
352
353 /* Add the current directory */
355
356 /* Copy it in the buffer, ASSERT there's enough space */
357 ASSERT(((PathCurrent - PathBuffer + 2) * sizeof(WCHAR)) <= PathLengthInBytes);
358 *PathCurrent++ = '.';
359
360 /* Add the path separator */
361 *PathCurrent++ = ';';
362 break;
363
364 default:
365 break;
366 }
367 }
368
369 /* Everything should've perfectly fit in there */
370 ASSERT((PathCurrent - PathBuffer) * sizeof(WCHAR) == PathLengthInBytes);
371 ASSERT(PathCurrent > PathBuffer);
372
373 /* Terminate the whole thing */
374 PathCurrent[-1] = UNICODE_NULL;
375
376Quickie:
377 /* Exit path: free our buffers */
378 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
379 if (PathBuffer)
380 {
381 /* This only gets freed in the failure path, since caller wants it */
382 if (!NT_SUCCESS(Status))
383 {
384 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
385 PathBuffer = NULL;
386 }
387 }
388
389 /* Return the path! */
390 return PathBuffer;
391}
392
393LPWSTR
394WINAPI
396{
397 DPRINT("Computing Process Search path\n");
398
399 /* Compute the path using default process order */
401}
402
403LPWSTR
404WINAPI
406{
407 PBASE_SEARCH_PATH_TYPE PathOrder;
408 DPRINT("Computing EXE path: %S\n", FullPath);
409
410 /* Check if we should use the current directory */
411 PathOrder = NeedCurrentDirectoryForExePathW(FullPath) ?
413
414 /* And now compute the path */
415 return BasepComputeProcessPath(PathOrder, NULL, NULL);
416}
417
418LPWSTR
419WINAPI
422{
424 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager");
425 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SafeDllSearchMode");
427 CHAR PartialInfoBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
431 BASE_CURRENT_DIR_PLACEMENT CurrentDirPlacement, OldCurrentDirPlacement;
432
433 /* Acquire DLL directory lock */
435
436 /* Check if we have a base dll directory */
438 {
439 /* Then compute the process path using DLL order (without curdir) */
441
442 /* Release DLL directory lock */
444
445 /* Return dll path */
446 return DllPath;
447 }
448
449 /* Release DLL directory lock */
451
452 /* Read the current placement */
453 CurrentDirPlacement = BasepDllCurrentDirPlacement;
454 if (CurrentDirPlacement == BaseCurrentDirPlacementInvalid)
455 {
456 /* Open the configuration key */
458 if (NT_SUCCESS(Status))
459 {
460 /* Query if safe search is enabled */
462 &ValueName,
464 PartialInfoBuffer,
465 sizeof(PartialInfoBuffer),
466 &ResultLength);
467 if (NT_SUCCESS(Status))
468 {
469 /* Read the value if the size is OK */
470 if (ResultLength == sizeof(PartialInfoBuffer))
471 {
472 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)PartialInfoBuffer;
473 CurrentDirPlacement = *(PULONG)PartialInfo->Data;
474 }
475 }
476
477 /* Close the handle */
479
480 /* Validate the registry value */
481 if ((CurrentDirPlacement <= BaseCurrentDirPlacementInvalid) ||
482 (CurrentDirPlacement >= BaseCurrentDirPlacementMax))
483 {
484 /* Default to safe search */
485 CurrentDirPlacement = BaseCurrentDirPlacementSafe;
486 }
487 }
488
489 /* Update the placement and read the old one */
491 CurrentDirPlacement,
493 if (OldCurrentDirPlacement != BaseCurrentDirPlacementInvalid)
494 {
495 /* If there already was a placement, use it */
496 CurrentDirPlacement = OldCurrentDirPlacement;
497 }
498 }
499
500 /* Check if the placement is invalid or not set */
501 if ((CurrentDirPlacement <= BaseCurrentDirPlacementInvalid) ||
502 (CurrentDirPlacement >= BaseCurrentDirPlacementMax))
503 {
504 /* Default to safe search */
505 CurrentDirPlacement = BaseCurrentDirPlacementSafe;
506 }
507
508 /* Compute the process path using either normal or safe search */
510 FullPath,
512
513 /* Return dll path */
514 return DllPath;
515}
516
518WINAPI
520{
521 PUNICODE_STRING CurDir;
522 USHORT CurLength;
524 UNICODE_STRING CurDirCopy;
525
526 CurDir = &NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath;
527
528 CurLength = CurDir->Length;
529 if (CurDir->Length <= 6)
530 {
531 if (CurLength != DirName->Length) return FALSE;
532 }
533 else
534 {
535 if ((CurLength - 2) != DirName->Length) return FALSE;
536 }
537
539
540 CurDirCopy = *CurDir;
541 if (CurDirCopy.Length > 6) CurDirCopy.Length -= 2;
542
543 Result = 0;
544
545 if (RtlEqualUnicodeString(&CurDirCopy, DirName, TRUE)) Result = TRUE;
546
548
549 return Result;
550}
551
552/*
553 * Why not use RtlIsNameLegalDOS8Dot3? In fact the actual algorithm body is
554 * identical (other than the Rtl can optionally check for spaces), however the
555 * Rtl will always convert to OEM, while kernel32 has two possible file modes
556 * (ANSI or OEM). Therefore we must duplicate the algorithm body to get
557 * the correct compatible results
558 */
559BOOL
560WINAPI
563{
564 BOOLEAN HasExtension;
565 UCHAR c;
568 ANSI_STRING AnsiName;
569 ULONG i, Dots;
571 ASSERT(Name);
572
573 /* What do you think 8.3 means? */
574 if (Length > 12) return FALSE;
575
576 /* Sure, any empty name is a short name */
577 if (!Length) return TRUE;
578
579 /* This could be . or .. or something else */
580 if (*Name == L'.')
581 {
582 /* Which one is it */
583 if ((Length == 1) || ((Length == 2) && *(Name + 1) == L'.'))
584 {
585 /* . or .., this is good */
586 return TRUE;
587 }
588
589 /* Some other bizare dot-based name, not good */
590 return FALSE;
591 }
592
593 /* Initialize our two strings */
594 RtlInitEmptyAnsiString(&AnsiName, AnsiBuffer, MAX_PATH);
595 RtlInitEmptyUnicodeString(&UnicodeName, Name, (USHORT)Length * sizeof(WCHAR));
596 UnicodeName.Length = UnicodeName.MaximumLength;
597
598 /* Now do the conversion */
600 if (!NT_SUCCESS(Status)) return FALSE;
601
602 /* Now we loop the name */
603 HasExtension = FALSE;
604 for (i = 0, Dots = Length - 1; i < AnsiName.Length; i++, Dots--)
605 {
606 /* Read the current byte */
607 c = AnsiName.Buffer[i];
608
609 /* Is it DBCS? */
610 if (IsDBCSLeadByte(c))
611 {
612 /* If we're near the end of the string, we can't allow a DBCS */
613 if ((!(HasExtension) && (i >= 7)) || (i == AnsiName.Length - 1))
614 {
615 return FALSE;
616 }
617
618 /* Otherwise we skip over it */
619 continue;
620 }
621
622 /* Check for illegal characters */
623 if ((c > 0x7F) || (IllegalMask[c / 32] & (1 << (c % 32))))
624 {
625 return FALSE;
626 }
627
628 /* Check if this is perhaps an extension? */
629 if (c == '.')
630 {
631 /* Unless the extension is too large or there's more than one */
632 if ((HasExtension) || (Dots > 3)) return FALSE;
633
634 /* This looks like an extension */
635 HasExtension = TRUE;
636 }
637
638 /* 8.3 length was validated, but now we must guard against 9.2 or similar */
639 if ((i >= 8) && !(HasExtension)) return FALSE;
640 }
641
642 /* You survived the loop, this is a good short name */
643 return TRUE;
644}
645
646BOOL
647WINAPI
650{
651 BOOLEAN HasExtension;
652 ULONG i, Dots;
653
654 /* More than 8.3, any combination of dots, and NULL names are all long */
655 if (!(Length) || (Length > 12) || (*FileName == L'.')) return TRUE;
656
657 /* Otherwise, initialize our scanning loop */
658 HasExtension = FALSE;
659 for (i = 0, Dots = Length - 1; i < Length; i++, Dots--)
660 {
661 /* Check if this could be an extension */
662 if (FileName[i] == L'.')
663 {
664 /* Unlike the short case, we WANT more than one extension, or a long one */
665 if ((HasExtension) || (Dots > 3))
666 {
667 return TRUE;
668 }
669 HasExtension = TRUE;
670 }
671
672 /* Check if this would violate the "8" in 8.3, ie. 9.2 */
673 if ((i >= 8) && (!HasExtension)) return TRUE;
674 }
675
676 /* The name *seems* to conform to 8.3 */
677 return FALSE;
678}
679
680BOOL
681WINAPI
684 OUT PWCHAR *Last,
685 IN BOOL UseShort)
686{
687 PWCHAR p;
689 BOOL Found = 0;
690 ASSERT(Path);
691
692 /* Loop while there is something in the path */
693 while (TRUE)
694 {
695 /* Loop within the path skipping slashes */
696 while ((*Path == L'\\') || (*Path == L'/')) Path++;
697
698 /* Make sure there's something after the slashes too! */
699 if (*Path == UNICODE_NULL) break;
700
701 /* Now skip past the file name until we get to the first slash */
702 p = Path + 1;
703 while ((*p) && ((*p != L'\\') && (*p != L'/'))) p++;
704
705 /* Whatever is in between those two is now the file name length */
706 Length = p - Path;
707
708 /*
709 * Check if it is valid
710 * Note that !IsShortName != IsLongName, these two functions simply help
711 * us determine if a conversion is necessary or not.
712 * "Found" really means: "Is a conversion necessary?", hence the "!"
713 */
715 if (Found)
716 {
717 /* It is! did the caller request to know the markers? */
718 if ((First) && (Last))
719 {
720 /* Return them */
721 *First = Path;
722 *Last = p;
723 }
724 break;
725 }
726
727 /* Is there anything else following this sub-path/filename? */
728 if (*p == UNICODE_NULL) break;
729
730 /* Yes, keep going */
731 Path = p + 1;
732 }
733
734 /* Return if anything was found and valid */
735 return Found;
736}
737
738PWCHAR
739WINAPI
741{
742 PWCHAR ReturnPath;
743 ULONG i;
744
745 /* Check what kind of path this is and how many slashes to skip */
747 {
750 {
751 /* Keep going until we bypass the path indicators */
752 for (ReturnPath = Path + 2, i = 2; (i > 0) && (*ReturnPath); ReturnPath++)
753 {
754 /* We look for 2 slashes, so keep at it until we find them */
755 if ((*ReturnPath == L'\\') || (*ReturnPath == L'/')) i--;
756 }
757
758 return ReturnPath;
759 }
760
762 return Path + 3;
763
765 return Path + 2;
766
768 return Path + 1;
769
771 return Path;
772
774 default:
775 return NULL;
776 }
777}
778
779BOOL
780WINAPI
782{
784 UNICODE_STRING EmptyString;
785
786 RtlInitEmptyUnicodeString(&EmptyString, NULL, 0);
789 &EmptyString);
791}
792
793/* PUBLIC FUNCTIONS ***********************************************************/
794
795/*
796 * @implemented
797 */
798BOOL
799WINAPI
801{
802 UNICODE_STRING OldDirectory, DllDirectory;
803
804 if (lpPathName)
805 {
806 if (wcschr(lpPathName, L';'))
807 {
809 return FALSE;
810 }
811 if (!RtlCreateUnicodeString(&DllDirectory, lpPathName))
812 {
814 return FALSE;
815 }
816 }
817 else
818 {
819 RtlInitUnicodeString(&DllDirectory, NULL);
820 }
821
823
824 OldDirectory = BaseDllDirectory;
825 BaseDllDirectory = DllDirectory;
826
828
829 RtlFreeUnicodeString(&OldDirectory);
830 return TRUE;
831}
832
833/*
834 * @implemented
835 */
836BOOL
837WINAPI
839{
840 ANSI_STRING AnsiDllDirectory;
841 UNICODE_STRING OldDirectory, DllDirectory;
843
844 if (lpPathName)
845 {
846 if (strchr(lpPathName, ';'))
847 {
849 return FALSE;
850 }
851
852 Status = RtlInitAnsiStringEx(&AnsiDllDirectory, lpPathName);
853 if (NT_SUCCESS(Status))
854 {
856 &AnsiDllDirectory,
857 TRUE);
858 }
859
860 if (!NT_SUCCESS(Status))
861 {
863 return FALSE;
864 }
865 }
866 else
867 {
868 RtlInitUnicodeString(&DllDirectory, NULL);
869 }
870
872
873 OldDirectory = BaseDllDirectory;
874 BaseDllDirectory = DllDirectory;
875
877
878 RtlFreeUnicodeString(&OldDirectory);
879 return TRUE;
880}
881
882/*
883 * @implemented
884 */
885DWORD
886WINAPI
889{
891
893
894 if ((nBufferLength * sizeof(WCHAR)) > BaseDllDirectory.Length)
895 {
899 }
900 else
901 {
902 Length = (BaseDllDirectory.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
904 }
905
907 return Length;
908}
909
910/*
911 * @implemented
912 */
913DWORD
914WINAPI
917{
919 ANSI_STRING AnsiDllDirectory;
921
922 RtlInitEmptyAnsiString(&AnsiDllDirectory, lpBuffer, (USHORT)nBufferLength);
923
925
927 if (Length > nBufferLength)
928 {
931 }
932 else
933 {
934 --Length;
935 Status = BasepUnicodeStringTo8BitString(&AnsiDllDirectory,
937 FALSE);
938 }
939
941
942 if (!NT_SUCCESS(Status))
943 {
945 Length = 0;
947 }
948
949 return Length;
950}
951
952/*
953 * @implemented
954 */
955BOOL
956WINAPI
958{
959 if (wcschr(ExeName, L'\\')) return TRUE;
960
962}
963
964/*
965 * @implemented
966 */
967BOOL
968WINAPI
970{
971 if (strchr(ExeName, '\\')) return TRUE;
972
974}
975
976/*
977 * @implemented
978 *
979 * NOTE: Many of these A functions may seem to do rather complex A<->W mapping
980 * beyond what you would usually expect. There are two main reasons:
981 *
982 * First, these APIs are subject to the ANSI/OEM File API selection status that
983 * the caller has chosen, so we must use the "8BitString" internal Base APIs.
984 *
985 * Secondly, the Wide APIs (coming from the 9x world) are coded to return the
986 * length of the paths in "ANSI" by dividing their internal Wide character count
987 * by two... this is usually correct when dealing with pure-ASCII codepages but
988 * not necessarily when dealing with MBCS pre-Unicode sets, which NT supports
989 * for CJK, for example.
990 */
991DWORD
992WINAPI
997{
1000 ULONG PathSize, FilePartSize;
1002 UNICODE_STRING FileNameString, UniString;
1003 PWCHAR LocalFilePart;
1004 PWCHAR* FilePart;
1005
1006 /* If the caller wants filepart, use a local wide buffer since this is A */
1007 FilePart = lpFilePart != NULL ? &LocalFilePart : NULL;
1008
1009 /* Initialize for Quickie */
1010 FilePartSize = PathSize = 0;
1011 FileNameString.Buffer = NULL;
1012
1013 /* First get our string in Unicode */
1015 if (!NT_SUCCESS(Status)) goto Quickie;
1016
1017 /* Allocate a buffer to hold teh path name */
1018 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
1019 0,
1020 MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1021 if (!Buffer)
1022 {
1024 goto Quickie;
1025 }
1026
1027 /* Call into RTL to get the full Unicode path name */
1028 PathSize = RtlGetFullPathName_U(FileNameString.Buffer,
1029 MAX_PATH * sizeof(WCHAR),
1030 Buffer,
1031 FilePart);
1032 if (PathSize <= (MAX_PATH * sizeof(WCHAR)))
1033 {
1034 /* The buffer will fit, get the real ANSI string size now */
1035 Status = RtlUnicodeToMultiByteSize(&PathSize, Buffer, PathSize);
1036 if (NT_SUCCESS(Status))
1037 {
1038 /* Now check if the user wanted file part size as well */
1039 if ((PathSize) && (lpFilePart) && (LocalFilePart))
1040 {
1041 /* Yep, so in this case get the length of the file part too */
1042 Status = RtlUnicodeToMultiByteSize(&FilePartSize,
1043 Buffer,
1044 (ULONG)(LocalFilePart - Buffer) *
1045 sizeof(WCHAR));
1046 if (!NT_SUCCESS(Status))
1047 {
1048 /* We failed to do that, so fail the whole call */
1050 PathSize = 0;
1051 }
1052 }
1053 }
1054 }
1055 else
1056 {
1057 /* Reset the path size since the buffer is not large enough */
1058 PathSize = 0;
1059 }
1060
1061 /* Either no path, or local buffer was too small, enter failure code */
1062 if (!PathSize) goto Quickie;
1063
1064 /* If the *caller's* buffer was too small, fail, but add in space for NULL */
1065 if (PathSize >= nBufferLength)
1066 {
1067 PathSize++;
1068 goto Quickie;
1069 }
1070
1071 /* So far so good, initialize a unicode string to convert back to ANSI/OEM */
1072 RtlInitUnicodeString(&UniString, Buffer);
1074 if (!NT_SUCCESS(Status))
1075 {
1076 /* Final conversion failed, fail the call */
1078 PathSize = 0;
1079 }
1080 else
1081 {
1082 /* Conversion worked, now copy the ANSI/OEM buffer into the buffer */
1083 RtlCopyMemory(lpBuffer, AnsiString.Buffer, PathSize + 1);
1085
1086 /* And finally, did the caller request file part information? */
1087 if (lpFilePart)
1088 {
1089 /* Use the size we computed earlier and add it to the buffer */
1090 *lpFilePart = LocalFilePart ? &lpBuffer[FilePartSize] : 0;
1091 }
1092 }
1093
1094Quickie:
1095 /* Cleanup and return the path size */
1096 if (FileNameString.Buffer) RtlFreeUnicodeString(&FileNameString);
1097 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1098 return PathSize;
1099}
1100
1101/*
1102 * @implemented
1103 */
1104DWORD
1105WINAPI
1110{
1111 /* Call Rtl to do the work */
1113 nBufferLength * sizeof(WCHAR),
1114 lpBuffer,
1115 lpFilePart) / sizeof(WCHAR);
1116}
1117
1118/*
1119 * @implemented
1120 */
1121DWORD
1122WINAPI
1129{
1130 PUNICODE_STRING FileNameString;
1131 UNICODE_STRING PathString, ExtensionString;
1133 ULONG PathSize, FilePartSize, AnsiLength;
1134 PWCHAR LocalFilePart, Buffer;
1135 PWCHAR* FilePart;
1136
1137 /* If the caller wants filepart, use a local wide buffer since this is A */
1138 FilePart = lpFilePart != NULL ? &LocalFilePart : NULL;
1139
1140 /* Initialize stuff for Quickie */
1141 PathSize = 0;
1142 Buffer = NULL;
1143 ExtensionString.Buffer = PathString.Buffer = NULL;
1144
1145 /* Get the UNICODE_STRING file name */
1147 if (!FileNameString) return 0;
1148
1149 /* Did the caller specify an extension */
1150 if (lpExtension)
1151 {
1152 /* Yup, convert it into UNICODE_STRING */
1154 lpExtension);
1155 if (!NT_SUCCESS(Status)) goto Quickie;
1156 }
1157
1158 /* Did the caller specify a path */
1159 if (lpPath)
1160 {
1161 /* Yup, convert it into UNICODE_STRING */
1162 Status = Basep8BitStringToDynamicUnicodeString(&PathString, lpPath);
1163 if (!NT_SUCCESS(Status)) goto Quickie;
1164 }
1165
1166 /* Allocate our output buffer */
1167 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nBufferLength * sizeof(WCHAR));
1168 if (!Buffer)
1169 {
1170 /* It failed, bail out */
1172 goto Quickie;
1173 }
1174
1175 /* Now run the Wide search with the input buffer lengths */
1176 PathSize = SearchPathW(PathString.Buffer,
1177 FileNameString->Buffer,
1178 ExtensionString.Buffer,
1180 Buffer,
1181 FilePart);
1182 if (PathSize <= nBufferLength)
1183 {
1184 /* It fits, but is it empty? If so, bail out */
1185 if (!PathSize) goto Quickie;
1186
1187 /* The length above is inexact, we need it in ANSI */
1188 Status = RtlUnicodeToMultiByteSize(&AnsiLength, Buffer, PathSize * sizeof(WCHAR));
1189 if (!NT_SUCCESS(Status))
1190 {
1191 /* Conversion failed, fail the call */
1192 PathSize = 0;
1194 goto Quickie;
1195 }
1196
1197 /* If the correct ANSI size is too big, return required length plus a NULL */
1198 if (AnsiLength >= nBufferLength)
1199 {
1200 PathSize = AnsiLength + 1;
1201 goto Quickie;
1202 }
1203
1204 /* Now apply the final conversion to ANSI */
1206 nBufferLength - 1,
1207 &AnsiLength,
1208 Buffer,
1209 PathSize * sizeof(WCHAR));
1210 if (!NT_SUCCESS(Status))
1211 {
1212 /* Conversion failed, fail the whole call */
1213 PathSize = 0;
1215 goto Quickie;
1216 }
1217
1218 /* NULL-terminate and return the real ANSI length */
1219 lpBuffer[AnsiLength] = ANSI_NULL;
1220 PathSize = AnsiLength;
1221
1222 /* Now check if the user wanted file part size as well */
1223 if (lpFilePart)
1224 {
1225 /* If we didn't get a file part, clear the caller's */
1226 if (!LocalFilePart)
1227 {
1228 *lpFilePart = NULL;
1229 }
1230 else
1231 {
1232 /* Yep, so in this case get the length of the file part too */
1233 Status = RtlUnicodeToMultiByteSize(&FilePartSize,
1234 Buffer,
1235 (ULONG)(LocalFilePart - Buffer) *
1236 sizeof(WCHAR));
1237 if (!NT_SUCCESS(Status))
1238 {
1239 /* We failed to do that, so fail the whole call */
1241 PathSize = 0;
1242 }
1243
1244 /* Return the file part buffer */
1245 *lpFilePart = lpBuffer + FilePartSize;
1246 }
1247 }
1248 }
1249 else
1250 {
1251 /* Our initial buffer guess was too small, allocate a bigger one */
1252 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1253 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize * sizeof(WCHAR));
1254 if (!Buffer)
1255 {
1256 /* Out of memory, fail everything */
1258 goto Quickie;
1259 }
1260
1261 /* Do the search again -- it will fail, we just want the path size */
1262 PathSize = SearchPathW(PathString.Buffer,
1263 FileNameString->Buffer,
1264 ExtensionString.Buffer,
1265 PathSize,
1266 Buffer,
1267 FilePart);
1268 if (!PathSize) goto Quickie;
1269
1270 /* Convert it to a correct size */
1271 Status = RtlUnicodeToMultiByteSize(&PathSize, Buffer, PathSize * sizeof(WCHAR));
1272 if (NT_SUCCESS(Status))
1273 {
1274 /* Make space for the NULL-char */
1275 PathSize++;
1276 }
1277 else
1278 {
1279 /* Conversion failed for some reason, fail the call */
1281 PathSize = 0;
1282 }
1283 }
1284
1285Quickie:
1286 /* Cleanup/complete path */
1287 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1288 if (ExtensionString.Buffer) RtlFreeUnicodeString(&ExtensionString);
1289 if (PathString.Buffer) RtlFreeUnicodeString(&PathString);
1290 return PathSize;
1291}
1292
1293/*
1294 * @implemented
1295 */
1296DWORD
1297WINAPI
1304{
1305 UNICODE_STRING FileNameString, ExtensionString, PathString, CallerBuffer;
1306 ULONG Flags;
1307 SIZE_T LengthNeeded, FilePartSize;
1309 DWORD Result = 0;
1310
1311 /* Default flags for RtlDosSearchPath_Ustr */
1312 Flags = 6;
1313
1314 /* Clear file part in case we fail */
1315 if (lpFilePart) *lpFilePart = NULL;
1316
1317 /* Initialize path buffer for free later */
1318 PathString.Buffer = NULL;
1319
1320 /* Convert filename to a unicode string and eliminate trailing spaces */
1321 RtlInitUnicodeString(&FileNameString, lpFileName);
1322 while ((FileNameString.Length >= sizeof(WCHAR)) &&
1323 (FileNameString.Buffer[(FileNameString.Length / sizeof(WCHAR)) - 1] == L' '))
1324 {
1325 FileNameString.Length -= sizeof(WCHAR);
1326 }
1327
1328 /* Was it all just spaces? */
1329 if (!FileNameString.Length)
1330 {
1331 /* Fail out */
1333 goto Quickie;
1334 }
1335
1336 /* Convert extension to a unicode string */
1337 RtlInitUnicodeString(&ExtensionString, lpExtension);
1338
1339 /* Check if the user sent a path */
1340 if (lpPath)
1341 {
1342 /* Convert it to a unicode string too */
1343 Status = RtlInitUnicodeStringEx(&PathString, lpPath);
1344 if (NT_ERROR(Status))
1345 {
1346 /* Fail if it was too long */
1348 goto Quickie;
1349 }
1350 }
1351 else
1352 {
1353 /* A path wasn't sent, so compute it ourselves */
1354 PathString.Buffer = BaseComputeProcessSearchPath();
1355 if (!PathString.Buffer)
1356 {
1357 /* Fail if we couldn't compute it */
1359 goto Quickie;
1360 }
1361
1362 /* See how big the computed path is */
1363 LengthNeeded = lstrlenW(PathString.Buffer);
1365 {
1366 /* Fail if it's too long */
1368 goto Quickie;
1369 }
1370
1371 /* Set the path size now that we have it */
1372 PathString.MaximumLength = PathString.Length = (USHORT)LengthNeeded * sizeof(WCHAR);
1373
1374 /* Request SxS isolation from RtlDosSearchPath_Ustr */
1375 Flags |= 1;
1376 }
1377
1378 /* Create the string that describes the output buffer from the caller */
1379 CallerBuffer.Length = 0;
1380 CallerBuffer.Buffer = lpBuffer;
1381
1382 /* How much space does the caller have? */
1384 {
1385 /* Add it into the string */
1386 CallerBuffer.MaximumLength = (USHORT)nBufferLength * sizeof(WCHAR);
1387 }
1388 else
1389 {
1390 /* Caller wants too much, limit it to the maximum length of a string */
1392 }
1393
1394 /* Call Rtl to do the work */
1396 &PathString,
1397 &FileNameString,
1398 &ExtensionString,
1399 &CallerBuffer,
1400 NULL,
1401 NULL,
1402 &FilePartSize,
1403 &LengthNeeded);
1404 if (NT_ERROR(Status))
1405 {
1406 /* Check for unusual status codes */
1408 {
1409 /* Print them out since maybe an app needs fixing */
1410 DbgPrint("%s on file %wZ failed; NTSTATUS = %08lx\n",
1412 &FileNameString,
1413 Status);
1414 DbgPrint(" Path = %wZ\n", &PathString);
1415 }
1416
1417 /* Check if the failure was due to a small buffer */
1419 {
1420 /* Check if the length was actually too big for Rtl to work with */
1421 Result = LengthNeeded / sizeof(WCHAR);
1423 }
1424 else
1425 {
1426 /* Some other error, set the error code */
1428 }
1429 }
1430 else
1431 {
1432 /* It worked! Write the file part now */
1433 if (lpFilePart) *lpFilePart = &lpBuffer[FilePartSize];
1434
1435 /* Convert the final result length */
1436 Result = CallerBuffer.Length / sizeof(WCHAR);
1437 }
1438
1439Quickie:
1440 /* Check if there was a dynamic path string to free */
1441 if ((PathString.Buffer != lpPath) && (PathString.Buffer))
1442 {
1443 /* And free it */
1444 RtlFreeHeap(RtlGetProcessHeap(), 0, PathString.Buffer);
1445 }
1446
1447 /* Return the final result length */
1448 return Result;
1449}
1450
1451/*
1452 * @implemented
1453 */
1454DWORD
1455WINAPI
1457 OUT LPWSTR lpszLongPath,
1459{
1460 PWCHAR Path, Original, First, Last, Buffer, Src, Dst;
1462 WCHAR LastChar;
1463 HANDLE FindHandle;
1464 ULONG ErrorMode;
1466 WIN32_FIND_DATAW FindFileData;
1467
1468 /* Initialize so Quickie knows there's nothing to do */
1469 Buffer = Original = NULL;
1470 ReturnLength = 0;
1471
1472 /* First check if the input path was obviously NULL */
1473 if (!lpszShortPath)
1474 {
1475 /* Fail the request */
1477 return 0;
1478 }
1479
1480 /* We will be touching removed, removable drives -- don't warn the user */
1482
1483 /* Do a simple check to see if the path exists */
1484 if (GetFileAttributesW(lpszShortPath) == INVALID_FILE_ATTRIBUTES)
1485 {
1486 /* It doesn't, so fail */
1487 ReturnLength = 0;
1488 goto Quickie;
1489 }
1490
1491 /* Now get a pointer to the actual path, skipping indicators */
1492 Path = SkipPathTypeIndicator_U((LPWSTR)lpszShortPath);
1493
1494 /* Is there any path or filename in there? */
1495 if (!(Path) ||
1496 (*Path == UNICODE_NULL) ||
1497 !(FindLFNorSFN_U(Path, &First, &Last, FALSE)))
1498 {
1499 /* There isn't, so the long path is simply the short path */
1500 ReturnLength = wcslen(lpszShortPath);
1501
1502 /* Is there space for it? */
1503 if ((cchBuffer > ReturnLength) && (lpszLongPath))
1504 {
1505 /* Make sure the pointers aren't already the same */
1506 if (lpszLongPath != lpszShortPath)
1507 {
1508 /* They're not -- copy the short path into the long path */
1509 RtlMoveMemory(lpszLongPath,
1510 lpszShortPath,
1511 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1512 }
1513 }
1514 else
1515 {
1516 /* Otherwise, let caller know we need a bigger buffer, include NULL */
1517 ReturnLength++;
1518 }
1519 goto Quickie;
1520 }
1521
1522 /* We are still in the game -- compute the current size */
1523 Length = wcslen(lpszShortPath) + sizeof(ANSI_NULL);
1524 Original = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1525 if (!Original) goto ErrorQuickie;
1526
1527 /* Make a copy of it */
1528 RtlMoveMemory(Original, lpszShortPath, Length * sizeof(WCHAR));
1529
1530 /* Compute the new first and last markers */
1531 First = &Original[First - lpszShortPath];
1532 Last = &Original[Last - lpszShortPath];
1533
1534 /* Set the current destination pointer for a copy */
1535 Dst = lpszLongPath;
1536
1537 /*
1538 * Windows allows the paths to overlap -- we have to be careful with this and
1539 * see if it's same to do so, and if not, allocate our own internal buffer
1540 * that we'll return at the end.
1541 *
1542 * This is also why we use RtlMoveMemory everywhere. Don't use RtlCopyMemory!
1543 */
1544 if ((cchBuffer) && (lpszLongPath) &&
1545 (((lpszLongPath >= lpszShortPath) && (lpszLongPath < &lpszShortPath[Length])) ||
1546 ((lpszLongPath < lpszShortPath) && (&lpszLongPath[cchBuffer] >= lpszShortPath))))
1547 {
1548 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchBuffer * sizeof(WCHAR));
1549 if (!Buffer) goto ErrorQuickie;
1550
1551 /* New destination */
1552 Dst = Buffer;
1553 }
1554
1555 /* Prepare for the loop */
1556 Src = Original;
1557 ReturnLength = 0;
1558 while (TRUE)
1559 {
1560 /* Current delta in the loop */
1561 Length = First - Src;
1562
1563 /* Update the return length by it */
1565
1566 /* Is there a delta? If so, is there space and buffer for it? */
1567 if ((Length) && (cchBuffer > ReturnLength) && (lpszLongPath))
1568 {
1569 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR));
1570 Dst += Length;
1571 }
1572
1573 /* "Terminate" this portion of the path's substring so we can do a find */
1574 LastChar = *Last;
1575 *Last = UNICODE_NULL;
1576 FindHandle = FindFirstFileW(Original, &FindFileData);
1577 *Last = LastChar;
1578
1579 /* This portion wasn't found, so fail */
1580 if (FindHandle == INVALID_HANDLE_VALUE)
1581 {
1582 ReturnLength = 0;
1583 break;
1584 }
1585
1586 /* Close the find handle */
1587 FindClose(FindHandle);
1588
1589 /* Now check the length of the long name */
1590 Length = wcslen(FindFileData.cFileName);
1591 if (Length)
1592 {
1593 /* This is our new first marker */
1594 First = FindFileData.cFileName;
1595 }
1596 else
1597 {
1598 /* Otherwise, the name is the delta between our current markers */
1599 Length = Last - First;
1600 }
1601
1602 /* Update the return length with the short name length, if any */
1604
1605 /* Once again check for appropriate space and buffer */
1606 if ((cchBuffer > ReturnLength) && (lpszLongPath))
1607 {
1608 /* And do the copy if there is */
1609 RtlMoveMemory(Dst, First, Length * sizeof(WCHAR));
1610 Dst += Length;
1611 }
1612
1613 /* Now update the source pointer */
1614 Src = Last;
1615 if (*Src == UNICODE_NULL) break;
1616
1617 /* Are there more names in there? */
1618 Found = FindLFNorSFN_U(Src, &First, &Last, FALSE);
1619 if (!Found) break;
1620 }
1621
1622 /* The loop is done, is there anything left? */
1623 if (ReturnLength)
1624 {
1625 /* Get the length of the straggling path */
1626 Length = wcslen(Src);
1628
1629 /* Once again check for appropriate space and buffer */
1630 if ((cchBuffer > ReturnLength) && (lpszLongPath))
1631 {
1632 /* And do the copy if there is -- accounting for NULL here */
1633 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1634
1635 /* What about our buffer? */
1636 if (Buffer)
1637 {
1638 /* Copy it into the caller's long path */
1639 RtlMoveMemory(lpszLongPath,
1640 Buffer,
1641 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1642 }
1643 }
1644 else
1645 {
1646 /* Buffer is too small, let the caller know, making space for NULL */
1647 ReturnLength++;
1648 }
1649 }
1650
1651 /* We're all done */
1652 goto Quickie;
1653
1654ErrorQuickie:
1655 /* This is the goto for memory failures */
1657
1658Quickie:
1659 /* General function end: free memory, restore error mode, return length */
1660 if (Original) RtlFreeHeap(RtlGetProcessHeap(), 0, Original);
1661 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1662 SetErrorMode(ErrorMode);
1663 return ReturnLength;
1664}
1665
1666/*
1667 * @implemented
1668 */
1669DWORD
1670WINAPI
1672 OUT LPSTR lpszLongPath,
1674{
1676 PWCHAR LongPath;
1678 UNICODE_STRING LongPathUni, ShortPathUni;
1679 ANSI_STRING LongPathAnsi;
1680 WCHAR LongPathBuffer[MAX_PATH];
1681
1682 LongPath = NULL;
1683 LongPathAnsi.Buffer = NULL;
1684 ShortPathUni.Buffer = NULL;
1685 Result = 0;
1686
1687 if (!lpszShortPath)
1688 {
1690 return 0;
1691 }
1692
1693 Status = Basep8BitStringToDynamicUnicodeString(&ShortPathUni, lpszShortPath);
1694 if (!NT_SUCCESS(Status)) goto Quickie;
1695
1696 LongPath = LongPathBuffer;
1697
1698 PathLength = GetLongPathNameW(ShortPathUni.Buffer, LongPathBuffer, MAX_PATH);
1699 if (PathLength >= MAX_PATH)
1700 {
1701 LongPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLength * sizeof(WCHAR));
1702 if (!LongPath)
1703 {
1704 PathLength = 0;
1706 }
1707 else
1708 {
1709 PathLength = GetLongPathNameW(ShortPathUni.Buffer, LongPath, PathLength);
1710 }
1711 }
1712
1713 if (!PathLength) goto Quickie;
1714
1715 ShortPathUni.MaximumLength = (USHORT)PathLength * sizeof(WCHAR) + sizeof(UNICODE_NULL);
1716 LongPathUni.Buffer = LongPath;
1717 LongPathUni.Length = (USHORT)PathLength * sizeof(WCHAR);
1718
1719 Status = BasepUnicodeStringTo8BitString(&LongPathAnsi, &LongPathUni, TRUE);
1720 if (!NT_SUCCESS(Status))
1721 {
1723 Result = 0;
1724 }
1725
1726 Result = LongPathAnsi.Length;
1727 if ((lpszLongPath) && (cchBuffer > LongPathAnsi.Length))
1728 {
1729 RtlMoveMemory(lpszLongPath, LongPathAnsi.Buffer, LongPathAnsi.Length);
1730 lpszLongPath[Result] = ANSI_NULL;
1731 }
1732 else
1733 {
1734 Result = LongPathAnsi.Length + sizeof(ANSI_NULL);
1735 }
1736
1737Quickie:
1738 if (ShortPathUni.Buffer) RtlFreeUnicodeString(&ShortPathUni);
1739 if (LongPathAnsi.Buffer) RtlFreeAnsiString(&LongPathAnsi);
1740 if ((LongPath) && (LongPath != LongPathBuffer))
1741 {
1742 RtlFreeHeap(RtlGetProcessHeap(), 0, LongPath);
1743 }
1744 return Result;
1745}
1746
1747/*
1748 * @implemented
1749 */
1750DWORD
1751WINAPI
1753 OUT LPSTR lpszShortPath,
1755{
1757 PWCHAR ShortPath;
1759 UNICODE_STRING LongPathUni, ShortPathUni;
1760 ANSI_STRING ShortPathAnsi;
1761 WCHAR ShortPathBuffer[MAX_PATH];
1762
1763 ShortPath = NULL;
1764 ShortPathAnsi.Buffer = NULL;
1765 LongPathUni.Buffer = NULL;
1766 Result = 0;
1767
1768 if (!lpszLongPath)
1769 {
1771 return 0;
1772 }
1773
1774 Status = Basep8BitStringToDynamicUnicodeString(&LongPathUni, lpszLongPath);
1775 if (!NT_SUCCESS(Status)) goto Quickie;
1776
1777 ShortPath = ShortPathBuffer;
1778
1779 PathLength = GetShortPathNameW(LongPathUni.Buffer, ShortPathBuffer, MAX_PATH);
1780 if (PathLength >= MAX_PATH)
1781 {
1782 ShortPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLength * sizeof(WCHAR));
1783 if (!ShortPath)
1784 {
1785 PathLength = 0;
1787 }
1788 else
1789 {
1790 PathLength = GetShortPathNameW(LongPathUni.Buffer, ShortPath, PathLength);
1791 }
1792 }
1793
1794 if (!PathLength) goto Quickie;
1795
1796 LongPathUni.MaximumLength = (USHORT)PathLength * sizeof(WCHAR) + sizeof(UNICODE_NULL);
1797 ShortPathUni.Buffer = ShortPath;
1798 ShortPathUni.Length = (USHORT)PathLength * sizeof(WCHAR);
1799
1800 Status = BasepUnicodeStringTo8BitString(&ShortPathAnsi, &ShortPathUni, TRUE);
1801 if (!NT_SUCCESS(Status))
1802 {
1804 Result = 0;
1805 }
1806
1807 Result = ShortPathAnsi.Length;
1808 if ((lpszShortPath) && (cchBuffer > ShortPathAnsi.Length))
1809 {
1810 RtlMoveMemory(lpszShortPath, ShortPathAnsi.Buffer, ShortPathAnsi.Length);
1811 lpszShortPath[Result] = ANSI_NULL;
1812 }
1813 else
1814 {
1815 Result = ShortPathAnsi.Length + sizeof(ANSI_NULL);
1816 }
1817
1818Quickie:
1819 if (LongPathUni.Buffer) RtlFreeUnicodeString(&LongPathUni);
1820 if (ShortPathAnsi.Buffer) RtlFreeAnsiString(&ShortPathAnsi);
1821 if ((ShortPath) && (ShortPath != ShortPathBuffer))
1822 {
1823 RtlFreeHeap(RtlGetProcessHeap(), 0, ShortPath);
1824 }
1825 return Result;
1826}
1827
1828/*
1829 * @implemented
1830 */
1831DWORD
1832WINAPI
1834 OUT LPWSTR lpszShortPath,
1836{
1837 PWCHAR Path, Original, First, Last, Buffer, Src, Dst;
1839 WCHAR LastChar;
1840 HANDLE FindHandle;
1841 ULONG ErrorMode;
1843 WIN32_FIND_DATAW FindFileData;
1844
1845 /* Initialize so Quickie knows there's nothing to do */
1846 Buffer = Original = NULL;
1847 ReturnLength = 0;
1848
1849 /* First check if the input path was obviously NULL */
1850 if (!lpszLongPath)
1851 {
1852 /* Fail the request */
1854 return 0;
1855 }
1856
1857 /* We will be touching removed, removable drives -- don't warn the user */
1859
1860 /* Do a simple check to see if the path exists */
1861 if (GetFileAttributesW(lpszLongPath) == INVALID_FILE_ATTRIBUTES)
1862 {
1863 /* Windows checks for an application compatibility flag to allow this */
1864 if (!(NtCurrentPeb()) || !(NtCurrentPeb()->AppCompatFlags.LowPart & GetShortPathNameNT4))
1865 {
1866 /* It doesn't, so fail */
1867 ReturnLength = 0;
1868 goto Quickie;
1869 }
1870 }
1871
1872 /* Now get a pointer to the actual path, skipping indicators */
1873 Path = SkipPathTypeIndicator_U((LPWSTR)lpszLongPath);
1874
1875 /* Is there any path or filename in there? */
1876 if (!(Path) ||
1877 (*Path == UNICODE_NULL) ||
1878 !(FindLFNorSFN_U(Path, &First, &Last, TRUE)))
1879 {
1880 /* There isn't, so the long path is simply the short path */
1881 ReturnLength = wcslen(lpszLongPath);
1882
1883 /* Is there space for it? */
1884 if ((cchBuffer > ReturnLength) && (lpszShortPath))
1885 {
1886 /* Make sure the pointers aren't already the same */
1887 if (lpszLongPath != lpszShortPath)
1888 {
1889 /* They're not -- copy the short path into the long path */
1890 RtlMoveMemory(lpszShortPath,
1891 lpszLongPath,
1892 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1893 }
1894 }
1895 else
1896 {
1897 /* Otherwise, let caller know we need a bigger buffer, include NULL */
1898 ReturnLength++;
1899 }
1900 goto Quickie;
1901 }
1902
1903 /* We are still in the game -- compute the current size */
1904 Length = wcslen(lpszLongPath) + sizeof(ANSI_NULL);
1905 Original = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
1906 if (!Original) goto ErrorQuickie;
1907
1908 /* Make a copy of it */
1909 wcsncpy(Original, lpszLongPath, Length);
1910
1911 /* Compute the new first and last markers */
1912 First = &Original[First - lpszLongPath];
1913 Last = &Original[Last - lpszLongPath];
1914
1915 /* Set the current destination pointer for a copy */
1916 Dst = lpszShortPath;
1917
1918 /*
1919 * Windows allows the paths to overlap -- we have to be careful with this and
1920 * see if it's same to do so, and if not, allocate our own internal buffer
1921 * that we'll return at the end.
1922 *
1923 * This is also why we use RtlMoveMemory everywhere. Don't use RtlCopyMemory!
1924 */
1925 if ((cchBuffer) && (lpszShortPath) &&
1926 (((lpszShortPath >= lpszLongPath) && (lpszShortPath < &lpszLongPath[Length])) ||
1927 ((lpszShortPath < lpszLongPath) && (&lpszShortPath[cchBuffer] >= lpszLongPath))))
1928 {
1929 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchBuffer * sizeof(WCHAR));
1930 if (!Buffer) goto ErrorQuickie;
1931
1932 /* New destination */
1933 Dst = Buffer;
1934 }
1935
1936 /* Prepare for the loop */
1937 Src = Original;
1938 ReturnLength = 0;
1939 while (TRUE)
1940 {
1941 /* Current delta in the loop */
1942 Length = First - Src;
1943
1944 /* Update the return length by it */
1946
1947 /* Is there a delta? If so, is there space and buffer for it? */
1948 if ((Length) && (cchBuffer > ReturnLength) && (lpszShortPath))
1949 {
1950 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR));
1951 Dst += Length;
1952 }
1953
1954 /* "Terminate" this portion of the path's substring so we can do a find */
1955 LastChar = *Last;
1956 *Last = UNICODE_NULL;
1957 FindHandle = FindFirstFileW(Original, &FindFileData);
1958 *Last = LastChar;
1959
1960 /* This portion wasn't found, so fail */
1961 if (FindHandle == INVALID_HANDLE_VALUE)
1962 {
1963 ReturnLength = 0;
1964 break;
1965 }
1966
1967 /* Close the find handle */
1968 FindClose(FindHandle);
1969
1970 /* Now check the length of the short name */
1971 Length = wcslen(FindFileData.cAlternateFileName);
1972 if (Length)
1973 {
1974 /* This is our new first marker */
1975 First = FindFileData.cAlternateFileName;
1976 }
1977 else
1978 {
1979 /* Otherwise, the name is the delta between our current markers */
1980 Length = Last - First;
1981 }
1982
1983 /* Update the return length with the short name length, if any */
1985
1986 /* Once again check for appropriate space and buffer */
1987 if ((cchBuffer > ReturnLength) && (lpszShortPath))
1988 {
1989 /* And do the copy if there is */
1990 RtlMoveMemory(Dst, First, Length * sizeof(WCHAR));
1991 Dst += Length;
1992 }
1993
1994 /* Now update the source pointer */
1995 Src = Last;
1996 if (*Src == UNICODE_NULL) break;
1997
1998 /* Are there more names in there? */
1999 Found = FindLFNorSFN_U(Src, &First, &Last, TRUE);
2000 if (!Found) break;
2001 }
2002
2003 /* The loop is done, is there anything left? */
2004 if (ReturnLength)
2005 {
2006 /* Get the length of the straggling path */
2007 Length = wcslen(Src);
2009
2010 /* Once again check for appropriate space and buffer */
2011 if ((cchBuffer > ReturnLength) && (lpszShortPath))
2012 {
2013 /* And do the copy if there is -- accounting for NULL here */
2014 RtlMoveMemory(Dst, Src, Length * sizeof(WCHAR) + sizeof(UNICODE_NULL));
2015
2016 /* What about our buffer? */
2017 if (Buffer)
2018 {
2019 /* Copy it into the caller's long path */
2020 RtlMoveMemory(lpszShortPath,
2021 Buffer,
2022 ReturnLength * sizeof(WCHAR) + sizeof(UNICODE_NULL));
2023 }
2024 }
2025 else
2026 {
2027 /* Buffer is too small, let the caller know, making space for NULL */
2028 ReturnLength++;
2029 }
2030 }
2031
2032 /* We're all done */
2033 goto Quickie;
2034
2035ErrorQuickie:
2036 /* This is the goto for memory failures */
2038
2039Quickie:
2040 /* General function end: free memory, restore error mode, return length */
2041 if (Original) RtlFreeHeap(RtlGetProcessHeap(), 0, Original);
2042 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
2043 SetErrorMode(ErrorMode);
2044 return ReturnLength;
2045}
2046
2047/*
2048 * @implemented
2049 *
2050 * NOTE: Windows returns a dos/short (8.3) path
2051 */
2052DWORD
2053WINAPI
2056{
2057 WCHAR BufferW[MAX_PATH];
2058 DWORD ret;
2059
2060 ret = GetTempPathW(MAX_PATH, BufferW);
2061
2062 if (!ret) return 0;
2063
2064 if (ret > MAX_PATH)
2065 {
2067 return 0;
2068 }
2069
2070 return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1);
2071}
2072
2073/*
2074 * @implemented
2075 *
2076 * ripped from wine
2077 */
2078DWORD
2079WINAPI
2081 OUT LPWSTR path)
2082{
2083 static const WCHAR tmp[] = { 'T', 'M', 'P', 0 };
2084 static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 };
2085 static const WCHAR userprofile[] = { 'U','S','E','R','P','R','O','F','I','L','E',0 };
2086 WCHAR tmp_path[MAX_PATH];
2087 WCHAR full_tmp_path[MAX_PATH];
2088 UINT ret;
2089
2090 DPRINT("%u,%p\n", count, path);
2091
2092 if (!(ret = GetEnvironmentVariableW( tmp, tmp_path, MAX_PATH )) &&
2093 !(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )) &&
2094 !(ret = GetEnvironmentVariableW( userprofile, tmp_path, MAX_PATH )) &&
2095 !(ret = GetWindowsDirectoryW( tmp_path, MAX_PATH )))
2096 {
2097 return 0;
2098 }
2099
2100 if (ret > MAX_PATH)
2101 {
2103 return 0;
2104 }
2105
2106 ret = GetFullPathNameW(tmp_path, MAX_PATH, full_tmp_path, NULL);
2107 if (!ret) return 0;
2108
2109 if (ret > MAX_PATH - 2)
2110 {
2112 return 0;
2113 }
2114
2115 if (full_tmp_path[ret-1] != '\\')
2116 {
2117 full_tmp_path[ret++] = '\\';
2118 full_tmp_path[ret] = '\0';
2119 }
2120
2121 ret++; /* add space for terminating 0 */
2122
2123 if (count >= ret)
2124 {
2125 lstrcpynW(path, full_tmp_path, count);
2126 /* the remaining buffer must be zeroed up to 32766 bytes in XP or 32767
2127 * bytes after it, we will assume the > XP behavior for now */
2128 memset(path + ret, 0, (min(count, 32767) - ret) * sizeof(WCHAR));
2129 ret--; /* return length without 0 */
2130 }
2131 else if (count)
2132 {
2133 /* the buffer must be cleared if contents will not fit */
2134 memset(path, 0, count * sizeof(WCHAR));
2135 }
2136
2137 DPRINT("GetTempPathW returning %u, %S\n", ret, path);
2138 return ret;
2139}
2140
2141/*
2142 * @implemented
2143 */
2144DWORD
2145WINAPI
2148{
2152 ULONG MaxLength;
2153
2154 StaticString = &NtCurrentTeb()->StaticUnicodeString;
2155
2156 MaxLength = nBufferLength;
2158 {
2159 MaxLength = UNICODE_STRING_MAX_BYTES - 1;
2160 }
2161
2167 if (!NT_SUCCESS(Status))
2168 {
2170 return 0;
2171 }
2172
2173 if (MaxLength <= nBufferLength)
2174 {
2175 return nBufferLength + 1;
2176 }
2177
2178 AnsiString.Buffer = lpBuffer;
2179 AnsiString.MaximumLength = (USHORT)MaxLength;
2181 if (!NT_SUCCESS(Status))
2182 {
2184 return 0;
2185 }
2186
2187 return AnsiString.Length;
2188}
2189
2190/*
2191 * @implemented
2192 */
2193DWORD
2194WINAPI
2197{
2198 return RtlGetCurrentDirectory_U(nBufferLength * sizeof(WCHAR), lpBuffer) / sizeof(WCHAR);
2199}
2200
2201/*
2202 * @implemented
2203 */
2204BOOL
2205WINAPI
2207{
2210
2211 if (!lpPathName)
2212 {
2214 return FALSE;
2215 }
2216
2218 if (!DirName) return FALSE;
2219
2220 if (CheckForSameCurdir(DirName)) return TRUE;
2221
2223 if (NT_SUCCESS(Status)) return TRUE;
2224
2225 if ((*DirName->Buffer != L'"') || (DirName->Length <= 2))
2226 {
2228 return 0;
2229 }
2230
2232 if (!DirName) return FALSE;
2233
2235 if (!NT_SUCCESS(Status))
2236 {
2238 return FALSE;
2239 }
2240
2241 return TRUE;
2242}
2243
2244/*
2245 * @implemented
2246 */
2247BOOL
2248WINAPI
2250{
2253
2254 if (!lpPathName)
2255 {
2257 return FALSE;
2258 }
2259
2261 if (NT_SUCCESS(Status))
2262 {
2264 {
2266 }
2267 }
2268
2269 if (!NT_SUCCESS(Status))
2270 {
2272 return FALSE;
2273 }
2274
2275 return TRUE;
2276}
2277
2278/*
2279 * @implemented
2280 */
2281UINT
2282WINAPI
2284 IN UINT uSize)
2285{
2288 ULONG AnsiLength;
2289
2290 /* Get the correct size of the Unicode Base directory */
2291 Status = RtlUnicodeToMultiByteSize(&AnsiLength,
2294 if (!NT_SUCCESS(Status)) return 0;
2295
2296 if (uSize < AnsiLength) return AnsiLength;
2297
2298 RtlInitEmptyAnsiString(&AnsiString, lpBuffer, uSize);
2299
2302 FALSE);
2303 if (!NT_SUCCESS(Status)) return 0;
2304
2305 return AnsiString.Length;
2306}
2307
2308/*
2309 * @implemented
2310 */
2311UINT
2312WINAPI
2314 IN UINT uSize)
2315{
2317
2319 if ((uSize * sizeof(WCHAR)) >= ReturnLength)
2320 {
2325
2327 }
2328
2329 return ReturnLength / sizeof(WCHAR);
2330}
2331
2332/*
2333 * @implemented
2334 */
2335UINT
2336WINAPI
2338 IN UINT uSize)
2339{
2340 /* Is this a TS installation? */
2342
2343 /* Otherwise, call the System API */
2344 return GetSystemWindowsDirectoryA(lpBuffer, uSize);
2345}
2346
2347/*
2348 * @implemented
2349 */
2350UINT
2351WINAPI
2353 IN UINT uSize)
2354{
2355 /* Is this a TS installation? */
2357
2358 /* Otherwise, call the System API */
2359 return GetSystemWindowsDirectoryW(lpBuffer, uSize);
2360}
2361
2362/*
2363 * @implemented
2364 */
2365UINT
2366WINAPI
2368 IN UINT uSize)
2369{
2372 ULONG AnsiLength;
2373
2374 /* Get the correct size of the Unicode Base directory */
2375 Status = RtlUnicodeToMultiByteSize(&AnsiLength,
2378 if (!NT_SUCCESS(Status)) return 0;
2379
2380 if (uSize < AnsiLength) return AnsiLength;
2381
2382 RtlInitEmptyAnsiString(&AnsiString, lpBuffer, uSize);
2383
2386 FALSE);
2387 if (!NT_SUCCESS(Status)) return 0;
2388
2389 return AnsiString.Length;
2390}
2391
2392/*
2393 * @implemented
2394 */
2395UINT
2396WINAPI
2398 IN UINT uSize)
2399{
2401
2403 if ((uSize * sizeof(WCHAR)) >= ReturnLength)
2404 {
2409
2411 }
2412
2413 return ReturnLength / sizeof(WCHAR);
2414}
2415
2416/*
2417 * @unimplemented
2418 */
2419UINT
2420WINAPI
2422 IN UINT uSize)
2423{
2424#ifdef _WIN64
2426 return 0;
2427#else
2429 return 0;
2430#endif
2431}
2432
2433/*
2434 * @unimplemented
2435 */
2436UINT
2437WINAPI
2439 IN UINT uSize)
2440{
2441#ifdef _WIN64
2443 return 0;
2444#else
2446 return 0;
2447#endif
2448}
2449
2450/* EOF */
#define NtCurrentPeb()
Definition: FLS.c:22
WCHAR First[]
Definition: FormatMessage.c:11
static USHORT PathLength
unsigned char BOOLEAN
IN PUNICODE_STRING StaticString
PRTL_UNICODE_STRING_BUFFER Path
WCHAR * ExeName
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
CHAR AnsiBuffer[1024]
Definition: debug.c:15
#define UNIMPLEMENTED
Definition: debug.h:115
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
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
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:175
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
#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:32
#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 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:749
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
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:2367
DWORD WINAPI GetDllDirectoryW(IN DWORD nBufferLength, OUT LPWSTR lpBuffer)
Definition: path.c:887
BOOLEAN WINAPI CheckForSameCurdir(IN PUNICODE_STRING DirName)
Definition: path.c:519
UNICODE_STRING BaseWindowsDirectory
Definition: path.c:20
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
LPWSTR WINAPI BaseComputeProcessSearchPath(VOID)
Definition: path.c:395
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:2438
PVOID gpTermsrvGetWindowsDirectoryW
Definition: path.c:24
DWORD IllegalMask[4]
Definition: path.c:28
UNICODE_STRING BasePathVariableName
Definition: proc.c:23
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1752
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:1123
BOOL WINAPI SetDllDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:800
BOOL WINAPI NeedCurrentDirectoryForExePathA(IN LPCSTR ExeName)
Definition: path.c:969
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2080
BOOL WINAPI SetDllDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:838
UNICODE_STRING BaseDefaultPathAppend
Definition: path.c:21
LPWSTR WINAPI BaseComputeProcessDllPath(IN LPWSTR FullPath, IN PVOID Environment)
Definition: path.c:420
PVOID gpTermsrvGetWindowsDirectoryA
Definition: path.c:23
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2337
UINT WINAPI GetSystemWow64DirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2421
DWORD WINAPI GetLongPathNameA(IN LPCSTR lpszShortPath, OUT LPSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1671
LPWSTR WINAPI BaseComputeProcessExePath(IN LPWSTR FullPath)
Definition: path.c:405
LPWSTR WINAPI BasepComputeProcessPath(IN PBASE_SEARCH_PATH_TYPE PathOrder, IN LPWSTR AppName, IN LPVOID Environment)
Definition: path.c:116
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2249
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:1298
BASE_SEARCH_PATH_TYPE BaseProcessOrder[BaseSearchPathMax]
Definition: path.c:72
BOOL WINAPI BasepIsCurDirAllowedForPlainExeNames(VOID)
Definition: path.c:781
BOOL WINAPI FindLFNorSFN_U(IN PWCHAR Path, OUT PWCHAR *First, OUT PWCHAR *Last, IN BOOL UseShort)
Definition: path.c:682
BOOL WINAPI IsLongName_U(IN PWCHAR FileName, IN ULONG Length)
Definition: path.c:648
UNICODE_STRING BaseWindowsSystemDirectory
Definition: path.c:20
PWCHAR WINAPI SkipPathTypeIndicator_U(IN LPWSTR Path)
Definition: path.c:740
DWORD WINAPI GetDllDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:915
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
UNICODE_STRING BaseDefaultPath
Definition: path.c:21
PWCHAR WINAPI BasepEndOfDirName(IN PWCHAR FileName)
Definition: path.c:89
UNICODE_STRING NoDefaultCurrentDirectoryInExePath
Definition: path.c:18
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
DWORD WINAPI GetLongPathNameW(IN LPCWSTR lpszShortPath, OUT LPWSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1456
BOOL WINAPI IsShortName_U(IN PWCHAR Name, IN ULONG Length)
Definition: path.c:561
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1833
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2397
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:1106
BOOL WINAPI NeedCurrentDirectoryForExePathW(IN LPCWSTR ExeName)
Definition: path.c:957
BASE_SEARCH_PATH_TYPE BaseDllOrderCurrent[BaseCurrentDirPlacementMax][BaseSearchPathMax]
Definition: path.c:36
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
UINT WINAPI GetSystemDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2283
PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry
Definition: proc.c:25
PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString
Definition: utils.c:27
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
VOID NTAPI BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry, IN PVOID Context, OUT BOOLEAN *StopEnumeration)
Definition: utils.c:156
PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
Definition: utils.c:26
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize
Definition: utils.c:28
BOOL WINAPI IsDBCSLeadByte(BYTE TestByte)
Definition: nls.c:2359
@ AnsiString
Definition: dnslib.h:19
#define __FUNCTION__
Definition: types.h:112
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
IN PDCB IN POEM_STRING IN PUNICODE_STRING UnicodeName
Definition: fatprocs.h:1305
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
Status
Definition: gdiplustypes.h:25
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
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
@ GetShortPathNameNT4
Definition: pstypes.h:759
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI void WINAPI RtlReleasePebLock(void)
Definition: libsupp.c:82
NTSYSAPI NTSTATUS WINAPI RtlInitAnsiStringEx(PANSI_STRING, PCSZ)
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
Definition: libsupp.c:72
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
#define InterlockedCompareExchange
Definition: interlocked.h:104
#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:95
@ BaseCurrentDirPlacementMax
Definition: kernel32.h:96
@ BaseCurrentDirPlacementInvalid
Definition: kernel32.h:93
@ BaseSearchPathMax
Definition: kernel32.h:88
@ BaseSearchPathDll
Definition: kernel32.h:83
@ BaseSearchPathInvalid
Definition: kernel32.h:82
@ BaseSearchPathApp
Definition: kernel32.h:84
@ BaseSearchPathDefault
Definition: kernel32.h:85
@ BaseSearchPathCurrent
Definition: kernel32.h:87
@ BaseSearchPathEnv
Definition: kernel32.h:86
enum _BASE_CURRENT_DIR_PLACEMENT BASE_CURRENT_DIR_PLACEMENT
NTSTATUS NTAPI LdrEnumerateLoadedModules(IN BOOLEAN ReservedFlag, IN PLDR_ENUM_CALLBACK EnumProc, IN PVOID Context)
Definition: ldrapi.c:1120
unsigned int * PULONG
Definition: retypes.h:1
signed int * PLONG
Definition: retypes.h:5
unsigned int ULONG
Definition: retypes.h:1
#define Dst
Definition: mesh.h:153
#define ASSERT(a)
Definition: mode.c:44
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
static const char const char * DllPath
Definition: image.c:34
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
_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)
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:478
@ RtlPathTypeDriveRelative
Definition: rtltypes.h:474
@ RtlPathTypeRelative
Definition: rtltypes.h:476
@ RtlPathTypeUncAbsolute
Definition: rtltypes.h:472
@ RtlPathTypeRooted
Definition: rtltypes.h:475
@ RtlPathTypeLocalDevice
Definition: rtltypes.h:477
@ RtlPathTypeDriveAbsolute
Definition: rtltypes.h:473
#define SEM_NOOPENFILEERRORBOX
Definition: rtltypes.h:72
_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:107
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:145
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:1182
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:1016
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#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_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_VARIABLE_NOT_FOUND
Definition: ntstatus.h:492
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
static calc_node_t temp
Definition: rpn_ieee.c:38
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
#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:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1882
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
#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
int ret
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_In_ LPCSTR _In_opt_ LPCSTR lpExtension
Definition: winbase.h:3059
_In_ LPCSTR lpFileName
Definition: winbase.h:3058
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD _Out_opt_ LPSTR * lpFilePart
Definition: winbase.h:3062
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD nBufferLength
Definition: winbase.h:3060
#define WINAPI
Definition: msvc.h:6
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
_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:426
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175