VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/cmn/VBoxDrvTool.cpp@ 69496

Last change on this file since 69496 was 69496, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: VBoxDrvTool.cpp 69496 2017-10-28 14:55:58Z vboxsync $ */
2/** @file
3 * Windows Driver R0 Tooling.
4 */
5
6/*
7 * Copyright (C) 2011-2017 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27#include "VBoxDrvTool.h"
28
29#include <iprt/assert.h>
30#include <VBox/log.h>
31
32#include "../../../win/VBoxDbgLog.h"
33
34#define VBOXDRVTOOL_MEMTAG 'TDBV'
35
36static PVOID vboxDrvToolMemAlloc(SIZE_T cbBytes)
37{
38 PVOID pvMem = ExAllocatePoolWithTag(NonPagedPool, cbBytes, VBOXDRVTOOL_MEMTAG);
39 Assert(pvMem);
40 return pvMem;
41}
42
43static PVOID vboxDrvToolMemAllocZ(SIZE_T cbBytes)
44{
45 PVOID pvMem = vboxDrvToolMemAlloc(cbBytes);
46 if (pvMem)
47 {
48 RtlZeroMemory(pvMem, cbBytes);
49 }
50 return pvMem;
51}
52
53static VOID vboxDrvToolMemFree(PVOID pvMem)
54{
55 ExFreePoolWithTag(pvMem, VBOXDRVTOOL_MEMTAG);
56}
57
58VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKeyU(OUT PHANDLE phKey, IN PUNICODE_STRING pName, IN ACCESS_MASK fAccess)
59{
60 OBJECT_ATTRIBUTES ObjAttr;
61
62 InitializeObjectAttributes(&ObjAttr, pName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
63
64 return ZwOpenKey(phKey, fAccess, &ObjAttr);
65}
66
67VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
68{
69 UNICODE_STRING RtlStr;
70 RtlInitUnicodeString(&RtlStr, pName);
71
72 return VBoxDrvToolRegOpenKeyU(phKey, &RtlStr, fAccess);
73}
74
75VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegCloseKey(IN HANDLE hKey)
76{
77 return ZwClose(hKey);
78}
79
80VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PULONG pDword)
81{
82 struct
83 {
84 KEY_VALUE_PARTIAL_INFORMATION Info;
85 UCHAR Buf[32]; /* should be enough */
86 } Buf;
87 ULONG cbBuf;
88 UNICODE_STRING RtlStr;
89 RtlInitUnicodeString(&RtlStr, pName);
90 NTSTATUS Status = ZwQueryValueKey(hKey,
91 &RtlStr,
92 KeyValuePartialInformation,
93 &Buf.Info,
94 sizeof(Buf),
95 &cbBuf);
96 if (Status == STATUS_SUCCESS)
97 {
98 if (Buf.Info.Type == REG_DWORD)
99 {
100 Assert(Buf.Info.DataLength == 4);
101 *pDword = *((PULONG)Buf.Info.Data);
102 return STATUS_SUCCESS;
103 }
104 }
105
106 return STATUS_INVALID_PARAMETER;
107}
108
109VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT ULONG val)
110{
111 UNICODE_STRING RtlStr;
112 RtlInitUnicodeString(&RtlStr, pName);
113 return ZwSetValueKey(hKey, &RtlStr,
114 NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
115 REG_DWORD,
116 &val,
117 sizeof(val));
118}
119
120static NTSTATUS vboxDrvToolIoCompletionSetEvent(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pvContext)
121{
122 RT_NOREF2(pDevObj, pIrp);
123 PKEVENT pEvent = (PKEVENT)pvContext;
124 KeSetEvent(pEvent, 0, FALSE);
125 return STATUS_MORE_PROCESSING_REQUIRED;
126}
127
128VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostAsync(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent)
129{
130 IoSetCompletionRoutine(pIrp, vboxDrvToolIoCompletionSetEvent, pEvent, TRUE, TRUE, TRUE);
131 return IoCallDriver(pDevObj, pIrp);
132}
133
134VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSync(PDEVICE_OBJECT pDevObj, PIRP pIrp)
135{
136 KEVENT Event;
137 KeInitializeEvent(&Event, NotificationEvent, FALSE);
138 NTSTATUS Status = VBoxDrvToolIoPostAsync(pDevObj, pIrp, &Event);
139 if (Status == STATUS_PENDING)
140 {
141 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
142 Status = pIrp->IoStatus.Status;
143 }
144 return Status;
145}
146
147/* !!!NOTE: the caller MUST be the IRP owner!!! *
148 * !! one can not post threaded IRPs this way!! */
149VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolIoPostSyncWithTimeout(PDEVICE_OBJECT pDevObj, PIRP pIrp, ULONG dwTimeoutMs)
150{
151 KEVENT Event;
152 LOG(("post irp (0x%p) to DevObj(0x%p) with timeout (%u)", pIrp, pDevObj, dwTimeoutMs));
153
154 KeInitializeEvent(&Event, NotificationEvent, FALSE);
155 NTSTATUS Status = VBoxDrvToolIoPostAsync(pDevObj, pIrp, &Event);
156 if (Status == STATUS_PENDING)
157 {
158 LARGE_INTEGER Interval;
159 PLARGE_INTEGER pInterval = NULL;
160 if (dwTimeoutMs != RT_INDEFINITE_WAIT)
161 {
162 Interval.QuadPart = -(int64_t) dwTimeoutMs /* ms */ * 10000;
163 pInterval = &Interval;
164 }
165
166 Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, pInterval);
167 if (Status == STATUS_TIMEOUT)
168 {
169 WARN(("irp (0x%p) to DevObj(0x%p) was not completed within timeout (%u), cancelling", pIrp, pDevObj, dwTimeoutMs));
170 if (!IoCancelIrp(pIrp))
171 {
172 /* this may happen, but this is something the caller with timeout is not expecting */
173 WARN(("IoCancelIrp failed"));
174 }
175
176 /* wait for the IRP to complete */
177 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
178 }
179 else
180 {
181 ASSERT_WARN(Status == STATUS_SUCCESS, ("uunexpected Status (0x%x)", Status));
182 }
183
184 /* by this time the IRP is completed */
185 Status = pIrp->IoStatus.Status;
186 LOG(("Pending IRP(0x%p) completed with status(0x%x)", pIrp, Status));
187 }
188 else
189 {
190 LOG(("IRP(0x%p) completed with status(0x%x)", pIrp, Status));
191 }
192 return Status;
193}
194
195VBOXDRVTOOL_DECL(VOID) VBoxDrvToolRefWaitEqual(PVBOXDRVTOOL_REF pRef, uint32_t u32Val)
196{
197 LARGE_INTEGER Interval;
198 Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
199 uint32_t cRefs;
200 size_t loops = 0;
201 KTIMER kTimer;
202 NTSTATUS status = STATUS_SUCCESS;
203
204 KeInitializeTimer(&kTimer);
205
206 while ((cRefs = ASMAtomicReadU32(&pRef->cRefs)) > u32Val && loops < 256)
207 {
208 Assert(cRefs >= u32Val);
209 Assert(cRefs < UINT32_MAX/2);
210
211 KeSetTimer(&kTimer, Interval, NULL);
212 status = KeWaitForSingleObject(&kTimer, Executive, KernelMode, false, NULL);
213 Assert(NT_SUCCESS(status));
214 loops++;
215 }
216}
217
218VBOXDRVTOOL_DECL(NTSTATUS) VBoxDrvToolStrCopy(PUNICODE_STRING pDst, CONST PUNICODE_STRING pSrc)
219{
220 USHORT cbLength = pSrc->Length + sizeof (pDst->Buffer[0]);
221 pDst->Buffer = (PWCHAR)vboxDrvToolMemAlloc(cbLength);
222 Assert(pDst->Buffer);
223 if (pDst->Buffer)
224 {
225 RtlMoveMemory(pDst->Buffer, pSrc->Buffer, pSrc->Length);
226 pDst->Buffer[pSrc->Length / sizeof (pDst->Buffer[0])] = L'\0';
227 pDst->Length = pSrc->Length;
228 pDst->MaximumLength = cbLength;
229 return STATUS_SUCCESS;
230 }
231 return STATUS_NO_MEMORY;
232}
233
234VBOXDRVTOOL_DECL(VOID) VBoxDrvToolStrFree(PUNICODE_STRING pStr)
235{
236 vboxDrvToolMemFree(pStr->Buffer);
237}
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