1 /* $Id: dosdev.c 54326 2011-11-07 00:18:13Z ion $
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)
12 /* INCLUDES ******************************************************************/
18 DEBUG_CHANNEL(kernel32file
);
20 /* FUNCTIONS *****************************************************************/
33 UNICODE_STRING DeviceNameU
= {0};
34 UNICODE_STRING TargetPathU
= {0};
38 ! RtlCreateUnicodeStringFromAsciiz(&DeviceNameU
,
41 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
46 ! RtlCreateUnicodeStringFromAsciiz(&TargetPathU
,
49 if (DeviceNameU
.Buffer
)
51 RtlFreeHeap(RtlGetProcessHeap (),
55 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
59 Result
= DefineDosDeviceW(dwFlags
,
63 if (TargetPathU
.Buffer
)
65 RtlFreeHeap(RtlGetProcessHeap (),
70 if (DeviceNameU
.Buffer
)
72 RtlFreeHeap(RtlGetProcessHeap (),
93 PCSR_CAPTURE_BUFFER CaptureBuffer
;
94 CSR_API_MESSAGE Request
;
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 Request
.Data
.DefineDosDeviceRequest
.dwFlags
= dwFlags
;
162 CsrCaptureMessageBuffer(CaptureBuffer
,
163 (PVOID
)DeviceUpcaseNameU
.Buffer
,
164 DeviceUpcaseNameU
.Length
,
165 (PVOID
*)&Request
.Data
.DefineDosDeviceRequest
.DeviceName
.Buffer
);
167 Request
.Data
.DefineDosDeviceRequest
.DeviceName
.Length
=
168 DeviceUpcaseNameU
.Length
;
169 Request
.Data
.DefineDosDeviceRequest
.DeviceName
.MaximumLength
=
170 DeviceUpcaseNameU
.Length
;
172 if (NtTargetPathU
.Buffer
)
174 CsrCaptureMessageBuffer(CaptureBuffer
,
175 (PVOID
)NtTargetPathU
.Buffer
,
176 NtTargetPathU
.Length
,
177 (PVOID
*)&Request
.Data
.DefineDosDeviceRequest
.TargetName
.Buffer
);
179 Request
.Data
.DefineDosDeviceRequest
.TargetName
.Length
=
180 NtTargetPathU
.Length
;
181 Request
.Data
.DefineDosDeviceRequest
.TargetName
.MaximumLength
=
182 NtTargetPathU
.Length
;
184 Status
= CsrClientCallServer(&Request
,
186 MAKE_CSR_API(DEFINE_DOS_DEVICE
, CSR_CONSOLE
),
187 sizeof(CSR_API_MESSAGE
));
188 CsrFreeCaptureBuffer(CaptureBuffer
);
190 if (! NT_SUCCESS(Status
) ||
191 ! NT_SUCCESS(Status
= Request
.Status
))
193 WARN("CsrClientCallServer() failed (Status %lx)\n",
195 BaseSetLastNTError(Status
);
200 if (! (dwFlags
& DDD_NO_BROADCAST_SYSTEM
) &&
201 DeviceUpcaseNameU
.Length
== 2 * sizeof(WCHAR
) &&
202 DeviceUpcaseNameU
.Buffer
[1] == L
':' &&
203 ( (DeviceUpcaseNameU
.Buffer
[0] - L
'A') < 26 ))
205 hUser32
= LoadLibraryA("user32.dll");
209 GetProcAddress(hUser32
, "BroadcastSystemMessageW");
212 dwRecipients
= BSM_APPLICATIONS
;
213 dbcv
.dbcv_size
= sizeof(DEV_BROADCAST_VOLUME
);
214 dbcv
.dbcv_devicetype
= DBT_DEVTYP_VOLUME
;
215 dbcv
.dbcv_reserved
= 0;
216 dbcv
.dbcv_unitmask
|=
217 (1 << (DeviceUpcaseNameU
.Buffer
[0] - L
'A'));
218 dbcv
.dbcv_flags
= DBTF_NET
;
219 (void) BSM_ptr(BSF_SENDNOTIFYMESSAGE
| BSF_FLUSHDISK
,
222 (WPARAM
)DBT_DEVICEARRIVAL
,
225 FreeLibrary(hUser32
);
231 if (NtTargetPathU
.Buffer
)
233 RtlFreeHeap(RtlGetProcessHeap(),
235 NtTargetPathU
.Buffer
);
237 RtlFreeUnicodeString(&DeviceUpcaseNameU
);
253 UNICODE_STRING DeviceNameU
;
254 UNICODE_STRING TargetPathU
;
255 ANSI_STRING TargetPathA
;
262 if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU
,
263 (LPSTR
)lpDeviceName
))
265 SetLastError (ERROR_NOT_ENOUGH_MEMORY
);
269 Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
271 ucchMax
* sizeof(WCHAR
));
276 RtlFreeHeap (RtlGetProcessHeap (),
280 SetLastError (ERROR_NOT_ENOUGH_MEMORY
);
284 Length
= QueryDosDeviceW (lpDeviceName
? DeviceNameU
.Buffer
: NULL
,
289 TargetPathA
.Buffer
= lpTargetPath
;
290 TargetPathU
.Buffer
= Buffer
;
295 CurrentLength
= min (ucchMax
, MAXUSHORT
/ 2);
296 TargetPathU
.MaximumLength
= TargetPathU
.Length
= (USHORT
)CurrentLength
* sizeof(WCHAR
);
298 TargetPathA
.Length
= 0;
299 TargetPathA
.MaximumLength
= (USHORT
)CurrentLength
;
301 RtlUnicodeStringToAnsiString (&TargetPathA
,
304 ucchMax
-= CurrentLength
;
305 TargetPathA
.Buffer
+= TargetPathA
.Length
;
306 TargetPathU
.Buffer
+= TargetPathU
.Length
/ sizeof(WCHAR
);
310 RtlFreeHeap (RtlGetProcessHeap (),
315 RtlFreeHeap (RtlGetProcessHeap (),
329 LPCWSTR lpDeviceName
,
334 POBJECT_DIRECTORY_INFORMATION DirInfo
;
335 OBJECT_ATTRIBUTES ObjectAttributes
;
336 UNICODE_STRING UnicodeString
;
337 HANDLE DirectoryHandle
;
348 /* Open the '\??' directory */
349 RtlInitUnicodeString (&UnicodeString
,
351 InitializeObjectAttributes (&ObjectAttributes
,
353 OBJ_CASE_INSENSITIVE
,
356 Status
= NtOpenDirectoryObject (&DirectoryHandle
,
359 if (!NT_SUCCESS (Status
))
361 WARN ("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
362 BaseSetLastNTError (Status
);
368 if (lpDeviceName
!= NULL
)
370 /* Open the lpDeviceName link object */
371 RtlInitUnicodeString (&UnicodeString
,
372 (PWSTR
)lpDeviceName
);
373 InitializeObjectAttributes (&ObjectAttributes
,
375 OBJ_CASE_INSENSITIVE
,
378 Status
= NtOpenSymbolicLinkObject (&DeviceHandle
,
381 if (!NT_SUCCESS (Status
))
383 WARN ("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status
);
384 NtClose (DirectoryHandle
);
385 BaseSetLastNTError (Status
);
389 /* Query link target */
390 UnicodeString
.Length
= 0;
391 UnicodeString
.MaximumLength
= (USHORT
)ucchMax
* sizeof(WCHAR
);
392 UnicodeString
.Buffer
= lpTargetPath
;
395 Status
= NtQuerySymbolicLinkObject (DeviceHandle
,
398 NtClose (DeviceHandle
);
399 NtClose (DirectoryHandle
);
400 if (!NT_SUCCESS (Status
))
402 WARN ("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status
);
403 BaseSetLastNTError (Status
);
407 TRACE ("ReturnLength: %lu\n", ReturnLength
);
408 TRACE ("TargetLength: %hu\n", UnicodeString
.Length
);
409 TRACE ("Target: '%wZ'\n", &UnicodeString
);
411 Length
= UnicodeString
.Length
/ sizeof(WCHAR
);
412 if (Length
< ucchMax
)
414 /* Append null-charcter */
415 lpTargetPath
[Length
] = UNICODE_NULL
;
420 TRACE ("Buffer is too small\n");
421 BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL
);
430 DirInfo
= (POBJECT_DIRECTORY_INFORMATION
)Buffer
;
434 Status
= NtQueryDirectoryObject (DirectoryHandle
,
441 if (!NT_SUCCESS(Status
))
443 if (Status
== STATUS_NO_MORE_ENTRIES
)
445 /* Terminate the buffer */
449 Status
= STATUS_SUCCESS
;
455 BaseSetLastNTError (Status
);
459 if (!wcscmp (DirInfo
->TypeName
.Buffer
, L
"SymbolicLink"))
461 TRACE ("Name: '%wZ'\n", &DirInfo
->Name
);
463 NameLength
= DirInfo
->Name
.Length
/ sizeof(WCHAR
);
464 if (Length
+ NameLength
+ 1 >= ucchMax
)
467 BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL
);
472 DirInfo
->Name
.Buffer
,
473 DirInfo
->Name
.Length
);
475 Length
+= NameLength
;
484 NtClose (DirectoryHandle
);