ReactOS  0.4.15-dev-5126-g3bb451b
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 
87 PWCHAR
88 WINAPI
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 
114 LPWSTR
115 WINAPI
117  IN LPWSTR AppName,
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 */
136  case BaseSearchPathDll:
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 */
157  case BaseSearchPathEnv:
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 */
227  ASSERT(!(BaseDefaultPath.Length & 1));
228  PathLengthInBytes += BaseDefaultPath.Length;
229  break;
230 
231  /* Compute the size of the current app directory */
232  case BaseSearchPathApp:
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? */
256  if (BasepExeLdrEntry)
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 */
298  case BaseSearchPathDll:
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 */
314  case BaseSearchPathApp:
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 */
340  case BaseSearchPathEnv:
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 
376 Quickie:
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 
393 LPWSTR
394 WINAPI
396 {
397  DPRINT("Computing Process Search path\n");
398 
399  /* Compute the path using default process order */
401 }
402 
403 LPWSTR
404 WINAPI
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 
418 LPWSTR
419 WINAPI
422 {
423  LPWSTR DllPath = NULL;
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 */
509  DllPath = BasepComputeProcessPath(BaseDllOrderCurrent[CurrentDirPlacement],
510  FullPath,
511  Environment);
512 
513  /* Return dll path */
514  return DllPath;
515 }
516 
517 BOOLEAN
518 WINAPI
520 {
521  PUNICODE_STRING CurDir;
522  USHORT CurLength;
523  BOOLEAN Result;
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  */
559 BOOL
560 WINAPI
562  IN ULONG Length)
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 
646 BOOL
647 WINAPI
649  IN ULONG Length)
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 
680 BOOL
681 WINAPI
683  OUT PWCHAR *First,
684  OUT PWCHAR *Last,
685  IN BOOL UseShort)
686 {
687  PWCHAR p;
688  ULONG Length;
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  */
714  Found = UseShort ? !IsShortName_U(Path, Length) : !IsLongName_U(Path, Length);
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 
738 PWCHAR
739 WINAPI
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 
767  case RtlPathTypeRooted:
768  return Path + 1;
769 
770  case RtlPathTypeRelative:
771  return Path;
772 
774  default:
775  return NULL;
776  }
777 }
778 
779 BOOL
780 WINAPI
782 {
784  UNICODE_STRING EmptyString;
785 
786  RtlInitEmptyUnicodeString(&EmptyString, NULL, 0);
789  &EmptyString);
791 }
792 
793 /* PUBLIC FUNCTIONS ***********************************************************/
794 
795 /*
796  * @implemented
797  */
798 BOOL
799 WINAPI
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  */
836 BOOL
837 WINAPI
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  {
855  Status = Basep8BitStringToUnicodeString(&DllDirectory,
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  */
885 DWORD
886 WINAPI
889 {
890  ULONG Length;
891 
893 
894  if ((nBufferLength * sizeof(WCHAR)) > BaseDllDirectory.Length)
895  {
897  Length = BaseDllDirectory.Length / sizeof(WCHAR);
899  }
900  else
901  {
902  Length = (BaseDllDirectory.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
904  }
905 
907  return Length;
908 }
909 
910 /*
911  * @implemented
912  */
913 DWORD
914 WINAPI
917 {
919  ANSI_STRING AnsiDllDirectory;
920  ULONG Length;
921 
922  RtlInitEmptyAnsiString(&AnsiDllDirectory, lpBuffer, (USHORT)nBufferLength);
923 
925 
927  if (Length > nBufferLength)
928  {
930  if (lpBuffer) *lpBuffer = ANSI_NULL;
931  }
932  else
933  {
934  --Length;
935  Status = BasepUnicodeStringTo8BitString(&AnsiDllDirectory,
937  FALSE);
938  }
939 
941 
942  if (!NT_SUCCESS(Status))
943  {
945  Length = 0;
946  if (lpBuffer) *lpBuffer = ANSI_NULL;
947  }
948 
949  return Length;
950 }
951 
952 /*
953  * @implemented
954  */
955 BOOL
956 WINAPI
958 {
959  if (wcschr(ExeName, L'\\')) return TRUE;
960 
962 }
963 
964 /*
965  * @implemented
966  */
967 BOOL
968 WINAPI
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  */
991 DWORD
992 WINAPI
997 {
999  PWCHAR Buffer = NULL;
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 
1094 Quickie:
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  */
1104 DWORD
1105 WINAPI
1110 {
1111  /* Call Rtl to do the work */
1113  nBufferLength * sizeof(WCHAR),
1114  lpBuffer,
1115  lpFilePart) / sizeof(WCHAR);
1116 }
1117 
1118 /*
1119  * @implemented
1120  */
1121 DWORD
1122 WINAPI
1127  OUT LPSTR lpBuffer,
1129 {
1130  PUNICODE_STRING FileNameString;
1131  UNICODE_STRING PathString, ExtensionString;
1132  NTSTATUS Status;
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 */
1153  Status = Basep8BitStringToDynamicUnicodeString(&ExtensionString,
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,
1179  nBufferLength,
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 
1285 Quickie:
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  */
1296 DWORD
1297 WINAPI
1304 {
1305  UNICODE_STRING FileNameString, ExtensionString, PathString, CallerBuffer;
1306  ULONG Flags;
1307  SIZE_T LengthNeeded, FilePartSize;
1308  NTSTATUS Status;
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 */
1391  CallerBuffer.MaximumLength = UNICODE_STRING_MAX_BYTES;
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",
1411  __FUNCTION__,
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);
1422  if (Result > 0xFFFFFFFF) BaseSetLastNTError(STATUS_NAME_TOO_LONG);
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 
1439 Quickie:
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  */
1454 DWORD
1455 WINAPI
1457  OUT LPWSTR lpszLongPath,
1458  IN DWORD cchBuffer)
1459 {
1460  PWCHAR Path, Original, First, Last, Buffer, Src, Dst;
1462  WCHAR LastChar;
1463  HANDLE FindHandle;
1464  ULONG ErrorMode;
1465  BOOLEAN Found = FALSE;
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 */
1564  ReturnLength += Length;
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 */
1603  ReturnLength += Length;
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);
1627  ReturnLength += Length;
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 
1654 ErrorQuickie:
1655  /* This is the goto for memory failures */
1657 
1658 Quickie:
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  */
1669 DWORD
1670 WINAPI
1672  OUT LPSTR lpszLongPath,
1673  IN DWORD cchBuffer)
1674 {
1676  PWCHAR LongPath;
1677  NTSTATUS Status;
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 
1737 Quickie:
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  */
1750 DWORD
1751 WINAPI
1753  OUT LPSTR lpszShortPath,
1754  IN DWORD cchBuffer)
1755 {
1757  PWCHAR ShortPath;
1758  NTSTATUS Status;
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 
1818 Quickie:
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  */
1831 DWORD
1832 WINAPI
1834  OUT LPWSTR lpszShortPath,
1835  IN DWORD cchBuffer)
1836 {
1837  PWCHAR Path, Original, First, Last, Buffer, Src, Dst;
1839  WCHAR LastChar;
1840  HANDLE FindHandle;
1841  ULONG ErrorMode;
1842  BOOLEAN Found = FALSE;
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 */
1945  ReturnLength += Length;
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 */
1984  ReturnLength += Length;
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);
2008  ReturnLength += Length;
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 
2035 ErrorQuickie:
2036  /* This is the goto for memory failures */
2038 
2039 Quickie:
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  */
2052 DWORD
2053 WINAPI
2055  OUT LPSTR lpBuffer)
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  */
2078 DWORD
2079 WINAPI
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  */
2144 DWORD
2145 WINAPI
2147  OUT LPSTR lpBuffer)
2148 {
2150  NTSTATUS Status;
2152  ULONG MaxLength;
2153 
2154  StaticString = &NtCurrentTeb()->StaticUnicodeString;
2155 
2156  MaxLength = nBufferLength;
2158  {
2159  MaxLength = UNICODE_STRING_MAX_BYTES - 1;
2160  }
2161 
2163  StaticString->Buffer);
2166  StaticString->Length);
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  */
2193 DWORD
2194 WINAPI
2197 {
2198  return RtlGetCurrentDirectory_U(nBufferLength * sizeof(WCHAR), lpBuffer) / sizeof(WCHAR);
2199 }
2200 
2201 /*
2202  * @implemented
2203  */
2204 BOOL
2205 WINAPI
2207 {
2209  NTSTATUS Status;
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  */
2247 BOOL
2248 WINAPI
2250 {
2251  NTSTATUS Status;
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  */
2281 UINT
2282 WINAPI
2284  IN UINT uSize)
2285 {
2287  NTSTATUS Status;
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  */
2311 UINT
2312 WINAPI
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  */
2335 UINT
2336 WINAPI
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  */
2350 UINT
2351 WINAPI
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  */
2365 UINT
2366 WINAPI
2368  IN UINT uSize)
2369 {
2371  NTSTATUS Status;
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  */
2395 UINT
2396 WINAPI
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  */
2419 UINT
2420 WINAPI
2422  IN UINT uSize)
2423 {
2424 #ifdef _WIN64
2425  UNIMPLEMENTED;
2426  return 0;
2427 #else
2429  return 0;
2430 #endif
2431 }
2432 
2433 /*
2434  * @unimplemented
2435  */
2436 UINT
2437 WINAPI
2439  IN UINT uSize)
2440 {
2441 #ifdef _WIN64
2442  UNIMPLEMENTED;
2443  return 0;
2444 #else
2446  return 0;
2447 #endif
2448 }
2449 
2450 /* EOF */
WCHAR * ExeName
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
UINT WINAPI SetErrorMode(IN UINT uMode)
Definition: except.c:749
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
UNICODE_STRING BaseDefaultPath
Definition: path.c:21
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define IN
Definition: typedefs.h:39
BOOL WINAPI BasepIsCurDirAllowedForPlainExeNames(VOID)
Definition: path.c:781
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2397
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD _Out_opt_ LPSTR * lpFilePart
Definition: winbase.h:3059
UINT WINAPI GetSystemWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2367
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
BOOL WINAPI IsShortName_U(IN PWCHAR Name, IN ULONG Length)
Definition: path.c:561
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
#define DbgPrint
Definition: hal.h:12
_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
#define SEM_FAILCRITICALERRORS
Definition: rtltypes.h:69
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSYSAPI NTSTATUS WINAPI RtlInitAnsiStringEx(PANSI_STRING, PCSZ)
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString
Definition: utils.c:27
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
GLuint GLuint GLsizei count
Definition: gl.h:1545
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
IN PDCB IN POEM_STRING IN PUNICODE_STRING UnicodeName
Definition: fatprocs.h:1303
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
UINT WINAPI GetSystemDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2283
PVOID gpTermsrvGetWindowsDirectoryA
Definition: path.c:23
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_opt_ PCUNICODE_STRING UnicodeString
Definition: wdfstring.h:64
uint16_t * PWCHAR
Definition: typedefs.h:56
char * LPSTR
Definition: xmlstorage.h:182
static USHORT PathLength
#define UNICODE_STRING_MAX_BYTES
#define lstrlenW
Definition: compat.h:609
BOOL WINAPI NeedCurrentDirectoryForExePathA(IN LPCSTR ExeName)
Definition: path.c:969
UNICODE_STRING BaseDllDirectory
Definition: path.c:21
DWORD ret
Definition: path.c:47
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define lstrcpynW
Definition: compat.h:597
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
LPWSTR WINAPI BaseComputeProcessSearchPath(VOID)
Definition: path.c:395
DWORD WINAPI GetLongPathNameA(IN LPCSTR lpszShortPath, OUT LPSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1671
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
WCHAR First[]
Definition: FormatMessage.c:11
ULONG NTAPI RtlGetFullPathName_U(_In_ PCWSTR FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PWSTR *ShortName)
Definition: path.c:1987
DWORD WINAPI GetDllDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:915
BOOL WINAPI IsLongName_U(IN PWCHAR FileName, IN ULONG Length)
Definition: path.c:648
BOOL WINAPI FindLFNorSFN_U(IN PWCHAR Path, OUT PWCHAR *First, OUT PWCHAR *Last, IN BOOL UseShort)
Definition: path.c:682
#define L(x)
Definition: ntvdm.h:50
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
BASE_SEARCH_PATH_TYPE BaseProcessOrderNoCurrent[BaseSearchPathMax]
Definition: path.c:54
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2080
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define ANSI_NULL
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
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
PWCHAR WINAPI BasepEndOfDirName(IN PWCHAR FileName)
Definition: path.c:89
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
PWCHAR WINAPI SkipPathTypeIndicator_U(IN LPWSTR Path)
Definition: path.c:740
static DWORD cchBuffer
Definition: fusion.c:85
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:175
unsigned char BOOLEAN
NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(_In_opt_ PWSTR Environment, _In_ PCUNICODE_STRING Name, _Out_ PUNICODE_STRING Value)
_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
BOOL WINAPI IsDBCSLeadByte(BYTE TestByte)
Definition: nls.c:2270
Definition: bufpool.h:45
UINT WINAPI GetSystemWow64DirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2438
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
BOOL WINAPI NeedCurrentDirectoryForExePathW(IN LPCWSTR ExeName)
Definition: path.c:957
BOOL WINAPI SetDllDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:838
return Found
Definition: dirsup.c:1270
const char * LPCSTR
Definition: xmlstorage.h:183
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2697
BOOLEAN WINAPI CheckForSameCurdir(IN PUNICODE_STRING DirName)
Definition: path.c:519
PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry
Definition: proc.c:25
_In_ LPCSTR _In_opt_ LPCSTR _In_ DWORD nBufferLength
Definition: winbase.h:3055
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
PVOID gpTermsrvGetWindowsDirectoryW
Definition: path.c:24
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
Status
Definition: gdiplustypes.h:24
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)
DWORD WINAPI GetLongPathNameW(IN LPCWSTR lpszShortPath, OUT LPWSTR lpszLongPath, IN DWORD cchBuffer)
Definition: path.c:1456
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define UNICODE_STRING_MAX_CHARS
UNICODE_STRING BaseWindowsDirectory
Definition: path.c:20
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
#define ASSERT(a)
Definition: mode.c:44
NTSTATUS NTAPI RtlSetCurrentDirectory_U(IN PUNICODE_STRING Path)
Definition: path.c:1739
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1833
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1752
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
const GLubyte * c
Definition: glext.h:8905
DWORD IllegalMask[4]
Definition: path.c:28
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
CHAR AnsiBuffer[1024]
Definition: debug.c:15
unsigned long DWORD
Definition: ntddk_ex.h:95
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define SetLastError(x)
Definition: compat.h:611
#define NT_ERROR(Status)
Definition: umtypes.h:106
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static ULONG
Definition: path.c:30
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
BASE_CURRENT_DIR_PLACEMENT BasepDllCurrentDirPlacement
Definition: path.c:81
ULONG NTAPI RtlGetCurrentDirectory_U(_In_ ULONG MaximumLength, _Out_bytecap_(MaximumLength) PWSTR Buffer)
Definition: path.c:1661
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:240
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define STATUS_VARIABLE_NOT_FOUND
Definition: ntstatus.h:492
UINT WINAPI GetSystemWow64DirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2421
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(IN PCWSTR Path)
Definition: path.c:1613
NTSTATUS NTAPI LdrEnumerateLoadedModules(IN BOOLEAN ReservedFlag, IN PLDR_ENUM_CALLBACK EnumProc, IN PVOID Context)
Definition: ldrapi.c:1120
VOID NTAPI BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry, IN PVOID Context, OUT BOOLEAN *StopEnumeration)
Definition: utils.c:156
#define wcsrchr
Definition: compat.h:16
_In_ LPCSTR _In_opt_ LPCSTR lpExtension
Definition: winbase.h:3055
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
#define Dst
Definition: mesh.h:153
RTL_CRITICAL_SECTION BaseDllDirectoryLock
Definition: dllmain.c:32
LPWSTR WINAPI BaseComputeProcessDllPath(IN LPWSTR FullPath, IN PVOID Environment)
Definition: path.c:420
enum _BASE_SEARCH_PATH_TYPE * PBASE_SEARCH_PATH_TYPE
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
PRTL_UNICODE_STRING_BUFFER Path
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
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
PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize
Definition: utils.c:28
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
#define NtCurrentPeb()
Definition: FLS.c:22
unsigned short USHORT
Definition: pedump.c:61
static calc_node_t temp
Definition: rpn_ieee.c:38
BASE_SEARCH_PATH_TYPE BaseProcessOrder[BaseSearchPathMax]
Definition: path.c:72
BOOL WINAPI SetDllDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:800
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:145
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
UNICODE_STRING BaseDefaultPathAppend
Definition: path.c:21
static const char const char * DllPath
Definition: image.c:34
UNICODE_STRING BasePathVariableName
Definition: proc.c:23
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2249
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
DWORD WINAPI GetDllDirectoryW(IN DWORD nBufferLength, OUT LPWSTR lpBuffer)
Definition: path.c:887
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2337
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1882
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define SEM_NOOPENFILEERRORBOX
Definition: rtltypes.h:72
PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
Definition: utils.c:26
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
LPWSTR WINAPI BaseComputeProcessExePath(IN LPWSTR FullPath)
Definition: path.c:405
DWORD FilenameW2A_FitOrFail(LPSTR DestA, INT destLen, LPCWSTR SourceW, INT sourceLen)
Definition: fileutils.c:98
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
DWORD WINAPI GetCurrentDirectoryW(IN DWORD nBufferLength, OUT LPWSTR lpBuffer)
Definition: path.c:2195
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
#define OUT
Definition: typedefs.h:40
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNIMPLEMENTED
Definition: debug.h:115
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:736
enum _BASE_CURRENT_DIR_PLACEMENT BASE_CURRENT_DIR_PLACEMENT
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION _In_ ULONG _Out_opt_ PULONG LengthNeeded
Definition: fltkernel.h:1342
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
UNICODE_STRING NoDefaultCurrentDirectoryInExePath
Definition: path.c:18
#define STATUS_SUCCESS
Definition: shellext.h:65
GLfloat GLfloat p
Definition: glext.h:8902
#define DPRINT
Definition: sndvol32.h:71
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:614
#define __FUNCTION__
Definition: types.h:112
#define memset(x, y, z)
Definition: compat.h:39
signed int * PLONG
Definition: retypes.h:5
BASE_SEARCH_PATH_TYPE BaseDllOrderCurrent[BaseCurrentDirPlacementMax][BaseSearchPathMax]
Definition: path.c:36
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
enum _BASE_SEARCH_PATH_TYPE BASE_SEARCH_PATH_TYPE
IN PUNICODE_STRING StaticString
LPWSTR WINAPI BasepComputeProcessPath(IN PBASE_SEARCH_PATH_TYPE PathOrder, IN LPWSTR AppName, IN LPVOID Environment)
Definition: path.c:116
_In_ LPCSTR lpFileName
Definition: winbase.h:3055
NTSTATUS NTAPI RtlDosSearchPath_Ustr(IN ULONG Flags, IN PUNICODE_STRING PathString, IN PUNICODE_STRING FileNameString, IN PUNICODE_STRING ExtensionString, IN PUNICODE_STRING CallerBuffer, IN OUT PUNICODE_STRING DynamicString OPTIONAL, OUT PUNICODE_STRING *FullNameOut OPTIONAL, OUT PSIZE_T FilePartSize OPTIONAL, OUT PSIZE_T LengthNeeded OPTIONAL)
Definition: path.c:2559
BASE_SEARCH_PATH_TYPE BaseDllOrderNoCurrent[BaseSearchPathMax]
Definition: path.c:63
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
UNICODE_STRING BaseWindowsSystemDirectory
Definition: path.c:20
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68