From ea292d6bf086e95edcec840168a4247db6d8ee61 Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Wed, 19 Feb 2020 15:04:37 -0800 Subject: [PATCH] Add computer name and CPU brand string support. --- src/PerfectHash/BulkCreateBestCsv.h | 8 ++ src/PerfectHash/PerfectHashContext.c | 23 +++++ src/PerfectHash/PerfectHashContext.h | 7 ++ src/PerfectHash/Rtl.c | 121 +++++++++++++++++---------- src/PerfectHash/Rtl.h | 19 ++++- 5 files changed, 134 insertions(+), 44 deletions(-) diff --git a/src/PerfectHash/BulkCreateBestCsv.h b/src/PerfectHash/BulkCreateBestCsv.h index 8acddc79..338c1b9c 100644 --- a/src/PerfectHash/BulkCreateBestCsv.h +++ b/src/PerfectHash/BulkCreateBestCsv.h @@ -46,6 +46,14 @@ Module Name: &Context->HexHeaderHash, \ OUTPUT_STRING) \ \ + ENTRY(ComputerName, \ + &Context->ComputerName, \ + OUTPUT_STRING) \ + \ + ENTRY(CpuBrand, \ + &Context->Rtl->CpuFeatures.Brand, \ + OUTPUT_STRING) \ + \ ENTRY(KeysName, \ &Keys->File->Path->BaseNameA, \ OUTPUT_STRING) \ diff --git a/src/PerfectHash/PerfectHashContext.c b/src/PerfectHash/PerfectHashContext.c index 10e940ea..a62d2bbb 100644 --- a/src/PerfectHash/PerfectHashContext.c +++ b/src/PerfectHash/PerfectHashContext.c @@ -97,6 +97,7 @@ Return Value: PACL Acl = NULL; BYTE Index; BYTE NumberOfEvents; + BOOL Success; HRESULT Result = S_OK; ULONG LastError; HANDLE Handle; @@ -108,6 +109,8 @@ Return Value: ULONG NumberOfProcessors; ULONG SizeOfNamesWideBuffer = 0; PWSTR NamesWideBuffer; + PSTRING ComputerName; + DWORD ComputerNameLength; PTP_POOL Threadpool; PALLOCATOR Allocator; ULARGE_INTEGER AllocSize; @@ -605,6 +608,26 @@ Return Value: goto Error; } + // + // Wire up the ComputerName string and buffer, then get the computer name. + // + + ComputerName = &Context->ComputerName; + ComputerName->Length = 0; + ComputerName->MaximumLength = sizeof(Context->ComputerNameBuffer); + ComputerNameLength = (DWORD)ComputerName->MaximumLength; + ComputerName->Buffer = (PCHAR)&Context->ComputerNameBuffer; + + Success = GetComputerNameA((PCHAR)ComputerName->Buffer, + &ComputerNameLength); + if (!Success) { + SYS_ERROR(GetComputerNameA); + Result = PH_E_SYSTEM_CALL_FAILED; + goto Error; + } + ASSERT(ComputerName->Length < MAX_COMPUTERNAME_LENGTH); + ComputerName->Length = (USHORT)ComputerNameLength; + // // We're done! Indicate success and finish up. // diff --git a/src/PerfectHash/PerfectHashContext.h b/src/PerfectHash/PerfectHashContext.h index 0f9b4554..2217e26d 100644 --- a/src/PerfectHash/PerfectHashContext.h +++ b/src/PerfectHash/PerfectHashContext.h @@ -388,6 +388,13 @@ typedef struct _Struct_size_bytes_(SizeOfStruct) _PERFECT_HASH_CONTEXT { PCSEED_MASKS SeedMasks; + // + // Computer name. + // + + STRING ComputerName; + CHAR ComputerNameBuffer[MAX_COMPUTERNAME_LENGTH+1]; + // // Hex string representation of the CSV header hash. // diff --git a/src/PerfectHash/Rtl.c b/src/PerfectHash/Rtl.c index 8d5f1738..da025522 100644 --- a/src/PerfectHash/Rtl.c +++ b/src/PerfectHash/Rtl.c @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2018-2019 Trent Nelson +Copyright (c) 2018-2020 Trent Nelson Module Name: @@ -471,34 +471,35 @@ Return Value: { HRESULT Result; CPU_INFO CpuInfo; - RTL_CPU_FEATURES Features; + PRTL_CPU_FEATURES Features; const LONG BaseExtendedId = 0x80000000; LONG ExtendedId; LONG HighestId; LONG HighestExtendedId; + PSTRING Brand; + Features = &Rtl->CpuFeatures; ZeroStruct(CpuInfo); - ZeroStruct(Features); __cpuid((PINT)&CpuInfo.AsIntArray, 0); HighestId = CpuInfo.Eax; - Features.Vendor.IsIntel = ( + Features->Vendor.IsIntel = ( CpuInfo.Ebx == (LONG)'uneG' && CpuInfo.Ecx == (LONG)'letn' && CpuInfo.Edx == (LONG)'Ieni' ); - if (!Features.Vendor.IsIntel) { - Features.Vendor.IsAMD = ( + if (!Features->Vendor.IsIntel) { + Features->Vendor.IsAMD = ( CpuInfo.Ebx == (LONG)'htuA' && CpuInfo.Ecx == (LONG)'DMAc' && CpuInfo.Edx == (LONG)'itne' ); - if (!Features.Vendor.IsAMD) { - Features.Vendor.Unknown = TRUE; + if (!Features->Vendor.IsAMD) { + Features->Vendor.Unknown = TRUE; } } @@ -506,16 +507,16 @@ Return Value: ZeroStruct(CpuInfo); __cpuidex((PINT)&CpuInfo.AsIntArray, 1, 0); - Features.F1Ecx.AsLong = CpuInfo.Ecx; - Features.F1Edx.AsLong = CpuInfo.Edx; + Features->F1Ecx.AsLong = CpuInfo.Ecx; + Features->F1Edx.AsLong = CpuInfo.Edx; } if (HighestId >= 7) { ZeroStruct(CpuInfo); __cpuidex((PINT)&CpuInfo.AsIntArray, 7, 0); - Features.F7Ebx.AsLong = CpuInfo.Ebx; - Features.F7Ecx.AsLong = CpuInfo.Ecx; + Features->F7Ebx.AsLong = CpuInfo.Ebx; + Features->F7Ecx.AsLong = CpuInfo.Ecx; } ZeroStruct(CpuInfo); @@ -527,44 +528,78 @@ Return Value: ZeroStruct(CpuInfo); __cpuidex((PINT)&CpuInfo.AsIntArray, ExtendedId, 0); - Features.F81Ecx.AsLong = CpuInfo.Ecx; - Features.F81Edx.AsLong = CpuInfo.Edx; + Features->F81Ecx.AsLong = CpuInfo.Ecx; + Features->F81Edx.AsLong = CpuInfo.Edx; } - Features.HighestFeatureId = HighestId; - Features.HighestExtendedFeatureId = HighestExtendedId; - - if (Features.Vendor.IsIntel) { - Features.Intel.HLE = Features.HLE; - Features.Intel.RTM = Features.RTM; - Features.Intel.BMI1 = Features.BMI1; - Features.Intel.BMI2 = Features.BMI2; - Features.Intel.LZCNT = Features.LZCNT; - Features.Intel.POPCNT = Features.POPCNT; - Features.Intel.SYSCALL = Features.SYSCALLSYSRET; - Features.Intel.RDTSCP = Features.RDTSCP_IA32_TSC_AUX; - } else if (Features.Vendor.IsAMD) { + Features->HighestFeatureId = HighestId; + Features->HighestExtendedFeatureId = HighestExtendedId; + + if (Features->Vendor.IsIntel) { + Features->Intel.HLE = Features->HLE; + Features->Intel.RTM = Features->RTM; + Features->Intel.BMI1 = Features->BMI1; + Features->Intel.BMI2 = Features->BMI2; + Features->Intel.LZCNT = Features->LZCNT; + Features->Intel.POPCNT = Features->POPCNT; + Features->Intel.SYSCALL = Features->SYSCALLSYSRET; + Features->Intel.RDTSCP = Features->RDTSCP_IA32_TSC_AUX; + } else if (Features->Vendor.IsAMD) { LONG F81Ecx; LONG F81Edx; - F81Ecx = Features.F81Ecx.AsLong; - F81Edx = Features.F81Edx.AsLong; - - Features.AMD.ABM = BooleanFlagOn(F81Ecx, 1 << 5); - Features.AMD.SSE4A = BooleanFlagOn(F81Ecx, 1 << 6); - Features.AMD.XOP = BooleanFlagOn(F81Ecx, 1 << 11); - Features.AMD.TBM = BooleanFlagOn(F81Ecx, 1 << 21); - Features.AMD.SVM = BooleanFlagOn(F81Ecx, 1 << 2); - Features.AMD.IBS = BooleanFlagOn(F81Ecx, 1 << 10); - Features.AMD.LWP = BooleanFlagOn(F81Ecx, 1 << 15); - Features.AMD.MMXEXT = BooleanFlagOn(F81Edx, 1 << 22); - Features.AMD.THREEDNOW = BooleanFlagOn(F81Edx, 1 << 31); - Features.AMD.THREEDNOWEXT = BooleanFlagOn(F81Edx, 1 << 30); + F81Ecx = Features->F81Ecx.AsLong; + F81Edx = Features->F81Edx.AsLong; + + Features->AMD.ABM = BooleanFlagOn(F81Ecx, 1 << 5); + Features->AMD.SSE4A = BooleanFlagOn(F81Ecx, 1 << 6); + Features->AMD.XOP = BooleanFlagOn(F81Ecx, 1 << 11); + Features->AMD.TBM = BooleanFlagOn(F81Ecx, 1 << 21); + Features->AMD.SVM = BooleanFlagOn(F81Ecx, 1 << 2); + Features->AMD.IBS = BooleanFlagOn(F81Ecx, 1 << 10); + Features->AMD.LWP = BooleanFlagOn(F81Ecx, 1 << 15); + Features->AMD.MMXEXT = BooleanFlagOn(F81Edx, 1 << 22); + Features->AMD.THREEDNOW = BooleanFlagOn(F81Edx, 1 << 31); + Features->AMD.THREEDNOWEXT = BooleanFlagOn(F81Edx, 1 << 30); } - CopyMemory(&Rtl->CpuFeatures, - &Features, - sizeof(Rtl->CpuFeatures)); + // + // Capture the CPU brand string if available. + // + + Brand = &Features->Brand; + Brand->Length = 0; + Brand->MaximumLength = sizeof(Features->BrandBuffer); + Brand->Buffer = (PCHAR)&Features->BrandBuffer; + + if (HighestExtendedId >= (BaseExtendedId + 4)) { + + __cpuid((PINT)&CpuInfo.AsIntArray, BaseExtendedId + 2); + CopyMemory(Brand->Buffer, CpuInfo.AsCharArray, 16); + + __cpuid((PINT)&CpuInfo.AsIntArray, BaseExtendedId + 3); + CopyMemory(Brand->Buffer + 16, CpuInfo.AsCharArray, 16); + + __cpuid((PINT)&CpuInfo.AsIntArray, BaseExtendedId + 4); + CopyMemory(Brand->Buffer + 32, CpuInfo.AsCharArray, 16); + + Brand->Length = (USHORT)strlen(Brand->Buffer); + _Analysis_assume_(Brand->Length <= 48); + ASSERT(Brand->Length < Brand->MaximumLength); + + // + // Disable the following warning: + // warning C6385: Reading invalid data from 'Brand->Buffer': + // the readable size is '_Old_13`16' bytes, but + // 'Brand->Length' bytes may be read. + // + +#pragma warning(push) +#pragma warning(disable: 6385) + ASSERT(Brand->Buffer[Brand->Length] == '\0'); +#pragma warning(pop) + + } Result = S_OK; diff --git a/src/PerfectHash/Rtl.h b/src/PerfectHash/Rtl.h index 7be1b48c..aa981f30 100644 --- a/src/PerfectHash/Rtl.h +++ b/src/PerfectHash/Rtl.h @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2018 Trent Nelson +Copyright (c) 2018-2020 Trent Nelson Module Name: @@ -435,6 +435,7 @@ typedef union _CPU_INFO { INT AsIntArray[4]; LONG AsLongArray[4]; ULONG AsULongArray[4]; + CHAR AsCharArray[16]; } CPU_INFO; typedef CPU_INFO *PCPU_INFO; @@ -987,6 +988,13 @@ typedef struct _RTL_CPU_FEATURES { ULONG AsULongArray[6]; }; + // + // CPU Brand String. + // + + STRING Brand; + CHAR BrandBuffer[48]; + } RTL_CPU_FEATURES; typedef RTL_CPU_FEATURES *PRTL_CPU_FEATURES; #endif // defined(_M_AMD64) || defined(_M_X64) || defined(_M_IX86) @@ -1119,6 +1127,15 @@ CopyMemoryInline( TrailingBytes = SizeInBytes - (NumberOfQuadwords << 3); while (NumberOfQuadwords) { + + // + // N.B. If you hit an exception on this next line, and the call stack + // contains PrepareBulkCreateCsvFile(), you probably need to adjust + // the number of pages used for the temporary row buffer in either + // the BulkCreateBestCsv.h or BulkCreateCsv.h header (e.g. bump + // BULK_CREATE_BEST_CSV_ROW_BUFFER_NUMBER_OF_PAGES by one). + // + *Dest++ = *Source++; NumberOfQuadwords--; }