reactos/dll/win32/kernel32/file/dosdev.c
Sylvain Petreolle 1fb94b1cb5 [CMAKE]
sync with trunk (r49230)

svn path=/branches/cmake-bringup/; revision=49246
2010-10-23 22:14:59 +00:00

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 */