mirror of
https://github.com/reactos/reactos.git
synced 2025-05-30 06:28:34 +00:00
[KERNEL32] Misc. fixes to DefineDosDeviceW
- Add support for LUIDDeviceMapsEnabled; - Broadcast proper message in case of device removal; - Use less memory for strings management; - Make code a bit cleaner.
This commit is contained in:
parent
d3fa3b0ca2
commit
204bfa8574
1 changed files with 116 additions and 87 deletions
|
@ -244,38 +244,52 @@ DefineDosDeviceW(
|
||||||
PCSR_CAPTURE_BUFFER CaptureBuffer;
|
PCSR_CAPTURE_BUFFER CaptureBuffer;
|
||||||
UNICODE_STRING NtTargetPathU;
|
UNICODE_STRING NtTargetPathU;
|
||||||
UNICODE_STRING DeviceNameU;
|
UNICODE_STRING DeviceNameU;
|
||||||
UNICODE_STRING DeviceUpcaseNameU;
|
|
||||||
HANDLE hUser32;
|
HANDLE hUser32;
|
||||||
DEV_BROADCAST_VOLUME dbcv;
|
DEV_BROADCAST_VOLUME dbcv;
|
||||||
BOOL Result = TRUE;
|
|
||||||
DWORD dwRecipients;
|
DWORD dwRecipients;
|
||||||
typedef long (WINAPI *BSM_type)(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
|
typedef long (WINAPI *BSM_type)(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
|
||||||
BSM_type BSM_ptr;
|
BSM_type BSM_ptr;
|
||||||
|
BOOLEAN LUIDDeviceMapsEnabled;
|
||||||
|
WCHAR Letter;
|
||||||
|
WPARAM wParam;
|
||||||
|
|
||||||
if ( (dwFlags & 0xFFFFFFF0) ||
|
/* Get status about local device mapping */
|
||||||
|
LUIDDeviceMapsEnabled = BaseStaticServerData->LUIDDeviceMapsEnabled;
|
||||||
|
|
||||||
|
/* Validate input & flags */
|
||||||
|
if ((dwFlags & 0xFFFFFFE0) ||
|
||||||
((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
|
((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
|
||||||
! (dwFlags & DDD_REMOVE_DEFINITION)) )
|
!(dwFlags & DDD_REMOVE_DEFINITION)) ||
|
||||||
|
(lpTargetPath == NULL && !(dwFlags & (DDD_LUID_BROADCAST_DRIVE | DDD_REMOVE_DEFINITION))) ||
|
||||||
|
((dwFlags & DDD_LUID_BROADCAST_DRIVE) &&
|
||||||
|
(lpDeviceName == NULL || lpTargetPath != NULL || dwFlags & (DDD_NO_BROADCAST_SYSTEM | DDD_EXACT_MATCH_ON_REMOVE | DDD_RAW_TARGET_PATH) || !LUIDDeviceMapsEnabled)))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize device unicode string to ease its use */
|
||||||
|
RtlInitUnicodeString(&DeviceNameU, lpDeviceName);
|
||||||
|
|
||||||
|
/* The buffer for CSR call will contain it */
|
||||||
|
BufferSize = DeviceNameU.MaximumLength;
|
||||||
ArgumentCount = 1;
|
ArgumentCount = 1;
|
||||||
BufferSize = 0;
|
|
||||||
if (!lpTargetPath)
|
/* If we don't have target path, use empty string */
|
||||||
|
if (lpTargetPath == NULL)
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&NtTargetPathU,
|
RtlInitUnicodeString(&NtTargetPathU, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Else, use it raw if asked to */
|
||||||
if (dwFlags & DDD_RAW_TARGET_PATH)
|
if (dwFlags & DDD_RAW_TARGET_PATH)
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&NtTargetPathU,
|
RtlInitUnicodeString(&NtTargetPathU, lpTargetPath);
|
||||||
lpTargetPath);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Otherwise, use it converted */
|
||||||
if (!RtlDosPathNameToNtPathName_U(lpTargetPath,
|
if (!RtlDosPathNameToNtPathName_U(lpTargetPath,
|
||||||
&NtTargetPathU,
|
&NtTargetPathU,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -286,104 +300,119 @@ DefineDosDeviceW(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This target path will be the second arg */
|
||||||
ArgumentCount = 2;
|
ArgumentCount = 2;
|
||||||
BufferSize += NtTargetPathU.Length;
|
BufferSize += NtTargetPathU.MaximumLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlInitUnicodeString(&DeviceNameU,
|
/* Allocate the capture buffer for our strings */
|
||||||
lpDeviceName);
|
|
||||||
RtlUpcaseUnicodeString(&DeviceUpcaseNameU,
|
|
||||||
&DeviceNameU,
|
|
||||||
TRUE);
|
|
||||||
BufferSize += DeviceUpcaseNameU.Length;
|
|
||||||
|
|
||||||
CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount,
|
CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount,
|
||||||
BufferSize);
|
BufferSize);
|
||||||
if (!CaptureBuffer)
|
if (CaptureBuffer == NULL)
|
||||||
{
|
{
|
||||||
|
if (!(dwFlags & DDD_RAW_TARGET_PATH))
|
||||||
|
{
|
||||||
|
RtlFreeUnicodeString(&NtTargetPathU);
|
||||||
|
}
|
||||||
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
Result = FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the flags */
|
||||||
|
DefineDosDeviceRequest->Flags = dwFlags;
|
||||||
|
|
||||||
|
/* Allocate a buffer for the device name */
|
||||||
|
DefineDosDeviceRequest->DeviceName.MaximumLength = CsrAllocateMessagePointer(CaptureBuffer,
|
||||||
|
DeviceNameU.MaximumLength,
|
||||||
|
(PVOID*)&DefineDosDeviceRequest->DeviceName.Buffer);
|
||||||
|
/* And copy it while upcasing it */
|
||||||
|
RtlUpcaseUnicodeString(&DefineDosDeviceRequest->DeviceName, &DeviceNameU, FALSE);
|
||||||
|
|
||||||
|
/* If we have a target path, copy it too, and free it if allocated */
|
||||||
|
if (NtTargetPathU.Length != 0)
|
||||||
|
{
|
||||||
|
DefineDosDeviceRequest->TargetPath.MaximumLength = CsrAllocateMessagePointer(CaptureBuffer,
|
||||||
|
NtTargetPathU.MaximumLength,
|
||||||
|
(PVOID*)&DefineDosDeviceRequest->TargetPath.Buffer);
|
||||||
|
RtlCopyUnicodeString(&DefineDosDeviceRequest->TargetPath, &NtTargetPathU);
|
||||||
|
|
||||||
|
if (!(dwFlags & DDD_RAW_TARGET_PATH))
|
||||||
|
{
|
||||||
|
RtlFreeUnicodeString(&NtTargetPathU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Otherwise, null initialize the string */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DefineDosDeviceRequest->Flags = dwFlags;
|
RtlInitUnicodeString(&DefineDosDeviceRequest->TargetPath, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
CsrCaptureMessageBuffer(CaptureBuffer,
|
/* Finally, call the server */
|
||||||
DeviceUpcaseNameU.Buffer,
|
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
|
||||||
DeviceUpcaseNameU.Length,
|
CaptureBuffer,
|
||||||
(PVOID*)&DefineDosDeviceRequest->DeviceName.Buffer);
|
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepDefineDosDevice),
|
||||||
|
sizeof(*DefineDosDeviceRequest));
|
||||||
|
CsrFreeCaptureBuffer(CaptureBuffer);
|
||||||
|
|
||||||
DefineDosDeviceRequest->DeviceName.Length =
|
/* Return failure if any */
|
||||||
DeviceUpcaseNameU.Length;
|
if (!NT_SUCCESS(ApiMessage.Status))
|
||||||
DefineDosDeviceRequest->DeviceName.MaximumLength =
|
{
|
||||||
DeviceUpcaseNameU.Length;
|
WARN("CsrClientCallServer() failed (Status %lx)\n", ApiMessage.Status);
|
||||||
|
BaseSetLastNTError(ApiMessage.Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (NtTargetPathU.Buffer)
|
/* Here is the success path, we will always return true */
|
||||||
|
|
||||||
|
/* Should broadcast the event? Only do if not denied and if drive letter */
|
||||||
|
if (!(dwFlags & DDD_NO_BROADCAST_SYSTEM) &&
|
||||||
|
DeviceNameU.Length == 2 * sizeof(WCHAR) &&
|
||||||
|
DeviceNameU.Buffer[1] == L':')
|
||||||
|
{
|
||||||
|
/* Make sure letter is valid and there are no local device mappings */
|
||||||
|
Letter = RtlUpcaseUnicodeChar(DeviceNameU.Buffer[0]) - L'A';
|
||||||
|
if (Letter < 26 && !LUIDDeviceMapsEnabled)
|
||||||
{
|
{
|
||||||
CsrCaptureMessageBuffer(CaptureBuffer,
|
/* Rely on user32 for broadcasting */
|
||||||
NtTargetPathU.Buffer,
|
hUser32 = LoadLibraryW(L"user32.dll");
|
||||||
NtTargetPathU.Length,
|
if (hUser32 != 0)
|
||||||
(PVOID*)&DefineDosDeviceRequest->TargetPath.Buffer);
|
|
||||||
}
|
|
||||||
DefineDosDeviceRequest->TargetPath.Length =
|
|
||||||
NtTargetPathU.Length;
|
|
||||||
DefineDosDeviceRequest->TargetPath.MaximumLength =
|
|
||||||
NtTargetPathU.Length;
|
|
||||||
|
|
||||||
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
|
|
||||||
CaptureBuffer,
|
|
||||||
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepDefineDosDevice),
|
|
||||||
sizeof(*DefineDosDeviceRequest));
|
|
||||||
CsrFreeCaptureBuffer(CaptureBuffer);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(ApiMessage.Status))
|
|
||||||
{
|
|
||||||
WARN("CsrClientCallServer() failed (Status %lx)\n", ApiMessage.Status);
|
|
||||||
BaseSetLastNTError(ApiMessage.Status);
|
|
||||||
Result = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (! (dwFlags & DDD_NO_BROADCAST_SYSTEM) &&
|
|
||||||
DeviceUpcaseNameU.Length == 2 * sizeof(WCHAR) &&
|
|
||||||
DeviceUpcaseNameU.Buffer[1] == L':' &&
|
|
||||||
( (DeviceUpcaseNameU.Buffer[0] - L'A') < 26 ))
|
|
||||||
{
|
{
|
||||||
hUser32 = LoadLibraryA("user32.dll");
|
/* Get the function pointer */
|
||||||
if (hUser32)
|
BSM_ptr = (BSM_type)GetProcAddress(hUser32, "BroadcastSystemMessageW");
|
||||||
|
if (BSM_ptr)
|
||||||
{
|
{
|
||||||
BSM_ptr = (BSM_type)
|
/* Set our target */
|
||||||
GetProcAddress(hUser32, "BroadcastSystemMessageW");
|
dwRecipients = BSM_APPLICATIONS;
|
||||||
if (BSM_ptr)
|
|
||||||
{
|
/* And initialize our structure */
|
||||||
dwRecipients = BSM_APPLICATIONS;
|
dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
|
||||||
dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
|
dbcv.dbcv_devicetype = DBT_DEVTYP_VOLUME;
|
||||||
dbcv.dbcv_devicetype = DBT_DEVTYP_VOLUME;
|
dbcv.dbcv_reserved = 0;
|
||||||
dbcv.dbcv_reserved = 0;
|
|
||||||
dbcv.dbcv_unitmask |=
|
/* Set the volume which had the event */
|
||||||
(1 << (DeviceUpcaseNameU.Buffer[0] - L'A'));
|
dbcv.dbcv_unitmask = 1 << Letter;
|
||||||
dbcv.dbcv_flags = DBTF_NET;
|
dbcv.dbcv_flags = DBTF_NET;
|
||||||
(void) BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK,
|
|
||||||
&dwRecipients,
|
/* And properly set the event (removal or arrival?) */
|
||||||
WM_DEVICECHANGE,
|
wParam = (dwFlags & DDD_REMOVE_DEFINITION) ? DBT_DEVICEREMOVECOMPLETE : DBT_DEVICEARRIVAL;
|
||||||
(WPARAM)DBT_DEVICEARRIVAL,
|
|
||||||
(LPARAM)&dbcv);
|
/* And broadcast! */
|
||||||
}
|
BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK,
|
||||||
FreeLibrary(hUser32);
|
&dwRecipients,
|
||||||
|
WM_DEVICECHANGE,
|
||||||
|
wParam,
|
||||||
|
(LPARAM)&dbcv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We're done! */
|
||||||
|
FreeLibrary(hUser32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NtTargetPathU.Buffer &&
|
return TRUE;
|
||||||
NtTargetPathU.Buffer != lpTargetPath)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(),
|
|
||||||
0,
|
|
||||||
NtTargetPathU.Buffer);
|
|
||||||
}
|
|
||||||
RtlFreeUnicodeString(&DeviceUpcaseNameU);
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue