VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/krnlmod-win.cpp@ 96407

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.6 KB
Line 
1/* $Id: krnlmod-win.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * IPRT - Kernel module, Windows.
4 */
5
6/*
7 * Copyright (C) 2017-2022 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_SYSTEM
42#include <iprt/nt/nt.h>
43
44#include <iprt/krnlmod.h>
45#include <iprt/asm.h>
46#include <iprt/assert.h>
47#include <iprt/dir.h>
48#include <iprt/errcore.h>
49#include <iprt/mem.h>
50#include <iprt/string.h>
51#include <iprt/types.h>
52
53
54/**
55 * Internal kernel information record state.
56 */
57typedef struct RTKRNLMODINFOINT
58{
59 /** Reference counter. */
60 volatile uint32_t cRefs;
61 /** Reference count for the kernel module. */
62 uint32_t cRefKrnlMod;
63 /** Load address of the kernel module. */
64 RTR0UINTPTR uLoadAddr;
65 /** Size of the kernel module. */
66 size_t cbKrnlMod;
67 /** Pointer to the driver name. */
68 const char *pszName;
69 /** Size of the name in characters including the zero terminator. */
70 size_t cchFilePath;
71 /** Module name - variable in size. */
72 char achFilePath[1];
73} RTKRNLMODINFOINT;
74/** Pointer to the internal kernel module information record. */
75typedef RTKRNLMODINFOINT *PRTKRNLMODINFOINT;
76/** Pointer to a const internal kernel module information record. */
77typedef const RTKRNLMODINFOINT *PCRTKRNLMODINFOINT;
78
79
80/**
81 * Destroy the given kernel module information record.
82 *
83 * @returns nothing.
84 * @param pThis The record to destroy.
85 */
86static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
87{
88 RTMemFree(pThis);
89}
90
91
92/**
93 * Queries the complete kernel modules structure and returns a pointer to it.
94 *
95 * @returns IPRT status code.
96 * @param ppKrnlMods Where to store the pointer to the kernel module list on success.
97 * Free with RTMemFree().
98 */
99static int rtKrnlModWinQueryKrnlMods(PRTL_PROCESS_MODULES *ppKrnlMods)
100{
101 int rc = VINF_SUCCESS;
102 RTL_PROCESS_MODULES KrnlModsSize;
103
104 NTSTATUS rcNt = NtQuerySystemInformation(SystemModuleInformation, &KrnlModsSize, sizeof(KrnlModsSize), NULL);
105 if (NT_SUCCESS(rcNt) || rcNt == STATUS_INFO_LENGTH_MISMATCH)
106 {
107 ULONG cbKrnlMods = RT_UOFFSETOF_DYN(RTL_PROCESS_MODULES, Modules[KrnlModsSize.NumberOfModules]);
108 PRTL_PROCESS_MODULES pKrnlMods = (PRTL_PROCESS_MODULES)RTMemAllocZ(cbKrnlMods);
109 if (RT_LIKELY(pKrnlMods))
110 {
111 rcNt = NtQuerySystemInformation(SystemModuleInformation, pKrnlMods, cbKrnlMods, NULL);
112 if (NT_SUCCESS(rcNt))
113 *ppKrnlMods = pKrnlMods;
114 else
115 rc = RTErrConvertFromNtStatus(rcNt);
116 }
117 else
118 rc = VERR_NO_MEMORY;
119 }
120 else
121 rc = RTErrConvertFromNtStatus(rcNt);
122
123 return rc;
124}
125
126/**
127 * Creates a new kernel module information record for the given module.
128 *
129 * @returns IPRT status code.
130 * @param pModInfo The kernel module information.
131 * @param phKrnlModInfo Where to store the handle to the kernel module information record
132 * on success.
133 */
134static int rtKrnlModWinInfoCreate(PRTL_PROCESS_MODULE_INFORMATION pModInfo, PRTKRNLMODINFO phKrnlModInfo)
135{
136 int rc = VINF_SUCCESS;
137 RT_NOREF2(pModInfo, phKrnlModInfo);
138 size_t cchFilePath = strlen((const char *)&pModInfo->FullPathName[0]) + 1;
139 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTKRNLMODINFOINT, achFilePath[cchFilePath]));
140 if (RT_LIKELY(pThis))
141 {
142 memcpy(&pThis->achFilePath[0], &pModInfo->FullPathName[0], cchFilePath);
143 pThis->cchFilePath = cchFilePath;
144 pThis->cRefs = 1;
145 pThis->cbKrnlMod = pModInfo->ImageSize;
146 pThis->uLoadAddr = (RTR0UINTPTR)pModInfo->ImageBase;
147 pThis->pszName = pModInfo->OffsetToFileName >= cchFilePath
148 ? NULL
149 : pThis->achFilePath + pModInfo->OffsetToFileName;
150
151 *phKrnlModInfo = pThis;
152 }
153 else
154 rc = VERR_NO_MEMORY;
155
156 return rc;
157}
158
159
160RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
161{
162 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
163 AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
164
165 int rc = VERR_NOT_IMPLEMENTED;
166
167 return rc;
168}
169
170
171RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
172{
173 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
174 AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
175
176 int rc = VERR_NOT_IMPLEMENTED;
177
178 return rc;
179}
180
181
182RTDECL(uint32_t) RTKrnlModLoadedGetCount(void)
183{
184 uint32_t cKrnlMods = 0;
185 RTL_PROCESS_MODULES ProcMods;
186
187 NTSTATUS rcNt = NtQuerySystemInformation(SystemModuleInformation, &ProcMods, sizeof(ProcMods), NULL);
188 if (NT_SUCCESS(rcNt) || rcNt == STATUS_INFO_LENGTH_MISMATCH)
189 cKrnlMods = ProcMods.NumberOfModules;
190
191 return cKrnlMods;
192}
193
194
195RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
196 uint32_t *pcEntries)
197{
198 if (cEntriesMax > 0)
199 AssertPtrReturn(pahKrnlModInfo, VERR_INVALID_POINTER);
200
201 PRTL_PROCESS_MODULES pKrnlMods = NULL;
202 int rc = rtKrnlModWinQueryKrnlMods(&pKrnlMods);
203 if (RT_SUCCESS(rc))
204 {
205 if (pKrnlMods->NumberOfModules <= cEntriesMax)
206 {
207 for (unsigned i = 0; i < pKrnlMods->NumberOfModules; i++)
208 {
209 pKrnlMods->Modules[i].FullPathName[255] = '\0'; /* Paranoia */
210 rc = rtKrnlModWinInfoCreate(&pKrnlMods->Modules[i], &pahKrnlModInfo[i]);
211 if (RT_FAILURE(rc))
212 {
213 while (i-- > 0)
214 RTKrnlModInfoRelease(pahKrnlModInfo[i]);
215 break;
216 }
217 }
218 }
219 else
220 rc = VERR_BUFFER_OVERFLOW;
221
222 if (pcEntries)
223 *pcEntries = pKrnlMods->NumberOfModules;
224
225 RTMemFree(pKrnlMods);
226 }
227
228 return rc;
229}
230
231
232RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo)
233{
234 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
235 AssertPtrReturn(pThis, UINT32_MAX);
236
237 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
238 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
239 return cRefs;
240}
241
242
243RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo)
244{
245 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
246 if (!pThis)
247 return 0;
248 AssertPtrReturn(pThis, UINT32_MAX);
249
250 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
251 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
252 if (cRefs == 0)
253 rtKrnlModInfoDestroy(pThis);
254 return cRefs;
255}
256
257
258RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo)
259{
260 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
261 AssertPtrReturn(pThis, 0);
262
263 return pThis->cRefKrnlMod;
264}
265
266
267RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo)
268{
269 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
270 AssertPtrReturn(pThis, NULL);
271
272 return pThis->pszName;
273}
274
275
276RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo)
277{
278 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
279 AssertPtrReturn(pThis, NULL);
280
281 return &pThis->achFilePath[0];
282}
283
284
285RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo)
286{
287 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
288 AssertPtrReturn(pThis, 0);
289
290 return pThis->cbKrnlMod;
291}
292
293
294RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo)
295{
296 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
297 AssertPtrReturn(pThis, 0);
298
299 return pThis->uLoadAddr;
300}
301
302
303RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
304 PRTKRNLMODINFO phKrnlModInfoRef)
305{
306 RT_NOREF3(hKrnlModInfo, idx, phKrnlModInfoRef);
307 return VERR_NOT_SUPPORTED;
308}
309
310
311RTDECL(int) RTKrnlModLoadByName(const char *pszName)
312{
313 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
314
315 return VERR_NOT_SUPPORTED;
316}
317
318
319RTDECL(int) RTKrnlModLoadByPath(const char *pszPath)
320{
321 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
322
323 return VERR_NOT_SUPPORTED;
324}
325
326
327RTDECL(int) RTKrnlModUnloadByName(const char *pszName)
328{
329 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
330
331 return VERR_NOT_SUPPORTED;
332}
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