[HACKSSIGN]
[reactos.git] / rosapps / applications / cmdutils / hackssign / client.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Hackssign application & driver
4 * FILE: cmdutils/hackssign/client.c
5 * PURPOSE: Client: Assign drive letter to shared folders for VMware/VBox VMs
6 * PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
7 */
8
9 #include <stdio.h>
10 #include <wchar.h>
11 #include <windows.h>
12
13 #include "ioctl.h"
14
15 /* DON'T MESS AROUND THIS! */
16 typedef enum _HV_TYPES
17 {
18 vmVMware,
19 vmVirtualBox,
20 vmMax,
21 } HV_TYPES;
22 PCWSTR hV[] = { L"vmware", L"virtualbox" };
23 PCWSTR dev[] = { L"\\Device\\hgfs\\;", L"\\Device\\VBoxMiniRdr\\;" };
24 PCWSTR unc[] = { L":\\vmware-host\\Shared Folders\\", L":\\vboxsvr\\" };
25
26 BOOL performDevIoCtl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize)
27 {
28 BOOL ret;
29 HANDLE dev;
30 DWORD lpBytesReturned;
31
32 dev = CreateFile(L"\\\\.\\hackssign",
33 GENERIC_READ | GENERIC_WRITE,
34 FILE_SHARE_READ | FILE_SHARE_WRITE,
35 NULL, OPEN_EXISTING, 0, NULL);
36 if (dev == INVALID_HANDLE_VALUE)
37 {
38 wprintf(L"Opening device failed\n");
39 return FALSE;
40 }
41
42 ret = DeviceIoControl(dev, dwIoControlCode, lpInBuffer, nInBufferSize, NULL, 0, &lpBytesReturned, NULL);
43 wprintf(L"Done: it %s with error: %lx\n", (ret != 0 ? L"succeed" : L"failed"), (ret != 0 ? ERROR_SUCCESS : GetLastError()));
44
45 CloseHandle(dev);
46
47 return ret;
48 }
49
50
51 BOOL startService()
52 {
53 PWSTR fileName;
54 WCHAR path[MAX_PATH];
55 SC_HANDLE hManager, hService;
56
57 hManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
58 if (hManager == NULL)
59 {
60 wprintf(L"Service manager opening failed\n");
61 return FALSE;
62 }
63
64 hService = OpenService(hManager, L"hackssign", SERVICE_START | SERVICE_STOP | DELETE);
65 if (hService == NULL)
66 {
67 if (GetModuleFileName(NULL, path, MAX_PATH) == 0)
68 {
69 wprintf(L"Getting own path failed\n");
70 CloseServiceHandle(hManager);
71 return FALSE;
72 }
73
74 fileName = wcsrchr(path, L'\\');
75 if (fileName == NULL)
76 {
77 wprintf(L"Invalid path: %s\n", path);
78 CloseServiceHandle(hManager);
79 return FALSE;
80 }
81
82 ++fileName;
83 *fileName = UNICODE_NULL;
84 wcscat(path, L"hackssign_driver.sys");
85
86 if (GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES)
87 {
88 wprintf(L"Driver not found: %s\n", path);
89 CloseServiceHandle(hManager);
90 return FALSE;
91 }
92
93 hService = CreateService(hManager, L"hackssign", L"hackssign",
94 SERVICE_START | SERVICE_STOP | DELETE, SERVICE_KERNEL_DRIVER,
95 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path, NULL, NULL,
96 NULL, NULL, NULL);
97 if (hService == NULL)
98 {
99 wprintf(L"Creating service failed\n");
100 CloseServiceHandle(hManager);
101 return FALSE;
102 }
103 }
104
105 if (!StartService(hService, 0, NULL) &&
106 GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
107 {
108 wprintf(L"Starting service failed\n");
109 CloseServiceHandle(hService);
110 CloseServiceHandle(hManager);
111 return FALSE;
112 }
113
114 wprintf(L"Starting service succeed\n");
115 CloseServiceHandle(hService);
116 CloseServiceHandle(hManager);
117 return TRUE;
118 }
119
120 int assignLetter(WCHAR letter, PCWSTR path, PCWSTR device)
121 {
122 BOOL ret;
123 DWORD len;
124 PWSTR str;
125 HV_TYPES vm;
126 WCHAR capsLetter;
127 DWORD inputBufferSize;
128 PASSIGN_INPUT inputBuffer;
129
130 for (vm = vmVMware; vm < vmMax; ++vm)
131 {
132 if (_wcsicmp(device, hV[vm]) == 0)
133 {
134 break;
135 }
136 }
137 if (vm == vmMax)
138 {
139 wprintf(L"Unsupported VM type\n");
140 return 1;
141 }
142
143 if (iswalpha(letter) == 0)
144 {
145 wprintf(L"Invalid letter provided\n");
146 return 1;
147 }
148
149 capsLetter = towupper(letter);
150 if (capsLetter == L'C')
151 {
152 wprintf(L"Looks suspicious, won't proceed\n");
153 return 1;
154 }
155
156 len = wcslen(path);
157 if (len == 0)
158 {
159 wprintf(L"Invalid share name\n");
160 return 1;
161 }
162
163 if (wcschr(path, L'\\') != NULL)
164 {
165 wprintf(L"Only give the name of a share\n");
166 return 1;
167 }
168
169 inputBufferSize = len * sizeof(WCHAR) + sizeof(ASSIGN_INPUT) + (wcslen(dev[vm]) + wcslen(unc[vm]) + 2) * sizeof(WCHAR);
170 inputBuffer = malloc(inputBufferSize);
171 if (inputBuffer == NULL)
172 {
173 wprintf(L"Memory failure\n");
174 return 1;
175 }
176
177 inputBuffer->letter = capsLetter;
178 inputBuffer->offset = sizeof(ASSIGN_INPUT);
179 inputBuffer->len = len * sizeof(WCHAR) + (wcslen(dev[vm]) + wcslen(unc[vm]) + 1) * sizeof(WCHAR);
180 str = (PWSTR)((ULONG_PTR)inputBuffer + inputBuffer->offset);
181 swprintf(str, L"%s%c%s%s", dev[vm], capsLetter, unc[vm], path);
182
183 if (!startService())
184 {
185 free(inputBuffer);
186 return 1;
187 }
188
189 Sleep(500);
190
191 ret = performDevIoCtl(FSCTL_HACKSSIGN_ASSIGN, inputBuffer, inputBufferSize);
192 free(inputBuffer);
193
194 return (ret == FALSE);
195 }
196
197 int deleteLetter(WCHAR letter)
198 {
199 WCHAR capsLetter;
200
201 if (iswalpha(letter) == 0)
202 {
203 wprintf(L"Invalid letter provided\n");
204 return 1;
205 }
206
207 capsLetter = towupper(letter);
208 if (capsLetter == L'C')
209 {
210 wprintf(L"Looks suspicious, won't proceed\n");
211 return 1;
212 }
213
214 if (!startService())
215 {
216 return 1;
217 }
218
219 Sleep(500);
220
221 return (performDevIoCtl(FSCTL_HACKSSIGN_DELETE, &capsLetter, sizeof(WCHAR)) == FALSE);
222 }
223
224 void printUsage(void)
225 {
226 wprintf(L"ReactOS Hackssign application\n");
227 wprintf(L"\assign <letter> <share name> <vmtype>: Assign a drive letter to the share given the VM type\n");
228 wprintf(L"\t\tVM types are: vmware or virtual\n");
229 wprintf(L"\tdelete <letter>: delete driver letter assignation\n");
230 }
231
232 int wmain(int argc, wchar_t *argv[])
233 {
234 PCWSTR cmd;
235
236 if (argc < 3)
237 {
238 printUsage();
239 return 0;
240 }
241
242 cmd = argv[1];
243
244 if (_wcsicmp(cmd, L"assign") == 0)
245 {
246 if (argc < 5)
247 {
248 printUsage();
249 return 0;
250 }
251
252 return assignLetter(argv[2][0], argv[3], argv[4]);
253 }
254 else if (_wcsicmp(cmd, L"delete") == 0)
255 {
256 return deleteLetter(argv[2][0]);
257 }
258 else
259 {
260 printUsage();
261 return 0;
262 }
263 }