ReactOS  0.4.15-dev-309-g7c8d563
smbios.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS System Control Panel Applet
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: dll/cpl/sysdm/smbios.c
5  * PURPOSE: Retrieve device or motherboard name identifier from DMI/SMBIOS
6  * COPYRIGHT: Copyright 2018-2020 Stanislav Motylkov <x86corez@gmail.com>
7  *
8  */
9 
10 #include "precomp.h"
11 
12 #include <strsafe.h>
13 #include <udmihelp.h>
14 
15 typedef struct GENERIC_NAME
16 {
20 } GENERIC_NAME;
21 
22 typedef struct VENDOR_LONG_NAME
23 {
27 
28 typedef struct REDUNDANT_WORD
29 {
33 
34 static
35 BOOL
37  _In_ WCHAR chr)
38 {
39  return (chr <= L' ' || chr == L'.' || chr == L',');
40 }
41 
42 static
44 {
45  PCHAR c = DmiString;
46  if (!c)
47  {
48  return FALSE;
49  }
50  while (*c)
51  {
52  if (*c >= '0' && *c <= '9')
53  {
54  c++;
55  }
56  else
57  {
58  return FALSE;
59  }
60  }
61  return TRUE;
62 }
63 
64 /*
65  * Trim redundant characters
66  */
67 static
68 VOID
70  _Inout_ PWSTR pStr)
71 {
72  SIZE_T Length;
73  UINT i = 0;
74 
75  if (!pStr)
76  return;
77 
78  Length = wcslen(pStr);
79  if (Length == 0)
80  return;
81 
82  /* Trim leading characters */
83  while (i < Length && IsPunctuation(pStr[i]))
84  {
85  i++;
86  }
87 
88  if (i > 0)
89  {
90  Length -= i;
91  memmove(pStr, pStr + i, (Length + 1) * sizeof(WCHAR));
92  }
93 
94  /* Trim trailing characters */
95  while (Length && IsPunctuation(pStr[Length-1]))
96  {
97  pStr[Length-1] = L'\0';
98  --Length;
99  }
100 }
101 
102 /*
103  * Case insensitive variant of wcsstr
104  */
105 static
106 wchar_t * wcsistr(const wchar_t *s, const wchar_t *b)
107 {
108  wchar_t *x;
109  wchar_t *y;
110  wchar_t *c;
111  x = (wchar_t *)s;
112  while (*x)
113  {
114  if (towlower(*x) == towlower(*b))
115  {
116  y = x;
117  c = (wchar_t *)b;
118  while (*y && *c && towlower(*y) == towlower(*c))
119  {
120  c++;
121  y++;
122  }
123  if (!*c)
124  return x;
125  }
126  x++;
127  }
128  return NULL;
129 }
130 
131 static
132 wchar_t * wcsistr_plus(const wchar_t *s, wchar_t *b)
133 {
134  wchar_t * result = wcsistr(s, b);
135  UINT len = wcslen(b);
136  // workarounds
137  if (!result && b[len - 1] == L' ' && wcschr(s, L',') != NULL)
138  {
139  b[len - 1] = L',';
140  result = wcsistr(s, b);
141  b[len - 1] = L' ';
142  if (!result)
143  {
144  b[0] = L',';
145  result = wcsistr(s, b);
146  b[0] = L' ';
147  }
148  }
149  if (!result && b[len - 1] == L' ' && wcschr(s, L'(') != NULL)
150  {
151  b[len - 1] = L'(';
152  result = wcsistr(s, b);
153  b[len - 1] = L' ';
154  }
155  if (!result && b[len - 1] == L' ' && wcschr(s, L'_') != NULL)
156  {
157  b[0] = L'_';
158  result = wcsistr(s, b);
159  b[0] = L' ';
160  }
161  if (!result && b[0] == L' ' && b[len - 1] == L' ' && wcschr(s, L')') != NULL)
162  {
163  b[0] = L')';
164  result = wcsistr(s, b);
165  if (!result && wcschr(s, L'.'))
166  {
167  b[len - 1] = L'.';
168  result = wcsistr(s, b);
169  b[len - 1] = L' ';
170  }
171  b[0] = L' ';
172  }
173  return result;
174 }
175 
176 /*
177  * Replaces full word with another shorter word
178  */
179 static
181  _Inout_ PWSTR pwStr,
182  _In_ PCWSTR pwFind,
183  _In_ PCWSTR pwReplace,
184  _In_ BOOL bReplaceFirstWord)
185 {
186  PWSTR pwsStr, pwsFind, pwsReplace, pwsBuf = NULL;
187  SIZE_T lenStr;
188  SIZE_T lenFind;
189  SIZE_T lenReplace;
190 
191  if (!pwStr || !pwFind || !pwReplace ||
192  wcslen(pwStr) == 0 ||
193  wcslen(pwFind) == 0 ||
194  wcslen(pwFind) < wcslen(pwReplace))
195  {
196  return;
197  }
198  lenStr = wcslen(pwStr) + 2 + 1;
199  lenFind = wcslen(pwFind) + 2 + 1;
200  lenReplace = wcslen(pwReplace) + 2 + 1;
201 
202  pwsStr = HeapAlloc(GetProcessHeap(), 0, lenStr * sizeof(WCHAR));
203  if (!pwsStr)
204  {
205  return;
206  }
207  StringCchCopyW(pwsStr, lenStr, L" ");
208  StringCchCatW(pwsStr, lenStr, pwStr);
209  StringCchCatW(pwsStr, lenStr, L" ");
210 
211  pwsFind = HeapAlloc(GetProcessHeap(), 0, lenFind * sizeof(WCHAR));
212  if (!pwsFind)
213  {
214  goto freeStr;
215  }
216  StringCchCopyW(pwsFind, lenFind, L" ");
217  StringCchCatW(pwsFind, lenFind, pwFind);
218  StringCchCatW(pwsFind, lenFind, L" ");
219 
220  if (!(pwsBuf = wcsistr_plus(pwsStr, pwsFind)))
221  {
222  goto freeFind;
223  }
224  if (!bReplaceFirstWord && pwsBuf - pwsStr < 2)
225  {
226  goto freeFind;
227  }
228 
229  pwsReplace = HeapAlloc(GetProcessHeap(), 0, lenReplace * sizeof(WCHAR));
230  if (!pwsReplace)
231  {
232  goto freeFind;
233  }
234  StringCchCopyW(pwsReplace, lenReplace, L" ");
235  StringCchCatW(pwsReplace, lenReplace, pwReplace);
236  StringCchCatW(pwsReplace, lenReplace, L" ");
237 
238  do
239  {
240  // replace substring
241  memmove(pwsBuf, pwsReplace, (lenReplace - 1) * sizeof(WCHAR));
242  // shift characters
243  memmove(pwsBuf + lenReplace - (wcslen(pwReplace) > 0 ? 1 : 2), pwsBuf + lenFind - 1, (lenStr - lenFind - (pwsBuf - pwsStr) + 1) * sizeof(WCHAR));
244  }
245  while ((pwsBuf = wcsistr_plus(pwsStr, pwsFind)) != NULL);
246 
247  TrimDmiStringW(pwsStr);
248  StringCchCopyW(pwStr, wcslen(pwStr), pwsStr);
249 
250  HeapFree(GetProcessHeap(), 0, pwsReplace);
251 freeFind:
252  HeapFree(GetProcessHeap(), 0, pwsFind);
253 freeStr:
254  HeapFree(GetProcessHeap(), 0, pwsStr);
255 }
256 
257 static
259 {
260  static const GENERIC_NAME Vendors[] =
261  {
262  // some ASUS boards
263  { L"To Be Filled By O.E.M.", FALSE, TRUE },
264  { L"To Be Filled By O.E.M", FALSE, TRUE },
265  { L"System manufacturer", FALSE, TRUE },
266  // some Gigabyte boards
267  { L"Default string", TRUE, TRUE },
268  { L"LTD Delovoy Office", TRUE, FALSE },
269  { L"Motherboard by ZOTAC", TRUE, FALSE },
270  // various boards
271  { L"Type2 - Board Manufacturer", TRUE, TRUE },
272  { L"Type2 - Board Vendor Name1", TRUE, TRUE },
273  { L"BASE_BOARD_MANUFACTURER", TRUE, TRUE },
274  { L"$(DEFAULT_STRING)", TRUE, TRUE },
275  { L"DEPO Computers", TRUE, FALSE },
276  { L"-", TRUE, TRUE },
277  { L"N/A", TRUE, TRUE },
278  { L"OEM", TRUE, TRUE },
279  { L"O.E.M", TRUE, TRUE },
280  { L"empty", TRUE, TRUE },
281  { L"insyde", TRUE, FALSE },
282  { L"Unknow", TRUE, TRUE },
283  { L"Not Applicable", TRUE, TRUE },
284  // distinguish between Oracle and older VirtualBox releases (Sun, etc.)
285  { L"innotek GmbH", TRUE, FALSE },
286  };
287  static const GENERIC_NAME Devices[] =
288  {
289  // some ASUS boards
290  { L"To Be Filled By O.E.M.", FALSE, TRUE },
291  { L"To Be Filled By O.E.M", FALSE, TRUE },
292  { L"All Series", TRUE, TRUE },
293  { L"System Product Name", TRUE, TRUE },
294  { L"System Name", TRUE, TRUE },
295  // some Gigabyte boards
296  { L"Default string", TRUE, TRUE },
297  // some MSI boards
298  { L"Please change product name", TRUE, TRUE },
299  // some Intel boards
300  { L"Computer", TRUE, TRUE },
301  { L"ChiefRiver Platform", TRUE, FALSE },
302  { L"OakTrail Platform", TRUE, FALSE },
303  { L"SharkBay Platform", TRUE, FALSE },
304  { L"HuronRiver Platform", TRUE, FALSE },
305  { L"SandyBridge Platform", TRUE, FALSE },
306  { L"Broadwell Platform", TRUE, FALSE },
307  { L"Kabylake Platform", TRUE, FALSE },
308  { L"Sabine Platform", TRUE, FALSE },
309  // various boards
310  { L"Base Board Product Name", TRUE, TRUE },
311  { L"Base Board Version", TRUE, TRUE },
312  { L"Type2 - Board Product Name1", TRUE, TRUE },
313  { L"Type2 - Board Product Name", TRUE, TRUE },
314  { L"Type2 - Board Version", TRUE, TRUE },
315  { L"MODEL_NAME", TRUE, TRUE },
316  { L"$(DEFAULT_STRING)", TRUE, TRUE },
317  { L"*", TRUE, TRUE },
318  { L"T", TRUE, TRUE },
319  { L"GEG", TRUE, TRUE },
320  { L"N/A", TRUE, TRUE },
321  { L"---", TRUE, TRUE },
322  { L"OEM", TRUE, TRUE },
323  { L"INVA", TRUE, TRUE },
324  { L"O.E.M", TRUE, TRUE },
325  { L"empty", TRUE, TRUE },
326  { L"DNSNB", TRUE, FALSE },
327  { L"12345", TRUE, FALSE },
328  { L"``````", TRUE, TRUE },
329  { L"Uknown", TRUE, TRUE },
330  { L"Desktop", FALSE, TRUE },
331  { L"Invalid", FALSE, TRUE },
332  { L"Reserved", TRUE, TRUE },
333  { L"Not Applicable", TRUE, TRUE },
334  { L"HaierComputer", TRUE, FALSE },
335  { L"DEPO Computers", TRUE, FALSE },
336  { L"InsydeH2O EFI BIOS", TRUE, TRUE },
337  { L"HP All-in-One", TRUE, FALSE },
338  { L"MP Server", TRUE, FALSE },
339  { L"0000000000", TRUE, TRUE },
340  // some Foxconn boards
341  { L"Aquarius Pro, Std, Elt Series", TRUE, FALSE },
342  // some ASUS server boards
343  { L"Aquarius Server", TRUE, FALSE },
344  { L"Aquarius Server G2", TRUE, FALSE },
345  // some Supermicro server boards
346  { L"Super Server", TRUE, FALSE },
347  // some Positivo devices
348  { L"POSITIVO MOBILE", FALSE, FALSE },
349  };
350  BOOL bMatch;
351  UINT i;
352 
353  if (bRemove)
354  {
355  *bRemove = FALSE;
356  }
357  for (i = 0; i < _countof(Vendors); i++)
358  {
359  if (!ven)
360  {
361  break;
362  }
363  if (Vendors[i].bCaseSensitive)
364  {
365  bMatch = !wcscmp(ven, Vendors[i].pwName);
366  }
367  else
368  {
369  bMatch = !wcsicmp(ven, Vendors[i].pwName);
370  }
371  if (bMatch)
372  {
373  if (bRemove)
374  {
375  *bRemove = Vendors[i].bRemove;
376  }
377  return TRUE;
378  }
379  }
380 
381  for (i = 0; i < _countof(Devices); i++)
382  {
383  if (!dev)
384  {
385  break;
386  }
387  if (Devices[i].bCaseSensitive)
388  {
389  bMatch = !wcscmp(dev, Devices[i].pwName);
390  }
391  else
392  {
393  bMatch = !wcsicmp(dev, Devices[i].pwName);
394  }
395  if (bMatch)
396  {
397  if (bRemove)
398  {
399  *bRemove = Devices[i].bRemove;
400  }
401  return TRUE;
402  }
403  }
404  return FALSE;
405 }
406 
407 static
408 void AppendSystemFamily(PWSTR pBuf, SIZE_T cchBuf, PCHAR * DmiStrings, PWSTR dev)
409 {
410  static const PCSTR KnownFamilies[] =
411  {
412  "Eee PC", // ASUS
413  "ThinkPad", // Lenovo
414  "IdeaPad", // Lenovo
415  "IdeaCentre", // Lenovo
416  };
417  static const PCWSTR Aliases[] =
418  {
419  NULL,
420  NULL,
421  NULL,
422  L"IdeaCenter",
423  };
424  UINT i;
425  WCHAR wideStr[128];
426 
427  for (i = 0; i < _countof(KnownFamilies); i++)
428  {
429  StringCchPrintfW(wideStr, _countof(wideStr), L"%S", KnownFamilies[i]);
430 
431  if (wcsistr(dev, wideStr) == NULL &&
432  (!Aliases[i] || wcsistr(dev, Aliases[i]) == NULL) &&
433  DmiStrings[SYS_FAMILY] != NULL &&
434  !stricmp(DmiStrings[SYS_FAMILY], KnownFamilies[i]))
435  {
436  if (wcslen(pBuf) > 0 && wcslen(dev) > 0)
437  {
438  StringCchCatW(pBuf, cchBuf, L" ");
439  }
440  StringCchCatW(pBuf, cchBuf, wideStr);
441  }
442  }
443 }
444 
445 static
447 {
448  PCHAR c = DmiString;
449  if (!c)
450  {
451  return FALSE;
452  }
453  while (*c)
454  {
455  if (*c >= 0x20 && *c <= 0x7e)
456  {
457  c++;
458  }
459  else
460  {
461  *c = 0;
462  return TRUE;
463  }
464  }
465  return FALSE;
466 }
467 
468 /* TrimNonPrintable function wrapper. It does special preprocessing
469  * so the function returns FALSE in some corner cases, making the parser
470  * use system strings anyway (instead of board strings). */
471 static
473 {
474  PCHAR c;
475 
476  if (!DmiString)
477  {
478  return FALSE;
479  }
480 
481  /* Special handling for HP with broken revision */
482  c = strstr(DmiString, "(\xFF\xFF");
483  if (c > DmiString)
484  {
485  *c = 0;
486  }
487 
488  return TrimNonPrintable(DmiString);
489 }
490 
492 {
493  static const VENDOR_LONG_NAME LongNames[] =
494  {
495  { L"ASUSTeK", L"ASUS" },
496  { L"First International Computer", L"FIC" },
497  { L"Hewlett-Packard", L"HP" },
498  { L"MICRO-STAR", L"MSI" },
499  { L"SGI.COM", L"SGI" },
500  { L"Silicon Graphics International", L"SGI" },
501  { L"Intel(R) Client Systems", L"Intel" },
502  { L"InformationComputerSystems", L"ICS" },
503  { L"Bernecker + Rainer Industrie-Elektronik", L"Bernecker & Rainer" },
504  { L"CHUWI INNOVATION AND TECHNOLOGY", L"CHUWI" },
505  { L"CHUWI INNOVATION LIMITED", L"CHUWI" },
506  { L"CHUWI INNOVATION LIMITED", L"CHUWI" },
507  { L"http://www.abit.com.tw/", L"ABIT" },
508  { L"http:\\\\www.abit.com.tw", L"ABIT" },
509  { L"www.abit.com.tw", L"ABIT" },
510  { L"CASPER BILGISAYAR SISTEMLERI A.S", L"Casper" },
511  { L"Colorful Technology And Development", L"Colorful" },
512  { L"Colorful Yu Gong Technology And Development", L"Colorful Yu Gong" },
513  { L"HaierComputer", L"Haier" },
514  { L"Haier Information Technology (Shen Zhen)", L"Haier" },
515  { L"HASEECOMPUTERS", L"Hasee" },
516  { L"HELIOS BUSINESS COMPUTER", L"HELIOS" },
517  { L"Shanghai Zongzhi InfoTech", L"Zongzhi" },
518  { L"TSING HUA TONGFANG CO.,LTD", L"TSINGHUA TONGFANG" },
519  { L"Yeston Digital Technology Co.,LTD", L"Yeston" },
520  };
521  static const REDUNDANT_WORD RedundantWords[] =
522  {
523  { L"Corporation", FALSE },
524  { L"Communication", FALSE },
525  { L"Computer", FALSE },
526  { L"Computers", FALSE },
527  { L"Group", FALSE },
528  { L"Cloud", FALSE },
529  { L"Center", FALSE },
530  { L"Systems", FALSE },
531  { L"Microsystems", FALSE },
532  { L"Infosystems", FALSE },
533  { L"Digital", FALSE },
534  { L"Electronics", FALSE },
535  { L"Electric", FALSE },
536  { L"Elektronik", FALSE },
537  { L"Software", FALSE },
538  { L"Foundation", FALSE },
539  { L"International", FALSE },
540  { L"Interantonal", FALSE }, // on purpose (some MSI boards)
541  { L"INTERANTIONAL", FALSE }, // on purpose (some MSI boards)
542  { L"Industrial", FALSE },
543  { L"Industrie", FALSE },
544  { L"Information", FALSE },
545  { L"Informatica", FALSE },
546  { L"Produkte", FALSE },
547  { L"Technology", FALSE },
548  { L"Tecohnology", FALSE }, // on purpose (some Gigabyte boards)
549  { L"Technologies", FALSE },
550  { L"Tecnologia", FALSE },
551  { L"Limited", FALSE },
552  { L"Int", FALSE },
553  { L"Inc", FALSE },
554  { L"Co", FALSE },
555  { L"Corp", FALSE },
556  { L"Crop", FALSE },
557  { L"LLC", FALSE },
558  { L"Ltd", FALSE },
559  { L"LTDA", FALSE },
560  { L"GmbH", FALSE },
561  { L"S.p.A", FALSE },
562  { L"A.S.", FALSE },
563  { L"S.A", FALSE },
564  { L"S.A.S", FALSE },
565  { L"S/A", FALSE },
566  { L"SA", FALSE },
567  { L"SAS", FALSE },
568  { L"BV", FALSE },
569  { L"AG", FALSE },
570  { L"OOO", TRUE },
571  { L"CJSC", FALSE },
572  { L"INT'L", FALSE },
573  { L"INTL", FALSE },
574  { L"plc", FALSE },
575  };
576  PVOID SMBiosBuf;
577  PCHAR DmiStrings[ID_STRINGS_MAX] = { 0 };
578  WCHAR ven[512], dev[512];
579  CHAR tmpstr[512];
580  BOOL bTrimProduct, bTrimFamily, bGenericName, bRemove;
581  UINT i;
582  PWCHAR j;
583 
584  SMBiosBuf = LoadSMBiosData(DmiStrings);
585  if (!SMBiosBuf)
586  {
587  return FALSE;
588  }
589 
590  TrimNonPrintable(DmiStrings[SYS_VENDOR]);
591  bTrimProduct = TrimNonPrintableProd(DmiStrings[SYS_PRODUCT]);
592  TrimNonPrintable(DmiStrings[SYS_VERSION]);
593  bTrimFamily = TrimNonPrintable(DmiStrings[SYS_FAMILY]);
594  TrimNonPrintable(DmiStrings[BOARD_VENDOR]);
595  TrimNonPrintable(DmiStrings[BOARD_NAME]);
596  TrimNonPrintable(DmiStrings[BOARD_VERSION]);
597 
598  if (bTrimProduct)
599  {
600  if (DmiStrings[SYS_FAMILY] && !bTrimFamily)
601  {
602  DmiStrings[SYS_PRODUCT] = DmiStrings[SYS_FAMILY];
603  bTrimProduct = FALSE;
604  }
605  }
606 
607  GetSMBiosStringW(DmiStrings[SYS_VENDOR], ven, _countof(ven), TRUE);
608  GetSMBiosStringW(DmiStrings[SYS_PRODUCT], dev, _countof(dev), TRUE);
609  bGenericName = IsGenericSystemName(ven, dev, NULL) || bTrimProduct;
610 
611  if (wcslen(dev) == 0 ||
612  !wcscmp(dev, ven) ||
613  bGenericName)
614  {
615  BOOL bGenericVen = FALSE, bRemoveVen = FALSE, bGenericDev = (wcslen(dev) == 0 || !wcscmp(dev, ven) || bTrimProduct);
616 
617  if (bGenericName && IsGenericSystemName(ven, NULL, &bRemove))
618  {
619  if (bRemove)
620  {
621  *ven = 0;
622  }
623  bGenericVen = TRUE;
624  bRemoveVen = bRemove;
625  }
626  if (bGenericName && IsGenericSystemName(NULL, dev, &bRemove))
627  {
628  if (bRemove)
629  {
630  *dev = 0;
631  }
632  bGenericDev = TRUE;
633  }
634  // system strings are unusable, use board strings
635  if (DmiStrings[BOARD_VENDOR] != NULL || !bGenericName)
636  {
637  if ((DmiStrings[BOARD_VENDOR] &&
638  strlen(DmiStrings[BOARD_VENDOR]) >= 2 &&
639  strstr(DmiStrings[BOARD_VENDOR], " ") != DmiStrings[BOARD_VENDOR]) ||
640  bGenericVen)
641  {
642  GetSMBiosStringW(DmiStrings[BOARD_VENDOR], ven, _countof(ven), TRUE);
643  }
644  GetSMBiosStringW(DmiStrings[BOARD_NAME], dev, _countof(dev), TRUE);
645 
646  if (IsGenericSystemName(ven, NULL, &bRemove) && bRemove)
647  {
648  *ven = 0;
649 
650  if (bGenericVen && !bRemoveVen)
651  {
652  GetSMBiosStringW(DmiStrings[SYS_VENDOR], ven, _countof(ven), TRUE);
653  }
654  }
655  if (IsGenericSystemName(NULL, dev, &bRemove) && bRemove)
656  {
657  *dev = 0;
658 
659  if (!bGenericDev)
660  {
661  GetSMBiosStringW(DmiStrings[SYS_PRODUCT], dev, _countof(dev), TRUE);
662  }
663  }
664  if (wcslen(dev) == 0 &&
665  DmiStrings[SYS_VERSION] != NULL)
666  {
667  GetSMBiosStringW(DmiStrings[SYS_VERSION], dev, _countof(dev), TRUE);
668 
669  if (IsGenericSystemName(NULL, dev, &bRemove) && bRemove)
670  {
671  *dev = 0;
672  }
673  }
674  if (wcslen(dev) == 0 &&
675  DmiStrings[BOARD_VERSION] != NULL)
676  {
678 
679  if (IsGenericSystemName(NULL, dev, &bRemove) && bRemove)
680  {
681  *dev = 0;
682  }
683  }
684  }
685  else if (DmiStrings[BOARD_NAME] != NULL)
686  {
687  GetSMBiosStringW(DmiStrings[BOARD_NAME], dev, _countof(dev), TRUE);
688 
689  if (IsGenericSystemName(NULL, dev, &bRemove) && bRemove)
690  {
691  *dev = 0;
692  }
693  }
694 
695  if (wcslen(ven) == 0 && wcslen(dev) == 0)
696  {
697  // board strings are empty, use BIOS vendor string
698  GetSMBiosStringW(DmiStrings[BIOS_VENDOR], ven, _countof(ven), TRUE);
699  }
700  }
701  else
702  {
703  if (wcslen(ven) < 2)
704  {
705  GetSMBiosStringW(DmiStrings[BOARD_VENDOR], ven, _countof(ven), TRUE);
706 
707  if (IsGenericSystemName(ven, NULL, &bRemove) && bRemove)
708  {
709  *ven = 0;
710  }
711  }
712  }
713 
714  // workaround for LORD ELECTRONICS
715  if (((j = wcsstr(ven, L" ")) != NULL) && (j - ven > 2))
716  {
717  i = j - ven;
718  if (!wcsncmp(ven + wcslen(ven) - i, ven, i))
719  {
720  ven[wcslen(ven) - i] = L'\0';
721  }
722  }
723 
724  // make vendor strings shorter
725  for (i = 0; i < _countof(LongNames); i++)
726  {
727  if (wcsstr(dev, LongNames[i].pwLongName) == dev)
728  {
729  // swap ven and dev
730  StringCchCopyW(pBuf, cchBuf, ven);
731  StringCchCopyW(ven, _countof(ven), dev);
732  StringCchCopyW(dev, _countof(dev), pBuf);
733  }
734  wcsrep(ven, LongNames[i].pwLongName, LongNames[i].pwShortName, TRUE);
735  }
736 
737  // remove redundant words
738  for (i = 0; i < _countof(RedundantWords); i++)
739  {
740  wcsrep(ven, RedundantWords[i].pwStr, L"", RedundantWords[i].bReplaceFirstWord);
741  }
742  for (i = 0; i < _countof(RedundantWords); i++)
743  {
744  StringCchCopyW(pBuf, cchBuf, RedundantWords[i].pwStr);
745  StringCchCatW(pBuf, cchBuf, L".");
746  wcsrep(ven, pBuf, L"", RedundantWords[i].bReplaceFirstWord);
747  }
748 
749  // workaround for LENOVO notebooks
750  if (!wcsicmp(ven, L"LENOVO"))
751  {
752  StringCchCopyW(ven, _countof(ven), L"Lenovo");
753 
754  if (DmiStrings[SYS_VERSION] != NULL)
755  {
756  if (!strncmp(DmiStrings[SYS_VERSION], "ThinkPad ", 11))
757  {
758  DmiStrings[SYS_VERSION][8] = L'\0';
759  }
760  if (wcslen(dev) > 0 &&
761  (!strcmp(DmiStrings[SYS_VERSION], "IdeaCentre") ||
762  !strcmp(DmiStrings[SYS_VERSION], "ThinkPad")))
763  {
764  DmiStrings[SYS_FAMILY] = DmiStrings[SYS_VERSION];
765  DmiStrings[SYS_VERSION] = NULL;
766  }
767  else
768  {
769  StringCchCopyA(tmpstr, _countof(tmpstr), DmiStrings[SYS_VERSION]);
770  _strupr(tmpstr);
771  }
772  }
773 
774  if (DmiStrings[SYS_VERSION] != NULL &&
775  strcmp(tmpstr, " ") &&
776  strcmp(tmpstr, "LENOVO") &&
777  strstr(tmpstr, "LENOVO ") == NULL &&
778  strstr(tmpstr, "LENOVO PRODUCT") == NULL &&
779  strstr(tmpstr, "LENOVOPRODUCT") == NULL &&
780  strstr(tmpstr, "INVALID") == NULL &&
781  strncmp(tmpstr, " ", 3) &&
782  (strlen(tmpstr) >= 3 || !IsDigitStrA(tmpstr)) &&
783  strstr(DmiStrings[SYS_VERSION], "Rev ") == NULL &&
784  strstr(DmiStrings[SYS_VERSION], "1.") == NULL &&
785  wcsistr(dev, L"System ") == NULL && // includes System x and ThinkSystem
786  wcsistr(dev, L"IdeaPad ") == NULL &&
787  wcsistr(dev, L"ThinkServer ") == NULL)
788  {
789  GetSMBiosStringW(DmiStrings[SYS_VERSION], dev, _countof(dev), TRUE);
790  }
791 
792  if (wcsstr(dev, L"Lenovo-") == dev)
793  {
794  // replace "-" with space
795  dev[6] = L' ';
796  }
797 
798  if (!wcscmp(dev, L"Lenovo"))
799  {
800  GetSMBiosStringW(DmiStrings[BOARD_NAME], dev, _countof(dev), TRUE);
801  }
802  }
803  if (!wcscmp(ven, L"IBM") &&
804  DmiStrings[SYS_VERSION] != NULL &&
805  (strstr(DmiStrings[SYS_VERSION], "ThinkPad ") != NULL ||
806  strstr(DmiStrings[SYS_VERSION], "ThinkCentre ") != NULL))
807  {
808  GetSMBiosStringW(DmiStrings[SYS_VERSION], dev, _countof(dev), TRUE);
809  }
810 
811  // workaround for DEXP
812  if (!wcscmp(ven, L"DEXP"))
813  {
814  if (DmiStrings[SYS_PRODUCT] != NULL &&
815  DmiStrings[SYS_VERSION] != NULL &&
816  (!stricmp(DmiStrings[SYS_PRODUCT], "Tablet PC") ||
817  !stricmp(DmiStrings[SYS_PRODUCT], "Notebook") ||
818  !stricmp(DmiStrings[SYS_PRODUCT], "Decktop")))
819  {
820  GetSMBiosStringW(DmiStrings[SYS_VERSION], dev, _countof(dev), TRUE);
821  }
822  }
823 
824  // workaround for Razer Blade
825  if (!wcscmp(ven, L"Razer") && !wcscmp(dev, L"Blade"))
826  {
827  if (DmiStrings[SYS_VERSION] != NULL)
828  {
829  StringCchCopyW(ven, _countof(ven), L"Razer Blade");
830  GetSMBiosStringW(DmiStrings[SYS_VERSION], dev, _countof(dev), TRUE);
831  }
832  }
833 
834  // workaround for MSI motherboards
835  if (!wcscmp(ven, L"MSI") &&
836  wcsstr(dev, L"MS-") != NULL &&
837  DmiStrings[BOARD_NAME] != NULL &&
838  strstr(DmiStrings[BOARD_NAME], "(MS-") != NULL)
839  {
840  GetSMBiosStringW(DmiStrings[BOARD_NAME], dev, _countof(dev), TRUE);
841  }
842  if (wcslen(ven) == 0 &&
843  wcsstr(dev, L"MS-") == dev)
844  {
845  StringCchCopyW(ven, _countof(ven), L"MSI");
846  }
847 
848  // trim redundant characters
849  TrimPunctuation(ven);
851 
852  if (wcsistr(dev, ven) == dev ||
853  (!wcscmp(ven, L"ASUS") && wcsstr(dev, L"ASUS") != NULL) ||
854  (!wcscmp(ven, L"HP") && wcsstr(dev, L" by HP") != NULL) ||
855  (!wcscmp(ven, L"INTEL") && wcsstr(dev, L" INTEL") != NULL))
856  {
857  // device string contains vendor string, use second only
858  StringCchCopyW(pBuf, cchBuf, dev);
859  }
860  else
861  {
862  if (wcslen(ven) > 0 && wcslen(dev) > 0 && (j = wcschr(dev, L' ')))
863  {
864  // check if vendor string ends with first word of device string
865  i = j - dev;
866  if (wcslen(ven) > i && !_wcsnicmp(ven + wcslen(ven) - i, dev, i))
867  {
868  ven[wcslen(ven) - i] = L'\0';
869  TrimPunctuation(ven);
870  }
871  }
872  StringCchCopyW(pBuf, cchBuf, ven);
873  AppendSystemFamily(pBuf, cchBuf, DmiStrings, dev);
874  if (wcslen(pBuf) > 0 && wcslen(dev) > 0)
875  {
876  StringCchCatW(pBuf, cchBuf, L" ");
877  }
878  StringCchCatW(pBuf, cchBuf, dev);
879  }
880 
881  FreeSMBiosData(SMBiosBuf);
882 
883  return (wcslen(pBuf) > 0);
884 }
signed char * PCHAR
Definition: retypes.h:7
const uint16_t * PCWSTR
Definition: typedefs.h:56
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static BOOL bCaseSensitive
Definition: systempage.cpp:56
#define TRUE
Definition: types.h:120
PCWSTR pwLongName
Definition: smbios.c:24
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
uint16_t * PWSTR
Definition: typedefs.h:55
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
char CHAR
Definition: xmlstorage.h:175
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
PCWSTR pwShortName
Definition: smbios.c:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
static VOID TrimPunctuation(_Inout_ PWSTR pStr)
Definition: smbios.c:69
uint16_t * PWCHAR
Definition: typedefs.h:55
static wchar_t * wcsistr_plus(const wchar_t *s, wchar_t *b)
Definition: smbios.c:132
SIZE_T GetSMBiosStringW(_In_ PCSTR DmiString, _Out_ PWSTR pBuf, _In_ DWORD cchBuf, _In_ BOOL bTrim)
Definition: udmihelp.c:145
static int dev
Definition: mkdosfs.c:536
static void AppendSystemFamily(PWSTR pBuf, SIZE_T cchBuf, PCHAR *DmiStrings, PWSTR dev)
Definition: smbios.c:408
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
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
PCWSTR pwName
Definition: smbios.c:17
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL bReplaceFirstWord
Definition: smbios.c:31
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
static VOID wcsrep(_Inout_ PWSTR pwStr, _In_ PCWSTR pwFind, _In_ PCWSTR pwReplace, _In_ BOOL bReplaceFirstWord)
Definition: smbios.c:180
smooth NULL
Definition: ftsmooth.c:416
_Check_return_ _CRTIMP int __cdecl stricmp(_In_z_ const char *_Str1, _In_z_ const char *_Str2)
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 GLint GLint j
Definition: glfuncs.h:250
struct VENDOR_LONG_NAME VENDOR_LONG_NAME
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define GetProcessHeap()
Definition: compat.h:404
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
BOOL bCaseSensitive
Definition: smbios.c:18
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define _countof(array)
Definition: sndvol32.h:68
const GLubyte * c
Definition: glext.h:8905
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define _Inout_
Definition: no_sal2.h:244
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
static BOOL TrimNonPrintable(PCHAR DmiString)
Definition: smbios.c:446
BOOL GetSystemName(PWSTR pBuf, SIZE_T cchBuf)
Definition: smbios.c:491
static const WCHAR L[]
Definition: oid.c:1250
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
static wchar_t * wcsistr(const wchar_t *s, const wchar_t *b)
Definition: smbios.c:106
int chr(char *serport)
Definition: gdblib.c:152
#define wcsicmp
Definition: string.h:1152
static BOOL IsDigitStrA(PCHAR DmiString)
Definition: smbios.c:43
#define _In_
Definition: no_sal2.h:204
PCWSTR pwStr
Definition: smbios.c:30
ULONG_PTR SIZE_T
Definition: typedefs.h:79
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
struct GENERIC_NAME GENERIC_NAME
VOID FreeSMBiosData(_In_ PVOID Buffer)
Definition: udmihelp.c:177
VOID TrimDmiStringW(_Inout_ PWSTR pStr)
Definition: udmihelp.c:110
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
static BOOL IsPunctuation(_In_ WCHAR chr)
Definition: smbios.c:36
unsigned int UINT
Definition: ndis.h:50
struct REDUNDANT_WORD REDUNDANT_WORD
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
static BOOL IsGenericSystemName(PCWSTR ven, PCWSTR dev, BOOL *bRemove)
Definition: smbios.c:258
#define c
Definition: ke_i.h:80
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define towlower(c)
Definition: wctype.h:97
PVOID LoadSMBiosData(_Inout_updates_(ID_STRINGS_MAX) PCHAR *Strings)
Definition: udmihelp.c:30
const char * PCSTR
Definition: typedefs.h:52
static BOOL TrimNonPrintableProd(PCHAR DmiString)
Definition: smbios.c:472
PWSTR LongNames[LONG_NAMES_COUNT]
GLuint64EXT * result
Definition: glext.h:11304
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:403
BOOL bRemove
Definition: smbios.c:19