492 lines
16 KiB
C
492 lines
16 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dosdev.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the implementation of the DefineDosDevice API
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 13-Dec-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "basedll.h"
|
|
|
|
BOOL
|
|
WINAPI
|
|
DefineDosDeviceA(
|
|
DWORD dwFlags,
|
|
LPCSTR lpDeviceName,
|
|
LPCSTR lpTargetPath
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOL Result;
|
|
ANSI_STRING AnsiString;
|
|
PUNICODE_STRING DeviceName;
|
|
UNICODE_STRING TargetPath;
|
|
PCWSTR lpDeviceNameW;
|
|
PCWSTR lpTargetPathW;
|
|
|
|
RtlInitAnsiString( &AnsiString, lpDeviceName );
|
|
DeviceName = &NtCurrentTeb()->StaticUnicodeString;
|
|
Status = RtlAnsiStringToUnicodeString( DeviceName, &AnsiString, FALSE );
|
|
if (!NT_SUCCESS( Status )) {
|
|
if ( Status == STATUS_BUFFER_OVERFLOW ) {
|
|
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
|
}
|
|
else {
|
|
BaseSetLastNTError( Status );
|
|
}
|
|
return FALSE;
|
|
}
|
|
else {
|
|
lpDeviceNameW = DeviceName->Buffer;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT( lpTargetPath )) {
|
|
RtlInitAnsiString( &AnsiString, lpTargetPath );
|
|
Status = RtlAnsiStringToUnicodeString( &TargetPath, &AnsiString, TRUE );
|
|
if (!NT_SUCCESS( Status )) {
|
|
BaseSetLastNTError( Status );
|
|
return FALSE;
|
|
}
|
|
else {
|
|
lpTargetPathW = TargetPath.Buffer;
|
|
}
|
|
}
|
|
else {
|
|
lpTargetPathW = NULL;
|
|
}
|
|
|
|
Result = DefineDosDeviceW( dwFlags,
|
|
lpDeviceNameW,
|
|
lpTargetPathW
|
|
);
|
|
|
|
if (lpTargetPathW != NULL) {
|
|
RtlFreeUnicodeString( &TargetPath );
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
typedef
|
|
long
|
|
(WINAPI *PBROADCASTSYSTEMMESSAGEW)( DWORD, LPDWORD, UINT, WPARAM, LPARAM );
|
|
|
|
HMODULE hUser32Dll;
|
|
PBROADCASTSYSTEMMESSAGEW pBroadCastSystemMessageW;
|
|
|
|
BOOL
|
|
WINAPI
|
|
DefineDosDeviceW(
|
|
DWORD dwFlags,
|
|
PCWSTR lpDeviceName,
|
|
PCWSTR lpTargetPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function provides the capability to define new DOS device names or
|
|
redefine or delete existing DOS device names. DOS Device names are stored
|
|
as symbolic links in the NT object name space. The code that converts
|
|
a DOS path into a corresponding NT path uses these symbolic links to
|
|
handle mapping of DOS devices and drive letters. This API provides a
|
|
mechanism for a Win32 Application to modify the symbolic links used
|
|
to implement the DOS Device namespace. Use the QueryDosDevice API
|
|
to query the current mapping for a DOS device name.
|
|
|
|
Arguments:
|
|
|
|
dwFlags - Supplies additional flags that control the creation
|
|
of the DOS device.
|
|
|
|
dwFlags Flags:
|
|
|
|
DDD_PUSH_POP_DEFINITION - If lpTargetPath is not NULL, then push
|
|
the new target path in front of any existing target path.
|
|
If lpTargetPath is NULL, then delete the existing target path
|
|
and pop the most recent one pushed. If nothing left to pop
|
|
then the device name will be deleted.
|
|
|
|
DDD_RAW_TARGET_PATH - Do not convert the lpTargetPath string from
|
|
a DOS path to an NT path, but take it as is.
|
|
|
|
lpDeviceName - Points to the DOS device name being defined, redefined or deleted.
|
|
It must NOT have a trailing colon unless it is a drive letter being defined,
|
|
redefined or deleted.
|
|
|
|
lpTargetPath - Points to the DOS path that will implement this device. If the
|
|
ADD_RAW_TARGET_PATH flag is specified, then this parameter points to an
|
|
NT path string. If this parameter is NULL, then the device name is being
|
|
deleted or restored if the ADD_PUSH_POP_DEFINITION flag is specified.
|
|
|
|
Return Value:
|
|
|
|
TRUE - The operation was successful
|
|
|
|
FALSE/NULL - The operation failed. Extended error status is available
|
|
using GetLastError.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
BASE_API_MSG m;
|
|
PBASE_DEFINEDOSDEVICE_MSG a = (PBASE_DEFINEDOSDEVICE_MSG)&m.u.DefineDosDeviceApi;
|
|
PCSR_CAPTURE_HEADER p;
|
|
ULONG PointerCount, n;
|
|
UNICODE_STRING DeviceName;
|
|
UNICODE_STRING NtDevicePath;
|
|
UNICODE_STRING TargetPath;
|
|
DWORD iDrive;
|
|
DEV_BROADCAST_VOLUME dbv;
|
|
DWORD dwRec = BSM_APPLICATIONS;
|
|
|
|
if (dwFlags & ~(DDD_RAW_TARGET_PATH |
|
|
DDD_REMOVE_DEFINITION |
|
|
DDD_EXACT_MATCH_ON_REMOVE |
|
|
DDD_NO_BROADCAST_SYSTEM
|
|
) ||
|
|
(((!ARGUMENT_PRESENT( lpTargetPath ) || (dwFlags & DDD_EXACT_MATCH_ON_REMOVE))) &&
|
|
!(dwFlags & DDD_REMOVE_DEFINITION)
|
|
)
|
|
) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
RtlInitUnicodeString( &DeviceName, lpDeviceName );
|
|
PointerCount = 1;
|
|
n = DeviceName.MaximumLength;
|
|
if (ARGUMENT_PRESENT( lpTargetPath )) {
|
|
if (!(dwFlags & DDD_RAW_TARGET_PATH)) {
|
|
if (!RtlDosPathNameToNtPathName_U( lpTargetPath,
|
|
&TargetPath,
|
|
NULL,
|
|
NULL
|
|
)
|
|
) {
|
|
BaseSetLastNTError( STATUS_OBJECT_NAME_INVALID );
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
RtlInitUnicodeString( &TargetPath, lpTargetPath );
|
|
}
|
|
|
|
PointerCount += 1;
|
|
n += TargetPath.MaximumLength;
|
|
}
|
|
else {
|
|
RtlInitUnicodeString( &TargetPath, NULL );
|
|
}
|
|
|
|
p = CsrAllocateCaptureBuffer( PointerCount, 0, n );
|
|
if (p == NULL) {
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
a->Flags = dwFlags;
|
|
a->DeviceName.MaximumLength =
|
|
(USHORT)CsrAllocateMessagePointer( p,
|
|
DeviceName.MaximumLength,
|
|
(PVOID *)&a->DeviceName.Buffer
|
|
);
|
|
RtlUpcaseUnicodeString( &a->DeviceName, &DeviceName, FALSE );
|
|
if (TargetPath.Length != 0) {
|
|
a->TargetPath.MaximumLength =
|
|
(USHORT)CsrAllocateMessagePointer( p,
|
|
TargetPath.MaximumLength,
|
|
(PVOID *)&a->TargetPath.Buffer
|
|
);
|
|
RtlCopyUnicodeString( &a->TargetPath, &TargetPath );
|
|
if (!(dwFlags & DDD_RAW_TARGET_PATH)) {
|
|
RtlFreeUnicodeString( &TargetPath );
|
|
}
|
|
}
|
|
else {
|
|
RtlInitUnicodeString( &a->TargetPath, NULL );
|
|
}
|
|
|
|
CsrClientCallServer( (PCSR_API_MSG)&m,
|
|
p,
|
|
CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
|
|
BasepDefineDosDevice
|
|
),
|
|
sizeof( *a )
|
|
);
|
|
CsrFreeCaptureBuffer( p );
|
|
if (NT_SUCCESS( (NTSTATUS)m.ReturnValue )) {
|
|
if (!(dwFlags & DDD_NO_BROADCAST_SYSTEM) &&
|
|
DeviceName.Length == (2 * sizeof( WCHAR )) &&
|
|
DeviceName.Buffer[ 1 ] == L':' &&
|
|
(iDrive = RtlUpcaseUnicodeChar( DeviceName.Buffer[ 0 ] ) - L'A') < 26
|
|
) {
|
|
dbv.dbcv_size = sizeof( dbv );
|
|
dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME;
|
|
dbv.dbcv_reserved = 0;
|
|
dbv.dbcv_unitmask = (1 << iDrive);
|
|
dbv.dbcv_flags = DBTF_NET;
|
|
|
|
if (hUser32Dll == NULL) {
|
|
hUser32Dll = GetModuleHandleW( L"USER32.DLL" );
|
|
if (hUser32Dll == NULL) {
|
|
hUser32Dll = LoadLibraryW( L"USER32.DLL" );
|
|
if (hUser32Dll == NULL) {
|
|
hUser32Dll = (HMODULE)0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
if (hUser32Dll != NULL && hUser32Dll != (HMODULE)0xFFFFFFFF) {
|
|
pBroadCastSystemMessageW = (PBROADCASTSYSTEMMESSAGEW)
|
|
GetProcAddress( hUser32Dll, "BroadcastSystemMessageW" );
|
|
}
|
|
}
|
|
|
|
// broadcast to all windows!
|
|
if (pBroadCastSystemMessageW != NULL) {
|
|
(*pBroadCastSystemMessageW)( BSF_FORCEIFHUNG |
|
|
BSF_NOHANG |
|
|
BSF_NOTIMEOUTIFNOTHUNG,
|
|
&dwRec,
|
|
WM_DEVICECHANGE,
|
|
(WPARAM)((dwFlags & DDD_REMOVE_DEFINITION) ?
|
|
DBT_DEVICEREMOVECOMPLETE :
|
|
DBT_DEVICEARRIVAL
|
|
),
|
|
(LPARAM)(DEV_BROADCAST_HDR *)&dbv
|
|
);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else {
|
|
BaseSetLastNTError( (NTSTATUS)m.ReturnValue );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
QueryDosDeviceA(
|
|
LPCSTR lpDeviceName,
|
|
LPSTR lpTargetPath,
|
|
DWORD ucchMax
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
DWORD Result;
|
|
ANSI_STRING AnsiString;
|
|
PUNICODE_STRING DeviceName;
|
|
UNICODE_STRING TargetPath;
|
|
PCWSTR lpDeviceNameW;
|
|
PWSTR lpTargetPathW;
|
|
|
|
if (ARGUMENT_PRESENT( lpDeviceName )) {
|
|
RtlInitAnsiString( &AnsiString, lpDeviceName );
|
|
DeviceName = &NtCurrentTeb()->StaticUnicodeString;
|
|
Status = RtlAnsiStringToUnicodeString( DeviceName, &AnsiString, FALSE );
|
|
if (!NT_SUCCESS( Status )) {
|
|
if ( Status == STATUS_BUFFER_OVERFLOW ) {
|
|
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
|
}
|
|
else {
|
|
BaseSetLastNTError( Status );
|
|
}
|
|
return FALSE;
|
|
}
|
|
else {
|
|
lpDeviceNameW = DeviceName->Buffer;
|
|
}
|
|
}
|
|
else {
|
|
lpDeviceNameW = NULL;
|
|
}
|
|
|
|
lpTargetPathW = RtlAllocateHeap( RtlProcessHeap(),
|
|
MAKE_TAG( TMP_TAG ),
|
|
ucchMax * sizeof( WCHAR )
|
|
);
|
|
if (lpTargetPathW == NULL) {
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
Result = QueryDosDeviceW( lpDeviceNameW,
|
|
lpTargetPathW,
|
|
ucchMax
|
|
);
|
|
|
|
if (Result != 0) {
|
|
TargetPath.Buffer = lpTargetPathW;
|
|
TargetPath.Length = (USHORT)(Result * sizeof( WCHAR ));
|
|
TargetPath.MaximumLength = (USHORT)(TargetPath.Length + 1);
|
|
|
|
AnsiString.Buffer = lpTargetPath;
|
|
AnsiString.Length = 0;
|
|
AnsiString.MaximumLength = (USHORT)ucchMax;
|
|
|
|
Status = RtlUnicodeStringToAnsiString( &AnsiString,
|
|
&TargetPath,
|
|
FALSE
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
BaseSetLastNTError( Status );
|
|
Result = 0;
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap( RtlProcessHeap(), 0, lpTargetPathW );
|
|
return Result;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
QueryDosDeviceW(
|
|
PCWSTR lpDeviceName,
|
|
PWSTR lpTargetPath,
|
|
DWORD ucchMax
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES Attributes;
|
|
HANDLE DirectoryHandle;
|
|
HANDLE LinkHandle;
|
|
POBJECT_DIRECTORY_INFORMATION DirInfo;
|
|
BOOLEAN RestartScan;
|
|
UCHAR DirInfoBuffer[ 512 ];
|
|
CLONG Count = 0;
|
|
ULONG Context = 0;
|
|
ULONG ReturnedLength;
|
|
DWORD ucchName, ucchReturned;
|
|
|
|
RtlInitUnicodeString( &UnicodeString, L"\\??" );
|
|
InitializeObjectAttributes( &Attributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Status = NtOpenDirectoryObject( &DirectoryHandle,
|
|
DIRECTORY_QUERY,
|
|
&Attributes
|
|
);
|
|
if (!NT_SUCCESS( Status )) {
|
|
BaseSetLastNTError( Status );
|
|
return 0;
|
|
}
|
|
|
|
ucchReturned = 0;
|
|
try {
|
|
if (ARGUMENT_PRESENT( lpDeviceName )) {
|
|
RtlInitUnicodeString( &UnicodeString, lpDeviceName );
|
|
InitializeObjectAttributes( &Attributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
DirectoryHandle,
|
|
NULL
|
|
);
|
|
Status = NtOpenSymbolicLinkObject( &LinkHandle,
|
|
SYMBOLIC_LINK_QUERY,
|
|
&Attributes
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
UnicodeString.Buffer = lpTargetPath;
|
|
UnicodeString.Length = 0;
|
|
UnicodeString.MaximumLength = (USHORT)(ucchMax * sizeof( WCHAR ));
|
|
ReturnedLength = 0;
|
|
Status = NtQuerySymbolicLinkObject( LinkHandle,
|
|
&UnicodeString,
|
|
&ReturnedLength
|
|
);
|
|
NtClose( LinkHandle );
|
|
if (NT_SUCCESS( Status )) {
|
|
ucchReturned = ReturnedLength / sizeof( WCHAR );
|
|
if (ucchReturned < ucchMax) {
|
|
lpTargetPath[ ucchReturned++ ] = UNICODE_NULL;
|
|
}
|
|
else {
|
|
ucchReturned = 0;
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
RestartScan = TRUE;
|
|
DirInfo = (POBJECT_DIRECTORY_INFORMATION)&DirInfoBuffer;
|
|
while (TRUE) {
|
|
Status = NtQueryDirectoryObject( DirectoryHandle,
|
|
(PVOID)DirInfo,
|
|
sizeof( DirInfoBuffer ),
|
|
TRUE,
|
|
RestartScan,
|
|
&Context,
|
|
&ReturnedLength
|
|
);
|
|
|
|
//
|
|
// Check the status of the operation.
|
|
//
|
|
|
|
if (!NT_SUCCESS( Status )) {
|
|
if (Status == STATUS_NO_MORE_ENTRIES) {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (!wcscmp( DirInfo->TypeName.Buffer, L"SymbolicLink" )) {
|
|
ucchName = DirInfo->Name.Length / sizeof( WCHAR );
|
|
if ((ucchReturned + ucchName + 1 + 1) > ucchMax) {
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
RtlMoveMemory( lpTargetPath,
|
|
DirInfo->Name.Buffer,
|
|
DirInfo->Name.Length
|
|
);
|
|
lpTargetPath += ucchName;
|
|
*lpTargetPath++ = UNICODE_NULL;
|
|
ucchReturned += ucchName + 1;
|
|
}
|
|
|
|
RestartScan = FALSE;
|
|
}
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
*lpTargetPath++ = UNICODE_NULL;
|
|
ucchReturned++;
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
NtClose( DirectoryHandle );
|
|
}
|
|
|
|
if (!NT_SUCCESS( Status )) {
|
|
BaseSetLastNTError( Status );
|
|
}
|
|
|
|
return ucchReturned;
|
|
}
|