VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • 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 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - Kernel module, Windows.
4 */
5
6/*
7 * Copyright (C) 2017-2024 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 * @param pThis The record to destroy.
84 */
85static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
86{
87 RTMemFree(pThis);
88}
89
90
91/**
92 * Queries the complete kernel modules structure and returns a pointer to it.
93 *
94 * @returns IPRT status code.
95 * @param ppKrnlMods Where to store the pointer to the kernel module list on success.
96 * Free with RTMemFree().
97 */
98static int rtKrnlModWinQueryKrnlMods(PRTL_PROCESS_MODULES *ppKrnlMods)
99{
100 int rc = VINF_SUCCESS;
101 RTL_PROCESS_MODULES KrnlModsSize;
102
103 NTSTATUS rcNt = NtQuerySystemInformation(SystemModuleInformation, &KrnlModsSize, sizeof(KrnlModsSize), NULL);
104 if (NT_SUCCESS(rcNt) || rcNt == STATUS_INFO_LENGTH_MISMATCH)
105 {
106 ULONG cbKrnlMods = RT_UOFFSETOF_DYN(RTL_PROCESS_MODULES, Modules[KrnlModsSize.NumberOfModules]);
107 PRTL_PROCESS_MODULES pKrnlMods = (PRTL_PROCESS_MODULES)RTMemAllocZ(cbKrnlMods);
108 if (RT_LIKELY(pKrnlMods))
109 {
110 rcNt = NtQuerySystemInformation(SystemModuleInformation, pKrnlMods, cbKrnlMods, NULL);
111 if (NT_SUCCESS(rcNt))
112 *ppKrnlMods = pKrnlMods;
113 else
114 rc = RTErrConvertFromNtStatus(rcNt);
115 }
116 else
117 rc = VERR_NO_MEMORY;
118 }
119 else
120 rc = RTErrConvertFromNtStatus(rcNt);
121
122 return rc;
123}
124
125/**
126 * Creates a new kernel module information record for the given module.
127 *
128 * @returns IPRT status code.
129 * @param pModInfo The kernel module information.
130 * @param phKrnlModInfo Where to store the handle to the kernel module information record
131 * on success.
132 */
133static int rtKrnlModWinInfoCreate(PRTL_PROCESS_MODULE_INFORMATION pModInfo, PRTKRNLMODINFO phKrnlModInfo)
134{
135 int rc = VINF_SUCCESS;
136 RT_NOREF2(pModInfo, phKrnlModInfo);
137 size_t cchFilePath = strlen((const char *)&pModInfo->FullPathName[0]) + 1;
138 PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(RT_UOFFSETOF_DYN(RTKRNLMODINFOINT, achFilePath[cchFilePath]));
139 if (RT_LIKELY(pThis))
140 {
141 memcpy(&pThis->achFilePath[0], &pModInfo->FullPathName[0], cchFilePath);
142 pThis->cchFilePath = cchFilePath;
143 pThis->cRefs = 1;
144 pThis->cbKrnlMod = pModInfo->ImageSize;
145 pThis->uLoadAddr = (RTR0UINTPTR)pModInfo->ImageBase;
146 pThis->pszName = pModInfo->OffsetToFileName >= cchFilePath
147 ? NULL
148 : pThis->achFilePath + pModInfo->OffsetToFileName;
149
150 *phKrnlModInfo = pThis;
151 }
152 else
153 rc = VERR_NO_MEMORY;
154
155 return rc;
156}
157
158
159RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
160{
161 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
162 AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
163
164 int rc = VERR_NOT_IMPLEMENTED;
165
166 return rc;
167}
168
169
170RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
171{
172 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
173 AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
174
175 int rc = VERR_NOT_IMPLEMENTED;
176
177 return rc;
178}
179
180
181RTDECL(uint32_t) RTKrnlModLoadedGetCount(void)
182{
183 uint32_t cKrnlMods = 0;
184 RTL_PROCESS_MODULES ProcMods;
185
186 NTSTATUS rcNt = NtQuerySystemInformation(SystemModuleInformation, &ProcMods, sizeof(ProcMods), NULL);
187 if (NT_SUCCESS(rcNt) || rcNt == STATUS_INFO_LENGTH_MISMATCH)
188 cKrnlMods = ProcMods.NumberOfModules;
189
190 return cKrnlMods;
191}
192
193
194RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
195 uint32_t *pcEntries)
196{
197 if (cEntriesMax > 0)
198 AssertPtrReturn(pahKrnlModInfo, VERR_INVALID_POINTER);
199
200 PRTL_PROCESS_MODULES pKrnlMods = NULL;
201 int rc = rtKrnlModWinQueryKrnlMods(&pKrnlMods);
202 if (RT_SUCCESS(rc))
203 {
204 if (pKrnlMods->NumberOfModules <= cEntriesMax)
205 {
206 for (unsigned i = 0; i < pKrnlMods->NumberOfModules; i++)
207 {
208 pKrnlMods->Modules[i].FullPathName[255] = '\0'; /* Paranoia */
209 rc = rtKrnlModWinInfoCreate(&pKrnlMods->Modules[i], &pahKrnlModInfo[i]);
210 if (RT_FAILURE(rc))
211 {
212 while (i-- > 0)
213 RTKrnlModInfoRelease(pahKrnlModInfo[i]);
214 break;
215 }
216 }
217 }
218 else
219 rc = VERR_BUFFER_OVERFLOW;
220
221 if (pcEntries)
222 *pcEntries = pKrnlMods->NumberOfModules;
223
224 RTMemFree(pKrnlMods);
225 }
226
227 return rc;
228}
229
230
231RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo)
232{
233 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
234 AssertPtrReturn(pThis, UINT32_MAX);
235
236 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
237 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
238 return cRefs;
239}
240
241
242RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo)
243{
244 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
245 if (!pThis)
246 return 0;
247 AssertPtrReturn(pThis, UINT32_MAX);
248
249 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
250 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
251 if (cRefs == 0)
252 rtKrnlModInfoDestroy(pThis);
253 return cRefs;
254}
255
256
257RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo)
258{
259 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
260 AssertPtrReturn(pThis, 0);
261
262 return pThis->cRefKrnlMod;
263}
264
265
266RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo)
267{
268 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
269 AssertPtrReturn(pThis, NULL);
270
271 return pThis->pszName;
272}
273
274
275RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo)
276{
277 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
278 AssertPtrReturn(pThis, NULL);
279
280 return &pThis->achFilePath[0];
281}
282
283
284RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo)
285{
286 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
287 AssertPtrReturn(pThis, 0);
288
289 return pThis->cbKrnlMod;
290}
291
292
293RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo)
294{
295 PRTKRNLMODINFOINT pThis = hKrnlModInfo;
296 AssertPtrReturn(pThis, 0);
297
298 return pThis->uLoadAddr;
299}
300
301
302RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
303 PRTKRNLMODINFO phKrnlModInfoRef)
304{
305 RT_NOREF3(hKrnlModInfo, idx, phKrnlModInfoRef);
306 return VERR_NOT_SUPPORTED;
307}
308
309
310RTDECL(int) RTKrnlModLoadByName(const char *pszName)
311{
312 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
313
314 return VERR_NOT_SUPPORTED;
315}
316
317
318RTDECL(int) RTKrnlModLoadByPath(const char *pszPath)
319{
320 AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
321
322 return VERR_NOT_SUPPORTED;
323}
324
325
326RTDECL(int) RTKrnlModUnloadByName(const char *pszName)
327{
328 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
329
330 return VERR_NOT_SUPPORTED;
331}
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