[HACKSSIGN]
authorPierre Schweitzer <pierre@reactos.org>
Sat, 22 Aug 2015 12:29:37 +0000 (12:29 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 22 Aug 2015 12:29:37 +0000 (12:29 +0000)
Stack hacks!
Let's introduce hackssign. This application (and its associated driver) are here to allow
users to assign drive letter to their VMware/VBox shared folders.
It relies on two components: a client to communicate the instructions and a driver to execute such instructions.

Do not execute this application nor its driver outside ReactOS. There are barely no security checks nor sanety checks.
You could do substantial damages.

So, let's go back to shared folders state in ReactOS nowadays...

VMware
------
Configure your shared folders
Install VMware Tools
Reboot
From here, you can access your share from cmd or explorer with UNC path (for instance: \\vmware-host\Shared Folders\ReactOS)
Go to C:\ReactOS\bin (or whatever, depending on your setup)
Execute hackssign assign z ReactOS vmware (for instance)
z is the letter you want to give, and ReactOS is the name of your share (you gave it in VMware configuration)
You're done, you can access your share with the Z drive letter

VirtualBox
----------
Configure your shared folders
Install VBox Guest Additions
Reboot
Go to C:\ReactOS\bin (or whatever, depending on your setup)
Execute rosvboxmgmt start
From here, you can access your share from cmd or explorer with UNC path (for instance: \\vboxsvr\ReactOS)
Execute hackssign assign z ReactOS virtualbox (for instance)
z is the letter you want to give, and ReactOS is the name of your share (you gave it in VMware configuration)
You're done, you can access your share with the Z drive letter

Note that you can delete an assignement by performing a hackssign delete z (or whatever drive you want to remove).
In such case, the share remains available with its UNC path.

svn path=/trunk/; revision=68794

rosapps/applications/cmdutils/CMakeLists.txt
rosapps/applications/cmdutils/hackssign/CMakeLists.txt [new file with mode: 0644]
rosapps/applications/cmdutils/hackssign/client.c [new file with mode: 0644]
rosapps/applications/cmdutils/hackssign/driver.c [new file with mode: 0644]
rosapps/applications/cmdutils/hackssign/hackssign.rc [new file with mode: 0644]
rosapps/applications/cmdutils/hackssign/ioctl.h [new file with mode: 0644]
rosapps/applications/cmdutils/rosvboxmgmt/rosvboxmgmt.c

index 148f867..16c508e 100644 (file)
@@ -1,5 +1,6 @@
 add_subdirectory(appwiz)
 add_subdirectory(cat)
 add_subdirectory(appwiz)
 add_subdirectory(cat)
+add_subdirectory(hackssign)
 add_subdirectory(ntfsinfo)
 add_subdirectory(rosvboxmgmt)
 add_subdirectory(tee)
 add_subdirectory(ntfsinfo)
 add_subdirectory(rosvboxmgmt)
 add_subdirectory(tee)
diff --git a/rosapps/applications/cmdutils/hackssign/CMakeLists.txt b/rosapps/applications/cmdutils/hackssign/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1eb93de
--- /dev/null
@@ -0,0 +1,9 @@
+add_executable(hackssign_client client.c hackssign.rc)
+set_module_type(hackssign_client win32cui UNICODE)
+add_importlibs(hackssign_client msvcrt kernel32 advapi32)
+add_cd_file(TARGET hackssign_client DESTINATION reactos/bin FOR all)
+
+add_library(hackssign_driver SHARED driver.c hackssign.rc)
+set_module_type(hackssign_driver kernelmodedriver)
+add_importlibs(hackssign_driver ntoskrnl hal)
+add_cd_file(TARGET hackssign_driver DESTINATION reactos/bin FOR all)
diff --git a/rosapps/applications/cmdutils/hackssign/client.c b/rosapps/applications/cmdutils/hackssign/client.c
new file mode 100644 (file)
index 0000000..d743f1f
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         Hackssign application & driver
+ * FILE:            cmdutils/hackssign/client.c
+ * PURPOSE:         Client: Assign drive letter to shared folders for VMware/VBox VMs
+ * PROGRAMMERS:     Pierre Schweitzer <pierre@reactos.org>
+ */
+
+#include <stdio.h>
+#include <wchar.h>
+#include <windows.h>
+
+#include "ioctl.h"
+
+/* DON'T MESS AROUND THIS! */
+typedef enum _HV_TYPES
+{
+    vmVMware,
+    vmVirtualBox,
+    vmMax,
+} HV_TYPES;
+PCWSTR hV[] = { L"vmware", L"virtualbox" };
+PCWSTR dev[] = { L"\\Device\\hgfs\\;", L"\\Device\\VBoxMiniRdr\\;" };
+PCWSTR unc[] = { L":\\vmware-host\\Shared Folders\\", L":\\vboxsvr\\" };
+
+BOOL performDevIoCtl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize)
+{
+    BOOL ret;
+    HANDLE dev;
+    DWORD lpBytesReturned;
+
+    dev = CreateFile(L"\\\\.\\hackssign",
+                     GENERIC_READ | GENERIC_WRITE,
+                     FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     NULL, OPEN_EXISTING, 0, NULL);
+    if (dev == INVALID_HANDLE_VALUE)
+    {
+        wprintf(L"Opening device failed\n");
+        return FALSE;
+    }
+
+    ret = DeviceIoControl(dev, dwIoControlCode, lpInBuffer, nInBufferSize, NULL, 0, &lpBytesReturned, NULL);
+    wprintf(L"Done: it %s with error: %lx\n", (ret != 0 ? L"succeed" : L"failed"), (ret != 0 ? ERROR_SUCCESS : GetLastError()));
+
+    CloseHandle(dev);
+
+    return ret;
+}
+
+
+BOOL startService()
+{
+    PWSTR fileName;
+    WCHAR path[MAX_PATH];
+    SC_HANDLE hManager, hService;
+
+    hManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+    if (hManager == NULL)
+    {
+        wprintf(L"Service manager opening failed\n");
+        return FALSE;
+    }
+
+    hService = OpenService(hManager, L"hackssign", SERVICE_START | SERVICE_STOP | DELETE);
+    if (hService == NULL)
+    {
+        if (GetModuleFileName(NULL, path, MAX_PATH) == 0)
+        {
+            wprintf(L"Getting own path failed\n");
+            CloseServiceHandle(hManager);
+            return FALSE;
+        }
+
+        fileName = wcsrchr(path, L'\\');
+        if (fileName == NULL)
+        {
+            wprintf(L"Invalid path: %s\n", path);
+            CloseServiceHandle(hManager);
+            return FALSE;
+        }
+
+        ++fileName;
+        *fileName = UNICODE_NULL;
+        wcscat(path, L"hackssign_driver.sys");
+
+        if (GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES)
+        {
+            wprintf(L"Driver not found: %s\n", path);
+            CloseServiceHandle(hManager);
+            return FALSE;
+        }
+
+        hService = CreateService(hManager, L"hackssign", L"hackssign",
+                                 SERVICE_START | SERVICE_STOP | DELETE, SERVICE_KERNEL_DRIVER,
+                                 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path, NULL, NULL,
+                                 NULL, NULL, NULL);
+        if (hService == NULL)
+        {
+            wprintf(L"Creating service failed\n");
+            CloseServiceHandle(hManager);
+            return FALSE;
+        }
+    }
+
+    if (!StartService(hService, 0, NULL) &&
+        GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
+    {
+        wprintf(L"Starting service failed\n");
+        CloseServiceHandle(hService);
+        CloseServiceHandle(hManager);
+        return FALSE;
+    }
+
+    wprintf(L"Starting service succeed\n");
+    CloseServiceHandle(hService);
+    CloseServiceHandle(hManager);
+    return TRUE;
+}
+
+int assignLetter(WCHAR letter, PCWSTR path, PCWSTR device)
+{
+    BOOL ret;
+    DWORD len;
+    PWSTR str;
+    HV_TYPES vm;
+    WCHAR capsLetter;
+    DWORD inputBufferSize;
+    PASSIGN_INPUT inputBuffer;
+
+    for (vm = vmVMware; vm < vmMax; ++vm)
+    {
+        if (_wcsicmp(device, hV[vm]) == 0)
+        {
+            break;
+        }
+    }
+    if (vm == vmMax)
+    {
+        wprintf(L"Unsupported VM type\n");
+        return 1;
+    }
+
+    if (iswalpha(letter) == 0)
+    {
+        wprintf(L"Invalid letter provided\n");
+        return 1;
+    }
+
+    capsLetter = towupper(letter);
+    if (capsLetter == L'C')
+    {
+        wprintf(L"Looks suspicious, won't proceed\n");
+        return 1;
+    }
+
+    len = wcslen(path);
+    if (len == 0)
+    {
+        wprintf(L"Invalid share name\n");
+        return 1;
+    }
+
+    if (wcschr(path, L'\\') != NULL)
+    {
+        wprintf(L"Only give the name of a share\n");
+        return 1;
+    }
+
+    inputBufferSize = len * sizeof(WCHAR) + sizeof(ASSIGN_INPUT) + (wcslen(dev[vm]) + wcslen(unc[vm]) + 2) * sizeof(WCHAR);
+    inputBuffer = malloc(inputBufferSize);
+    if (inputBuffer == NULL)
+    {
+        wprintf(L"Memory failure\n");
+        return 1;
+    }
+
+    inputBuffer->letter = capsLetter;
+    inputBuffer->offset = sizeof(ASSIGN_INPUT);
+    inputBuffer->len = len * sizeof(WCHAR) + (wcslen(dev[vm]) + wcslen(unc[vm]) + 1) * sizeof(WCHAR);
+    str = (PWSTR)((ULONG_PTR)inputBuffer + inputBuffer->offset);
+    swprintf(str, L"%s%c%s%s", dev[vm], capsLetter, unc[vm], path);
+
+    if (!startService())
+    {
+        free(inputBuffer);
+        return 1;
+    }
+
+    Sleep(500);
+
+    ret = performDevIoCtl(FSCTL_HACKSSIGN_ASSIGN, inputBuffer, inputBufferSize);
+    free(inputBuffer);
+
+    return (ret == FALSE);
+}
+
+int deleteLetter(WCHAR letter)
+{
+    WCHAR capsLetter;
+
+    if (iswalpha(letter) == 0)
+    {
+        wprintf(L"Invalid letter provided\n");
+        return 1;
+    }
+
+    capsLetter = towupper(letter);
+    if (capsLetter == L'C')
+    {
+        wprintf(L"Looks suspicious, won't proceed\n");
+        return 1;
+    }
+
+    if (!startService())
+    {
+        return 1;
+    }
+
+    Sleep(500);
+
+    return (performDevIoCtl(FSCTL_HACKSSIGN_DELETE, &capsLetter, sizeof(WCHAR)) == FALSE);
+}
+
+void printUsage(void)
+{
+    wprintf(L"ReactOS Hackssign application\n");
+    wprintf(L"\assign <letter> <share name> <vmtype>: Assign a drive letter to the share given the VM type\n");
+    wprintf(L"\t\tVM types are: vmware or virtual\n");
+    wprintf(L"\tdelete <letter>: delete driver letter assignation\n");
+}
+
+int wmain(int argc, wchar_t *argv[])
+{
+    PCWSTR cmd;
+
+    if (argc < 3)
+    {
+        printUsage();
+        return 0;
+    }
+
+    cmd = argv[1];
+
+    if (_wcsicmp(cmd, L"assign") == 0)
+    {
+        if (argc < 5)
+        {
+            printUsage();
+            return 0;
+        }
+
+        return assignLetter(argv[2][0], argv[3], argv[4]);
+    }
+    else if (_wcsicmp(cmd, L"delete") == 0)
+    {
+        return deleteLetter(argv[2][0]);
+    }
+    else
+    {
+        printUsage();
+        return 0;
+    }
+}
diff --git a/rosapps/applications/cmdutils/hackssign/driver.c b/rosapps/applications/cmdutils/hackssign/driver.c
new file mode 100644 (file)
index 0000000..47785a7
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         Hackssign application & driver
+ * FILE:            cmdutils/hackssign/driver.c
+ * PURPOSE:         Driver: Assign drive letter to shared folders for VMware/VBox VMs
+ * PROGRAMMERS:     Pierre Schweitzer <pierre@reactos.org>
+ */
+
+#include <wdm.h>
+#include <ntifs.h>
+#include <wchar.h>
+#define NDEBUG
+#include <debug.h>
+
+#include "ioctl.h"
+
+typedef struct _HS_VCB
+{
+    SHARE_ACCESS shareAccess;
+} HS_VCB, *PHS_VCB;
+
+ERESOURCE globalLock;
+PDEVICE_OBJECT gDevObj;
+
+NTSTATUS
+NTAPI
+hsDispatch(PDEVICE_OBJECT DeviceObject,
+           PIRP Irp)
+{
+    PHS_VCB vcb;
+    NTSTATUS status;
+    WCHAR dosBuffer[7];
+    PFILE_OBJECT fileObject;
+    PIO_STACK_LOCATION stack;
+    PASSIGN_INPUT inputBuffer;
+    UNICODE_STRING target, source;
+
+    FsRtlEnterFileSystem();
+    ExAcquireResourceExclusiveLite(&globalLock, TRUE);
+
+    stack = IoGetCurrentIrpStackLocation(Irp);
+    fileObject = stack->FileObject;
+    switch (stack->MajorFunction)
+    {
+        case IRP_MJ_CREATE:
+            if (fileObject->FileName.Length != 0)
+            {
+                status = STATUS_INVALID_DEVICE_REQUEST;
+                break;
+            }
+
+            status = IoCheckShareAccess(stack->Parameters.Create.SecurityContext->DesiredAccess,
+                                        stack->Parameters.Create.ShareAccess,
+                                        fileObject, &((PHS_VCB)DeviceObject->DeviceExtension)->shareAccess, TRUE);
+            if (NT_SUCCESS(status))
+            {
+                DPRINT1("Device opened\n");
+
+                Irp->IoStatus.Information = FILE_OPENED;
+                fileObject->FsContext = DeviceObject->DeviceExtension;
+                status = STATUS_SUCCESS;
+            }
+            break;
+
+        case IRP_MJ_FILE_SYSTEM_CONTROL:
+            if (stack->Parameters.FileSystemControl.FsControlCode == FSCTL_HACKSSIGN_ASSIGN)
+            {
+                if (stack->Parameters.FileSystemControl.InputBufferLength <= sizeof(ASSIGN_INPUT) ||
+                    Irp->AssociatedIrp.SystemBuffer == NULL)
+                {
+                    status = STATUS_INVALID_DEVICE_REQUEST;
+                    break;
+                }
+
+                inputBuffer = Irp->AssociatedIrp.SystemBuffer;
+
+                swprintf(dosBuffer, L"\\??\\%c:", inputBuffer->letter);
+                RtlInitUnicodeString(&source, dosBuffer);
+                target.Buffer = (PWSTR)((ULONG_PTR)inputBuffer + inputBuffer->offset);
+                target.Length = inputBuffer->len;
+                target.MaximumLength = target.Length;
+
+                DPRINT1("Will link %wZ to %wZ\n", &source, &target);
+
+                status = IoCreateSymbolicLink(&source, &target);
+                break;
+            }
+            else if (stack->Parameters.FileSystemControl.FsControlCode == FSCTL_HACKSSIGN_DELETE)
+            {
+                if (stack->Parameters.FileSystemControl.InputBufferLength < sizeof(WCHAR) ||
+                    Irp->AssociatedIrp.SystemBuffer == NULL)
+                {
+                    status = STATUS_INVALID_DEVICE_REQUEST;
+                    break;
+                }
+
+                inputBuffer = Irp->AssociatedIrp.SystemBuffer;
+
+                swprintf(dosBuffer, L"\\??\\%c:", inputBuffer->letter);
+                RtlInitUnicodeString(&source, dosBuffer);
+
+                DPRINT1("Will unlink %wZ\n", &source);
+
+                status = IoDeleteSymbolicLink(&source);
+                break;
+            }
+
+            status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+
+        case IRP_MJ_CLEANUP:
+            vcb = fileObject->FsContext;
+            if (vcb == NULL)
+            {
+                status = STATUS_INVALID_HANDLE;
+                break;
+            }
+
+            DPRINT1("Device cleaned up\n");
+            IoRemoveShareAccess(fileObject, &vcb->shareAccess);
+            status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MJ_CLOSE:
+            vcb = fileObject->FsContext;
+            if (vcb == NULL)
+            {
+                status = STATUS_INVALID_HANDLE;
+                break;
+            }
+
+            DPRINT1("Device closed\n");
+            fileObject->FsContext = NULL;
+            status = STATUS_SUCCESS;
+            break;
+
+        default:
+            status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+    }
+
+    ExReleaseResourceLite(&globalLock);
+    FsRtlExitFileSystem();
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+VOID
+NTAPI
+hsUnload(PDRIVER_OBJECT DriverObject)
+{
+    IoDeleteDevice(gDevObj);
+    ExDeleteResourceLite(&globalLock);
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(PDRIVER_OBJECT DriverObject,
+            PUNICODE_STRING RegistryPath)
+{
+    NTSTATUS status;
+    PDEVICE_OBJECT devObj;
+    UNICODE_STRING devName, uDevName;
+
+    DPRINT1("Starting hackssign driver\n");
+
+    RtlInitUnicodeString(&devName, L"\\Device\\hackssign");
+    status = IoCreateDevice(DriverObject, sizeof(HS_VCB), &devName, FILE_DEVICE_FILE_SYSTEM, 0, FALSE, &devObj);
+    if (!NT_SUCCESS(status))
+    {
+        DPRINT1("IoCreateDevice failed\n");
+        return status;
+    }
+
+    RtlInitUnicodeString(&uDevName,  L"\\??\\hackssign");
+    status = IoCreateSymbolicLink(&uDevName, &devName);
+    if (!NT_SUCCESS(status))
+    {
+        DPRINT1("IoCreateSymbolicLink failed\n");
+        IoDeleteDevice(devObj);
+        return status;
+    }
+
+    gDevObj = devObj;
+    ExInitializeResourceLite(&globalLock);
+    RtlZeroMemory(devObj->DeviceExtension, sizeof(HS_VCB));
+
+    DriverObject->DriverUnload = hsUnload;
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = hsDispatch;
+    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = hsDispatch;
+    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = hsDispatch;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = hsDispatch;
+
+    return STATUS_SUCCESS;
+}
diff --git a/rosapps/applications/cmdutils/hackssign/hackssign.rc b/rosapps/applications/cmdutils/hackssign/hackssign.rc
new file mode 100644 (file)
index 0000000..1b791f9
--- /dev/null
@@ -0,0 +1,5 @@
+
+#define REACTOS_STR_FILE_DESCRIPTION   "Hack assign letters\0"
+#define REACTOS_STR_INTERNAL_NAME      "hackssign\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "hackssign.exe\0"
+#include <reactos/version.rc>
diff --git a/rosapps/applications/cmdutils/hackssign/ioctl.h b/rosapps/applications/cmdutils/hackssign/ioctl.h
new file mode 100644 (file)
index 0000000..3d29399
--- /dev/null
@@ -0,0 +1,9 @@
+typedef struct _ASSIGN_INPUT
+{
+    WCHAR letter;
+    USHORT offset;
+    USHORT len;
+} ASSIGN_INPUT, *PASSIGN_INPUT;
+
+#define FSCTL_HACKSSIGN_ASSIGN CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x42, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define FSCTL_HACKSSIGN_DELETE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42,   METHOD_BUFFERED, FILE_ANY_ACCESS)
index 20704d6..ef3982a 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS VBox Shared Folders Management
+ * FILE:            cmdutils/hackssign/client.c
+ * PURPOSE:         Communicate with VBox mini redirector to deal with shared folders
+ * PROGRAMMERS:     Pierre Schweitzer <pierre@reactos.org>
+ */
+
 #include <stdio.h>
 #include <wchar.h>
 #include <windows.h>
 #include <stdio.h>
 #include <wchar.h>
 #include <windows.h>