ReactOS  0.4.14-dev-593-g1793dcc
RtlGetFullPathName_Ustr.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: GPLv2+ - See COPYING in the top level directory
4  * PURPOSE: Test for RtlGetFullPathName_Ustr
5  * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 /*
11 ULONG
12 NTAPI
13 RtlGetFullPathName_Ustr(
14  IN PCUNICODE_STRING FileName,
15  IN ULONG Size,
16  IN PWSTR Buffer,
17  OUT PCWSTR *ShortName,
18  OUT PBOOLEAN InvalidName,
19  OUT RTL_PATH_TYPE* PathType
20 );
21 */
22 
23 /* This seems to be a struct of some kind in Windows 7... returns 0 or 32 in the second member */
24 typedef struct _PATH_TYPE_AND_UNKNOWN
25 {
29 
30 static
31 ULONG
32 (NTAPI
36  IN PWSTR Buffer,
40 )
41 //= (PVOID)0x7c83086c // 2003 sp1 x86
42 //= (PVOID)0x77ef49f0 // 2003 sp1 x64
43 //= (PVOID)0x7769a3dd // win7 sp1 wow64
44 ;
45 
46 #define ok_eq_ustr(str1, str2) do { \
47  ok((str1)->Buffer == (str2)->Buffer, "Buffer modified\n"); \
48  ok((str1)->Length == (str2)->Length, "Length modified\n"); \
49  ok((str1)->MaximumLength == (str2)->MaximumLength, "MaximumLength modified\n"); \
50  } while (0)
51 
52 static
53 BOOLEAN
55  PCWSTR Buffer,
56  SIZE_T Length,
59 {
60  SIZE_T ExpectedLength = wcslen(Expected) * sizeof(WCHAR);
61  SIZE_T EqualLength;
63  SIZE_T i;
64 
65  if (Length != ExpectedLength)
66  {
67  ok(0, "String length is %lu, expected %lu\n", (ULONG)Length, (ULONG)ExpectedLength);
68  Result = FALSE;
69  }
70 
71  EqualLength = RtlCompareMemory(Buffer, Expected, Length);
72  if (EqualLength != Length)
73  {
74  ok(0, "String is '%S', expected '%S'\n", Buffer, Expected);
75  Result = FALSE;
76  }
77 
78  if (Buffer[Length / sizeof(WCHAR)] != UNICODE_NULL)
79  {
80  ok(0, "Not null terminated\n");
81  Result = FALSE;
82  }
83 
84  /* The function nulls the rest of the buffer! */
85  for (i = Length + sizeof(UNICODE_NULL); i < MaximumLength; i++)
86  {
87  UCHAR Char = ((PUCHAR)Buffer)[i];
88  if (Char != 0)
89  {
90  ok(0, "Found 0x%x at offset %lu, expected 0x%x\n", Char, (ULONG)i, 0);
91  /* Don't count this as a failure unless the string was actually wrong */
92  //Result = FALSE;
93  /* Don't flood the log */
94  break;
95  }
96  }
97 
98  return Result;
99 }
100 
101 static
102 BOOLEAN
104  PVOID Buffer,
105  SIZE_T Size,
106  UCHAR Value)
107 {
108  PUCHAR Array = Buffer;
109  SIZE_T i;
110 
111  for (i = 0; i < Size; i++)
112  if (Array[i] != Value)
113  {
114  trace("Expected %x, found %x at offset %lu\n", Value, Array[i], (ULONG)i);
115  return FALSE;
116  }
117  return TRUE;
118 }
119 
120 #define RtlPathTypeNotSet 123
121 
122 /* winetest_platform is "windows" for us, so broken() doesn't do what it should :( */
123 #undef broken
124 #define broken(x) 0
125 
126 typedef enum
127 {
132 } PREFIX_TYPE;
133 
134 static
135 VOID
137 {
138  /* TODO: don't duplicate this in the other tests */
139  /* TODO: Drive Relative tests don't work yet if the current drive isn't C: */
140  struct
141  {
143  PREFIX_TYPE PrefixType;
144  PCWSTR FullPathName;
146  PREFIX_TYPE FilePartPrefixType;
147  SIZE_T FilePartSize;
148  } TestCases[] =
149  {
151  { L"C:\\", PrefixNone, L"C:\\", RtlPathTypeDriveAbsolute },
152  { L"C:\\test", PrefixNone, L"C:\\test", RtlPathTypeDriveAbsolute, PrefixCurrentDrive },
153  { L"C:\\test\\", PrefixNone, L"C:\\test\\", RtlPathTypeDriveAbsolute },
154  { L"C:/test/", PrefixNone, L"C:\\test\\", RtlPathTypeDriveAbsolute },
155 
156  { L"C:\\\\test", PrefixNone, L"C:\\test", RtlPathTypeDriveAbsolute, PrefixCurrentDrive },
157  { L"test", PrefixCurrentPath, L"\\test", RtlPathTypeRelative, PrefixCurrentPath, sizeof(WCHAR) },
160  { L".\\test", PrefixCurrentPath, L"\\test", RtlPathTypeRelative, PrefixCurrentPath, sizeof(WCHAR) },
161 
162  { L"\\.", PrefixCurrentDrive, L"", RtlPathTypeRooted },
163  { L"\\.\\", PrefixCurrentDrive, L"", RtlPathTypeRooted },
164  { L"\\\\.", PrefixNone, L"\\\\.\\", RtlPathTypeRootLocalDevice },
165  { L"\\\\.\\", PrefixNone, L"\\\\.\\", RtlPathTypeLocalDevice },
166  { L"\\\\.\\Something\\", PrefixNone, L"\\\\.\\Something\\", RtlPathTypeLocalDevice },
167 
168  { L"\\??\\", PrefixCurrentDrive, L"??\\", RtlPathTypeRooted },
169  { L"\\??\\C:", PrefixCurrentDrive, L"??\\C:", RtlPathTypeRooted, PrefixCurrentDrive, 3 * sizeof(WCHAR) },
170  { L"\\??\\C:\\", PrefixCurrentDrive, L"??\\C:\\", RtlPathTypeRooted },
171  { L"\\??\\C:\\test", PrefixCurrentDrive, L"??\\C:\\test", RtlPathTypeRooted, PrefixCurrentDrive, 6 * sizeof(WCHAR) },
172  { L"\\??\\C:\\test\\", PrefixCurrentDrive, L"??\\C:\\test\\", RtlPathTypeRooted },
173 
174  { L"\\\\??\\", PrefixNone, L"\\\\??\\", RtlPathTypeUncAbsolute },
175  { L"\\\\??\\C:", PrefixNone, L"\\\\??\\C:", RtlPathTypeUncAbsolute },
176  { L"\\\\??\\C:\\", PrefixNone, L"\\\\??\\C:\\", RtlPathTypeUncAbsolute },
177  { L"\\\\??\\C:\\test", PrefixNone, L"\\\\??\\C:\\test", RtlPathTypeUncAbsolute, PrefixNone, sizeof(L"\\\\??\\C:\\") },
178  { L"\\\\??\\C:\\test\\", PrefixNone, L"\\\\??\\C:\\test\\", RtlPathTypeUncAbsolute },
179  };
180  ULONG Length;
182  WCHAR FullPathNameBuffer[MAX_PATH];
183  UNICODE_STRING TempString;
184  const WCHAR *ShortName;
187  WCHAR ExpectedPathName[MAX_PATH];
188  SIZE_T ExpectedFilePartSize;
189  const WCHAR *ExpectedShortName;
190  const INT TestCount = sizeof(TestCases) / sizeof(TestCases[0]);
191  INT i;
192  BOOLEAN Okay;
193 
194  for (i = 0; i < TestCount; i++)
195  {
196  trace("i = %d\n", i);
197  switch (TestCases[i].PrefixType)
198  {
199  case PrefixNone:
200  ExpectedPathName[0] = UNICODE_NULL;
201  break;
202  case PrefixCurrentDrive:
203  GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
204  ExpectedPathName[3] = UNICODE_NULL;
205  break;
206  case PrefixCurrentPath:
207  {
208  ULONG Length;
209  Length = GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
210  if (Length == 3 && TestCases[i].FullPathName[0])
211  ExpectedPathName[2] = UNICODE_NULL;
212  break;
213  }
214  default:
215  skip("Invalid test!\n");
216  continue;
217  }
218  wcscat(ExpectedPathName, TestCases[i].FullPathName);
220  RtlFillMemory(FullPathNameBuffer, sizeof(FullPathNameBuffer), 0xAA);
221  TempString = FileName;
223  PathType.Unknown = 1234;
225  NameInvalid = (BOOLEAN)-1;
226  Length = 1234;
227  StartSeh()
229  sizeof(FullPathNameBuffer),
230  FullPathNameBuffer,
231  &ShortName,
232  &NameInvalid,
233  &PathType);
235  ok_eq_ustr(&FileName, &TempString);
236  Okay = CheckStringBuffer(FullPathNameBuffer, Length, sizeof(FullPathNameBuffer), ExpectedPathName);
237  ok(Okay, "Wrong path name '%S', expected '%S'\n", FullPathNameBuffer, ExpectedPathName);
238  switch (TestCases[i].FilePartPrefixType)
239  {
240  case PrefixNone:
241  ExpectedFilePartSize = 0;
242  break;
243  case PrefixCurrentDrive:
244  ExpectedFilePartSize = sizeof(L"C:\\");
245  break;
246  case PrefixCurrentPath:
247  ExpectedFilePartSize = GetCurrentDirectoryW(0, NULL) * sizeof(WCHAR);
248  if (ExpectedFilePartSize == sizeof(L"C:\\"))
249  ExpectedFilePartSize -= sizeof(WCHAR);
250  break;
252  {
253  WCHAR CurrentPath[MAX_PATH];
255  ExpectedFilePartSize = GetCurrentDirectoryW(sizeof(CurrentPath) / sizeof(WCHAR), CurrentPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
256  if (ExpectedFilePartSize == sizeof(L"C:\\"))
257  ExpectedFilePartSize = 0;
258  else
259  {
260  BackSlash = wcsrchr(CurrentPath, L'\\');
261  if (BackSlash)
262  ExpectedFilePartSize -= wcslen(BackSlash + 1) * sizeof(WCHAR);
263  else
264  ok(0, "GetCurrentDirectory returned %S\n", CurrentPath);
265  }
266  break;
267  }
268  default:
269  skip("Invalid test!\n");
270  continue;
271  }
272  ExpectedFilePartSize += TestCases[i].FilePartSize;
273  if (ExpectedFilePartSize == 0)
274  {
275  ExpectedShortName = NULL;
276  }
277  else
278  {
279  ExpectedFilePartSize = (ExpectedFilePartSize - sizeof(UNICODE_NULL)) / sizeof(WCHAR);
280  ExpectedShortName = FullPathNameBuffer + ExpectedFilePartSize;
281  }
282  ok(ShortName == ExpectedShortName,
283  "ShortName = %p, expected %p\n", ShortName, ExpectedShortName);
284  ok(NameInvalid == FALSE, "NameInvalid = %u\n", NameInvalid);
285  ok(PathType.Type == TestCases[i].PathType, "PathType = %d, expected %d\n", PathType.Type, TestCases[i].PathType);
286  ok(PathType.Unknown == 1234 ||
287  broken(PathType.Unknown == 0) ||
288  broken(PathType.Unknown == 32), "Unknown = %lu\n", PathType.Unknown);
289  }
290 }
291 
293 {
294  ULONG Length;
296  UNICODE_STRING TempString;
299  BOOLEAN NameInvalidArray[sizeof(ULONGLONG)];
301  BOOLEAN Okay;
302 
304  {
305  RtlGetFullPathName_Ustr = (PVOID)GetProcAddress(GetModuleHandleW(L"ntdll"), "RtlGetFullPathName_Ustr");
307  {
308  skip("RtlGetFullPathName_Ustr unavailable\n");
309  return;
310  }
311  }
312 
313  /* NULL parameters */
314  StartSeh()
317 
319  TempString = FileName;
320  StartSeh()
323  ok_eq_ustr(&FileName, &TempString);
324 
326  TempString = FileName;
327  StartSeh()
330  ok_eq_ustr(&FileName, &TempString);
331 
333  PathType.Unknown = 1234;
334  StartSeh()
337  ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
338  ok(PathType.Unknown == 1234 ||
339  broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %lu\n", PathType.Unknown);
340 
341  /* check what else is initialized before it crashes */
343  PathType.Unknown = 1234;
345  NameInvalid = (BOOLEAN)-1;
346  StartSeh()
349  ok(NameInvalid == FALSE, "NameInvalid = %u\n", NameInvalid);
351  broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
352  ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
353  ok(PathType.Unknown == 1234 ||
354  broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %lu\n", PathType.Unknown);
355 
357  TempString = FileName;
359  NameInvalid = (BOOLEAN)-1;
360  StartSeh()
363  ok_eq_ustr(&FileName, &TempString);
365  broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
366  ok(NameInvalid == FALSE, "NameInvalid = %u\n", NameInvalid);
367 
368  /* This is the first one that doesn't crash. FileName and PathType cannot be NULL */
370  TempString = FileName;
372  PathType.Unknown = 1234;
373  StartSeh()
375  ok(Length == 0, "Length = %lu\n", Length);
377  ok_eq_ustr(&FileName, &TempString);
378  ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
379  ok(PathType.Unknown == 1234 ||
380  broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %lu\n", PathType.Unknown);
381 
383  TempString = FileName;
385  PathType.Unknown = 1234;
386  StartSeh()
388  ok(Length == 0, "Length = %lu\n", Length);
390  ok_eq_ustr(&FileName, &TempString);
391  ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
392  ok(PathType.Unknown == 1234 ||
393  broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %lu\n", PathType.Unknown);
394 
395  /* Show that NameInvalid is indeed BOOLEAN */
397  TempString = FileName;
399  PathType.Unknown = 1234;
400  RtlFillMemory(NameInvalidArray, sizeof(NameInvalidArray), 0x55);
401  StartSeh()
402  Length = RtlGetFullPathName_Ustr(&FileName, 0, NULL, NULL, NameInvalidArray, &PathType);
403  ok(Length == 0, "Length = %lu\n", Length);
405  ok_eq_ustr(&FileName, &TempString);
406  ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
407  ok(PathType.Unknown == 1234 ||
408  broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %lu\n", PathType.Unknown);
409  ok(NameInvalidArray[0] == FALSE, "NameInvalid = %u\n", NameInvalidArray[0]);
410  Okay = CheckBuffer(NameInvalidArray + 1, sizeof(NameInvalidArray) - sizeof(NameInvalidArray[0]), 0x55);
411  ok(Okay, "CheckBuffer failed\n");
412 
413  /* Give it a valid path */
414  RtlInitUnicodeString(&FileName, L"C:\\test");
415  TempString = FileName;
417  PathType.Unknown = 1234;
418  StartSeh()
420  ok(Length == sizeof(L"C:\\test"), "Length = %lu\n", Length);
422  ok_eq_ustr(&FileName, &TempString);
423  ok(PathType.Type == RtlPathTypeDriveAbsolute, "PathType = %d\n", PathType.Type);
424  ok(PathType.Unknown == 1234 ||
425  broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %lu\n", PathType.Unknown);
426 
427  /* check the actual functionality with different paths */
428  RunTestCases();
429 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
static BOOLEAN CheckBuffer(PVOID Buffer, SIZE_T Size, UCHAR Value)
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN InvalidName
enum _RTL_PATH_TYPE RTL_PATH_TYPE
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
static IN ULONG Size
uint16_t * PWSTR
Definition: typedefs.h:54
unsigned char * PUCHAR
Definition: retypes.h:3
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:421
ULONG NTAPI RtlGetFullPathName_Ustr(_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
Definition: path.c:615
#define StartSeh()
Definition: _sntprintf.h:16
static IN ULONG IN PWSTR Buffer
int32_t INT
Definition: typedefs.h:56
static ULONG(NTAPI *RtlGetFullPathName_Ustr)(IN PCUNICODE_STRING FileName
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
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
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
static BOOLEAN CheckStringBuffer(PCWSTR Buffer, SIZE_T Length, SIZE_T MaximumLength, PCWSTR Expected)
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_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
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
#define InvalidPointer
#define trace
Definition: atltest.h:70
__wchar_t WCHAR
Definition: xmlstorage.h:180
uint64_t ULONGLONG
Definition: typedefs.h:65
#define MAX_PATH
Definition: compat.h:26
#define RtlPathTypeNotSet
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static TEST_CASE TestCases[]
Definition: CommandLine.c:101
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
static const WCHAR L[]
Definition: oid.c:1250
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
static VOID RunTestCases(VOID)
UnicodeString MaximumLength
Definition: rtlfuncs.h:2982
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define broken(x)
struct _FileName FileName
Definition: fatprocs.h:884
static IN ULONG IN PWSTR OUT PCWSTR * ShortName
IN PUNICODE_STRING IN PUNICODE_STRING IN PUNICODE_STRING IN PSIZE_T FilePartSize OUT PBOOLEAN NameInvalid
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
#define ok(value,...)
Definition: atltest.h:57
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
START_TEST(RtlGetFullPathName_Ustr)
struct _PATH_TYPE_AND_UNKNOWN PATH_TYPE_AND_UNKNOWN
#define skip(...)
Definition: atltest.h:64
#define BOOLEAN
Definition: pedump.c:73
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:847
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define GetProcAddress(x, y)
Definition: compat.h:418
BOOLEAN Expected
static const WCHAR BackSlash[]
Definition: devclass.c:29
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ok_eq_ustr(str1, str2)
#define EndSeh(ExpectedStatus)
Definition: _sntprintf.h:17