Author: fireball Date: Mon Apr 18 21:48:19 2011 New Revision: 51393
URL: http://svn.reactos.org/svn/reactos?rev=51393&view=rev Log: 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.
Added: trunk/reactos/base/system/subst/ trunk/reactos/base/system/subst/subst.c (with props) trunk/reactos/base/system/subst/subst.rbuild (with props) trunk/reactos/base/system/subst/subst.rc (with props) Modified: trunk/reactos/base/system/system.rbuild trunk/reactos/boot/bootdata/packages/reactos.dff trunk/reactos/dll/win32/kernel32/file/dosdev.c trunk/reactos/include/reactos/subsys/csrss/csrss.h trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c trunk/reactos/subsystems/win32/csrss/win32csr/file.c trunk/reactos/subsystems/win32/csrss/win32csr/file.h
Added: trunk/reactos/base/system/subst/subst.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/subst/subst.c?r... ============================================================================== --- trunk/reactos/base/system/subst/subst.c (added) +++ trunk/reactos/base/system/subst/subst.c [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -1,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 */
Propchange: trunk/reactos/base/system/subst/subst.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/base/system/subst/subst.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/subst/subst.rbu... ============================================================================== --- trunk/reactos/base/system/subst/subst.rbuild (added) +++ trunk/reactos/base/system/subst/subst.rbuild [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -1,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>
Propchange: trunk/reactos/base/system/subst/subst.rbuild ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/base/system/subst/subst.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/subst/subst.rc?... ============================================================================== --- trunk/reactos/base/system/subst/subst.rc (added) +++ trunk/reactos/base/system/subst/subst.rc [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -1,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>
Propchange: trunk/reactos/base/system/subst/subst.rc ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/base/system/system.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/system.rbuild?r... ============================================================================== --- trunk/reactos/base/system/system.rbuild [iso-8859-1] (original) +++ trunk/reactos/base/system/system.rbuild [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -9,6 +9,9 @@ </directory> <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" />
Modified: trunk/reactos/boot/bootdata/packages/reactos.dff URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/packages/reac... ============================================================================== --- trunk/reactos/boot/bootdata/packages/reactos.dff [iso-8859-1] (original) +++ trunk/reactos/boot/bootdata/packages/reactos.dff [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -115,6 +115,7 @@ 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
Modified: trunk/reactos/dll/win32/kernel32/file/dosdev.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/file/dos... ============================================================================== --- trunk/reactos/dll/win32/kernel32/file/dosdev.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/file/dosdev.c [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -14,6 +14,7 @@ #include <k32.h> #define NDEBUG #include <debug.h> +#include <Dbt.h> DEBUG_CHANNEL(kernel32file);
/* FUNCTIONS *****************************************************************/ @@ -29,44 +30,55 @@ 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; + UNICODE_STRING DeviceNameU = {0}; + UNICODE_STRING TargetPathU = {0}; + BOOL Result; + + if (lpDeviceName && + ! RtlCreateUnicodeStringFromAsciiz(&DeviceNameU, + (LPSTR)lpDeviceName)) + { + 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); + + if (TargetPathU.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap (), + 0, + TargetPathU.Buffer); + } + + if (DeviceNameU.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap (), + 0, + DeviceNameU.Buffer); + } + return Result; }
/* - * @unimplemented + * @implemented */ BOOL WINAPI @@ -76,8 +88,154 @@ 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 @@ 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 */
Modified: trunk/reactos/include/reactos/subsys/csrss/csrss.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/csrs... ============================================================================== --- trunk/reactos/include/reactos/subsys/csrss/csrss.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/subsys/csrss/csrss.h [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -517,6 +517,13 @@ { 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)) @@ -598,6 +605,7 @@ #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 @@ 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;
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win3... ============================================================================== --- trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -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 @@ 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 @@ InitializeAppSwitchHook(); }
+ if (DLL_PROCESS_DETACH == dwReason) + { + CsrCleanupDefineDosDevice(); + } return TRUE; }
@@ -174,6 +182,8 @@ ServerProcs->ProcessInheritProc = Win32CsrDuplicateHandleTable; ServerProcs->ProcessDeletedProc = Win32CsrReleaseConsole;
+ Status = RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec); + InitializeListHead(&DosDeviceHistory); return TRUE; }
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win3... ============================================================================== --- trunk/reactos/subsystems/win32/csrss/win32csr/file.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/csrss/win32csr/file.c [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -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 @@
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 */
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/file.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win3... ============================================================================== --- trunk/reactos/subsystems/win32/csrss/win32csr/file.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/csrss/win32csr/file.h [iso-8859-1] Mon Apr 18 21:48:19 2011 @@ -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 */