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?…
==============================================================================
--- 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.rb…
==============================================================================
--- 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?…
==============================================================================
--- 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/rea…
==============================================================================
--- 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/do…
==============================================================================
--- 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/csr…
==============================================================================
--- 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/win…
==============================================================================
--- 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/win…
==============================================================================
--- 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/win…
==============================================================================
--- 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 */