ReactOS 0.4.16-dev-311-g9382aa2
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
14typedef struct GENERIC_NAME
15{
20
21typedef struct VENDOR_LONG_NAME
22{
26
27typedef struct REDUNDANT_WORD
28{
32
33static
34BOOL
36 _In_ WCHAR chr)
37{
38 return (chr <= L' ' || chr == L'.' || chr == L',');
39}
40
41static
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 */
66static
67VOID
69 _Inout_ PWSTR pStr)
70{
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 */
104static
105wchar_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
130static
131wchar_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 */
178static
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);
250freeFind:
251 HeapFree(GetProcessHeap(), 0, pwsFind);
252freeStr:
253 HeapFree(GetProcessHeap(), 0, pwsStr);
254}
255
256static
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
406static
407void 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
444static
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). */
470static
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);
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 }
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 {
661 }
662 }
663 if (wcslen(dev) == 0 &&
664 DmiStrings[SYS_VERSION] != NULL)
665 {
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 {
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);
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 {
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 {
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 {
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 {
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");
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 {
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}
PWSTR LongNames[LONG_NAMES_COUNT]
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define _stricmp
Definition: cat.c:22
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static BOOL TrimNonPrintableProd(PCHAR DmiString)
Definition: smbios.c:471
static VOID wcsrep(_Inout_ PWSTR pwStr, _In_ PCWSTR pwFind, _In_ PCWSTR pwReplace, _In_ BOOL bReplaceFirstWord)
Definition: smbios.c:179
static wchar_t * wcsistr(const wchar_t *s, const wchar_t *b)
Definition: smbios.c:105
static BOOL IsPunctuation(_In_ WCHAR chr)
Definition: smbios.c:35
static void AppendSystemFamily(PWSTR pBuf, SIZE_T cchBuf, PCHAR *DmiStrings, PWSTR dev)
Definition: smbios.c:407
static BOOL TrimNonPrintable(PCHAR DmiString)
Definition: smbios.c:445
static wchar_t * wcsistr_plus(const wchar_t *s, wchar_t *b)
Definition: smbios.c:131
BOOL GetSystemName(PWSTR pBuf, SIZE_T cchBuf)
Definition: smbios.c:490
static VOID TrimPunctuation(_Inout_ PWSTR pStr)
Definition: smbios.c:68
static BOOL IsDigitStrA(PCHAR DmiString)
Definition: smbios.c:42
static BOOL IsGenericSystemName(PCWSTR ven, PCWSTR dev, BOOL *bRemove)
Definition: smbios.c:257
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
@ BOARD_VENDOR
Definition: dmilib.h:22
@ SYS_VERSION
Definition: dmilib.h:18
@ SYS_PRODUCT
Definition: dmilib.h:17
@ ID_STRINGS_MAX
Definition: dmilib.h:28
@ SYS_VENDOR
Definition: dmilib.h:16
@ BIOS_VENDOR
Definition: dmilib.h:13
@ BOARD_NAME
Definition: dmilib.h:23
@ BOARD_VERSION
Definition: dmilib.h:24
@ SYS_FAMILY
Definition: dmilib.h:21
unsigned int BOOL
Definition: ntddk_ex.h:94
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
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
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
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
#define c
Definition: ke_i.h:80
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
unsigned int UINT
Definition: ndis.h:50
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_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)
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
_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)
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
BOOL bRemove
Definition: smbios.c:18
PCWSTR pwName
Definition: smbios.c:16
BOOL bCaseSensitive
Definition: smbios.c:17
PCWSTR pwStr
Definition: smbios.c:29
BOOL bReplaceFirstWord
Definition: smbios.c:30
PCWSTR pwShortName
Definition: smbios.c:24
PCWSTR pwLongName
Definition: smbios.c:23
static BOOL bCaseSensitive
Definition: systempage.cpp:56
#define towlower(c)
Definition: wctype.h:97
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
uint16_t * PWCHAR
Definition: typedefs.h:56
char * PCHAR
Definition: typedefs.h:51
SIZE_T GetSMBiosStringW(_In_ PCSTR DmiString, _Out_ PWSTR pBuf, _In_ DWORD cchBuf, _In_ BOOL bTrim)
Definition: udmihelp.c:145
PVOID LoadSMBiosData(_Inout_updates_(ID_STRINGS_MAX) PCHAR *Strings)
Definition: udmihelp.c:30
VOID FreeSMBiosData(_In_ PVOID Buffer)
Definition: udmihelp.c:177
VOID TrimDmiStringW(_Inout_ PWSTR pStr)
Definition: udmihelp.c:110
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175