HyperDbg Debugger
Loading...
Searching...
No Matches
pci-id.cpp File Reference

Provides runtime access to PCI ID database. More...

#include "pch.h"

Functions

CHARTrimWhitespace (CHAR *Str, UINT8 MaxLen)
 Trims whitespaces in passed string.
CHARToLower (CHAR *Str)
 Converts passed string to lowercase.
CHARReadLine (CHAR *DestBuffer, UINT64 CharLimit, CHAR **SrcBuffer)
 Read line from string. Treats SrcBuffer as a stream (similar to fgets and friends), i.e. updates SrcBuffer by number of characters read.
VendorGetVendorByIdStr (const CHAR *Filename, const CHAR *VendorId)
 Get Vendor by PCI ID, encoded in ASCII. Do not call directly - use GetVendorById() instead.
VOID FreeVendor (Vendor *VendorToFree)
 Frees Vendor and all of its members.
VOID FreePciIdDatabase ()
 Frees PciIdDatabaseBuffer.
VendorGetVendorById (UINT16 VendorId)
 Returns Vendor entry, including corresponding devices and subdevices.
DeviceGetDeviceFromVendor (Vendor *VendorToUse, UINT16 DeviceId)
 Returns Device entry corresponding to DeviceId.
SubDeviceGetSubDeviceFromDevice (Device *DeviceToUse, UINT16 SubVendorId, UINT16 SubDeviceId)
 Returns SubDevice entry corresponding to SubVendorId and DeviceId.

Detailed Description

Provides runtime access to PCI ID database.

Author
Bj�rn Ruytenberg (bjorn.nosp@m.@bjo.nosp@m.rnweb.nosp@m..nl)
Version
0.12
Date
2024-12-04

Function Documentation

◆ FreePciIdDatabase()

VOID FreePciIdDatabase ( )

Frees PciIdDatabaseBuffer.

Returns
VOID
289{
290 if (PciIdDatabaseBuffer != NULL)
291 {
292 free(PciIdDatabaseBuffer);
293 PciIdDatabaseBuffer = NULL;
294 }
295}
NULL()
Definition test-case-generator.py:530

◆ FreeVendor()

VOID FreeVendor ( Vendor * VendorToFree)

Frees Vendor and all of its members.

Parameters
VendorToFree
Returns
VOID
261{
262 if (VendorToFree == NULL)
263 return;
264
265 Device * CurrentDevice = VendorToFree->Devices;
266 while (CurrentDevice)
267 {
268 SubDevice * CurrentSubDevice = CurrentDevice->SubDevices;
269
270 while (CurrentSubDevice)
271 {
272 SubDevice * NextSubDevice = CurrentSubDevice->Next;
273 free(CurrentSubDevice);
274 CurrentSubDevice = NextSubDevice;
275 }
276
277 Device * NextDevice = CurrentDevice->Next;
278 free(CurrentDevice);
279 CurrentDevice = NextDevice;
280 }
281}
Definition pci-id.h:26
SubDevice * SubDevices
Definition pci-id.h:29
struct Device * Next
Definition pci-id.h:30
Definition pci-id.h:18
struct SubDevice * Next
Definition pci-id.h:22
Device * Devices
Definition pci-id.h:37

◆ GetDeviceFromVendor()

Device * GetDeviceFromVendor ( Vendor * VendorToUse,
UINT16 DeviceId )

Returns Device entry corresponding to DeviceId.

Parameters
VendorToUse
DeviceId
Returns
Device
340{
341 Device * CurrentDevice = NULL;
342 if (!VendorToUse)
343 {
344 return NULL;
345 }
346
347 CurrentDevice = VendorToUse->Devices;
348 while (CurrentDevice != NULL)
349 {
350 if (CurrentDevice->DeviceId == DeviceId)
351 {
352 return CurrentDevice;
353 }
354 CurrentDevice = CurrentDevice->Next;
355 }
356 return NULL;
357}
UINT16 DeviceId
Definition pci-id.h:27

◆ GetSubDeviceFromDevice()

SubDevice * GetSubDeviceFromDevice ( Device * DeviceToUse,
UINT16 SubVendorId,
UINT16 SubDeviceId )

Returns SubDevice entry corresponding to SubVendorId and DeviceId.

Parameters
DeviceToUse
SubVendorId
SubDeviceId
Returns
SubDevice
369{
370 SubDevice * CurrentSubDevice = NULL;
371 if (!DeviceToUse)
372 {
373 return NULL;
374 }
375
376 CurrentSubDevice = DeviceToUse->SubDevices;
377 while (CurrentSubDevice != NULL)
378 {
379 if (CurrentSubDevice->SubVendorId == SubVendorId && CurrentSubDevice->SubDeviceId == SubDeviceId)
380 {
381 return CurrentSubDevice;
382 }
383 CurrentSubDevice = CurrentSubDevice->Next;
384 }
385 return NULL;
386}
UINT16 SubDeviceId
Definition pci-id.h:20
UINT16 SubVendorId
Definition pci-id.h:19

◆ GetVendorById()

Vendor * GetVendorById ( UINT16 VendorId)

Returns Vendor entry, including corresponding devices and subdevices.

Use FreeVendor() on returned Vendor pointer after usage. First call will initialize database - call FreeDatabase() once done querying.

Parameters
VendorId
Returns
Vendor
306{
307 CHAR VendorIdAsStr[5];
308 CHAR ExecutablePath[MAX_PATH];
309 HMODULE hModule = GetModuleHandle(NULL);
310
311 snprintf(VendorIdAsStr, sizeof(VendorIdAsStr), "%04X", VendorId);
312 GetModuleFileName(hModule, ExecutablePath, sizeof(ExecutablePath));
313
314 // Extract executable name
315 CHAR * ExecutableName = strrchr(ExecutablePath, '\\');
316 if (ExecutableName != NULL)
317 {
318 ExecutableName++;
319 }
320 else
321 {
322 ExecutableName = ExecutablePath;
323 }
324
325 // Swap executable name for PCI_ID_DATABASE_PATH
326 strncpy(ExecutableName, PCI_ID_DATABASE_PATH, sizeof(PCI_ID_DATABASE_PATH));
327
328 return GetVendorByIdStr(ExecutablePath, ToLower(VendorIdAsStr));
329}
char CHAR
Definition BasicTypes.h:33
CHAR * ToLower(CHAR *Str)
Converts passed string to lowercase.
Definition pci-id.cpp:45
Vendor * GetVendorByIdStr(const CHAR *Filename, const CHAR *VendorId)
Get Vendor by PCI ID, encoded in ASCII. Do not call directly - use GetVendorById() instead.
Definition pci-id.cpp:90
#define PCI_ID_DATABASE_PATH
Definition pci-id.h:44

◆ GetVendorByIdStr()

Vendor * GetVendorByIdStr ( const CHAR * Filename,
const CHAR * VendorId )

Get Vendor by PCI ID, encoded in ASCII. Do not call directly - use GetVendorById() instead.

Parameters
Filename
VendorId
Returns
Vendor *
91{
92 Vendor * MatchedVendor = NULL;
93 BOOLEAN FoundVendorId = FALSE;
94 Device * LastDevice = NULL;
95 SubDevice * LastSubDevice = NULL;
96 CHAR * PciIdDbBufPtr = NULL;
97 CHAR Line[1024] = {'\0'};
98
99 if (!PciIdDatabaseBuffer)
100 {
101 FILE * f = fopen(Filename, "rb");
102 SIZE_T Length = 0;
103
104 if (f == NULL)
105 {
106 ShowMessages("Error: Cannot open file '%s': error %d\n", Filename, errno);
107 return NULL;
108 }
109
110 fseek(f, 0, SEEK_END);
111 Length = ftell(f);
112
113 PciIdDatabaseBuffer = (CHAR *)malloc(Length);
114 if (!PciIdDatabaseBuffer)
115 {
116 return NULL;
117 }
118
119 fseek(f, 0, SEEK_SET);
120 fread(PciIdDatabaseBuffer, 1, Length, f);
121 fclose(f);
122 }
123
124 PciIdDbBufPtr = PciIdDatabaseBuffer;
125
126 while (ReadLine(Line, sizeof(Line), &PciIdDbBufPtr) != NULL)
127 {
128 CHAR FormatStr[24];
129
130 // Skip comments and empty lines
131 if (Line[0] == '#' || Line[0] == '\0')
132 {
133 continue;
134 }
135
136 // Find vendor
137 // We assume PCI ID database comprises unique entries only, i.e. we return the first matching entry
138 if (Line[0] != '\t' && FoundVendorId == FALSE)
139 {
140 CHAR VendorBuf[PCI_ID_AS_STR_LENGTH + 1], VendorNameBuf[PCI_NAME_STR_LENGTH + 1];
141
142 snprintf(FormatStr, sizeof(FormatStr), "%%4s %%%d[^\n]", PCI_NAME_STR_LENGTH); // FormatStr = "%4s %PCI_NAME_STR_LENGTH[^\n]"
143 if (sscanf(Line, FormatStr, VendorBuf, VendorNameBuf) == 2)
144 {
145 if (strncmp(VendorBuf, VendorId, sizeof(VendorId)) == 0)
146 {
147 MatchedVendor = (Vendor *)malloc(sizeof(Vendor));
148 if (!MatchedVendor)
149 {
150 return NULL;
151 }
152
153 INT Result = sscanf(VendorBuf, "%hx", &(MatchedVendor->VendorId));
154 if (Result != 1)
155 {
156 return NULL;
157 }
158 strncpy_s(MatchedVendor->VendorName, sizeof(MatchedVendor->VendorName), TrimWhitespace(VendorNameBuf, PCI_NAME_STR_LENGTH), _TRUNCATE);
159 FoundVendorId = TRUE;
160 }
161 }
162 }
163 // Get all devices for vendor
164 else if (Line[0] == '\t' && Line[1] != '\t' && FoundVendorId == TRUE)
165 {
166 CHAR DeviceBuf[PCI_ID_AS_STR_LENGTH + 1], DeviceNameBuf[PCI_NAME_STR_LENGTH + 1];
167
168 snprintf(FormatStr, sizeof(FormatStr), "%%4s %%%d[^\n]", PCI_NAME_STR_LENGTH); // FormatStr = "%4s %PCI_NAME_STR_LENGTH[^\n]"
169 if (sscanf(Line + 1, FormatStr, DeviceBuf, DeviceNameBuf) == 2)
170 {
171 Device * NewDevice = (Device *)malloc(sizeof(Device));
172 if (!NewDevice)
173 {
174 FreeVendor(MatchedVendor);
175 return NULL;
176 }
177
178 int Result = sscanf(DeviceBuf, "%hx", &(NewDevice->DeviceId));
179 if (Result != 1)
180 {
181 FreeVendor(MatchedVendor);
182 return NULL;
183 }
184
185 strncpy_s(NewDevice->DeviceName, sizeof(NewDevice->DeviceName), TrimWhitespace(DeviceNameBuf, PCI_NAME_STR_LENGTH), _TRUNCATE);
186 NewDevice->SubDevices = NULL;
187 NewDevice->Next = NULL;
188
189 if (LastDevice)
190 {
191 LastDevice->Next = NewDevice;
192 }
193 else
194 {
195 MatchedVendor->Devices = NewDevice; // First device
196 }
197 LastDevice = NewDevice;
198 LastSubDevice = NULL;
199 }
200 }
201 // Get all subdevices for device
202 else if (Line[0] == '\t' && Line[1] == '\t' && FoundVendorId == TRUE && LastDevice)
203 {
204 CHAR SubVendorBuf[PCI_ID_AS_STR_LENGTH + 1], SubDeviceBuf[PCI_ID_AS_STR_LENGTH + 1], SubsystemNameBuf[PCI_NAME_STR_LENGTH + 1];
205
206 snprintf(FormatStr, sizeof(FormatStr), "%%4s %%4s %%%d[^\n]", PCI_NAME_STR_LENGTH); // FormatStr = "%4s %4s %PCI_NAME_STR_LENGTH[^\n]"
207 if (sscanf(Line + 2, FormatStr, SubVendorBuf, SubDeviceBuf, SubsystemNameBuf) == 3)
208 {
209 SubDevice * NewSubDevice = (SubDevice *)malloc(sizeof(SubDevice));
210 if (!NewSubDevice)
211 {
212 FreeVendor(MatchedVendor);
213 return NULL;
214 }
215
216 int Result = sscanf(SubVendorBuf, "%hx", &NewSubDevice->SubVendorId);
217 if (Result != 1)
218 {
219 FreeVendor(MatchedVendor);
220 return NULL;
221 }
222
223 Result = sscanf(SubDeviceBuf, "%hx", &NewSubDevice->SubDeviceId);
224 if (Result != 1)
225 {
226 FreeVendor(MatchedVendor);
227 return NULL;
228 }
229
230 strncpy_s(NewSubDevice->SubSystemName, sizeof(NewSubDevice->SubSystemName), TrimWhitespace(SubsystemNameBuf, PCI_NAME_STR_LENGTH), _TRUNCATE);
231 NewSubDevice->Next = NULL;
232
233 if (LastSubDevice)
234 {
235 LastSubDevice->Next = NewSubDevice;
236 }
237 else
238 {
239 LastDevice->SubDevices = NewSubDevice; // First subdevice
240 }
241 LastSubDevice = NewSubDevice;
242 }
243 }
244 else if (Line[0] != '\t' && FoundVendorId == TRUE) // We hit the next vendor entry, so we're done parsing
245 {
246 break;
247 }
248 }
249
250 return MatchedVendor;
251}
UCHAR BOOLEAN
Definition BasicTypes.h:35
int INT
Definition BasicTypes.h:43
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
f
Definition test-case-generator.py:581
CHAR * TrimWhitespace(CHAR *Str, UINT8 MaxLen)
Trims whitespaces in passed string.
Definition pci-id.cpp:24
VOID FreeVendor(Vendor *VendorToFree)
Frees Vendor and all of its members.
Definition pci-id.cpp:260
CHAR * ReadLine(CHAR *DestBuffer, UINT64 CharLimit, CHAR **SrcBuffer)
Read line from string. Treats SrcBuffer as a stream (similar to fgets and friends),...
Definition pci-id.cpp:67
#define PCI_NAME_STR_LENGTH
Definition pci-id.h:15
#define PCI_ID_AS_STR_LENGTH
Definition pci-id.h:14
CHAR DeviceName[PCI_NAME_STR_LENGTH]
Definition pci-id.h:28
CHAR SubSystemName[PCI_NAME_STR_LENGTH]
Definition pci-id.h:21
Definition pci-id.h:34
CHAR VendorName[PCI_NAME_STR_LENGTH]
Definition pci-id.h:36
UINT16 VendorId
Definition pci-id.h:35

◆ ReadLine()

CHAR * ReadLine ( CHAR * DestBuffer,
UINT64 CharLimit,
CHAR ** SrcBuffer )

Read line from string. Treats SrcBuffer as a stream (similar to fgets and friends), i.e. updates SrcBuffer by number of characters read.

Parameters
DestBuffer
CharLimit
SrcBuffer
Returns
CHAR*
68{
69 CHAR * Line = strchr(*SrcBuffer, '\n');
70 if (!Line)
71 {
72 return NULL;
73 }
74 else
75 {
76 strncpy_s(DestBuffer, CharLimit, *SrcBuffer, (Line - *SrcBuffer));
77 *SrcBuffer += (Line - *SrcBuffer + 1);
78 return *SrcBuffer;
79 }
80}

◆ ToLower()

CHAR * ToLower ( CHAR * Str)

Converts passed string to lowercase.

Parameters
Str
Returns
CHAR*
46{
47 UINT8 StrLength = (UINT8)strnlen_s(Str, PCI_ID_AS_STR_LENGTH);
48 CHAR * CurrentChar = Str;
49
50 while (CurrentChar < Str + StrLength)
51 {
52 *CurrentChar = tolower(*CurrentChar);
53 CurrentChar++;
54 }
55 return Str;
56}
unsigned char UINT8
Definition BasicTypes.h:52

◆ TrimWhitespace()

CHAR * TrimWhitespace ( CHAR * Str,
UINT8 MaxLen )

Trims whitespaces in passed string.

Parameters
Str
MaxLen
Returns
CHAR*
25{
26 CHAR * End;
27 while (*Str == ' ')
28 Str++; // Trim leading space
29 if (*Str == '\0')
30 return Str;
31 End = Str + strnlen_s(Str, MaxLen) - 1;
32 while (End > Str && (*End == ' ' || *End == '\n' || *End == '\r'))
33 End--;
34 *(End + 1) = '\0';
35 return Str;
36}