reactos/rosapps/applications/cmdutils/rosvboxmgmt/rosvboxmgmt.c
Pierre Schweitzer cae19acb7a [ROSVBOXMGMT]
Let's add hacks to glue hacks together:
In case rosvboxmgmt is started with its current directory not being the directory where it is along with hackssign_client.exe, then autoassign fails finding the hackssign client executable and thus, fails assigning drive letter.
This is what happens when you starts rosvboxmgmt on boot with shell.
So, when using autoassign, first look for the location of rosvboxmgmt and set our current directory there.

This fixes rosvboxmgmt autoassign not working on boot.

CORE-10032
ROSAPPS-303

svn path=/trunk/; revision=70578
2016-01-11 22:41:32 +00:00

407 lines
10 KiB
C

/*
* 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 <shlobj.h>
#include <shobjidl.h>
#include <shlwapi.h>
/* DON'T CHANGE ORDER!!!! */
PCWSTR devices[3] = { L"\\\\.\\VBoxMiniRdrDN", L"\\??\\VBoxMiniRdrDN", L"\\Device\\VBoxMiniRdr" };
#define MAX_LEN 255
/* Taken from VBox header */
#define _MRX_MAX_DRIVE_LETTERS 26
#define IOCTL_MRX_VBOX_BASE FILE_DEVICE_NETWORK_FILE_SYSTEM
#define _MRX_VBOX_CONTROL_CODE(request, method, access) \
CTL_CODE(IOCTL_MRX_VBOX_BASE, request, method, access)
#define IOCTL_MRX_VBOX_ADDCONN _MRX_VBOX_CONTROL_CODE(100, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MRX_VBOX_GETLIST _MRX_VBOX_CONTROL_CODE(103, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MRX_VBOX_GETGLOBALLIST _MRX_VBOX_CONTROL_CODE(104, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MRX_VBOX_GETGLOBALCONN _MRX_VBOX_CONTROL_CODE(105, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MRX_VBOX_START _MRX_VBOX_CONTROL_CODE(106, METHOD_BUFFERED, FILE_ANY_ACCESS)
BOOL performDevIoCtl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize)
{
short i;
BOOL ret;
DWORD lpBytesReturned;
HANDLE dev = INVALID_HANDLE_VALUE;
wprintf(L"Trying to open a VBoxSRV device\n");
for (i = 0; i < 3; ++i)
{
dev = CreateFile(devices[i],
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (dev != INVALID_HANDLE_VALUE)
{
break;
}
}
if (dev == INVALID_HANDLE_VALUE)
{
return FALSE;
}
wprintf(L"%s opened.\n", devices[i]);
ret = DeviceIoControl(dev, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, &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;
}
int startVBoxSrv(void)
{
return (performDevIoCtl(IOCTL_MRX_VBOX_START, NULL, 0, NULL, 0) == FALSE);
}
int addConn(PCWSTR letter, PCWSTR path)
{
BOOL ret;
PWSTR inputBuffer;
DWORD inputBufferSize;
if (iswalpha(letter[0]) == 0)
{
wprintf(L"Invalid letter provided\n");
return 1;
}
if (wcschr(path, L'\\') != NULL)
{
wprintf(L"Only give the name of a share\n");
return 1;
}
inputBufferSize = (wcslen(path) + wcslen(devices[2]) + wcslen(L"\\;Z:\\vboxsvr\\")) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
inputBuffer = malloc(inputBufferSize);
if (inputBuffer == NULL)
{
wprintf(L"Memory failure\n");
return 1;
}
swprintf(inputBuffer, L"%s\\;%c:\\vboxsvr\\%s", devices[2], towupper(letter[0]), path);
wprintf(L"Will create the following connection: %s\n", inputBuffer);
ret = performDevIoCtl(IOCTL_MRX_VBOX_ADDCONN, inputBuffer, inputBufferSize, NULL, 0);
free(inputBuffer);
return (ret == FALSE);
}
int getList(void)
{
short i;
BOOL ret;
DWORD outputBufferSize;
char outputBuffer[_MRX_MAX_DRIVE_LETTERS];
outputBufferSize = sizeof(outputBuffer);
ret = performDevIoCtl(IOCTL_MRX_VBOX_GETLIST, NULL, 0, &outputBuffer, outputBufferSize);
if (ret == FALSE)
{
return 1;
}
for (i = 0; i < _MRX_MAX_DRIVE_LETTERS; i += 2)
{
wprintf(L"%c: %s\t%c: %s\n", 'A' + i, (outputBuffer[i] == 0 ? L"FALSE" : L"TRUE"),
'A' + (i + 1), (outputBuffer[i + 1] == 0 ? L"FALSE" : L"TRUE"));
}
return 0;
}
PCWSTR getGlobalConn(CHAR id)
{
BOOL ret;
static WCHAR name[MAX_LEN];
ret = performDevIoCtl(IOCTL_MRX_VBOX_GETGLOBALCONN, &id, sizeof(id), name, sizeof(name));
if (ret == FALSE)
{
return NULL;
}
name[MAX_LEN - 1] = 0;
return name;
}
int getGlobalList(void)
{
short i;
BOOL ret;
DWORD outputBufferSize;
char outputBuffer[_MRX_MAX_DRIVE_LETTERS];
outputBufferSize = sizeof(outputBuffer);
memset(outputBuffer, 0, outputBufferSize);
ret = performDevIoCtl(IOCTL_MRX_VBOX_GETGLOBALLIST, NULL, 0, &outputBuffer, outputBufferSize);
if (ret == FALSE)
{
return 1;
}
for (i = 0; i < _MRX_MAX_DRIVE_LETTERS; ++i)
{
CHAR id = outputBuffer[i];
BOOL active = ((id & 0x80) == 0x80);
PCWSTR name = NULL;
if (active)
{
name = getGlobalConn(id);
}
if (name == NULL)
{
name = L"None";
}
wprintf(L"%c: %s (%s)%c", 'A' + i, (active ? L"Active" : L"Inactive"), name, (i & 1 ? '\n' : '\t'));
}
return 0;
}
BOOL createUNCShortcut(PCWSTR share)
{
HRESULT res;
IShellLink *link;
IPersistFile *persist;
WCHAR path[MAX_PATH];
WCHAR linkPath[MAX_PATH];
res = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void**)&link);
if (FAILED(res))
{
return FALSE;
}
res = link->lpVtbl->QueryInterface(link, &IID_IPersistFile, (void **)&persist);
if (FAILED(res))
{
link->lpVtbl->Release(link);
return FALSE;
}
wcscpy(path, L"\\\\vboxsvr\\");
wcscat(path, share);
link->lpVtbl->SetPath(link, path);
res = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, path);
if (FAILED(res))
{
persist->lpVtbl->Release(persist);
link->lpVtbl->Release(link);
return FALSE;
}
wsprintf(linkPath, L"%s\\Browse %s (VBox).lnk", path, share);
res = persist->lpVtbl->Save(persist, linkPath, TRUE);
persist->lpVtbl->Release(persist);
link->lpVtbl->Release(link);
return SUCCEEDED(res);
}
BOOL assignDriveLetter(PCWSTR share)
{
DWORD driveMap;
char drive;
wchar_t cmdLine[MAX_PATH];
STARTUPINFOW startupInfo;
PROCESS_INFORMATION processInformation;
BOOL ok = FALSE;
driveMap = GetLogicalDrives();
for (drive = _MRX_MAX_DRIVE_LETTERS - 1; drive >= 0; ++drive)
{
if (!(driveMap & (1 << drive)))
{
break;
}
}
if (drive < 0)
{
wprintf(L"Failed finding an appropriate drive for shared folder\n");
return 1;
}
drive += 'A';
wsprintf(cmdLine, L"hackssign_client.exe assign %c %s", drive, share);
RtlZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(STARTUPINFOW);
if (!CreateProcessW(NULL,
(PVOID)cmdLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&startupInfo,
&processInformation))
{
wprintf(L"Failed starting hackssign_client.exe\n");
return 1;
}
ok = (WaitForSingleObject(processInformation.hProcess, -1) == WAIT_OBJECT_0);
CloseHandle(processInformation.hProcess);
CloseHandle(processInformation.hThread);
wprintf(L"%c assigned to %s\n", drive, share);
return ok;
}
int autoStart(BOOL assign)
{
short i;
BOOL ret;
DWORD outputBufferSize;
char outputBuffer[_MRX_MAX_DRIVE_LETTERS];
OFSTRUCT ofs;
if (startVBoxSrv() != 0)
{
return 1;
}
outputBufferSize = sizeof(outputBuffer);
memset(outputBuffer, 0, outputBufferSize);
ret = performDevIoCtl(IOCTL_MRX_VBOX_GETGLOBALLIST, NULL, 0, &outputBuffer, outputBufferSize);
if (ret == FALSE)
{
return 1;
}
if (assign)
{
wchar_t path[MAX_PATH];
if (GetModuleFileName(NULL, path, ARRAYSIZE(path)) != 0)
{
*(wcsrchr(path, '\\')) = 0;
wprintf(L"Switching to %s\n", path);
SetCurrentDirectory(path);
}
if (OpenFile("hackssign_client.exe", &ofs, OF_EXIST) != 1)
{
wprintf(L"hackssign_client.exe not found, falling back to links\n");
assign = FALSE;
}
}
if (!assign)
{
CoInitialize(NULL);
}
for (i = 0; i < _MRX_MAX_DRIVE_LETTERS; ++i)
{
CHAR id = outputBuffer[i];
BOOL active = ((id & 0x80) == 0x80);
PCWSTR name = NULL;
if (active)
{
name = getGlobalConn(id);
}
if (name == NULL)
{
continue;
}
if (!assign)
{
createUNCShortcut(name);
}
else
{
assignDriveLetter(name);
}
}
return 0;
}
void printUsage(void)
{
wprintf(L"ReactOS VBox Shared Folders Management\n");
wprintf(L"\tstart: start the VBox Shared folders (mandatory prior any operation!)\n");
wprintf(L"\taddconn <letter> <share name>: add a connection\n");
wprintf(L"\tgetlist: list connections\n");
wprintf(L"\tgetgloballist: list available shares\n");
wprintf(L"\tautolink: automagically configure the VBox Shared folders and creates desktop folders\n");
wprintf(L"\tautoassign: automagically configure the VBox Shared folders and assigns drive letters\n");
}
int wmain(int argc, wchar_t *argv[])
{
PCWSTR cmd;
if (argc == 1)
{
printUsage();
return 0;
}
cmd = argv[1];
if (_wcsicmp(cmd, L"start") == 0)
{
return startVBoxSrv();
}
else if (_wcsicmp(cmd, L"addconn") == 0)
{
if (argc < 4)
{
printUsage();
return 0;
}
return addConn(argv[2], argv[3]);
}
else if (_wcsicmp(cmd, L"getlist") == 0)
{
return getList();
}
else if (_wcsicmp(cmd, L"getgloballist") == 0)
{
return getGlobalList();
}
else if (_wcsicmp(cmd, L"autolink") == 0)
{
return autoStart(FALSE);
}
else if (_wcsicmp(cmd, L"autoassign") == 0)
{
return autoStart(TRUE);
}
else
{
printUsage();
return 0;
}
}