[CMAKE]
[reactos.git] / dll / win32 / kernel32 / file / dosdev.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/dosdev.c
6 * PURPOSE: Dos device functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <k32.h>
15 #define NDEBUG
16 #include <debug.h>
17 static ULONG gDebugChannel = kernel32file;
18
19 /* FUNCTIONS *****************************************************************/
20
21 /*
22 * @implemented
23 */
24 BOOL
25 WINAPI
26 DefineDosDeviceA(
27 DWORD dwFlags,
28 LPCSTR lpDeviceName,
29 LPCSTR lpTargetPath
30 )
31 {
32 UNICODE_STRING DeviceNameU;
33 UNICODE_STRING TargetPathU;
34 BOOL Result;
35
36 if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU,
37 (LPSTR)lpDeviceName))
38 {
39 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
40 return 0;
41 }
42
43 if (!RtlCreateUnicodeStringFromAsciiz (&TargetPathU,
44 (LPSTR)lpTargetPath))
45 {
46 RtlFreeHeap (RtlGetProcessHeap (),
47 0,
48 DeviceNameU.Buffer);
49 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
50 return 0;
51 }
52
53 Result = DefineDosDeviceW (dwFlags,
54 DeviceNameU.Buffer,
55 TargetPathU.Buffer);
56
57 RtlFreeHeap (RtlGetProcessHeap (),
58 0,
59 TargetPathU.Buffer);
60 RtlFreeHeap (RtlGetProcessHeap (),
61 0,
62 DeviceNameU.Buffer);
63
64 return Result;
65 }
66
67
68 /*
69 * @unimplemented
70 */
71 BOOL
72 WINAPI
73 DefineDosDeviceW(
74 DWORD dwFlags,
75 LPCWSTR lpDeviceName,
76 LPCWSTR lpTargetPath
77 )
78 {
79 UNIMPLEMENTED;
80 return FALSE;
81 }
82
83
84 /*
85 * @implemented
86 */
87 DWORD
88 WINAPI
89 QueryDosDeviceA(
90 LPCSTR lpDeviceName,
91 LPSTR lpTargetPath,
92 DWORD ucchMax
93 )
94 {
95 UNICODE_STRING DeviceNameU;
96 UNICODE_STRING TargetPathU;
97 ANSI_STRING TargetPathA;
98 DWORD Length;
99 DWORD CurrentLength;
100 PWCHAR Buffer;
101
102 if (lpDeviceName)
103 {
104 if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU,
105 (LPSTR)lpDeviceName))
106 {
107 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
108 return 0;
109 }
110 }
111 Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
112 0,
113 ucchMax * sizeof(WCHAR));
114 if (Buffer == NULL)
115 {
116 if (lpDeviceName)
117 {
118 RtlFreeHeap (RtlGetProcessHeap (),
119 0,
120 DeviceNameU.Buffer);
121 }
122 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
123 return 0;
124 }
125
126 Length = QueryDosDeviceW (lpDeviceName ? DeviceNameU.Buffer : NULL,
127 Buffer,
128 ucchMax);
129 if (Length != 0)
130 {
131 TargetPathA.Buffer = lpTargetPath;
132 TargetPathU.Buffer = Buffer;
133 ucchMax = Length;
134
135 while (ucchMax)
136 {
137 CurrentLength = min (ucchMax, MAXUSHORT / 2);
138 TargetPathU.MaximumLength = TargetPathU.Length = (USHORT)CurrentLength * sizeof(WCHAR);
139
140 TargetPathA.Length = 0;
141 TargetPathA.MaximumLength = (USHORT)CurrentLength;
142
143 RtlUnicodeStringToAnsiString (&TargetPathA,
144 &TargetPathU,
145 FALSE);
146 ucchMax -= CurrentLength;
147 TargetPathA.Buffer += TargetPathA.Length;
148 TargetPathU.Buffer += TargetPathU.Length / sizeof(WCHAR);
149 }
150 }
151
152 RtlFreeHeap (RtlGetProcessHeap (),
153 0,
154 Buffer);
155 if (lpDeviceName)
156 {
157 RtlFreeHeap (RtlGetProcessHeap (),
158 0,
159 DeviceNameU.Buffer);
160 }
161 return Length;
162 }
163
164
165 /*
166 * @implemented
167 */
168 DWORD
169 WINAPI
170 QueryDosDeviceW(
171 LPCWSTR lpDeviceName,
172 LPWSTR lpTargetPath,
173 DWORD ucchMax
174 )
175 {
176 POBJECT_DIRECTORY_INFORMATION DirInfo;
177 OBJECT_ATTRIBUTES ObjectAttributes;
178 UNICODE_STRING UnicodeString;
179 HANDLE DirectoryHandle;
180 HANDLE DeviceHandle;
181 ULONG ReturnLength;
182 ULONG NameLength;
183 ULONG Length;
184 ULONG Context;
185 BOOLEAN RestartScan;
186 NTSTATUS Status;
187 UCHAR Buffer[512];
188 PWSTR Ptr;
189
190 /* Open the '\??' directory */
191 RtlInitUnicodeString (&UnicodeString,
192 L"\\??");
193 InitializeObjectAttributes (&ObjectAttributes,
194 &UnicodeString,
195 OBJ_CASE_INSENSITIVE,
196 NULL,
197 NULL);
198 Status = NtOpenDirectoryObject (&DirectoryHandle,
199 DIRECTORY_QUERY,
200 &ObjectAttributes);
201 if (!NT_SUCCESS (Status))
202 {
203 WARN ("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
204 SetLastErrorByStatus (Status);
205 return 0;
206 }
207
208 Length = 0;
209
210 if (lpDeviceName != NULL)
211 {
212 /* Open the lpDeviceName link object */
213 RtlInitUnicodeString (&UnicodeString,
214 (PWSTR)lpDeviceName);
215 InitializeObjectAttributes (&ObjectAttributes,
216 &UnicodeString,
217 OBJ_CASE_INSENSITIVE,
218 DirectoryHandle,
219 NULL);
220 Status = NtOpenSymbolicLinkObject (&DeviceHandle,
221 SYMBOLIC_LINK_QUERY,
222 &ObjectAttributes);
223 if (!NT_SUCCESS (Status))
224 {
225 WARN ("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status);
226 NtClose (DirectoryHandle);
227 SetLastErrorByStatus (Status);
228 return 0;
229 }
230
231 /* Query link target */
232 UnicodeString.Length = 0;
233 UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR);
234 UnicodeString.Buffer = lpTargetPath;
235
236 ReturnLength = 0;
237 Status = NtQuerySymbolicLinkObject (DeviceHandle,
238 &UnicodeString,
239 &ReturnLength);
240 NtClose (DeviceHandle);
241 NtClose (DirectoryHandle);
242 if (!NT_SUCCESS (Status))
243 {
244 WARN ("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status);
245 SetLastErrorByStatus (Status);
246 return 0;
247 }
248
249 TRACE ("ReturnLength: %lu\n", ReturnLength);
250 TRACE ("TargetLength: %hu\n", UnicodeString.Length);
251 TRACE ("Target: '%wZ'\n", &UnicodeString);
252
253 Length = ReturnLength / sizeof(WCHAR);
254 if (Length < ucchMax)
255 {
256 /* Append null-charcter */
257 lpTargetPath[Length] = UNICODE_NULL;
258 Length++;
259 }
260 else
261 {
262 TRACE ("Buffer is too small\n");
263 SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
264 return 0;
265 }
266 }
267 else
268 {
269 RestartScan = TRUE;
270 Context = 0;
271 Ptr = lpTargetPath;
272 DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
273
274 while (TRUE)
275 {
276 Status = NtQueryDirectoryObject (DirectoryHandle,
277 Buffer,
278 sizeof (Buffer),
279 TRUE,
280 RestartScan,
281 &Context,
282 &ReturnLength);
283 if (!NT_SUCCESS(Status))
284 {
285 if (Status == STATUS_NO_MORE_ENTRIES)
286 {
287 /* Terminate the buffer */
288 *Ptr = UNICODE_NULL;
289 Length++;
290
291 Status = STATUS_SUCCESS;
292 }
293 else
294 {
295 Length = 0;
296 }
297 SetLastErrorByStatus (Status);
298 break;
299 }
300
301 if (!wcscmp (DirInfo->TypeName.Buffer, L"SymbolicLink"))
302 {
303 TRACE ("Name: '%wZ'\n", &DirInfo->Name);
304
305 NameLength = DirInfo->Name.Length / sizeof(WCHAR);
306 if (Length + NameLength + 1 >= ucchMax)
307 {
308 Length = 0;
309 SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
310 break;
311 }
312
313 memcpy (Ptr,
314 DirInfo->Name.Buffer,
315 DirInfo->Name.Length);
316 Ptr += NameLength;
317 Length += NameLength;
318 *Ptr = UNICODE_NULL;
319 Ptr++;
320 Length++;
321 }
322
323 RestartScan = FALSE;
324 }
325
326 NtClose (DirectoryHandle);
327 }
328
329 return Length;
330 }
331
332 /* EOF */