mirror of
https://github.com/reactos/reactos.git
synced 2024-10-09 10:48:55 +00:00
1fb94b1cb5
sync with trunk (r49230) svn path=/branches/cmake-bringup/; revision=49246
333 lines
6.8 KiB
C
333 lines
6.8 KiB
C
/* $Id$
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* FILE: lib/kernel32/file/dosdev.c
|
|
* PURPOSE: Dos device functions
|
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
|
* UPDATE HISTORY:
|
|
* Created 01/11/98
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <k32.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
DEBUG_CHANNEL(kernel32file);
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
DefineDosDeviceA(
|
|
DWORD dwFlags,
|
|
LPCSTR lpDeviceName,
|
|
LPCSTR lpTargetPath
|
|
)
|
|
{
|
|
UNICODE_STRING DeviceNameU;
|
|
UNICODE_STRING TargetPathU;
|
|
BOOL Result;
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU,
|
|
(LPSTR)lpDeviceName))
|
|
{
|
|
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz (&TargetPathU,
|
|
(LPSTR)lpTargetPath))
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
DeviceNameU.Buffer);
|
|
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
|
|
Result = DefineDosDeviceW (dwFlags,
|
|
DeviceNameU.Buffer,
|
|
TargetPathU.Buffer);
|
|
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
TargetPathU.Buffer);
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
DeviceNameU.Buffer);
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
DefineDosDeviceW(
|
|
DWORD dwFlags,
|
|
LPCWSTR lpDeviceName,
|
|
LPCWSTR lpTargetPath
|
|
)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD
|
|
WINAPI
|
|
QueryDosDeviceA(
|
|
LPCSTR lpDeviceName,
|
|
LPSTR lpTargetPath,
|
|
DWORD ucchMax
|
|
)
|
|
{
|
|
UNICODE_STRING DeviceNameU;
|
|
UNICODE_STRING TargetPathU;
|
|
ANSI_STRING TargetPathA;
|
|
DWORD Length;
|
|
DWORD CurrentLength;
|
|
PWCHAR Buffer;
|
|
|
|
if (lpDeviceName)
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU,
|
|
(LPSTR)lpDeviceName))
|
|
{
|
|
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
}
|
|
Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
|
0,
|
|
ucchMax * sizeof(WCHAR));
|
|
if (Buffer == NULL)
|
|
{
|
|
if (lpDeviceName)
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
DeviceNameU.Buffer);
|
|
}
|
|
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
|
|
Length = QueryDosDeviceW (lpDeviceName ? DeviceNameU.Buffer : NULL,
|
|
Buffer,
|
|
ucchMax);
|
|
if (Length != 0)
|
|
{
|
|
TargetPathA.Buffer = lpTargetPath;
|
|
TargetPathU.Buffer = Buffer;
|
|
ucchMax = Length;
|
|
|
|
while (ucchMax)
|
|
{
|
|
CurrentLength = min (ucchMax, MAXUSHORT / 2);
|
|
TargetPathU.MaximumLength = TargetPathU.Length = (USHORT)CurrentLength * sizeof(WCHAR);
|
|
|
|
TargetPathA.Length = 0;
|
|
TargetPathA.MaximumLength = (USHORT)CurrentLength;
|
|
|
|
RtlUnicodeStringToAnsiString (&TargetPathA,
|
|
&TargetPathU,
|
|
FALSE);
|
|
ucchMax -= CurrentLength;
|
|
TargetPathA.Buffer += TargetPathA.Length;
|
|
TargetPathU.Buffer += TargetPathU.Length / sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
Buffer);
|
|
if (lpDeviceName)
|
|
{
|
|
RtlFreeHeap (RtlGetProcessHeap (),
|
|
0,
|
|
DeviceNameU.Buffer);
|
|
}
|
|
return Length;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD
|
|
WINAPI
|
|
QueryDosDeviceW(
|
|
LPCWSTR lpDeviceName,
|
|
LPWSTR lpTargetPath,
|
|
DWORD ucchMax
|
|
)
|
|
{
|
|
POBJECT_DIRECTORY_INFORMATION DirInfo;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE DirectoryHandle;
|
|
HANDLE DeviceHandle;
|
|
ULONG ReturnLength;
|
|
ULONG NameLength;
|
|
ULONG Length;
|
|
ULONG Context;
|
|
BOOLEAN RestartScan;
|
|
NTSTATUS Status;
|
|
UCHAR Buffer[512];
|
|
PWSTR Ptr;
|
|
|
|
/* Open the '\??' directory */
|
|
RtlInitUnicodeString (&UnicodeString,
|
|
L"\\??");
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenDirectoryObject (&DirectoryHandle,
|
|
DIRECTORY_QUERY,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS (Status))
|
|
{
|
|
WARN ("NtOpenDirectoryObject() failed (Status %lx)\n", Status);
|
|
SetLastErrorByStatus (Status);
|
|
return 0;
|
|
}
|
|
|
|
Length = 0;
|
|
|
|
if (lpDeviceName != NULL)
|
|
{
|
|
/* Open the lpDeviceName link object */
|
|
RtlInitUnicodeString (&UnicodeString,
|
|
(PWSTR)lpDeviceName);
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
DirectoryHandle,
|
|
NULL);
|
|
Status = NtOpenSymbolicLinkObject (&DeviceHandle,
|
|
SYMBOLIC_LINK_QUERY,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS (Status))
|
|
{
|
|
WARN ("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status);
|
|
NtClose (DirectoryHandle);
|
|
SetLastErrorByStatus (Status);
|
|
return 0;
|
|
}
|
|
|
|
/* Query link target */
|
|
UnicodeString.Length = 0;
|
|
UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR);
|
|
UnicodeString.Buffer = lpTargetPath;
|
|
|
|
ReturnLength = 0;
|
|
Status = NtQuerySymbolicLinkObject (DeviceHandle,
|
|
&UnicodeString,
|
|
&ReturnLength);
|
|
NtClose (DeviceHandle);
|
|
NtClose (DirectoryHandle);
|
|
if (!NT_SUCCESS (Status))
|
|
{
|
|
WARN ("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status);
|
|
SetLastErrorByStatus (Status);
|
|
return 0;
|
|
}
|
|
|
|
TRACE ("ReturnLength: %lu\n", ReturnLength);
|
|
TRACE ("TargetLength: %hu\n", UnicodeString.Length);
|
|
TRACE ("Target: '%wZ'\n", &UnicodeString);
|
|
|
|
Length = ReturnLength / sizeof(WCHAR);
|
|
if (Length < ucchMax)
|
|
{
|
|
/* Append null-charcter */
|
|
lpTargetPath[Length] = UNICODE_NULL;
|
|
Length++;
|
|
}
|
|
else
|
|
{
|
|
TRACE ("Buffer is too small\n");
|
|
SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RestartScan = TRUE;
|
|
Context = 0;
|
|
Ptr = lpTargetPath;
|
|
DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
|
|
|
|
while (TRUE)
|
|
{
|
|
Status = NtQueryDirectoryObject (DirectoryHandle,
|
|
Buffer,
|
|
sizeof (Buffer),
|
|
TRUE,
|
|
RestartScan,
|
|
&Context,
|
|
&ReturnLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
|
{
|
|
/* Terminate the buffer */
|
|
*Ptr = UNICODE_NULL;
|
|
Length++;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Length = 0;
|
|
}
|
|
SetLastErrorByStatus (Status);
|
|
break;
|
|
}
|
|
|
|
if (!wcscmp (DirInfo->TypeName.Buffer, L"SymbolicLink"))
|
|
{
|
|
TRACE ("Name: '%wZ'\n", &DirInfo->Name);
|
|
|
|
NameLength = DirInfo->Name.Length / sizeof(WCHAR);
|
|
if (Length + NameLength + 1 >= ucchMax)
|
|
{
|
|
Length = 0;
|
|
SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
|
|
break;
|
|
}
|
|
|
|
memcpy (Ptr,
|
|
DirInfo->Name.Buffer,
|
|
DirInfo->Name.Length);
|
|
Ptr += NameLength;
|
|
Length += NameLength;
|
|
*Ptr = UNICODE_NULL;
|
|
Ptr++;
|
|
Length++;
|
|
}
|
|
|
|
RestartScan = FALSE;
|
|
}
|
|
|
|
NtClose (DirectoryHandle);
|
|
}
|
|
|
|
return Length;
|
|
}
|
|
|
|
/* EOF */
|