VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/SharedFolders/driver/vbsfhlp.c@ 78280

Last change on this file since 78280 was 78280, checked in by vboxsync, 6 years ago

winnt/vboxsf: Use 'vrc' for the vbox/iprt status code like we do in main and other places, rather than 'vboxRC'. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1/* $Id: vbsfhlp.c 78280 2019-04-24 16:29:00Z vboxsync $ */
2/** @file
3 * VirtualBox Windows Guest Shared Folders - File System Driver system helpers
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/nt/nt.h> /* includes ntifs.h and wdm.h */
19#include <iprt/win/ntdddisk.h>
20
21#include "vbsfhlp.h"
22#include <iprt/err.h>
23
24#ifdef DEBUG
25static int s_iAllocRefCount = 0;
26#endif
27
28void vbsfHlpSleep(ULONG ulMillies)
29{
30 KEVENT event;
31 LARGE_INTEGER dueTime;
32
33 KeInitializeEvent(&event, NotificationEvent, FALSE);
34
35 dueTime.QuadPart = -10000 * (int)ulMillies;
36
37 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &dueTime);
38}
39
40/**
41 * Converts VBox (IPRT) file mode to NT file attributes.
42 *
43 * @returns NT file attributes
44 * @param fIprtMode IPRT file mode.
45 *
46 */
47uint32_t VBoxToNTFileAttributes(uint32_t fIprtMode)
48{
49 AssertCompile((RTFS_DOS_READONLY >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_READONLY);
50 AssertCompile((RTFS_DOS_HIDDEN >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_HIDDEN);
51 AssertCompile((RTFS_DOS_SYSTEM >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_SYSTEM);
52 AssertCompile((RTFS_DOS_DIRECTORY >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_DIRECTORY);
53 AssertCompile((RTFS_DOS_ARCHIVED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_ARCHIVE);
54 /* skipping: RTFS_DOS_NT_DEVICE */
55 AssertCompile((RTFS_DOS_NT_NORMAL >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_NORMAL);
56 AssertCompile((RTFS_DOS_NT_TEMPORARY >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_TEMPORARY);
57 AssertCompile((RTFS_DOS_NT_SPARSE_FILE >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_SPARSE_FILE);
58 AssertCompile((RTFS_DOS_NT_REPARSE_POINT >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_REPARSE_POINT);
59 AssertCompile((RTFS_DOS_NT_COMPRESSED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_COMPRESSED);
60 /* skipping: RTFS_DOS_NT_OFFLINE */
61 AssertCompile((RTFS_DOS_NT_NOT_CONTENT_INDEXED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
62 AssertCompile((RTFS_DOS_NT_ENCRYPTED >> RTFS_DOS_SHIFT) == FILE_ATTRIBUTE_ENCRYPTED);
63
64 uint32_t fNtAttribs = (fIprtMode & (RTFS_DOS_MASK_NT & ~(RTFS_DOS_NT_OFFLINE | RTFS_DOS_NT_DEVICE)) >> RTFS_DOS_SHIFT);
65 return fNtAttribs ? fNtAttribs : FILE_ATTRIBUTE_NORMAL;
66}
67
68/**
69 * Converts NT file attributes to VBox (IPRT) ones.
70 *
71 * @returns IPRT file mode
72 * @param fNtAttribs NT file attributes
73 */
74uint32_t NTToVBoxFileAttributes(uint32_t fNtAttribs)
75{
76 uint32_t fIprtMode = (fNtAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT;
77 return fIprtMode ? fIprtMode : RTFS_DOS_NT_NORMAL;
78}
79
80NTSTATUS vbsfHlpCreateDriveLetter(WCHAR Letter, UNICODE_STRING *pDeviceName)
81{
82 UNICODE_STRING driveName;
83 RtlInitUnicodeString(&driveName,L"\\??\\_:" );
84
85 /* Replace '_' with actual drive letter */
86 driveName.Buffer[driveName.Length/sizeof(WCHAR) - 2] = Letter;
87
88 return IoCreateSymbolicLink(&driveName, pDeviceName);
89}
90
91NTSTATUS vbsfHlpDeleteDriveLetter(WCHAR Letter)
92{
93 UNICODE_STRING driveName;
94 RtlInitUnicodeString(&driveName,L"\\??\\_:" );
95
96 /* Replace '_' with actual drive letter */
97 driveName.Buffer[driveName.Length/sizeof(WCHAR) - 2] = Letter;
98
99 return IoDeleteSymbolicLink(&driveName);
100}
101
102/**
103 * Convert VBox error code to NT status code
104 *
105 * @returns NT status code
106 * @param vrc VBox status code.
107 *
108 */
109NTSTATUS VBoxErrorToNTStatus(int vrc)
110{
111 NTSTATUS Status;
112
113 switch (vrc)
114 {
115 case VINF_SUCCESS:
116 Status = STATUS_SUCCESS;
117 break;
118
119 case VERR_ACCESS_DENIED:
120 Status = STATUS_ACCESS_DENIED;
121 break;
122
123 case VERR_NO_MORE_FILES:
124 Status = STATUS_NO_MORE_FILES;
125 break;
126
127 case VERR_PATH_NOT_FOUND:
128 Status = STATUS_OBJECT_PATH_NOT_FOUND;
129 break;
130
131 case VERR_FILE_NOT_FOUND:
132 Status = STATUS_OBJECT_NAME_NOT_FOUND;
133 break;
134
135 case VERR_DIR_NOT_EMPTY:
136 Status = STATUS_DIRECTORY_NOT_EMPTY;
137 break;
138
139 case VERR_SHARING_VIOLATION:
140 Status = STATUS_SHARING_VIOLATION;
141 break;
142
143 case VERR_FILE_LOCK_VIOLATION:
144 Status = STATUS_FILE_LOCK_CONFLICT;
145 break;
146
147 case VERR_FILE_LOCK_FAILED:
148 Status = STATUS_LOCK_NOT_GRANTED;
149 break;
150
151 case VINF_BUFFER_OVERFLOW:
152 Status = STATUS_BUFFER_OVERFLOW;
153 break;
154
155 case VERR_EOF:
156 case VINF_EOF:
157 Status = STATUS_END_OF_FILE;
158 break;
159
160 case VERR_READ_ERROR:
161 case VERR_WRITE_ERROR:
162 case VERR_FILE_IO_ERROR:
163 Status = STATUS_UNEXPECTED_IO_ERROR;
164 break;
165
166 case VERR_WRITE_PROTECT:
167 Status = STATUS_MEDIA_WRITE_PROTECTED;
168 break;
169
170 case VERR_ALREADY_EXISTS:
171 Status = STATUS_OBJECT_NAME_COLLISION;
172 break;
173
174 case VERR_NOT_A_DIRECTORY:
175 Status = STATUS_NOT_A_DIRECTORY;
176 break;
177
178 case VERR_SEEK:
179 Status = STATUS_INVALID_PARAMETER;
180 break;
181
182 case VERR_INVALID_PARAMETER:
183 Status = STATUS_INVALID_PARAMETER;
184 break;
185
186 case VERR_NOT_SUPPORTED:
187 Status = STATUS_NOT_SUPPORTED;
188 break;
189
190 default:
191 /** @todo error handling */
192 Status = STATUS_INVALID_PARAMETER;
193 Log(("Unexpected vbox error %Rrc\n",
194 vrc));
195 break;
196 }
197 return Status;
198}
199
200PVOID vbsfAllocNonPagedMem(ULONG ulSize)
201{
202 PVOID pMemory = NULL;
203
204#ifdef DEBUG
205 s_iAllocRefCount = s_iAllocRefCount + 1;
206 Log(("vbsfAllocNonPagedMem: RefCnt after incrementing: %d\n", s_iAllocRefCount));
207#endif
208
209 /* Tag is reversed (a.k.a "SHFL") to display correctly in debuggers, so search for "SHFL" */
210 pMemory = ExAllocatePoolWithTag(NonPagedPool, ulSize, 'LFHS');
211
212 if (NULL != pMemory)
213 {
214 RtlZeroMemory(pMemory, ulSize);
215#ifdef DEBUG
216 Log(("vbsfAllocNonPagedMem: Allocated %d bytes of memory at %p.\n", ulSize, pMemory));
217#endif
218 }
219 else
220 {
221#ifdef DEBUG
222 Log(("vbsfAllocNonPagedMem: ERROR: Could not allocate %d bytes of memory!\n", ulSize));
223#endif
224 }
225
226 return pMemory;
227}
228
229void vbsfFreeNonPagedMem(PVOID lpMem)
230{
231#ifdef DEBUG
232 s_iAllocRefCount = s_iAllocRefCount - 1;
233 Log(("vbsfFreeNonPagedMem: RefCnt after decrementing: %d\n", s_iAllocRefCount));
234#endif
235
236 Assert(lpMem);
237
238 /* MSDN: The ExFreePoolWithTag routine issues a bug check if the specified value for Tag does not match the tag value passed
239 to the routine that originally allocated the memory block. Otherwise, the behavior of this routine is identical to ExFreePool. */
240 ExFreePoolWithTag(lpMem, 'LFHS');
241 lpMem = NULL;
242}
243
244#if 0 //def DEBUG
245/**
246 * Callback for RTLogFormatV which writes to the backdoor.
247 * See PFNLOGOUTPUT() for details.
248 */
249static DECLCALLBACK(size_t) rtLogBackdoorOutput(void *pv, const char *pachChars, size_t cbChars)
250{
251 RTLogWriteUser(pachChars, cbChars);
252 return cbChars;
253}
254
255int RTLogBackdoorPrintf1(const char *pszFormat, ...)
256{
257 va_list args;
258
259 LARGE_INTEGER time;
260
261 KeQueryTickCount(&time);
262
263 RTLogBackdoorPrintf("T=%RX64 ", time.QuadPart);
264 va_start(args, pszFormat);
265 RTLogFormatV(rtLogBackdoorOutput, NULL, pszFormat, args);
266 va_end(args);
267
268 return 0;
269}
270#endif
271
272#if defined(DEBUG) || defined(LOG_ENABLED)
273
274static PCHAR PnPMinorFunctionString(LONG MinorFunction)
275{
276 switch (MinorFunction)
277 {
278 case IRP_MN_START_DEVICE:
279 return "IRP_MJ_PNP - IRP_MN_START_DEVICE";
280 case IRP_MN_QUERY_REMOVE_DEVICE:
281 return "IRP_MJ_PNP - IRP_MN_QUERY_REMOVE_DEVICE";
282 case IRP_MN_REMOVE_DEVICE:
283 return "IRP_MJ_PNP - IRP_MN_REMOVE_DEVICE";
284 case IRP_MN_CANCEL_REMOVE_DEVICE:
285 return "IRP_MJ_PNP - IRP_MN_CANCEL_REMOVE_DEVICE";
286 case IRP_MN_STOP_DEVICE:
287 return "IRP_MJ_PNP - IRP_MN_STOP_DEVICE";
288 case IRP_MN_QUERY_STOP_DEVICE:
289 return "IRP_MJ_PNP - IRP_MN_QUERY_STOP_DEVICE";
290 case IRP_MN_CANCEL_STOP_DEVICE:
291 return "IRP_MJ_PNP - IRP_MN_CANCEL_STOP_DEVICE";
292 case IRP_MN_QUERY_DEVICE_RELATIONS:
293 return "IRP_MJ_PNP - IRP_MN_QUERY_DEVICE_RELATIONS";
294 case IRP_MN_QUERY_INTERFACE:
295 return "IRP_MJ_PNP - IRP_MN_QUERY_INTERFACE";
296 case IRP_MN_QUERY_CAPABILITIES:
297 return "IRP_MJ_PNP - IRP_MN_QUERY_CAPABILITIES";
298 case IRP_MN_QUERY_RESOURCES:
299 return "IRP_MJ_PNP - IRP_MN_QUERY_RESOURCES";
300 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
301 return "IRP_MJ_PNP - IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
302 case IRP_MN_QUERY_DEVICE_TEXT:
303 return "IRP_MJ_PNP - IRP_MN_QUERY_DEVICE_TEXT";
304 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
305 return "IRP_MJ_PNP - IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
306 case IRP_MN_READ_CONFIG:
307 return "IRP_MJ_PNP - IRP_MN_READ_CONFIG";
308 case IRP_MN_WRITE_CONFIG:
309 return "IRP_MJ_PNP - IRP_MN_WRITE_CONFIG";
310 case IRP_MN_EJECT:
311 return "IRP_MJ_PNP - IRP_MN_EJECT";
312 case IRP_MN_SET_LOCK:
313 return "IRP_MJ_PNP - IRP_MN_SET_LOCK";
314 case IRP_MN_QUERY_ID:
315 return "IRP_MJ_PNP - IRP_MN_QUERY_ID";
316 case IRP_MN_QUERY_PNP_DEVICE_STATE:
317 return "IRP_MJ_PNP - IRP_MN_QUERY_PNP_DEVICE_STATE";
318 case IRP_MN_QUERY_BUS_INFORMATION:
319 return "IRP_MJ_PNP - IRP_MN_QUERY_BUS_INFORMATION";
320 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
321 return "IRP_MJ_PNP - IRP_MN_DEVICE_USAGE_NOTIFICATION";
322 case IRP_MN_SURPRISE_REMOVAL:
323 return "IRP_MJ_PNP - IRP_MN_SURPRISE_REMOVAL";
324 default:
325 return "IRP_MJ_PNP - unknown_pnp_irp";
326 }
327}
328
329PCHAR MajorFunctionString(UCHAR MajorFunction, LONG MinorFunction)
330{
331 switch (MajorFunction)
332 {
333 case IRP_MJ_CREATE:
334 return "IRP_MJ_CREATE";
335 case IRP_MJ_CREATE_NAMED_PIPE:
336 return "IRP_MJ_CREATE_NAMED_PIPE";
337 case IRP_MJ_CLOSE:
338 return "IRP_MJ_CLOSE";
339 case IRP_MJ_READ:
340 return "IRP_MJ_READ";
341 case IRP_MJ_WRITE:
342 return "IRP_MJ_WRITE";
343 case IRP_MJ_QUERY_INFORMATION:
344 return "IRP_MJ_QUERY_INFORMATION";
345 case IRP_MJ_SET_INFORMATION:
346 return "IRP_MJ_SET_INFORMATION";
347 case IRP_MJ_QUERY_EA:
348 return "IRP_MJ_QUERY_EA";
349 case IRP_MJ_SET_EA:
350 return "IRP_MJ_SET_EA";
351 case IRP_MJ_FLUSH_BUFFERS:
352 return "IRP_MJ_FLUSH_BUFFERS";
353 case IRP_MJ_QUERY_VOLUME_INFORMATION:
354 return "IRP_MJ_QUERY_VOLUME_INFORMATION";
355 case IRP_MJ_SET_VOLUME_INFORMATION:
356 return "IRP_MJ_SET_VOLUME_INFORMATION";
357 case IRP_MJ_DIRECTORY_CONTROL:
358 return "IRP_MJ_DIRECTORY_CONTROL";
359 case IRP_MJ_FILE_SYSTEM_CONTROL:
360 return "IRP_MJ_FILE_SYSTEM_CONTROL";
361 case IRP_MJ_DEVICE_CONTROL:
362 return "IRP_MJ_DEVICE_CONTROL";
363 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
364 return "IRP_MJ_INTERNAL_DEVICE_CONTROL";
365 case IRP_MJ_SHUTDOWN:
366 return "IRP_MJ_SHUTDOWN";
367 case IRP_MJ_LOCK_CONTROL:
368 return "IRP_MJ_LOCK_CONTROL";
369 case IRP_MJ_CLEANUP:
370 return "IRP_MJ_CLEANUP";
371 case IRP_MJ_CREATE_MAILSLOT:
372 return "IRP_MJ_CREATE_MAILSLOT";
373 case IRP_MJ_QUERY_SECURITY:
374 return "IRP_MJ_QUERY_SECURITY";
375 case IRP_MJ_SET_SECURITY:
376 return "IRP_MJ_SET_SECURITY";
377 case IRP_MJ_POWER:
378 return "IRP_MJ_POWER";
379 case IRP_MJ_SYSTEM_CONTROL:
380 return "IRP_MJ_SYSTEM_CONTROL";
381 case IRP_MJ_DEVICE_CHANGE:
382 return "IRP_MJ_DEVICE_CHANGE";
383 case IRP_MJ_QUERY_QUOTA:
384 return "IRP_MJ_QUERY_QUOTA";
385 case IRP_MJ_SET_QUOTA:
386 return "IRP_MJ_SET_QUOTA";
387 case IRP_MJ_PNP:
388 return PnPMinorFunctionString(MinorFunction);
389
390 default:
391 return "unknown_pnp_irp";
392 }
393}
394
395#endif /* DEBUG || LOG_ENABLED */
396
397/** Allocate and initialize a SHFLSTRING from a UNICODE string.
398 *
399 * @param ppShflString Where to store the pointer to the allocated SHFLSTRING structure.
400 * The structure must be deallocated with vbsfFreeNonPagedMem.
401 * @param pwc The UNICODE string. If NULL then SHFL is only allocated.
402 * @param cb Size of the UNICODE string in bytes without the trailing nul.
403 *
404 * @return Status code.
405 */
406NTSTATUS vbsfShflStringFromUnicodeAlloc(PSHFLSTRING *ppShflString, const WCHAR *pwc, uint16_t cb)
407{
408 NTSTATUS Status = STATUS_SUCCESS;
409
410 PSHFLSTRING pShflString;
411 ULONG ulShflStringSize;
412
413 /* Calculate length required for the SHFL structure: header + chars + nul. */
414 ulShflStringSize = SHFLSTRING_HEADER_SIZE + cb + sizeof(WCHAR);
415 pShflString = (PSHFLSTRING)vbsfAllocNonPagedMem(ulShflStringSize);
416 if (pShflString)
417 {
418 if (ShflStringInitBuffer(pShflString, ulShflStringSize))
419 {
420 if (pwc)
421 {
422 RtlCopyMemory(pShflString->String.ucs2, pwc, cb);
423 pShflString->String.ucs2[cb / sizeof(WCHAR)] = 0;
424 pShflString->u16Length = cb; /* without terminating null */
425 AssertMsg(pShflString->u16Length + sizeof(WCHAR) == pShflString->u16Size,
426 ("u16Length %d, u16Size %d\n", pShflString->u16Length, pShflString->u16Size));
427 }
428 else
429 {
430 RtlZeroMemory(pShflString->String.ucs2, cb + sizeof(WCHAR));
431 pShflString->u16Length = 0; /* without terminating null */
432 AssertMsg(pShflString->u16Size >= sizeof(WCHAR),
433 ("u16Size %d\n", pShflString->u16Size));
434 }
435
436 *ppShflString = pShflString;
437 }
438 else
439 {
440 vbsfFreeNonPagedMem(pShflString);
441 Status = STATUS_INSUFFICIENT_RESOURCES;
442 }
443 }
444 else
445 {
446 Status = STATUS_INSUFFICIENT_RESOURCES;
447 }
448
449 return Status;
450}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette