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