mirror of
https://github.com/reactos/reactos.git
synced 2024-06-28 17:01:28 +00:00
Sam Arun Raj Seeniraj:
[KERNEL32] - DefineDosDeviceW() is implemented and calls into csrss.exe CsrDefineDosDevice(). - Fixed a minor bug in DefineDosDeviceA(), as calling RtlCreateUnicodeStringFromAsciiz() prevented NULL lpTargetPath to be passed down to DefineDosDeviceW(). - Fixed a minor bug in QueryDosDeviceW() that causes lpTargetPath buffer to be returned with NULL string terminator placed at the wrong point in the buffer. [WIN32CSR.DLL] - Implemented CsrDefineDosDevice() in win32csr.dll, the symbolic links are created in global name space currently. [SUBST.EXE] - Implemented a subst.exe clone. See issue #993 for more details. svn path=/trunk/; revision=51393
This commit is contained in:
parent
46662954bd
commit
a63e424516
257
reactos/base/system/subst/subst.c
Normal file
257
reactos/base/system/subst/subst.c
Normal file
|
@ -0,0 +1,257 @@
|
|||
/* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: base/system/subst/subst.c
|
||||
* PURPOSE: Associates a path with a drive letter
|
||||
* PROGRAMMERS: Sam Arun Raj
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#define LEAN_AND_MEAN
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
void PrintError(DWORD ErrCode)
|
||||
{
|
||||
TCHAR *buffer = (TCHAR*) calloc(2048,
|
||||
sizeof(TCHAR));
|
||||
TCHAR *msg = NULL;
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
ErrCode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(TCHAR*)&msg,
|
||||
0,
|
||||
NULL);
|
||||
_sntprintf(buffer,
|
||||
2048,
|
||||
_T("Failed with error code 0x%x: %s\n"),
|
||||
ErrCode,
|
||||
msg);
|
||||
_tprintf(_T("%s"),
|
||||
buffer);
|
||||
if (msg)
|
||||
LocalFree(msg);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySubstUsage()
|
||||
{
|
||||
_tprintf(_T("Associates a path with a drive letter.\n\n"));
|
||||
_tprintf(_T("SUBST [drive1: [drive2:]path]\n"));
|
||||
_tprintf(_T("SUBST drive1: /D\n\n"));
|
||||
_tprintf(_T(" drive1: Specifies a virtual drive to which you want to assign a path.\n"));
|
||||
_tprintf(_T(" [drive2:]path Specifies a physical drive and path you want to assign to\n"));
|
||||
_tprintf(_T(" a virtual drive.\n"));
|
||||
_tprintf(_T(" /D Deletes a substituted (virtual) drive.\n\n"));
|
||||
_tprintf(_T("Type SUBST with no parameters to display a list of current virtual drives.\n"));
|
||||
}
|
||||
|
||||
BOOLEAN IsSubstedDrive(TCHAR *Drive)
|
||||
{
|
||||
BOOLEAN Result = FALSE;
|
||||
LPTSTR lpTargetPath = NULL;
|
||||
DWORD CharCount, dwSize;
|
||||
|
||||
if (_tcslen(Drive) > 2)
|
||||
return FALSE;
|
||||
|
||||
dwSize = sizeof(TCHAR) * MAX_PATH;
|
||||
lpTargetPath = (LPTSTR) malloc(sizeof(TCHAR) * MAX_PATH);
|
||||
if ( lpTargetPath)
|
||||
{
|
||||
CharCount = QueryDosDevice(Drive,
|
||||
lpTargetPath,
|
||||
dwSize / sizeof(TCHAR));
|
||||
while (! CharCount &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
free(lpTargetPath);
|
||||
dwSize *= 2;
|
||||
lpTargetPath = (LPTSTR) malloc(dwSize);
|
||||
if (lpTargetPath)
|
||||
{
|
||||
CharCount = QueryDosDevice(Drive,
|
||||
lpTargetPath,
|
||||
dwSize / sizeof(TCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
if (CharCount)
|
||||
{
|
||||
if ( _tcsncmp(lpTargetPath, _T("\\??\\"), 4) == 0 &&
|
||||
( (lpTargetPath[4] >= _T('A') &&
|
||||
lpTargetPath[4] <= _T('Z')) ||
|
||||
(lpTargetPath[4] >= _T('a') &&
|
||||
lpTargetPath[4] <= _T('z')) ) )
|
||||
{
|
||||
Result = TRUE;
|
||||
}
|
||||
}
|
||||
free(lpTargetPath);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void DumpSubstedDrives()
|
||||
{
|
||||
TCHAR Drive[3] = _T("A:");
|
||||
LPTSTR lpTargetPath = NULL;
|
||||
DWORD CharCount, dwSize;
|
||||
INT i = 0;
|
||||
|
||||
dwSize = sizeof(TCHAR) * MAX_PATH;
|
||||
lpTargetPath = (LPTSTR) malloc(sizeof(TCHAR) * MAX_PATH);
|
||||
if (! lpTargetPath)
|
||||
return;
|
||||
|
||||
while (i < 26)
|
||||
{
|
||||
Drive[0] = _T('A') + i;
|
||||
CharCount = QueryDosDevice(Drive,
|
||||
lpTargetPath,
|
||||
dwSize / sizeof(TCHAR));
|
||||
while (! CharCount &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
free(lpTargetPath);
|
||||
dwSize *= 2;
|
||||
lpTargetPath = (LPTSTR) malloc(dwSize);
|
||||
if (lpTargetPath)
|
||||
{
|
||||
CharCount = QueryDosDevice(Drive,
|
||||
lpTargetPath,
|
||||
dwSize / sizeof(TCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
if (! CharCount)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( _tcsncmp(lpTargetPath, _T("\\??\\"), 4) == 0 &&
|
||||
( (lpTargetPath[4] >= _T('A') &&
|
||||
lpTargetPath[4] <= _T('Z')) ||
|
||||
(lpTargetPath[4] >= _T('a') &&
|
||||
lpTargetPath[4] <= _T('z')) ) )
|
||||
{
|
||||
_tprintf(_T("%s\\: => %s\n"),
|
||||
Drive,
|
||||
lpTargetPath + 4);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
free(lpTargetPath);
|
||||
}
|
||||
|
||||
int DeleteSubst(TCHAR* Drive)
|
||||
{
|
||||
BOOL Result;
|
||||
|
||||
if (_tcslen(Drive) > 2)
|
||||
{
|
||||
_tprintf(_T("Invalid parameter - %s\n"),
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! IsSubstedDrive(Drive))
|
||||
{
|
||||
_tprintf(_T("Invalid Parameter - %s\n"),
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Result = DefineDosDevice(DDD_REMOVE_DEFINITION,
|
||||
Drive,
|
||||
NULL);
|
||||
if (! Result)
|
||||
{
|
||||
PrintError(GetLastError());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AddSubst(TCHAR* Drive, TCHAR *Path)
|
||||
{
|
||||
BOOL Result;
|
||||
|
||||
if (_tcslen(Drive) > 2)
|
||||
{
|
||||
_tprintf(_T("Invalid parameter - %s\n"),
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IsSubstedDrive(Drive))
|
||||
{
|
||||
_tprintf(_T("Drive already SUBSTed\n"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
Result = DefineDosDevice(0,
|
||||
Drive,
|
||||
Path);
|
||||
if (! Result)
|
||||
{
|
||||
PrintError(GetLastError());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _tmain(int argc, TCHAR* argv[])
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (!_tcsicmp(argv[i], _T("/?")))
|
||||
{
|
||||
DisplaySubstUsage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
if (argc >= 2)
|
||||
{
|
||||
_tprintf(_T("Invalid parameter - %s\n"),
|
||||
argv[1]);
|
||||
return 1;
|
||||
}
|
||||
DumpSubstedDrives();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
_tprintf(_T("Incorrect number of parameters - %s\n"),
|
||||
argv[3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! _tcsicmp(argv[1], _T("/D")))
|
||||
return DeleteSubst(argv[2]);
|
||||
if (! _tcsicmp(argv[2], _T("/D")))
|
||||
return DeleteSubst(argv[1]);
|
||||
return AddSubst(argv[1], argv[2]);
|
||||
}
|
||||
|
||||
/* EOF */
|
9
reactos/base/system/subst/subst.rbuild
Normal file
9
reactos/base/system/subst/subst.rbuild
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="subst" type="win32cui" installbase="system32" installname="subst.exe" >
|
||||
<include base="ReactOS">include/reactos/wine</include>
|
||||
<include base="subst">.</include>
|
||||
<library>kernel32</library>
|
||||
<file>subst.c</file>
|
||||
<file>subst.rc</file>
|
||||
</module>
|
5
reactos/base/system/subst/subst.rc
Normal file
5
reactos/base/system/subst/subst.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#include <windows.h>
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Virtual Drive Utility Version 1.0 \0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "subst\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "subst.exe\0"
|
||||
#include <reactos/version.rc>
|
|
@ -10,6 +10,9 @@
|
|||
<directory name="expand">
|
||||
<xi:include href="expand/expand.rbuild" />
|
||||
</directory>
|
||||
<directory name="subst">
|
||||
<xi:include href="subst/subst.rbuild" />
|
||||
</directory>
|
||||
<directory name="format">
|
||||
<xi:include href="format/format.rbuild" />
|
||||
</directory>
|
||||
|
|
|
@ -115,6 +115,7 @@ base\shell\explorer-new\explorer_new.exe 4 optional
|
|||
base\system\autochk\autochk.exe 1
|
||||
base\system\bootok\bootok.exe 1
|
||||
base\system\expand\expand.exe 1
|
||||
base\system\subst\subst.exe 1
|
||||
base\system\format\format.exe 1
|
||||
base\system\lsass\lsass.exe 1
|
||||
base\system\msiexec\msiexec.exe 1
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <k32.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include <Dbt.h>
|
||||
DEBUG_CHANNEL(kernel32file);
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
@ -29,44 +30,55 @@ DefineDosDeviceA(
|
|||
LPCSTR lpTargetPath
|
||||
)
|
||||
{
|
||||
UNICODE_STRING DeviceNameU;
|
||||
UNICODE_STRING TargetPathU;
|
||||
BOOL Result;
|
||||
UNICODE_STRING DeviceNameU = {0};
|
||||
UNICODE_STRING TargetPathU = {0};
|
||||
BOOL Result;
|
||||
|
||||
if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU,
|
||||
(LPSTR)lpDeviceName))
|
||||
{
|
||||
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
if (lpDeviceName &&
|
||||
! 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;
|
||||
}
|
||||
if (lpTargetPath &&
|
||||
! RtlCreateUnicodeStringFromAsciiz(&TargetPathU,
|
||||
(LPSTR)lpTargetPath))
|
||||
{
|
||||
if (DeviceNameU.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap (),
|
||||
0,
|
||||
DeviceNameU.Buffer);
|
||||
}
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result = DefineDosDeviceW (dwFlags,
|
||||
DeviceNameU.Buffer,
|
||||
TargetPathU.Buffer);
|
||||
Result = DefineDosDeviceW(dwFlags,
|
||||
DeviceNameU.Buffer,
|
||||
TargetPathU.Buffer);
|
||||
|
||||
RtlFreeHeap (RtlGetProcessHeap (),
|
||||
0,
|
||||
TargetPathU.Buffer);
|
||||
RtlFreeHeap (RtlGetProcessHeap (),
|
||||
0,
|
||||
DeviceNameU.Buffer);
|
||||
if (TargetPathU.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap (),
|
||||
0,
|
||||
TargetPathU.Buffer);
|
||||
}
|
||||
|
||||
return Result;
|
||||
if (DeviceNameU.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap (),
|
||||
0,
|
||||
DeviceNameU.Buffer);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
|
@ -76,8 +88,154 @@ DefineDosDeviceW(
|
|||
LPCWSTR lpTargetPath
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
ULONG ArgumentCount;
|
||||
ULONG BufferSize;
|
||||
PCSR_CAPTURE_BUFFER CaptureBuffer;
|
||||
CSR_API_MESSAGE Request;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING NtTargetPathU;
|
||||
UNICODE_STRING DeviceNameU;
|
||||
UNICODE_STRING DeviceUpcaseNameU;
|
||||
HANDLE hUser32;
|
||||
DEV_BROADCAST_VOLUME dbcv;
|
||||
BOOL Result = TRUE;
|
||||
DWORD dwRecipients;
|
||||
typedef long (WINAPI *BSM_type)(DWORD,LPDWORD,UINT,WPARAM,LPARAM);
|
||||
BSM_type BSM_ptr;
|
||||
|
||||
if ( (dwFlags & 0xFFFFFFF0) ||
|
||||
((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
|
||||
! (dwFlags & DDD_REMOVE_DEFINITION)) )
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ArgumentCount = 1;
|
||||
BufferSize = 0;
|
||||
if (! lpTargetPath)
|
||||
{
|
||||
RtlInitUnicodeString(&NtTargetPathU,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dwFlags & DDD_RAW_TARGET_PATH)
|
||||
{
|
||||
RtlInitUnicodeString(&NtTargetPathU,
|
||||
lpTargetPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! RtlDosPathNameToNtPathName_U(lpTargetPath,
|
||||
&NtTargetPathU,
|
||||
0,
|
||||
0))
|
||||
{
|
||||
WARN("RtlDosPathNameToNtPathName_U() failed\n");
|
||||
BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
ArgumentCount = 2;
|
||||
BufferSize += NtTargetPathU.Length;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&DeviceNameU,
|
||||
lpDeviceName);
|
||||
RtlUpcaseUnicodeString(&DeviceUpcaseNameU,
|
||||
&DeviceNameU,
|
||||
TRUE);
|
||||
BufferSize += DeviceUpcaseNameU.Length;
|
||||
|
||||
CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount,
|
||||
BufferSize);
|
||||
if (! CaptureBuffer)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
Result = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Request.Data.DefineDosDeviceRequest.dwFlags = dwFlags;
|
||||
|
||||
CsrCaptureMessageBuffer(CaptureBuffer,
|
||||
(PVOID)DeviceUpcaseNameU.Buffer,
|
||||
DeviceUpcaseNameU.Length,
|
||||
(PVOID*)&Request.Data.DefineDosDeviceRequest.DeviceName.Buffer);
|
||||
|
||||
Request.Data.DefineDosDeviceRequest.DeviceName.Length =
|
||||
DeviceUpcaseNameU.Length;
|
||||
Request.Data.DefineDosDeviceRequest.DeviceName.MaximumLength =
|
||||
DeviceUpcaseNameU.Length;
|
||||
|
||||
if (NtTargetPathU.Buffer)
|
||||
{
|
||||
CsrCaptureMessageBuffer(CaptureBuffer,
|
||||
(PVOID)NtTargetPathU.Buffer,
|
||||
NtTargetPathU.Length,
|
||||
(PVOID*)&Request.Data.DefineDosDeviceRequest.TargetName.Buffer);
|
||||
}
|
||||
Request.Data.DefineDosDeviceRequest.TargetName.Length =
|
||||
NtTargetPathU.Length;
|
||||
Request.Data.DefineDosDeviceRequest.TargetName.MaximumLength =
|
||||
NtTargetPathU.Length;
|
||||
|
||||
Status = CsrClientCallServer(&Request,
|
||||
CaptureBuffer,
|
||||
MAKE_CSR_API(DEFINE_DOS_DEVICE, CSR_CONSOLE),
|
||||
sizeof(CSR_API_MESSAGE));
|
||||
CsrFreeCaptureBuffer(CaptureBuffer);
|
||||
|
||||
if (! NT_SUCCESS(Status) ||
|
||||
! NT_SUCCESS(Status = Request.Status))
|
||||
{
|
||||
WARN("CsrClientCallServer() failed (Status %lx)\n",
|
||||
Status);
|
||||
SetLastErrorByStatus(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");
|
||||
if (hUser32)
|
||||
{
|
||||
BSM_ptr = (BSM_type)
|
||||
GetProcAddress(hUser32, "BroadcastSystemMessageW");
|
||||
if (BSM_ptr)
|
||||
{
|
||||
dwRecipients = BSM_APPLICATIONS;
|
||||
dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
|
||||
dbcv.dbcv_devicetype = DBT_DEVTYP_VOLUME;
|
||||
dbcv.dbcv_reserved = 0;
|
||||
dbcv.dbcv_unitmask |=
|
||||
(1 << (DeviceUpcaseNameU.Buffer[0] - L'A'));
|
||||
dbcv.dbcv_flags = DBTF_NET;
|
||||
(void) BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK,
|
||||
&dwRecipients,
|
||||
WM_DEVICECHANGE,
|
||||
(WPARAM)DBT_DEVICEARRIVAL,
|
||||
(LPARAM)&dbcv);
|
||||
}
|
||||
FreeLibrary(hUser32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NtTargetPathU.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
NtTargetPathU.Buffer);
|
||||
}
|
||||
RtlFreeUnicodeString(&DeviceUpcaseNameU);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -250,7 +408,7 @@ QueryDosDeviceW(
|
|||
TRACE ("TargetLength: %hu\n", UnicodeString.Length);
|
||||
TRACE ("Target: '%wZ'\n", &UnicodeString);
|
||||
|
||||
Length = ReturnLength / sizeof(WCHAR);
|
||||
Length = UnicodeString.Length / sizeof(WCHAR);
|
||||
if (Length < ucchMax)
|
||||
{
|
||||
/* Append null-charcter */
|
||||
|
|
|
@ -518,6 +518,13 @@ typedef struct
|
|||
UINT UniqueID;
|
||||
} CSRSS_GET_TEMP_FILE, *PCSRSS_GET_TEMP_FILE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING TargetName;
|
||||
DWORD dwFlags;
|
||||
} CSRSS_DEFINE_DOS_DEVICE, *PCSRSS_DEFINE_DOS_DEVICE;
|
||||
|
||||
#define CSR_API_MESSAGE_HEADER_SIZE(Type) (FIELD_OFFSET(CSR_API_MESSAGE, Data) + sizeof(Type))
|
||||
#define CSRSS_MAX_WRITE_CONSOLE (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE))
|
||||
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR))
|
||||
|
@ -598,6 +605,7 @@ typedef struct
|
|||
#define GET_HISTORY_INFO (0x46)
|
||||
#define SET_HISTORY_INFO (0x47)
|
||||
#define GET_TEMP_FILE (0x48)
|
||||
#define DEFINE_DOS_DEVICE (0X49)
|
||||
|
||||
/* Keep in sync with definition below. */
|
||||
#define CSRSS_HEADER_SIZE (sizeof(PORT_MESSAGE) + sizeof(ULONG) + sizeof(NTSTATUS))
|
||||
|
@ -680,6 +688,7 @@ typedef struct _CSR_API_MESSAGE
|
|||
CSRSS_GET_HISTORY_INFO GetHistoryInfo;
|
||||
CSRSS_SET_HISTORY_INFO SetHistoryInfo;
|
||||
CSRSS_GET_TEMP_FILE GetTempFile;
|
||||
CSRSS_DEFINE_DOS_DEVICE DefineDosDeviceRequest;
|
||||
} Data;
|
||||
} CSR_API_MESSAGE, *PCSR_API_MESSAGE;
|
||||
|
||||
|
|
|
@ -9,11 +9,14 @@
|
|||
/* INCLUDES ******************************************************************/
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include "file.h"
|
||||
#include <debug.h>
|
||||
|
||||
/* Not defined in any header file */
|
||||
extern VOID WINAPI PrivateCsrssManualGuiCheck(LONG Check);
|
||||
extern VOID WINAPI InitializeAppSwitchHook();
|
||||
extern LIST_ENTRY DosDeviceHistory;
|
||||
extern RTL_CRITICAL_SECTION Win32CsrDefineDosDeviceCritSec;
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
|
@ -88,6 +91,7 @@ static CSRSS_API_DEFINITION Win32CsrApiDefinitions[] =
|
|||
CSRSS_DEFINE_API(GET_HISTORY_INFO, CsrGetHistoryInfo),
|
||||
CSRSS_DEFINE_API(SET_HISTORY_INFO, CsrSetHistoryInfo),
|
||||
CSRSS_DEFINE_API(GET_TEMP_FILE, CsrGetTempFile),
|
||||
CSRSS_DEFINE_API(DEFINE_DOS_DEVICE, CsrDefineDosDevice),
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -104,6 +108,10 @@ DllMain(HANDLE hDll,
|
|||
InitializeAppSwitchHook();
|
||||
}
|
||||
|
||||
if (DLL_PROCESS_DETACH == dwReason)
|
||||
{
|
||||
CsrCleanupDefineDosDevice();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -174,6 +182,8 @@ Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions,
|
|||
ServerProcs->ProcessInheritProc = Win32CsrDuplicateHandleTable;
|
||||
ServerProcs->ProcessDeletedProc = Win32CsrReleaseConsole;
|
||||
|
||||
Status = RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
InitializeListHead(&DosDeviceHistory);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,15 @@
|
|||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <w32csr.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include "file.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
UINT CsrGetTempFileUnique;
|
||||
LIST_ENTRY DosDeviceHistory;
|
||||
RTL_CRITICAL_SECTION Win32CsrDefineDosDeviceCritSec;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
@ -31,3 +33,508 @@ CSR_API(CsrGetTempFile)
|
|||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrDefineDosDevice)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE LinkHandle = NULL;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING DeviceName = {0};
|
||||
UNICODE_STRING RequestDeviceName = {0};
|
||||
UNICODE_STRING LinkTarget = {0};
|
||||
PUNICODE_STRING RequestLinkTarget;
|
||||
ULONG Length;
|
||||
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
||||
SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
PACL Dacl;
|
||||
PSID AdminSid;
|
||||
PSID SystemSid;
|
||||
PSID WorldSid;
|
||||
ULONG SidLength;
|
||||
PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
|
||||
PLIST_ENTRY Entry;
|
||||
PLIST_ENTRY ListHead;
|
||||
BOOLEAN Matched, AddHistory;
|
||||
DWORD dwFlags;
|
||||
PWSTR lpBuffer;
|
||||
|
||||
DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
|
||||
Request->Data.DefineDosDeviceRequest.dwFlags,
|
||||
&Request->Data.DefineDosDeviceRequest.DeviceName,
|
||||
&Request->Data.DefineDosDeviceRequest.TargetName);
|
||||
|
||||
Matched = AddHistory = FALSE;
|
||||
HistoryEntry = NULL;
|
||||
AdminSid = SystemSid = WorldSid = NULL;
|
||||
SecurityDescriptor = NULL;
|
||||
ListHead = &DosDeviceHistory;
|
||||
dwFlags = Request->Data.DefineDosDeviceRequest.dwFlags;
|
||||
|
||||
/* Validate the flags */
|
||||
if ( (dwFlags & 0xFFFFFFF0) ||
|
||||
((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
|
||||
! (dwFlags & DDD_REMOVE_DEFINITION)) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = RtlEnterCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlEnterCriticalSection() failed (Status %lx)",
|
||||
Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
Status =
|
||||
RtlUpcaseUnicodeString(&RequestDeviceName,
|
||||
&Request->Data.DefineDosDeviceRequest.DeviceName,
|
||||
TRUE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
_SEH2_LEAVE;
|
||||
|
||||
RequestLinkTarget =
|
||||
&Request->Data.DefineDosDeviceRequest.TargetName;
|
||||
lpBuffer = (PWSTR) RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
RequestDeviceName.MaximumLength + 5 * sizeof(WCHAR));
|
||||
if (! lpBuffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
swprintf(lpBuffer,
|
||||
L"\\??\\%wZ",
|
||||
&RequestDeviceName);
|
||||
RtlInitUnicodeString(&DeviceName,
|
||||
lpBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenSymbolicLinkObject(&LinkHandle,
|
||||
DELETE | 0x1,
|
||||
&ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = NtQuerySymbolicLinkObject(LinkHandle,
|
||||
&LinkTarget,
|
||||
&Length);
|
||||
if (! NT_SUCCESS(Status) &&
|
||||
Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
LinkTarget.Length = 0;
|
||||
LinkTarget.MaximumLength = Length;
|
||||
LinkTarget.Buffer = (PWSTR)
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
Length);
|
||||
if (! LinkTarget.Buffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Status = NtQuerySymbolicLinkObject(LinkHandle,
|
||||
&LinkTarget,
|
||||
&Length);
|
||||
}
|
||||
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)",
|
||||
&DeviceName, Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
if ((dwFlags & DDD_REMOVE_DEFINITION))
|
||||
{
|
||||
/* If no target name specified we remove the current symlink target */
|
||||
if (RequestLinkTarget->Length == 0)
|
||||
Matched = TRUE;
|
||||
else
|
||||
{
|
||||
if (dwFlags & DDD_EXACT_MATCH_ON_REMOVE)
|
||||
Matched = ! RtlCompareUnicodeString(RequestLinkTarget,
|
||||
&LinkTarget,
|
||||
TRUE);
|
||||
else
|
||||
Matched = RtlPrefixUnicodeString(RequestLinkTarget,
|
||||
&LinkTarget,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
if (Matched && IsListEmpty(ListHead))
|
||||
{
|
||||
/* Current symlink target macthed and there is nothing to revert to */
|
||||
RequestLinkTarget = NULL;
|
||||
}
|
||||
else if (Matched && ! IsListEmpty(ListHead))
|
||||
{
|
||||
/* Fetch the first history entry we come across for the device name */
|
||||
/* This will become the current symlink target for the device name */
|
||||
Matched = FALSE;
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Matched =
|
||||
! RtlCompareUnicodeString(&RequestDeviceName,
|
||||
&HistoryEntry->Device,
|
||||
FALSE);
|
||||
if (Matched)
|
||||
{
|
||||
RemoveEntryList(&HistoryEntry->Entry);
|
||||
RequestLinkTarget = &HistoryEntry->Target;
|
||||
break;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
HistoryEntry = NULL;
|
||||
}
|
||||
|
||||
/* Nothing to revert to so delete the symlink */
|
||||
if (! Matched)
|
||||
RequestLinkTarget = NULL;
|
||||
}
|
||||
else if (! Matched)
|
||||
{
|
||||
/* Locate a previous symlink target as we did not get a hit earlier */
|
||||
/* If we find one we need to remove it */
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Matched =
|
||||
! RtlCompareUnicodeString(&RequestDeviceName,
|
||||
&HistoryEntry->Device,
|
||||
FALSE);
|
||||
if (! Matched)
|
||||
{
|
||||
HistoryEntry = NULL;
|
||||
Entry = Entry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
Matched = FALSE;
|
||||
if (dwFlags & DDD_EXACT_MATCH_ON_REMOVE)
|
||||
{
|
||||
if (! RtlCompareUnicodeString(RequestLinkTarget,
|
||||
&HistoryEntry->Target,
|
||||
TRUE))
|
||||
{
|
||||
Matched = TRUE;
|
||||
}
|
||||
}
|
||||
else if (RtlPrefixUnicodeString(RequestLinkTarget,
|
||||
&HistoryEntry->Target,
|
||||
TRUE))
|
||||
{
|
||||
Matched = TRUE;
|
||||
}
|
||||
|
||||
if (Matched)
|
||||
{
|
||||
RemoveEntryList(&HistoryEntry->Entry);
|
||||
break;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
HistoryEntry = NULL;
|
||||
}
|
||||
|
||||
/* Leave existing symlink as is */
|
||||
if (! Matched)
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
else
|
||||
Status = STATUS_SUCCESS;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddHistory = TRUE;
|
||||
}
|
||||
|
||||
Status = NtMakeTemporaryObject(LinkHandle);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)",
|
||||
&DeviceName, Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Status = NtClose(LinkHandle);
|
||||
LinkHandle = NULL;
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtClose(%wZ) failed (Status %lx)",
|
||||
&DeviceName, Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't create symlink if we don't have a target */
|
||||
if (! RequestLinkTarget || RequestLinkTarget->Length == 0)
|
||||
_SEH2_LEAVE;
|
||||
|
||||
if (AddHistory)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(CSRSS_DOS_DEVICE_HISTORY_ENTRY));
|
||||
if (! HistoryEntry)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
HistoryEntry->Target.Buffer =
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
LinkTarget.Length);
|
||||
if (! HistoryEntry->Target.Buffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
HistoryEntry->Target.Length =
|
||||
HistoryEntry->Target.MaximumLength =
|
||||
LinkTarget.Length;
|
||||
RtlCopyUnicodeString(&HistoryEntry->Target,
|
||||
&LinkTarget);
|
||||
|
||||
HistoryEntry->Device.Buffer =
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
RequestDeviceName.Length);
|
||||
if (! HistoryEntry->Device.Buffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
HistoryEntry->Device.Length =
|
||||
HistoryEntry->Device.MaximumLength =
|
||||
RequestDeviceName.Length;
|
||||
RtlCopyUnicodeString(&HistoryEntry->Device,
|
||||
&RequestDeviceName);
|
||||
|
||||
/* Remember previous symlink target for this device */
|
||||
InsertHeadList(ListHead,
|
||||
&HistoryEntry->Entry);
|
||||
HistoryEntry = NULL;
|
||||
}
|
||||
|
||||
RtlAllocateAndInitializeSid(&WorldAuthority,
|
||||
1,
|
||||
SECURITY_WORLD_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
&WorldSid);
|
||||
|
||||
RtlAllocateAndInitializeSid(&SystemAuthority,
|
||||
1,
|
||||
SECURITY_LOCAL_SYSTEM_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
&SystemSid);
|
||||
|
||||
RtlAllocateAndInitializeSid(&SystemAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
&AdminSid);
|
||||
|
||||
SidLength = RtlLengthSid(SystemSid) +
|
||||
RtlLengthSid(AdminSid) +
|
||||
RtlLengthSid(WorldSid);
|
||||
Length = sizeof(ACL) + SidLength + 3 * sizeof(ACCESS_ALLOWED_ACE);
|
||||
|
||||
SecurityDescriptor = RtlAllocateHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
|
||||
if (! SecurityDescriptor)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Dacl = (PACL)((ULONG_PTR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)",
|
||||
Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Status = RtlCreateAcl(Dacl,
|
||||
Length,
|
||||
ACL_REVISION);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlCreateAcl() failed (Status %lx)",
|
||||
Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
(void) RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
GENERIC_ALL,
|
||||
SystemSid);
|
||||
(void) RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
GENERIC_ALL,
|
||||
AdminSid);
|
||||
(void) RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
STANDARD_RIGHTS_READ,
|
||||
WorldSid);
|
||||
|
||||
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
|
||||
TRUE,
|
||||
Dacl,
|
||||
FALSE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)",
|
||||
Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
SecurityDescriptor);
|
||||
Status = NtCreateSymbolicLinkObject(&LinkHandle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
RequestLinkTarget);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = NtMakePermanentObject(LinkHandle);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)",
|
||||
&DeviceName, Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)",
|
||||
&DeviceName, Status);
|
||||
}
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
(void) RtlLeaveCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
if (DeviceName.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
DeviceName.Buffer);
|
||||
if (LinkTarget.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
LinkTarget.Buffer);
|
||||
if (SecurityDescriptor)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
SecurityDescriptor);
|
||||
if (LinkHandle)
|
||||
(void) NtClose(LinkHandle);
|
||||
if (SystemSid)
|
||||
(void) RtlFreeSid(SystemSid);
|
||||
if (AdminSid)
|
||||
(void) RtlFreeSid(AdminSid);
|
||||
if (WorldSid)
|
||||
(void) RtlFreeSid(WorldSid);
|
||||
RtlFreeUnicodeString(&RequestDeviceName);
|
||||
if (HistoryEntry)
|
||||
{
|
||||
if (HistoryEntry->Target.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Target.Buffer);
|
||||
if (HistoryEntry->Device.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Device.Buffer);
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry);
|
||||
}
|
||||
}
|
||||
_SEH2_END
|
||||
|
||||
DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
void CsrCleanupDefineDosDevice()
|
||||
{
|
||||
PLIST_ENTRY Entry, ListHead;
|
||||
PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
|
||||
|
||||
(void) RtlDeleteCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
|
||||
ListHead = &DosDeviceHistory;
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Entry = Entry->Flink;
|
||||
|
||||
if (HistoryEntry)
|
||||
{
|
||||
if (HistoryEntry->Target.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Target.Buffer);
|
||||
if (HistoryEntry->Device.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Device.Buffer);
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* EOF */
|
||||
|
|
|
@ -11,7 +11,18 @@
|
|||
|
||||
#include "api.h"
|
||||
|
||||
typedef struct tagCSRSS_DOS_DEVICE_HISTORY_ENTRY
|
||||
{
|
||||
UNICODE_STRING Device;
|
||||
UNICODE_STRING Target;
|
||||
LIST_ENTRY Entry;
|
||||
} CSRSS_DOS_DEVICE_HISTORY_ENTRY, *PCSRSS_DOS_DEVICE_HISTORY_ENTRY;
|
||||
|
||||
/* Api functions */
|
||||
CSR_API(CsrGetTempFile);
|
||||
CSR_API(CsrDefineDosDevice);
|
||||
|
||||
/* functions */
|
||||
void CsrCleanupDefineDosDevice();
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue