2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/dosdev.c
5 * PURPOSE: Dos device functions
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
11 /* INCLUDES ******************************************************************/
17 DEBUG_CHANNEL(kernel32file
);
19 /* FUNCTIONS *****************************************************************/
32 UNICODE_STRING DeviceNameU
= {0};
33 UNICODE_STRING TargetPathU
= {0};
37 ! RtlCreateUnicodeStringFromAsciiz(&DeviceNameU
,
40 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
45 ! RtlCreateUnicodeStringFromAsciiz(&TargetPathU
,
48 if (DeviceNameU
.Buffer
)
50 RtlFreeHeap(RtlGetProcessHeap (),
54 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
58 Result
= DefineDosDeviceW(dwFlags
,
62 if (TargetPathU
.Buffer
)
64 RtlFreeHeap(RtlGetProcessHeap (),
69 if (DeviceNameU
.Buffer
)
71 RtlFreeHeap(RtlGetProcessHeap (),
92 BASE_API_MESSAGE ApiMessage
;
93 PBASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest
= &ApiMessage
.Data
.DefineDosDeviceRequest
;
94 PCSR_CAPTURE_BUFFER CaptureBuffer
;
96 UNICODE_STRING NtTargetPathU
;
97 UNICODE_STRING DeviceNameU
;
98 UNICODE_STRING DeviceUpcaseNameU
;
100 DEV_BROADCAST_VOLUME dbcv
;
103 typedef long (WINAPI
*BSM_type
)(DWORD
,LPDWORD
,UINT
,WPARAM
,LPARAM
);
106 if ( (dwFlags
& 0xFFFFFFF0) ||
107 ((dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
) &&
108 ! (dwFlags
& DDD_REMOVE_DEFINITION
)) )
110 SetLastError(ERROR_INVALID_PARAMETER
);
118 RtlInitUnicodeString(&NtTargetPathU
,
123 if (dwFlags
& DDD_RAW_TARGET_PATH
)
125 RtlInitUnicodeString(&NtTargetPathU
,
130 if (! RtlDosPathNameToNtPathName_U(lpTargetPath
,
135 WARN("RtlDosPathNameToNtPathName_U() failed\n");
136 BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID
);
141 BufferSize
+= NtTargetPathU
.Length
;
144 RtlInitUnicodeString(&DeviceNameU
,
146 RtlUpcaseUnicodeString(&DeviceUpcaseNameU
,
149 BufferSize
+= DeviceUpcaseNameU
.Length
;
151 CaptureBuffer
= CsrAllocateCaptureBuffer(ArgumentCount
,
155 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
160 DefineDosDeviceRequest
->Flags
= dwFlags
;
162 CsrCaptureMessageBuffer(CaptureBuffer
,
163 (PVOID
)DeviceUpcaseNameU
.Buffer
,
164 DeviceUpcaseNameU
.Length
,
165 (PVOID
*)&DefineDosDeviceRequest
->DeviceName
.Buffer
);
167 DefineDosDeviceRequest
->DeviceName
.Length
=
168 DeviceUpcaseNameU
.Length
;
169 DefineDosDeviceRequest
->DeviceName
.MaximumLength
=
170 DeviceUpcaseNameU
.Length
;
172 if (NtTargetPathU
.Buffer
)
174 CsrCaptureMessageBuffer(CaptureBuffer
,
175 (PVOID
)NtTargetPathU
.Buffer
,
176 NtTargetPathU
.Length
,
177 (PVOID
*)&DefineDosDeviceRequest
->TargetPath
.Buffer
);
179 DefineDosDeviceRequest
->TargetPath
.Length
=
180 NtTargetPathU
.Length
;
181 DefineDosDeviceRequest
->TargetPath
.MaximumLength
=
182 NtTargetPathU
.Length
;
184 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
186 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepDefineDosDevice
),
187 sizeof(BASE_DEFINE_DOS_DEVICE
));
188 CsrFreeCaptureBuffer(CaptureBuffer
);
190 if (!NT_SUCCESS(Status
))
192 WARN("CsrClientCallServer() failed (Status %lx)\n", Status
);
193 BaseSetLastNTError(Status
);
198 if (! (dwFlags
& DDD_NO_BROADCAST_SYSTEM
) &&
199 DeviceUpcaseNameU
.Length
== 2 * sizeof(WCHAR
) &&
200 DeviceUpcaseNameU
.Buffer
[1] == L
':' &&
201 ( (DeviceUpcaseNameU
.Buffer
[0] - L
'A') < 26 ))
203 hUser32
= LoadLibraryA("user32.dll");
207 GetProcAddress(hUser32
, "BroadcastSystemMessageW");
210 dwRecipients
= BSM_APPLICATIONS
;
211 dbcv
.dbcv_size
= sizeof(DEV_BROADCAST_VOLUME
);
212 dbcv
.dbcv_devicetype
= DBT_DEVTYP_VOLUME
;
213 dbcv
.dbcv_reserved
= 0;
214 dbcv
.dbcv_unitmask
|=
215 (1 << (DeviceUpcaseNameU
.Buffer
[0] - L
'A'));
216 dbcv
.dbcv_flags
= DBTF_NET
;
217 (void) BSM_ptr(BSF_SENDNOTIFYMESSAGE
| BSF_FLUSHDISK
,
220 (WPARAM
)DBT_DEVICEARRIVAL
,
223 FreeLibrary(hUser32
);
229 if (NtTargetPathU
.Buffer
)
231 RtlFreeHeap(RtlGetProcessHeap(),
233 NtTargetPathU
.Buffer
);
235 RtlFreeUnicodeString(&DeviceUpcaseNameU
);
251 UNICODE_STRING DeviceNameU
;
252 UNICODE_STRING TargetPathU
;
253 ANSI_STRING TargetPathA
;
260 if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU
,
261 (LPSTR
)lpDeviceName
))
263 SetLastError (ERROR_NOT_ENOUGH_MEMORY
);
267 Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
269 ucchMax
* sizeof(WCHAR
));
274 RtlFreeHeap (RtlGetProcessHeap (),
278 SetLastError (ERROR_NOT_ENOUGH_MEMORY
);
282 Length
= QueryDosDeviceW (lpDeviceName
? DeviceNameU
.Buffer
: NULL
,
287 TargetPathA
.Buffer
= lpTargetPath
;
288 TargetPathU
.Buffer
= Buffer
;
293 CurrentLength
= min (ucchMax
, MAXUSHORT
/ 2);
294 TargetPathU
.MaximumLength
= TargetPathU
.Length
= (USHORT
)CurrentLength
* sizeof(WCHAR
);
296 TargetPathA
.Length
= 0;
297 TargetPathA
.MaximumLength
= (USHORT
)CurrentLength
;
299 RtlUnicodeStringToAnsiString (&TargetPathA
,
302 ucchMax
-= CurrentLength
;
303 TargetPathA
.Buffer
+= TargetPathA
.Length
;
304 TargetPathU
.Buffer
+= TargetPathU
.Length
/ sizeof(WCHAR
);
308 RtlFreeHeap (RtlGetProcessHeap (),
313 RtlFreeHeap (RtlGetProcessHeap (),
327 LPCWSTR lpDeviceName
,
332 POBJECT_DIRECTORY_INFORMATION DirInfo
;
333 OBJECT_ATTRIBUTES ObjectAttributes
;
334 UNICODE_STRING UnicodeString
;
335 HANDLE DirectoryHandle
;
346 /* Open the '\??' directory */
347 RtlInitUnicodeString (&UnicodeString
,
349 InitializeObjectAttributes (&ObjectAttributes
,
351 OBJ_CASE_INSENSITIVE
,
354 Status
= NtOpenDirectoryObject (&DirectoryHandle
,
357 if (!NT_SUCCESS (Status
))
359 WARN ("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
360 BaseSetLastNTError (Status
);
366 if (lpDeviceName
!= NULL
)
368 /* Open the lpDeviceName link object */
369 RtlInitUnicodeString (&UnicodeString
,
370 (PWSTR
)lpDeviceName
);
371 InitializeObjectAttributes (&ObjectAttributes
,
373 OBJ_CASE_INSENSITIVE
,
376 Status
= NtOpenSymbolicLinkObject (&DeviceHandle
,
379 if (!NT_SUCCESS (Status
))
381 WARN ("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status
);
382 NtClose (DirectoryHandle
);
383 BaseSetLastNTError (Status
);
387 /* Query link target */
388 UnicodeString
.Length
= 0;
389 UnicodeString
.MaximumLength
= (USHORT
)ucchMax
* sizeof(WCHAR
);
390 UnicodeString
.Buffer
= lpTargetPath
;
393 Status
= NtQuerySymbolicLinkObject (DeviceHandle
,
396 NtClose (DeviceHandle
);
397 NtClose (DirectoryHandle
);
398 if (!NT_SUCCESS (Status
))
400 WARN ("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status
);
401 BaseSetLastNTError (Status
);
405 TRACE ("ReturnLength: %lu\n", ReturnLength
);
406 TRACE ("TargetLength: %hu\n", UnicodeString
.Length
);
407 TRACE ("Target: '%wZ'\n", &UnicodeString
);
409 Length
= UnicodeString
.Length
/ sizeof(WCHAR
);
410 if (Length
< ucchMax
)
412 /* Append null-charcter */
413 lpTargetPath
[Length
] = UNICODE_NULL
;
418 TRACE ("Buffer is too small\n");
419 BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL
);
428 DirInfo
= (POBJECT_DIRECTORY_INFORMATION
)Buffer
;
432 Status
= NtQueryDirectoryObject (DirectoryHandle
,
439 if (!NT_SUCCESS(Status
))
441 if (Status
== STATUS_NO_MORE_ENTRIES
)
443 /* Terminate the buffer */
447 Status
= STATUS_SUCCESS
;
453 BaseSetLastNTError (Status
);
457 if (!wcscmp (DirInfo
->TypeName
.Buffer
, L
"SymbolicLink"))
459 TRACE ("Name: '%wZ'\n", &DirInfo
->Name
);
461 NameLength
= DirInfo
->Name
.Length
/ sizeof(WCHAR
);
462 if (Length
+ NameLength
+ 1 >= ucchMax
)
465 BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL
);
470 DirInfo
->Name
.Buffer
,
471 DirInfo
->Name
.Length
);
473 Length
+= NameLength
;
482 NtClose (DirectoryHandle
);