VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibIdc-win.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: VBoxGuestR0LibIdc-win.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxGuestLib - Ring-0 Support Library for VBoxGuest, IDC, Windows specific.
4 */
5
6/*
7 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include <iprt/nt/nt.h>
36#include "VBoxGuestR0LibInternal.h"
37#include <VBox/VBoxGuest.h>
38#include <iprt/errcore.h>
39#include <VBox/log.h>
40
41
42/**
43 * Internal I/O Control call worker.
44 *
45 * @returns VBox status code.
46 * @param pDeviceObject The device object to call.
47 * @param pFileObject The file object for the connection.
48 * @param uReq The request.
49 * @param pReq The request packet.
50 */
51static int vbglR0IdcNtCallInternal(PDEVICE_OBJECT pDeviceObject, PFILE_OBJECT pFileObject, uint32_t uReq, PVBGLREQHDR pReq)
52{
53 int rc;
54 NTSTATUS rcNt;
55
56 /*
57 * Build the request.
58 *
59 * We want to avoid double buffering of the request, therefore we don't
60 * specify any request pointers or sizes when asking the kernel to build
61 * the IRP for us, but instead do that part our selves.
62 *
63 * See https://www.osr.com/blog/2018/02/14/beware-iobuilddeviceiocontrolrequest/
64 * for how fun this is when we're not at IRQL PASSIVE (HACK ALERT futher down).
65 * Ran into this little issue when LoadLibraryEx on a .NET DLL using the
66 * LOAD_LIBRARY_AS_DATAFILE and LOAD_LIBRARY_AS_IMAGE_RESOURCE flags.
67 */
68 KEVENT Event;
69 KeInitializeEvent(&Event, NotificationEvent, FALSE);
70
71 IO_STATUS_BLOCK IoStatusBlock = RTNT_IO_STATUS_BLOCK_INITIALIZER;
72#if 0
73 PIRP pIrp = IoBuildDeviceIoControlRequest(uReq, /* IoControlCode */
74 pDeviceObject,
75 pReq, /* InputBuffer */
76 pReq->cbIn, /* InputBufferLength */
77 pReq, /* OutputBuffer */
78 pReq->cbOut, /* OutputBufferLength */
79 TRUE, /* InternalDeviceIoControl (=> IRP_MJ_INTERNAL_DEVICE_CONTROL) */
80 &Event, /* Event */
81 &IoStatusBlock); /* IoStatusBlock */
82#else
83 PIRP pIrp = IoBuildDeviceIoControlRequest(uReq, /* IoControlCode */
84 pDeviceObject,
85 NULL, /* InputBuffer */
86 0, /* InputBufferLength */
87 NULL, /* OutputBuffer */
88 0, /* OutputBufferLength */
89 TRUE, /* InternalDeviceIoControl (=> IRP_MJ_INTERNAL_DEVICE_CONTROL) */
90 &Event, /* Event */
91 &IoStatusBlock); /* IoStatusBlock */
92#endif
93 if (pIrp)
94 {
95#if 0
96 IoGetNextIrpStackLocation(pIrp)->FileObject = pFileObject;
97#else
98 //w2k3sp1+: if (!KeAreAllApcsDisabled())
99 //w2k3sp1+: pIrp->Flags |= IRP_SYNCHRONOUS_API;
100 //w2k3sp1+: else
101 {
102 /* HACK ALERT! Causes IoCompleteRequest to update UserIosb and free the IRP w/o any APC happening. */
103 pIrp->Flags |= IRP_SYNCHRONOUS_API | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO;
104 KIRQL bIrqlSaved;
105 KeRaiseIrql(APC_LEVEL, &bIrqlSaved);
106 RemoveEntryList(&pIrp->ThreadListEntry);
107 InitializeListHead(&pIrp->ThreadListEntry);
108 KeLowerIrql(bIrqlSaved);
109 }
110 pIrp->UserBuffer = pReq;
111 pIrp->AssociatedIrp.SystemBuffer = pReq;
112 PIO_STACK_LOCATION pStack = IoGetNextIrpStackLocation(pIrp);
113 pStack->FileObject = pFileObject;
114 pStack->Parameters.DeviceIoControl.OutputBufferLength = pReq->cbOut;
115 pStack->Parameters.DeviceIoControl.InputBufferLength = pReq->cbIn;
116#endif
117
118 /*
119 * Call the driver, wait for an async request to complete (should never happen).
120 */
121 rcNt = IoCallDriver(pDeviceObject, pIrp);
122 if (rcNt == STATUS_PENDING)
123 rcNt = KeWaitForSingleObject(&Event, /* Object */
124 Executive, /* WaitReason */
125 KernelMode, /* WaitMode */
126 FALSE, /* Alertable */
127 NULL); /* TimeOut */
128 if (NT_SUCCESS(rcNt))
129 rcNt = IoStatusBlock.Status;
130 if (NT_SUCCESS(rcNt))
131 rc = pReq->rc;
132 else
133 rc = RTErrConvertFromNtStatus(rcNt);
134 }
135 else
136 rc = VERR_NO_MEMORY;
137 return rc;
138}
139
140
141int VBOXCALL vbglR0IdcNativeOpen(PVBGLIDCHANDLE pHandle, PVBGLIOCIDCCONNECT pReq)
142{
143 PDEVICE_OBJECT pDeviceObject = NULL;
144 PFILE_OBJECT pFileObject = NULL;
145 UNICODE_STRING wszDeviceName;
146 NTSTATUS rcNt;
147 int rc;
148
149 /*
150 * Get the device object pointer.
151 */
152 RtlInitUnicodeString(&wszDeviceName, VBOXGUEST_DEVICE_NAME_NT);
153 rcNt = IoGetDeviceObjectPointer(&wszDeviceName, FILE_ALL_ACCESS, &pFileObject, &pDeviceObject);
154 if (NT_SUCCESS(rcNt))
155 {
156 /*
157 * Make the connection call.
158 */
159 rc = vbglR0IdcNtCallInternal(pDeviceObject, pFileObject, VBGL_IOCTL_IDC_CONNECT, &pReq->Hdr);
160 if (RT_SUCCESS(rc) && RT_SUCCESS(pReq->Hdr.rc))
161 {
162 pHandle->s.pDeviceObject = pDeviceObject;
163 pHandle->s.pFileObject = pFileObject;
164 return rc;
165 }
166
167 /* only the file object. */
168 ObDereferenceObject(pFileObject);
169 }
170 else
171 rc = RTErrConvertFromNtStatus(rcNt);
172
173 pHandle->s.pDeviceObject = NULL;
174 pHandle->s.pFileObject = NULL;
175 return rc;
176}
177
178
179int VBOXCALL vbglR0IdcNativeClose(PVBGLIDCHANDLE pHandle, PVBGLIOCIDCDISCONNECT pReq)
180{
181 PFILE_OBJECT pFileObject = pHandle->s.pFileObject;
182 int rc = vbglR0IdcNtCallInternal(pHandle->s.pDeviceObject, pFileObject, VBGL_IOCTL_IDC_DISCONNECT, &pReq->Hdr);
183 if (RT_SUCCESS(rc) && RT_SUCCESS(pReq->Hdr.rc))
184 {
185 pHandle->s.pDeviceObject = NULL;
186 pHandle->s.pFileObject = NULL;
187 ObDereferenceObject(pFileObject);
188 }
189
190 return rc;
191}
192
193
194/**
195 * Makes an IDC call, returning only the I/O control status code.
196 *
197 * @returns VBox status code (the I/O control failure status).
198 * @param pHandle The IDC handle.
199 * @param uReq The request number.
200 * @param pReqHdr The request header.
201 * @param cbReq The request size.
202 */
203DECLR0VBGL(int) VbglR0IdcCallRaw(PVBGLIDCHANDLE pHandle, uintptr_t uReq, PVBGLREQHDR pReqHdr, uint32_t cbReq)
204{
205 NOREF(cbReq);
206 return vbglR0IdcNtCallInternal(pHandle->s.pDeviceObject, pHandle->s.pFileObject, (uint32_t)uReq, pReqHdr);
207}
208
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use