ReactOS  0.4.13-dev-99-g7e18b6d
id.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS PCI Bus Driver
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: drivers/bus/pci/pci/id.c
5  * PURPOSE: PCI Device Identification
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <pci.h>
12 #include <stdio.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* FUNCTIONS ******************************************************************/
18 
19 PWCHAR
20 NTAPI
23 {
25  ULONG TextLength;
27  ANSI_STRING MessageString;
30 
31  /* Find the message identifier in the message table */
32  MessageString.Buffer = NULL;
34  11, // RT_MESSAGETABLE
36  Identifier,
37  &Entry);
38  if (!NT_SUCCESS(Status)) return NULL;
39 
40  /* Check if the resource data is Unicode or ANSI */
41  if (Entry->Flags & MESSAGE_RESOURCE_UNICODE)
42  {
43  /* Subtract one space for the end-of-message terminator */
44  TextLength = Entry->Length -
46  sizeof(WCHAR);
47 
48  /* Grab the text */
49  Description = (PWCHAR)Entry->Text;
50 
51  /* Validate valid message length, ending with a newline character */
52  ASSERT(TextLength > 1);
53  ASSERT(Description[TextLength / sizeof(WCHAR)] == L'\n');
54 
55  /* Allocate the buffer to hold the message string */
56  Buffer = ExAllocatePoolWithTag(PagedPool, TextLength, 'BicP');
57  if (!Buffer) return NULL;
58 
59  /* Copy the message, minus the newline character, and terminate it */
60  RtlCopyMemory(Buffer, Entry->Text, TextLength - 1);
61  Buffer[TextLength / sizeof(WCHAR)] = UNICODE_NULL;
62 
63  /* Return the length to the caller, minus the terminating NULL */
64  if (Length) *Length = TextLength - 1;
65  }
66  else
67  {
68  /* Initialize the entry as a string */
69  RtlInitAnsiString(&MessageString, (PCHAR)Entry->Text);
70 
71  /* Remove the newline character */
72  MessageString.Length -= sizeof(CHAR);
73 
74  /* Convert it to Unicode */
76  Buffer = UnicodeString.Buffer;
77 
78  /* Return the length to the caller */
79  if (Length) *Length = UnicodeString.Length;
80  }
81 
82  /* Return the message buffer to the caller */
83  return Buffer;
84 }
85 
86 PWCHAR
87 NTAPI
89  IN UCHAR SubClass)
90 {
92  ULONG Identifier;
93 
94  /* The message identifier in the table is encoded based on the PCI class */
95  Identifier = (BaseClass << 8) | SubClass;
96 
97  /* Go grab the description message for this device */
98  Message = PciGetDescriptionMessage(Identifier, NULL);
99  if (!Message)
100  {
101  /* It wasn't found, allocate a buffer for a generic description */
102  Message = ExAllocatePoolWithTag(PagedPool, sizeof(L"PCI Device"), 'bicP');
103  if (Message) RtlCopyMemory(Message, L"PCI Device", sizeof(L"PCI Device"));
104  }
105 
106  /* Return the description message */
107  return Message;
108 }
109 
110 VOID
111 NTAPI
113 {
114  /* Initialize the sizes to zero and the pointer to the start of the buffer */
115  IdBuffer->TotalLength = 0;
116  IdBuffer->Count = 0;
117  IdBuffer->CharBuffer = IdBuffer->BufferData;
118 }
119 
120 ULONG
121 __cdecl
123  IN PCCH Format,
124  ...)
125 {
126  ULONG Size, Length;
128  va_list va;
129 
130  ASSERT(IdBuffer->Count < MAX_ANSI_STRINGS);
131 
132  /* Do the actual string formatting into the character buffer */
133  va_start(va, Format);
134  vsprintf(IdBuffer->CharBuffer, Format, va);
135  va_end(va);
136 
137  /* Initialize the ANSI_STRING that will hold this string buffer */
138  AnsiString = &IdBuffer->Strings[IdBuffer->Count];
139  RtlInitAnsiString(AnsiString, IdBuffer->CharBuffer);
140 
141  /* Calculate the final size of the string, in Unicode */
143 
144  /* Update hte buffer with the size,and update the character pointer */
145  IdBuffer->StringSize[IdBuffer->Count] = Size;
146  IdBuffer->TotalLength += Size;
147  Length = AnsiString->Length + sizeof(ANSI_NULL);
148  IdBuffer->CharBuffer += Length;
149 
150  /* Move to the next string for next time */
151  IdBuffer->Count++;
152 
153  /* Return the length */
154  return Length;
155 }
156 
157 ULONG
158 __cdecl
160  IN PCCH Format,
161  ...)
162 {
163  ULONG NextId, Size, Length, MaxLength;
165  va_list va;
166 
167  ASSERT(IdBuffer->Count);
168 
169  /* Choose the next static ANSI_STRING to use */
170  NextId = IdBuffer->Count - 1;
171 
172  /* Max length is from the end of the buffer up until the current pointer */
173  MaxLength = (PCHAR)(IdBuffer + 1) - IdBuffer->CharBuffer;
174 
175  /* Do the actual append, and return the length this string took */
176  va_start(va, Format);
177  Length = vsprintf(IdBuffer->CharBuffer - 1, Format, va);
178  va_end(va);
179  ASSERT(Length < MaxLength);
180 
181  /* Select the static ANSI_STRING, and update its length information */
182  AnsiString = &IdBuffer->Strings[NextId];
183  AnsiString->Length += Length;
184  AnsiString->MaximumLength += Length;
185 
186  /* Calculate the final size of the string, in Unicode */
188 
189  /* Update the buffer with the size, and update the character pointer */
190  IdBuffer->StringSize[NextId] = Size;
191  IdBuffer->TotalLength += Size;
192  IdBuffer->CharBuffer += Length;
193 
194  /* Return the size */
195  return Size;
196 }
197 
198 NTSTATUS
199 NTAPI
202  OUT PWCHAR *Buffer)
203 {
204  ULONG SubsysId;
205  CHAR VendorString[22];
207  PPCI_FDO_EXTENSION ParentExtension;
209  ULONG i, Size;
211  PANSI_STRING NextString;
213  PCI_ID_BUFFER IdBuffer;
214  PAGED_CODE();
215 
216  /* Assume failure */
218  *Buffer = NULL;
219 
220  /* Start with the genric vendor string, which is the vendor ID + device ID */
221  sprintf(VendorString,
222  "PCI\\VEN_%04X&DEV_%04X",
223  DeviceExtension->VendorId,
224  DeviceExtension->DeviceId);
225 
226  /* Initialize the PCI ID Buffer */
227  PciInitIdBuffer(&IdBuffer);
228 
229  /* Build the subsystem ID as shown in PCI ID Strings */
230  SubsysId = DeviceExtension->SubsystemVendorId | (DeviceExtension->SubsystemId << 16);
231 
232  /* Check what the caller is requesting */
233  switch (QueryType)
234  {
235  case BusQueryDeviceID:
236 
237  /* A single ID, the vendor string + the revision ID */
238  PciIdPrintf(&IdBuffer,
239  "%s&SUBSYS_%08X&REV_%02X",
240  VendorString,
241  SubsysId,
242  DeviceExtension->RevisionId);
243  break;
244 
245  case BusQueryHardwareIDs:
246 
247  /* First the vendor string + the subsystem ID + the revision ID */
248  PciIdPrintf(&IdBuffer,
249  "%s&SUBSYS_%08X&REV_%02X",
250  VendorString,
251  SubsysId,
252  DeviceExtension->RevisionId);
253 
254  /* Next, without the revision */
255  PciIdPrintf(&IdBuffer,
256  "%s&SUBSYS_%08X",
257  VendorString,
258  SubsysId);
259 
260  /* Next, the vendor string + the base class + sub class + progif */
261  PciIdPrintf(&IdBuffer,
262  "%s&CC_%02X%02X%02X",
263  VendorString,
264  DeviceExtension->BaseClass,
265  DeviceExtension->SubClass,
266  DeviceExtension->ProgIf);
267 
268  /* Next, without the progif */
269  PciIdPrintf(&IdBuffer,
270  "%s&CC_%02X%02X",
271  VendorString,
272  DeviceExtension->BaseClass,
273  DeviceExtension->SubClass);
274 
275  /* And finally, a terminator */
276  PciIdPrintf(&IdBuffer, "\0");
277  break;
278 
280 
281  /* First, the vendor + revision ID only */
282  PciIdPrintf(&IdBuffer,
283  "%s&REV_%02X",
284  VendorString,
285  DeviceExtension->RevisionId);
286 
287  /* Next, the vendor string alone */
288  PciIdPrintf(&IdBuffer, "%s", VendorString);
289 
290  /* Next, the vendor ID + the base class + the sub class + progif */
291  PciIdPrintf(&IdBuffer,
292  "PCI\\VEN_%04X&CC_%02X%02X%02X",
293  DeviceExtension->VendorId,
294  DeviceExtension->BaseClass,
295  DeviceExtension->SubClass,
296  DeviceExtension->ProgIf);
297 
298  /* Now without the progif */
299  PciIdPrintf(&IdBuffer,
300  "PCI\\VEN_%04X&CC_%02X%02X",
301  DeviceExtension->VendorId,
302  DeviceExtension->BaseClass,
303  DeviceExtension->SubClass);
304 
305  /* And then just the vendor ID itself */
306  PciIdPrintf(&IdBuffer,
307  "PCI\\VEN_%04X",
308  DeviceExtension->VendorId);
309 
310  /* Then the base class + subclass + progif, without any vendor */
311  PciIdPrintf(&IdBuffer,
312  "PCI\\CC_%02X%02X%02X",
313  DeviceExtension->BaseClass,
314  DeviceExtension->SubClass,
315  DeviceExtension->ProgIf);
316 
317  /* Next, without the progif */
318  PciIdPrintf(&IdBuffer,
319  "PCI\\CC_%02X%02X",
320  DeviceExtension->BaseClass,
321  DeviceExtension->SubClass);
322 
323  /* And finally, a terminator */
324  PciIdPrintf(&IdBuffer, "\0");
325  break;
326 
327  case BusQueryInstanceID:
328 
329  /* Start with a terminator */
330  PciIdPrintf(&IdBuffer, "\0");
331 
332  /* And then encode the device and function number */
333  PciIdPrintfAppend(&IdBuffer,
334  "%02X",
335  (DeviceExtension->Slot.u.bits.DeviceNumber << 3) |
336  DeviceExtension->Slot.u.bits.FunctionNumber);
337 
338  /* Loop every parent until the root */
339  ParentExtension = DeviceExtension->ParentFdoExtension;
340  while (!PCI_IS_ROOT_FDO(ParentExtension))
341  {
342  /* And encode the parent's device and function number as well */
344  PciIdPrintfAppend(&IdBuffer,
345  "%02X",
346  (PdoExtension->Slot.u.bits.DeviceNumber << 3) |
347  PdoExtension->Slot.u.bits.FunctionNumber);
348  }
349  break;
350 
351  default:
352 
353  /* Unknown query type */
354  DPRINT1("PciQueryId expected ID type = %d\n", QueryType);
355  return STATUS_NOT_SUPPORTED;
356  }
357 
358  /* Something should've been generated if this has been reached */
359  ASSERT(IdBuffer.Count > 0);
360 
361  /* Allocate the final string buffer to hold the ID */
364 
365  /* Build the UNICODE_STRING structure for it */
366  DPRINT1("PciQueryId(%d)\n", QueryType);
369 
370  /* Loop every ID in the buffer */
371  for (i = 0; i < IdBuffer.Count; i++)
372  {
373  /* Select the ANSI_STRING for the ID */
374  NextString = &IdBuffer.Strings[i];
375  DPRINT1(" <- \"%s\"\n", NextString->Buffer);
376 
377  /* Convert it to a UNICODE_STRING */
380 
381  /* Add it into the final destination buffer */
382  Size = IdBuffer.StringSize[i];
384  DestinationString.Buffer += (Size / sizeof(WCHAR));
385  }
386 
387  /* Return the buffer to the caller and return status (should be success) */
388  *Buffer = StringBuffer;
389  return Status;
390 }
391 
392 NTSTATUS
393 NTAPI
396  IN ULONG Locale,
397  OUT PWCHAR *Buffer)
398 {
399  PWCHAR MessageBuffer, LocationBuffer;
400  ULONG Length;
402 
403  UNREFERENCED_PARAMETER(Locale);
404 
405  /* Check what the caller is requesting */
406  switch (QueryType)
407  {
409 
410  /* Get the message from the resource section */
411  MessageBuffer = PciGetDeviceDescriptionMessage(PdoExtension->BaseClass,
412  PdoExtension->SubClass);
413 
414  /* Return it to the caller, and select proper status code */
415  *Buffer = MessageBuffer;
416  Status = MessageBuffer ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
417  break;
418 
420 
421  /* Get the message from the resource section */
422  MessageBuffer = PciGetDescriptionMessage(0x10000, &Length);
423  if (!MessageBuffer)
424  {
425  /* It should be there, but fail if it wasn't found for some reason */
427  break;
428  }
429 
430  /* Add space for a null-terminator, and allocate the buffer */
431  Length += 2 * sizeof(UNICODE_NULL);
432  LocationBuffer = ExAllocatePoolWithTag(PagedPool,
433  Length * sizeof(WCHAR),
434  'BicP');
435  *Buffer = LocationBuffer;
436 
437  /* Check if the allocation succeeded */
438  if (LocationBuffer)
439  {
440  /* Build the location string based on bus, function, and device */
441  swprintf(LocationBuffer,
442  MessageBuffer,
443  PdoExtension->ParentFdoExtension->BaseBus,
444  PdoExtension->Slot.u.bits.FunctionNumber,
445  PdoExtension->Slot.u.bits.DeviceNumber);
446  }
447 
448  /* Free the original string from the resource section */
449  ExFreePoolWithTag(MessageBuffer, 0);
450 
451  /* Select the correct status */
453  break;
454 
455  default:
456 
457  /* Anything else is unsupported */
459  break;
460  }
461 
462  /* Return whether or not a device text string was indeed found */
463  return Status;
464 }
465 
466 /* EOF */
signed char * PCHAR
Definition: retypes.h:7
#define MESSAGE_RESOURCE_UNICODE
Definition: rtltypes.h:354
#define IN
Definition: typedefs.h:38
Definition: rtltypes.h:1827
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
*BytesInUnicodeString PWCH UnicodeString
Definition: rtlfuncs.h:1980
ULONG StringSize[MAX_ANSI_STRINGS]
Definition: pci.h:426
struct _Entry Entry
Definition: kefuncs.h:640
#define __cdecl
Definition: accygwin.h:79
PWCHAR NTAPI PciGetDescriptionMessage(IN ULONG Identifier, OUT PULONG Length)
Definition: id.c:21
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define LANG_NEUTRAL
Definition: nls.h:22
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI PciQueryId(IN PPCI_PDO_EXTENSION DeviceExtension, IN BUS_QUERY_ID_TYPE QueryType, OUT PWCHAR *Buffer)
Definition: id.c:200
PVOID DriverStart
Definition: iotypes.h:2170
NTSYSAPI NTSTATUS NTAPI RtlFindMessage(_In_ PVOID BaseAddress, _In_ ULONG Type, _In_ ULONG Language, _In_ ULONG MessageId, _Out_ PMESSAGE_RESOURCE_ENTRY *MessageResourceEntry)
static const WCHAR Description[]
Definition: oid.c:1266
uint16_t * PWCHAR
Definition: typedefs.h:54
enum _DEVICE_TEXT_TYPE DEVICE_TEXT_TYPE
#define PAGED_CODE()
Definition: video.h:57
ULONG Count
Definition: pci.h:424
struct _PCI_FDO_EXTENSION * ParentFdoExtension
Definition: pci.h:204
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define sprintf(buf, format,...)
Definition: sprintf.c:55
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
void * Buffer
Definition: sprintf.c:453
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define va_end(ap)
Definition: acmsvcex.h:90
#define UNICODE_NULL
#define ANSI_NULL
PVOID DeviceExtension
Definition: env_spec_w32.h:418
_Out_ _Inout_ POEM_STRING DestinationString
Definition: rtlfuncs.h:1869
smooth NULL
Definition: ftsmooth.c:416
char * va_list
Definition: acmsvcex.h:78
Definition: bufpool.h:45
#define PCHAR
Definition: match.c:90
CONST CHAR * PCCH
Definition: ntbasedef.h:399
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define swprintf(buf, format,...)
Definition: sprintf.c:56
ULONG __cdecl PciIdPrintfAppend(IN PPCI_ID_BUFFER IdBuffer, IN PCCH Format,...)
Definition: id.c:159
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Must_inspect_result_ _In_ KTMOBJECT_TYPE QueryType
Definition: nttmapi.h:404
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
CHAR Message[80]
Definition: alive.c:5
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
NTSTATUS NTAPI PciQueryDeviceText(IN PPCI_PDO_EXTENSION PdoExtension, IN DEVICE_TEXT_TYPE QueryType, IN ULONG Locale, OUT PWCHAR *Buffer)
Definition: id.c:394
#define MAX_ANSI_STRINGS
Definition: pci.h:85
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
#define PCI_IS_ROOT_FDO(x)
Definition: pci.h:30
PDRIVER_OBJECT PciDriverObject
Definition: init.c:19
NTSYSAPI DWORD WINAPI RtlAnsiStringToUnicodeSize(const STRING *)
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
#define va_start(ap, A)
Definition: acmsvcex.h:91
VOID NTAPI PciInitIdBuffer(IN PPCI_ID_BUFFER IdBuffer)
Definition: id.c:112
#define DPRINT1
Definition: precomp.h:8
PDEVICE_OBJECT PhysicalDeviceObject
Definition: pci.h:198
ULONG TotalLength
Definition: pci.h:427
#define OUT
Definition: typedefs.h:39
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
ULONG __cdecl PciIdPrintf(IN PPCI_ID_BUFFER IdBuffer, IN PCCH Format,...)
Definition: id.c:122
PWCHAR NTAPI PciGetDeviceDescriptionMessage(IN UCHAR BaseClass, IN UCHAR SubClass)
Definition: id.c:88
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
ANSI_STRING Strings[MAX_ANSI_STRINGS]
Definition: pci.h:425
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned short MaximumLength
Definition: sprintf.c:452
#define CHAR(Char)
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
base of all file and directory entries
Definition: entries.h:82
char * Text
Definition: combotst.c:136