xref: /reactos/dll/win32/kernel32/client/dosdev.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3*c2c66affSColin Finck  * PROJECT:         ReactOS system libraries
4*c2c66affSColin Finck  * FILE:            dll/win32/kernel32/client/dosdev.c
5*c2c66affSColin Finck  * PURPOSE:         Dos device functions
6*c2c66affSColin Finck  * PROGRAMMER:      Ariadne (ariadne@xs4all.nl)
7*c2c66affSColin Finck  * UPDATE HISTORY:
8*c2c66affSColin Finck  *                  Created 01/11/98
9*c2c66affSColin Finck  */
10*c2c66affSColin Finck 
11*c2c66affSColin Finck /* INCLUDES ******************************************************************/
12*c2c66affSColin Finck 
13*c2c66affSColin Finck #include <k32.h>
14*c2c66affSColin Finck 
15*c2c66affSColin Finck #define NDEBUG
16*c2c66affSColin Finck #include <debug.h>
17*c2c66affSColin Finck #include <dbt.h>
18*c2c66affSColin Finck DEBUG_CHANNEL(kernel32file);
19*c2c66affSColin Finck 
20*c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
21*c2c66affSColin Finck 
22*c2c66affSColin Finck /*
23*c2c66affSColin Finck  * @implemented
24*c2c66affSColin Finck  */
25*c2c66affSColin Finck BOOL
26*c2c66affSColin Finck WINAPI
27*c2c66affSColin Finck DefineDosDeviceA(
28*c2c66affSColin Finck     DWORD dwFlags,
29*c2c66affSColin Finck     LPCSTR lpDeviceName,
30*c2c66affSColin Finck     LPCSTR lpTargetPath
31*c2c66affSColin Finck     )
32*c2c66affSColin Finck {
33*c2c66affSColin Finck     UNICODE_STRING DeviceNameU = {0};
34*c2c66affSColin Finck     UNICODE_STRING TargetPathU = {0};
35*c2c66affSColin Finck     BOOL Result;
36*c2c66affSColin Finck 
37*c2c66affSColin Finck     if (lpDeviceName &&
38*c2c66affSColin Finck         !RtlCreateUnicodeStringFromAsciiz(&DeviceNameU, lpDeviceName))
39*c2c66affSColin Finck     {
40*c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
41*c2c66affSColin Finck         return 0;
42*c2c66affSColin Finck     }
43*c2c66affSColin Finck 
44*c2c66affSColin Finck     if (lpTargetPath &&
45*c2c66affSColin Finck         !RtlCreateUnicodeStringFromAsciiz(&TargetPathU, lpTargetPath))
46*c2c66affSColin Finck     {
47*c2c66affSColin Finck         if (DeviceNameU.Buffer)
48*c2c66affSColin Finck         {
49*c2c66affSColin Finck             RtlFreeUnicodeString(&DeviceNameU);
50*c2c66affSColin Finck         }
51*c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
52*c2c66affSColin Finck         return 0;
53*c2c66affSColin Finck     }
54*c2c66affSColin Finck 
55*c2c66affSColin Finck     Result = DefineDosDeviceW(dwFlags,
56*c2c66affSColin Finck                               DeviceNameU.Buffer,
57*c2c66affSColin Finck                               TargetPathU.Buffer);
58*c2c66affSColin Finck 
59*c2c66affSColin Finck     if (TargetPathU.Buffer)
60*c2c66affSColin Finck     {
61*c2c66affSColin Finck         RtlFreeUnicodeString(&TargetPathU);
62*c2c66affSColin Finck     }
63*c2c66affSColin Finck 
64*c2c66affSColin Finck     if (DeviceNameU.Buffer)
65*c2c66affSColin Finck     {
66*c2c66affSColin Finck         RtlFreeUnicodeString(&DeviceNameU);
67*c2c66affSColin Finck     }
68*c2c66affSColin Finck     return Result;
69*c2c66affSColin Finck }
70*c2c66affSColin Finck 
71*c2c66affSColin Finck 
72*c2c66affSColin Finck /*
73*c2c66affSColin Finck  * @implemented
74*c2c66affSColin Finck  */
75*c2c66affSColin Finck BOOL
76*c2c66affSColin Finck WINAPI
77*c2c66affSColin Finck DefineDosDeviceW(
78*c2c66affSColin Finck     DWORD dwFlags,
79*c2c66affSColin Finck     LPCWSTR lpDeviceName,
80*c2c66affSColin Finck     LPCWSTR lpTargetPath
81*c2c66affSColin Finck     )
82*c2c66affSColin Finck {
83*c2c66affSColin Finck     ULONG ArgumentCount;
84*c2c66affSColin Finck     ULONG BufferSize;
85*c2c66affSColin Finck     BASE_API_MESSAGE ApiMessage;
86*c2c66affSColin Finck     PBASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest = &ApiMessage.Data.DefineDosDeviceRequest;
87*c2c66affSColin Finck     PCSR_CAPTURE_BUFFER CaptureBuffer;
88*c2c66affSColin Finck     UNICODE_STRING NtTargetPathU;
89*c2c66affSColin Finck     UNICODE_STRING DeviceNameU;
90*c2c66affSColin Finck     UNICODE_STRING DeviceUpcaseNameU;
91*c2c66affSColin Finck     HANDLE hUser32;
92*c2c66affSColin Finck     DEV_BROADCAST_VOLUME dbcv;
93*c2c66affSColin Finck     BOOL Result = TRUE;
94*c2c66affSColin Finck     DWORD dwRecipients;
95*c2c66affSColin Finck     typedef long (WINAPI *BSM_type)(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
96*c2c66affSColin Finck     BSM_type BSM_ptr;
97*c2c66affSColin Finck 
98*c2c66affSColin Finck     if ( (dwFlags & 0xFFFFFFF0) ||
99*c2c66affSColin Finck         ((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
100*c2c66affSColin Finck         ! (dwFlags & DDD_REMOVE_DEFINITION)) )
101*c2c66affSColin Finck     {
102*c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
103*c2c66affSColin Finck         return FALSE;
104*c2c66affSColin Finck     }
105*c2c66affSColin Finck 
106*c2c66affSColin Finck     ArgumentCount = 1;
107*c2c66affSColin Finck     BufferSize = 0;
108*c2c66affSColin Finck     if (!lpTargetPath)
109*c2c66affSColin Finck     {
110*c2c66affSColin Finck         RtlInitUnicodeString(&NtTargetPathU,
111*c2c66affSColin Finck                              NULL);
112*c2c66affSColin Finck     }
113*c2c66affSColin Finck     else
114*c2c66affSColin Finck     {
115*c2c66affSColin Finck         if (dwFlags & DDD_RAW_TARGET_PATH)
116*c2c66affSColin Finck         {
117*c2c66affSColin Finck             RtlInitUnicodeString(&NtTargetPathU,
118*c2c66affSColin Finck                                  lpTargetPath);
119*c2c66affSColin Finck         }
120*c2c66affSColin Finck         else
121*c2c66affSColin Finck         {
122*c2c66affSColin Finck             if (!RtlDosPathNameToNtPathName_U(lpTargetPath,
123*c2c66affSColin Finck                                               &NtTargetPathU,
124*c2c66affSColin Finck                                               NULL,
125*c2c66affSColin Finck                                               NULL))
126*c2c66affSColin Finck             {
127*c2c66affSColin Finck                 WARN("RtlDosPathNameToNtPathName_U() failed\n");
128*c2c66affSColin Finck                 BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
129*c2c66affSColin Finck                 return FALSE;
130*c2c66affSColin Finck             }
131*c2c66affSColin Finck         }
132*c2c66affSColin Finck         ArgumentCount = 2;
133*c2c66affSColin Finck         BufferSize += NtTargetPathU.Length;
134*c2c66affSColin Finck     }
135*c2c66affSColin Finck 
136*c2c66affSColin Finck     RtlInitUnicodeString(&DeviceNameU,
137*c2c66affSColin Finck                          lpDeviceName);
138*c2c66affSColin Finck     RtlUpcaseUnicodeString(&DeviceUpcaseNameU,
139*c2c66affSColin Finck                            &DeviceNameU,
140*c2c66affSColin Finck                            TRUE);
141*c2c66affSColin Finck     BufferSize += DeviceUpcaseNameU.Length;
142*c2c66affSColin Finck 
143*c2c66affSColin Finck     CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount,
144*c2c66affSColin Finck                                              BufferSize);
145*c2c66affSColin Finck     if (!CaptureBuffer)
146*c2c66affSColin Finck     {
147*c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
148*c2c66affSColin Finck         Result = FALSE;
149*c2c66affSColin Finck     }
150*c2c66affSColin Finck     else
151*c2c66affSColin Finck     {
152*c2c66affSColin Finck         DefineDosDeviceRequest->Flags = dwFlags;
153*c2c66affSColin Finck 
154*c2c66affSColin Finck         CsrCaptureMessageBuffer(CaptureBuffer,
155*c2c66affSColin Finck                                 DeviceUpcaseNameU.Buffer,
156*c2c66affSColin Finck                                 DeviceUpcaseNameU.Length,
157*c2c66affSColin Finck                                 (PVOID*)&DefineDosDeviceRequest->DeviceName.Buffer);
158*c2c66affSColin Finck 
159*c2c66affSColin Finck         DefineDosDeviceRequest->DeviceName.Length =
160*c2c66affSColin Finck             DeviceUpcaseNameU.Length;
161*c2c66affSColin Finck         DefineDosDeviceRequest->DeviceName.MaximumLength =
162*c2c66affSColin Finck             DeviceUpcaseNameU.Length;
163*c2c66affSColin Finck 
164*c2c66affSColin Finck         if (NtTargetPathU.Buffer)
165*c2c66affSColin Finck         {
166*c2c66affSColin Finck             CsrCaptureMessageBuffer(CaptureBuffer,
167*c2c66affSColin Finck                                     NtTargetPathU.Buffer,
168*c2c66affSColin Finck                                     NtTargetPathU.Length,
169*c2c66affSColin Finck                                     (PVOID*)&DefineDosDeviceRequest->TargetPath.Buffer);
170*c2c66affSColin Finck         }
171*c2c66affSColin Finck         DefineDosDeviceRequest->TargetPath.Length =
172*c2c66affSColin Finck             NtTargetPathU.Length;
173*c2c66affSColin Finck         DefineDosDeviceRequest->TargetPath.MaximumLength =
174*c2c66affSColin Finck             NtTargetPathU.Length;
175*c2c66affSColin Finck 
176*c2c66affSColin Finck         CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
177*c2c66affSColin Finck                             CaptureBuffer,
178*c2c66affSColin Finck                             CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepDefineDosDevice),
179*c2c66affSColin Finck                             sizeof(*DefineDosDeviceRequest));
180*c2c66affSColin Finck         CsrFreeCaptureBuffer(CaptureBuffer);
181*c2c66affSColin Finck 
182*c2c66affSColin Finck         if (!NT_SUCCESS(ApiMessage.Status))
183*c2c66affSColin Finck         {
184*c2c66affSColin Finck             WARN("CsrClientCallServer() failed (Status %lx)\n", ApiMessage.Status);
185*c2c66affSColin Finck             BaseSetLastNTError(ApiMessage.Status);
186*c2c66affSColin Finck             Result = FALSE;
187*c2c66affSColin Finck         }
188*c2c66affSColin Finck         else
189*c2c66affSColin Finck         {
190*c2c66affSColin Finck             if (! (dwFlags & DDD_NO_BROADCAST_SYSTEM) &&
191*c2c66affSColin Finck                 DeviceUpcaseNameU.Length == 2 * sizeof(WCHAR) &&
192*c2c66affSColin Finck                 DeviceUpcaseNameU.Buffer[1] == L':' &&
193*c2c66affSColin Finck                 ( (DeviceUpcaseNameU.Buffer[0] - L'A') < 26 ))
194*c2c66affSColin Finck             {
195*c2c66affSColin Finck                 hUser32 = LoadLibraryA("user32.dll");
196*c2c66affSColin Finck                 if (hUser32)
197*c2c66affSColin Finck                 {
198*c2c66affSColin Finck                     BSM_ptr = (BSM_type)
199*c2c66affSColin Finck                         GetProcAddress(hUser32, "BroadcastSystemMessageW");
200*c2c66affSColin Finck                     if (BSM_ptr)
201*c2c66affSColin Finck                     {
202*c2c66affSColin Finck                         dwRecipients = BSM_APPLICATIONS;
203*c2c66affSColin Finck                         dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
204*c2c66affSColin Finck                         dbcv.dbcv_devicetype = DBT_DEVTYP_VOLUME;
205*c2c66affSColin Finck                         dbcv.dbcv_reserved = 0;
206*c2c66affSColin Finck                         dbcv.dbcv_unitmask |=
207*c2c66affSColin Finck                             (1 << (DeviceUpcaseNameU.Buffer[0] - L'A'));
208*c2c66affSColin Finck                         dbcv.dbcv_flags = DBTF_NET;
209*c2c66affSColin Finck                         (void) BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK,
210*c2c66affSColin Finck                                        &dwRecipients,
211*c2c66affSColin Finck                                        WM_DEVICECHANGE,
212*c2c66affSColin Finck                                        (WPARAM)DBT_DEVICEARRIVAL,
213*c2c66affSColin Finck                                        (LPARAM)&dbcv);
214*c2c66affSColin Finck                     }
215*c2c66affSColin Finck                     FreeLibrary(hUser32);
216*c2c66affSColin Finck                 }
217*c2c66affSColin Finck             }
218*c2c66affSColin Finck         }
219*c2c66affSColin Finck     }
220*c2c66affSColin Finck 
221*c2c66affSColin Finck     if (NtTargetPathU.Buffer &&
222*c2c66affSColin Finck         NtTargetPathU.Buffer != lpTargetPath)
223*c2c66affSColin Finck     {
224*c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(),
225*c2c66affSColin Finck                     0,
226*c2c66affSColin Finck                     NtTargetPathU.Buffer);
227*c2c66affSColin Finck     }
228*c2c66affSColin Finck     RtlFreeUnicodeString(&DeviceUpcaseNameU);
229*c2c66affSColin Finck     return Result;
230*c2c66affSColin Finck }
231*c2c66affSColin Finck 
232*c2c66affSColin Finck 
233*c2c66affSColin Finck /*
234*c2c66affSColin Finck  * @implemented
235*c2c66affSColin Finck  */
236*c2c66affSColin Finck DWORD
237*c2c66affSColin Finck WINAPI
238*c2c66affSColin Finck QueryDosDeviceA(
239*c2c66affSColin Finck     LPCSTR lpDeviceName,
240*c2c66affSColin Finck     LPSTR lpTargetPath,
241*c2c66affSColin Finck     DWORD ucchMax
242*c2c66affSColin Finck     )
243*c2c66affSColin Finck {
244*c2c66affSColin Finck     UNICODE_STRING DeviceNameU;
245*c2c66affSColin Finck     UNICODE_STRING TargetPathU;
246*c2c66affSColin Finck     ANSI_STRING TargetPathA;
247*c2c66affSColin Finck     DWORD Length;
248*c2c66affSColin Finck     DWORD CurrentLength;
249*c2c66affSColin Finck     PWCHAR Buffer;
250*c2c66affSColin Finck 
251*c2c66affSColin Finck     if (lpDeviceName)
252*c2c66affSColin Finck     {
253*c2c66affSColin Finck         if (!RtlCreateUnicodeStringFromAsciiz(&DeviceNameU,
254*c2c66affSColin Finck                                               (LPSTR)lpDeviceName))
255*c2c66affSColin Finck         {
256*c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
257*c2c66affSColin Finck             return 0;
258*c2c66affSColin Finck         }
259*c2c66affSColin Finck     }
260*c2c66affSColin Finck     Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ucchMax * sizeof(WCHAR));
261*c2c66affSColin Finck     if (Buffer == NULL)
262*c2c66affSColin Finck     {
263*c2c66affSColin Finck         if (lpDeviceName)
264*c2c66affSColin Finck         {
265*c2c66affSColin Finck             RtlFreeHeap(RtlGetProcessHeap(), 0, DeviceNameU.Buffer);
266*c2c66affSColin Finck         }
267*c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
268*c2c66affSColin Finck         return 0;
269*c2c66affSColin Finck     }
270*c2c66affSColin Finck 
271*c2c66affSColin Finck     Length = QueryDosDeviceW(lpDeviceName ? DeviceNameU.Buffer : NULL,
272*c2c66affSColin Finck                              Buffer, ucchMax);
273*c2c66affSColin Finck     if (Length != 0)
274*c2c66affSColin Finck     {
275*c2c66affSColin Finck         TargetPathA.Buffer = lpTargetPath;
276*c2c66affSColin Finck         TargetPathU.Buffer = Buffer;
277*c2c66affSColin Finck         ucchMax = Length;
278*c2c66affSColin Finck 
279*c2c66affSColin Finck         while (ucchMax)
280*c2c66affSColin Finck         {
281*c2c66affSColin Finck             CurrentLength = min(ucchMax, MAXUSHORT / 2);
282*c2c66affSColin Finck             TargetPathU.MaximumLength = TargetPathU.Length = (USHORT)CurrentLength * sizeof(WCHAR);
283*c2c66affSColin Finck 
284*c2c66affSColin Finck             TargetPathA.Length = 0;
285*c2c66affSColin Finck             TargetPathA.MaximumLength = (USHORT)CurrentLength;
286*c2c66affSColin Finck 
287*c2c66affSColin Finck             RtlUnicodeStringToAnsiString(&TargetPathA, &TargetPathU, FALSE);
288*c2c66affSColin Finck             ucchMax -= CurrentLength;
289*c2c66affSColin Finck             TargetPathA.Buffer += TargetPathA.Length;
290*c2c66affSColin Finck             TargetPathU.Buffer += TargetPathU.Length / sizeof(WCHAR);
291*c2c66affSColin Finck         }
292*c2c66affSColin Finck     }
293*c2c66affSColin Finck 
294*c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
295*c2c66affSColin Finck     if (lpDeviceName)
296*c2c66affSColin Finck     {
297*c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, DeviceNameU.Buffer);
298*c2c66affSColin Finck     }
299*c2c66affSColin Finck     return Length;
300*c2c66affSColin Finck }
301*c2c66affSColin Finck 
302*c2c66affSColin Finck 
303*c2c66affSColin Finck /*
304*c2c66affSColin Finck  * @implemented
305*c2c66affSColin Finck  */
306*c2c66affSColin Finck DWORD
307*c2c66affSColin Finck WINAPI
308*c2c66affSColin Finck QueryDosDeviceW(
309*c2c66affSColin Finck     LPCWSTR lpDeviceName,
310*c2c66affSColin Finck     LPWSTR lpTargetPath,
311*c2c66affSColin Finck     DWORD ucchMax
312*c2c66affSColin Finck     )
313*c2c66affSColin Finck {
314*c2c66affSColin Finck     POBJECT_DIRECTORY_INFORMATION DirInfo;
315*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
316*c2c66affSColin Finck     UNICODE_STRING UnicodeString;
317*c2c66affSColin Finck     HANDLE DirectoryHandle;
318*c2c66affSColin Finck     HANDLE DeviceHandle;
319*c2c66affSColin Finck     ULONG ReturnLength;
320*c2c66affSColin Finck     ULONG NameLength;
321*c2c66affSColin Finck     ULONG Length;
322*c2c66affSColin Finck     ULONG Context;
323*c2c66affSColin Finck     BOOLEAN RestartScan;
324*c2c66affSColin Finck     NTSTATUS Status;
325*c2c66affSColin Finck     UCHAR Buffer[512];
326*c2c66affSColin Finck     PWSTR Ptr;
327*c2c66affSColin Finck 
328*c2c66affSColin Finck     /* Open the '\??' directory */
329*c2c66affSColin Finck     RtlInitUnicodeString(&UnicodeString, L"\\??");
330*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
331*c2c66affSColin Finck                                &UnicodeString,
332*c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
333*c2c66affSColin Finck                                NULL,
334*c2c66affSColin Finck                                NULL);
335*c2c66affSColin Finck     Status = NtOpenDirectoryObject(&DirectoryHandle,
336*c2c66affSColin Finck                                    DIRECTORY_QUERY,
337*c2c66affSColin Finck                                    &ObjectAttributes);
338*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
339*c2c66affSColin Finck     {
340*c2c66affSColin Finck         WARN("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
341*c2c66affSColin Finck         BaseSetLastNTError(Status);
342*c2c66affSColin Finck         return 0;
343*c2c66affSColin Finck     }
344*c2c66affSColin Finck 
345*c2c66affSColin Finck     Length = 0;
346*c2c66affSColin Finck 
347*c2c66affSColin Finck     if (lpDeviceName != NULL)
348*c2c66affSColin Finck     {
349*c2c66affSColin Finck         /* Open the lpDeviceName link object */
350*c2c66affSColin Finck         RtlInitUnicodeString(&UnicodeString, (PWSTR)lpDeviceName);
351*c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
352*c2c66affSColin Finck                                    &UnicodeString,
353*c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
354*c2c66affSColin Finck                                    DirectoryHandle,
355*c2c66affSColin Finck                                    NULL);
356*c2c66affSColin Finck         Status = NtOpenSymbolicLinkObject(&DeviceHandle,
357*c2c66affSColin Finck                                           SYMBOLIC_LINK_QUERY,
358*c2c66affSColin Finck                                           &ObjectAttributes);
359*c2c66affSColin Finck         if (!NT_SUCCESS(Status))
360*c2c66affSColin Finck         {
361*c2c66affSColin Finck             WARN("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status);
362*c2c66affSColin Finck             NtClose(DirectoryHandle);
363*c2c66affSColin Finck             BaseSetLastNTError(Status);
364*c2c66affSColin Finck             return 0;
365*c2c66affSColin Finck         }
366*c2c66affSColin Finck 
367*c2c66affSColin Finck         /* Query link target */
368*c2c66affSColin Finck         UnicodeString.Length = 0;
369*c2c66affSColin Finck         UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR);
370*c2c66affSColin Finck         UnicodeString.Buffer = lpTargetPath;
371*c2c66affSColin Finck 
372*c2c66affSColin Finck         ReturnLength = 0;
373*c2c66affSColin Finck         Status = NtQuerySymbolicLinkObject(DeviceHandle,
374*c2c66affSColin Finck                                            &UnicodeString,
375*c2c66affSColin Finck                                            &ReturnLength);
376*c2c66affSColin Finck         NtClose(DeviceHandle);
377*c2c66affSColin Finck         NtClose(DirectoryHandle);
378*c2c66affSColin Finck         if (!NT_SUCCESS(Status))
379*c2c66affSColin Finck         {
380*c2c66affSColin Finck             WARN("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status);
381*c2c66affSColin Finck             BaseSetLastNTError(Status);
382*c2c66affSColin Finck             return 0;
383*c2c66affSColin Finck         }
384*c2c66affSColin Finck 
385*c2c66affSColin Finck         TRACE("ReturnLength: %lu\n", ReturnLength);
386*c2c66affSColin Finck         TRACE("TargetLength: %hu\n", UnicodeString.Length);
387*c2c66affSColin Finck         TRACE("Target: '%wZ'\n", &UnicodeString);
388*c2c66affSColin Finck 
389*c2c66affSColin Finck         Length = UnicodeString.Length / sizeof(WCHAR);
390*c2c66affSColin Finck         if (Length < ucchMax)
391*c2c66affSColin Finck         {
392*c2c66affSColin Finck             /* Append null-character */
393*c2c66affSColin Finck             lpTargetPath[Length] = UNICODE_NULL;
394*c2c66affSColin Finck             Length++;
395*c2c66affSColin Finck         }
396*c2c66affSColin Finck         else
397*c2c66affSColin Finck         {
398*c2c66affSColin Finck             TRACE("Buffer is too small\n");
399*c2c66affSColin Finck             BaseSetLastNTError(STATUS_BUFFER_TOO_SMALL);
400*c2c66affSColin Finck             return 0;
401*c2c66affSColin Finck         }
402*c2c66affSColin Finck     }
403*c2c66affSColin Finck     else
404*c2c66affSColin Finck     {
405*c2c66affSColin Finck         RestartScan = TRUE;
406*c2c66affSColin Finck         Context = 0;
407*c2c66affSColin Finck         Ptr = lpTargetPath;
408*c2c66affSColin Finck         DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
409*c2c66affSColin Finck 
410*c2c66affSColin Finck         while (TRUE)
411*c2c66affSColin Finck         {
412*c2c66affSColin Finck             Status = NtQueryDirectoryObject(DirectoryHandle,
413*c2c66affSColin Finck                                             Buffer,
414*c2c66affSColin Finck                                             sizeof(Buffer),
415*c2c66affSColin Finck                                             TRUE,
416*c2c66affSColin Finck                                             RestartScan,
417*c2c66affSColin Finck                                             &Context,
418*c2c66affSColin Finck                                             &ReturnLength);
419*c2c66affSColin Finck             if (!NT_SUCCESS(Status))
420*c2c66affSColin Finck             {
421*c2c66affSColin Finck                 if (Status == STATUS_NO_MORE_ENTRIES)
422*c2c66affSColin Finck                 {
423*c2c66affSColin Finck                     /* Terminate the buffer */
424*c2c66affSColin Finck                     *Ptr = UNICODE_NULL;
425*c2c66affSColin Finck                     Length++;
426*c2c66affSColin Finck 
427*c2c66affSColin Finck                     Status = STATUS_SUCCESS;
428*c2c66affSColin Finck                 }
429*c2c66affSColin Finck                 else
430*c2c66affSColin Finck                 {
431*c2c66affSColin Finck                     Length = 0;
432*c2c66affSColin Finck                 }
433*c2c66affSColin Finck                 BaseSetLastNTError(Status);
434*c2c66affSColin Finck                 break;
435*c2c66affSColin Finck             }
436*c2c66affSColin Finck 
437*c2c66affSColin Finck             if (!wcscmp(DirInfo->TypeName.Buffer, L"SymbolicLink"))
438*c2c66affSColin Finck             {
439*c2c66affSColin Finck                 TRACE("Name: '%wZ'\n", &DirInfo->Name);
440*c2c66affSColin Finck 
441*c2c66affSColin Finck                 NameLength = DirInfo->Name.Length / sizeof(WCHAR);
442*c2c66affSColin Finck                 if (Length + NameLength + 1 >= ucchMax)
443*c2c66affSColin Finck                 {
444*c2c66affSColin Finck                     Length = 0;
445*c2c66affSColin Finck                     BaseSetLastNTError(STATUS_BUFFER_TOO_SMALL);
446*c2c66affSColin Finck                     break;
447*c2c66affSColin Finck                 }
448*c2c66affSColin Finck 
449*c2c66affSColin Finck                 memcpy(Ptr, DirInfo->Name.Buffer, DirInfo->Name.Length);
450*c2c66affSColin Finck                 Ptr += NameLength;
451*c2c66affSColin Finck                 Length += NameLength;
452*c2c66affSColin Finck                 *Ptr = UNICODE_NULL;
453*c2c66affSColin Finck                 Ptr++;
454*c2c66affSColin Finck                 Length++;
455*c2c66affSColin Finck             }
456*c2c66affSColin Finck 
457*c2c66affSColin Finck             RestartScan = FALSE;
458*c2c66affSColin Finck         }
459*c2c66affSColin Finck 
460*c2c66affSColin Finck         NtClose(DirectoryHandle);
461*c2c66affSColin Finck     }
462*c2c66affSColin Finck 
463*c2c66affSColin Finck     return Length;
464*c2c66affSColin Finck }
465*c2c66affSColin Finck 
466*c2c66affSColin Finck /* EOF */
467