[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 typedef BOOL (*HV_DET)(void);
23 BOOL isVMware(void)
24 {
25 HANDLE dev = CreateFile(L"\\\\.\\hgfs",
26 GENERIC_READ | GENERIC_WRITE,
27 FILE_SHARE_READ | FILE_SHARE_WRITE,
28 NULL, OPEN_EXISTING, 0, NULL);
29 if (dev != INVALID_HANDLE_VALUE)
30 {
31 wprintf(L"VMware detected\n");
32 CloseHandle(dev);
33 return TRUE;
34 }
35
36 return FALSE;
37 }
38 BOOL isVBox(void)
39 {
40 HANDLE dev = CreateFile(L"\\\\.\\VBoxMiniRdrDN",
41 GENERIC_READ | GENERIC_WRITE,
42 FILE_SHARE_READ | FILE_SHARE_WRITE,
43 NULL, OPEN_EXISTING, 0, NULL);
44 if (dev != INVALID_HANDLE_VALUE)
45 {
46 wprintf(L"VirtualBox detected\n");
47 CloseHandle(dev);
48 return TRUE;
49 }
50
51 return FALSE;
52 }
53 PCWSTR dev[] = { L"\\Device\\hgfs\\;", L"\\Device\\VBoxMiniRdr\\;" };
54 PCWSTR unc[] = { L":\\vmware-host\\Shared Folders\\", L":\\vboxsvr\\" };
55 HV_DET det[] = { isVMware, isVBox };
56
57 HV_TYPES detectVM(void)
58 {
59 HV_TYPES vm;
60
61 for (vm = vmVMware; vm < vmMax; ++vm)
62 {
63 if (det[vm]() == TRUE)
64 {
65 break;
66 }
67 }
68
69 return vm;
70 }
71
72 BOOL performDevIoCtl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize)
73 {
74 BOOL ret;
75 HANDLE dev;
76 DWORD lpBytesReturned;
77
78 dev = CreateFile(L"\\\\.\\hackssign",
79 GENERIC_READ | GENERIC_WRITE,
80 FILE_SHARE_READ | FILE_SHARE_WRITE,
81 NULL, OPEN_EXISTING, 0, NULL);
82 if (dev == INVALID_HANDLE_VALUE)
83 {
84 wprintf(L"Opening device failed\n");
85 return FALSE;
86 }
87
88 ret = DeviceIoControl(dev, dwIoControlCode, lpInBuffer, nInBufferSize, NULL, 0, &lpBytesReturned, NULL);
89 wprintf(L"Done: it %s with error: %lx\n", (ret != 0 ? L"succeed" : L"failed"), (ret != 0 ? ERROR_SUCCESS : GetLastError()));
90
91 CloseHandle(dev);
92
93 return ret;
94 }
95
96
97 BOOL startService()
98 {
99 PWSTR fileName;
100 WCHAR path[MAX_PATH];
101 SC_HANDLE hManager, hService;
102
103 hManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
104 if (hManager == NULL)
105 {
106 wprintf(L"Service manager opening failed\n");
107 return FALSE;
108 }
109
110 hService = OpenService(hManager, L"hackssign", SERVICE_START | SERVICE_STOP | DELETE);
111 if (hService == NULL)
112 {
113 if (GetModuleFileName(NULL, path, MAX_PATH) == 0)
114 {
115 wprintf(L"Getting own path failed\n");
116 CloseServiceHandle(hManager);
117 return FALSE;
118 }
119
120 fileName = wcsrchr(path, L'\\');
121 if (fileName == NULL)
122 {
123 wprintf(L"Invalid path: %s\n", path);
124 CloseServiceHandle(hManager);
125 return FALSE;
126 }
127
128 ++fileName;
129 *fileName = UNICODE_NULL;
130 wcscat(path, L"hackssign_driver.sys");
131
132 if (GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES)
133 {
134 wprintf(L"Driver not found: %s\n", path);
135 CloseServiceHandle(hManager);
136 return FALSE;
137 }
138
139 hService = CreateService(hManager, L"hackssign", L"hackssign",
140 SERVICE_START | SERVICE_STOP | DELETE, SERVICE_KERNEL_DRIVER,
141 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path, NULL, NULL,
142 NULL, NULL, NULL);
143 if (hService == NULL)
144 {
145 wprintf(L"Creating service failed\n");
146 CloseServiceHandle(hManager);
147 return FALSE;
148 }
149 }
150
151 if (!StartService(hService, 0, NULL) &&
152 GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
153 {
154 wprintf(L"Starting service failed\n");
155 CloseServiceHandle(hService);
156 CloseServiceHandle(hManager);
157 return FALSE;
158 }
159
160 wprintf(L"Starting service succeed\n");
161 CloseServiceHandle(hService);
162 CloseServiceHandle(hManager);
163 return TRUE;
164 }
165
166 int assignLetter(WCHAR letter, PCWSTR path)
167 {
168 BOOL ret;
169 DWORD len;
170 PWSTR str;
171 HV_TYPES vm;
172 WCHAR capsLetter;
173 DWORD inputBufferSize;
174 PASSIGN_INPUT inputBuffer;
175
176 vm = detectVM();
177 if (vm == vmMax)
178 {
179 wprintf(L"Unsupported VM type\n");
180 return 1;
181 }
182
183 if (iswalpha(letter) == 0)
184 {
185 wprintf(L"Invalid letter provided\n");
186 return 1;
187 }
188
189 capsLetter = towupper(letter);
190 if (capsLetter == L'C')
191 {
192 wprintf(L"Looks suspicious, won't proceed\n");
193 return 1;
194 }
195
196 len = wcslen(path);
197 if (len == 0)
198 {
199 wprintf(L"Invalid share name\n");
200 return 1;
201 }
202
203 if (wcschr(path, L'\\') != NULL)
204 {
205 wprintf(L"Only give the name of a share\n");
206 return 1;
207 }
208
209 inputBufferSize = len * sizeof(WCHAR) + sizeof(ASSIGN_INPUT) + (wcslen(dev[vm]) + wcslen(unc[vm]) + 2) * sizeof(WCHAR);
210 inputBuffer = malloc(inputBufferSize);
211 if (inputBuffer == NULL)
212 {
213 wprintf(L"Memory failure\n");
214 return 1;
215 }
216
217 inputBuffer->letter = capsLetter;
218 inputBuffer->offset = sizeof(ASSIGN_INPUT);
219 inputBuffer->len = len * sizeof(WCHAR) + (wcslen(dev[vm]) + wcslen(unc[vm]) + 1) * sizeof(WCHAR);
220 str = (PWSTR)((ULONG_PTR)inputBuffer + inputBuffer->offset);
221 swprintf(str, L"%s%c%s%s", dev[vm], capsLetter, unc[vm], path);
222
223 if (!startService())
224 {
225 free(inputBuffer);
226 return 1;
227 }
228
229 Sleep(500);
230
231 ret = performDevIoCtl(FSCTL_HACKSSIGN_ASSIGN, inputBuffer, inputBufferSize);
232 free(inputBuffer);
233
234 return (ret == FALSE);
235 }
236
237 int deleteLetter(WCHAR letter)
238 {
239 WCHAR capsLetter;
240
241 if (iswalpha(letter) == 0)
242 {
243 wprintf(L"Invalid letter provided\n");
244 return 1;
245 }
246
247 capsLetter = towupper(letter);
248 if (capsLetter == L'C')
249 {
250 wprintf(L"Looks suspicious, won't proceed\n");
251 return 1;
252 }
253
254 if (!startService())
255 {
256 return 1;
257 }
258
259 Sleep(500);
260
261 return (performDevIoCtl(FSCTL_HACKSSIGN_DELETE, &capsLetter, sizeof(WCHAR)) == FALSE);
262 }
263
264 int detect(void)
265 {
266 HV_TYPES vm;
267
268 vm = detectVM();
269 if (vm == vmMax)
270 {
271 wprintf(L"Unsupported VM type\n");
272 return 1;
273 }
274
275 return 0;
276 }
277
278 void printUsage(void)
279 {
280 wprintf(L"ReactOS Hackssign application\n");
281 wprintf(L"\tassign <letter> <share name>: Assign a drive letter to the share\n");
282 wprintf(L"\tdelete <letter>: delete driver letter assignation\n");
283 wprintf(L"\tdetect: detect VM type\n");
284 }
285
286 int wmain(int argc, wchar_t *argv[])
287 {
288 PCWSTR cmd;
289
290 if (argc < 2)
291 {
292 printUsage();
293 return 0;
294 }
295
296 cmd = argv[1];
297
298 if (_wcsicmp(cmd, L"assign") == 0)
299 {
300 if (argc < 4)
301 {
302 printUsage();
303 return 0;
304 }
305
306 return assignLetter(argv[2][0], argv[3]);
307 }
308 else if (_wcsicmp(cmd, L"delete") == 0)
309 {
310 if (argc < 3)
311 {
312 printUsage();
313 return 0;
314 }
315
316 return deleteLetter(argv[2][0]);
317 }
318 else if (_wcsicmp(cmd, L"detect") == 0)
319 {
320 return detect();
321 }
322 else
323 {
324 printUsage();
325 return 0;
326 }
327 }