in CPUSamplesCollector/Windows/lib/Program.cpp [1635:1890]
HRESULT ReadAndSetupConfiguration(LPWSTR iniFilePathPtr, Configuration &configuration)
{
auto providerList = ReadETWSessionStringListData(L"Providers", iniFilePathPtr);
if (providerList.size() == 0)
{
wprintf(L" ERROR: No provider list found. You must have at least one provider.\n");
return E_FAIL;
}
auto classicEventIdsStackList = ReadETWSessionStringListData(L"ClassicEventIdsStack", iniFilePathPtr);
configuration.SessionName = ReadETWSessionStringData(L"Name", iniFilePathPtr);
if (configuration.SessionName.empty())
{
wprintf(L" ERROR: The 'Name' property is required in the '[ETWSession]' section in your configuration file.\n");
return E_FAIL;
}
configuration.SessionNameBSTR = SysAllocString(configuration.SessionName.c_str());
configuration.FileNamePrefix = ReadETWSessionStringData(L"FileNamePrefix", iniFilePathPtr);
if (configuration.FileNamePrefix.empty())
{
wprintf(L" ERROR: The 'FileNamePrefix' property is required in the '[ETWSession]' section in your configuration file.\n");
return E_FAIL;
}
if (configuration.FileNamePrefix.length() > 512)
{
wprintf(L" ERROR: The 'FileNamePrefix' property is greater than the 512 max limit. Please consider a shorter prefix.\n");
return E_FAIL;
}
auto onDiskFormat = ReadETWSessionStringData(L"OnDiskFormat", iniFilePathPtr);
if (onDiskFormat == std::wstring(L"BTL"))
{
configuration.OnDiskFormat = OnDiskFormat::BTL;
}
else if (onDiskFormat == std::wstring(L"ETL"))
{
configuration.OnDiskFormat = OnDiskFormat::ETL;
}
else
{
wprintf(L" ERROR: The 'OnDiskFormat' property must either be 'BTL' or 'ETL'.\n");
return E_FAIL;
}
configuration.BufferSizeInKB = ReadETWSessionIntData(L"BufferSizeInKB", iniFilePathPtr, 64);
configuration.LogRotationIntervalInSeconds = ReadETWSessionIntData(L"LogRotationIntervalInSeconds", iniFilePathPtr, 900);
configuration.CPUSamplingRateInMS = ReadETWSessionIntData(L"CPUSamplingRateInMS", iniFilePathPtr, 1);
configuration.KernelEnableFlags = ReadETWSessionIntData(L"KernelEnableFlags", iniFilePathPtr, 0);
configuration.EnableEmbeddingEventMetadata = ReadETWSessionIntData(L"EnableEmbeddingEventMetadata", iniFilePathPtr, 1);
configuration.EnableEmbeddingSymbolServerKeyInfo = ReadETWSessionIntData(L"EnableEmbeddingSymbolServerKeyInfo", iniFilePathPtr, 1);
configuration.EnableMetadataSideStream = ReadETWSessionIntData(L"EnableMetadataSideStream", iniFilePathPtr, 1);
configuration.DataDirectory = ReadETWSessionStringData(L"DataDirectory", iniFilePathPtr);
configuration.EnableCLRSymbolCollection = ReadETWSessionIntData(L"EnableCLRSymbolCollection", iniFilePathPtr, 0);
if (configuration.EnableCLRSymbolCollection)
{
std::unordered_set<std::wstring> set;
configuration.CLRSymbolCollectionProcessNames = ReadETWSessionStringData(L"CLRSymbolCollectionProcessNames", iniFilePathPtr);
for (auto &s : split(configuration.CLRSymbolCollectionProcessNames, ';'))
{
set.insert(s);
}
configuration.CLRSymbolCollectionProcessNamesSet = set;
}
std::wstring expandedDataDirectory(32767, '0');
auto retSize = ExpandEnvironmentStrings(configuration.DataDirectory.c_str(), &expandedDataDirectory[0], 32767);
expandedDataDirectory.resize(retSize);
auto fileAttr = GetFileAttributes(expandedDataDirectory.c_str());
if (0xFFFFFFFF == fileAttr)
{
auto err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
{
wprintf(L" ERROR: Data Directory '%s' does not exist.", expandedDataDirectory.c_str());
}
else
{
wprintf(L" ERROR: Data Directory '%s' unknown error getting file attributes: %d", expandedDataDirectory.c_str(), fileAttr);
}
return E_FAIL;
}
configuration.DataDirectory = expandedDataDirectory;
if (configuration.DataDirectory.empty())
{
wprintf(L" ERROR: The 'DataDirectory' property is required in the '[ETWSession]' section in your configuration file.\n");
return E_FAIL;
}
for (size_t i = 0; i < providerList.size(); ++i)
{
auto providerSectionName = providerList[i].c_str();
std::wstring temp(255, '0');
if (GetPrivateProfileSection(providerSectionName, &temp[0], 255, iniFilePathPtr) == 0)
{
wprintf(L" ERROR: Section '[%s]' not found in the configuration File.", providerSectionName);
return E_FAIL;
}
Provider provider;
auto guidStr = ReadStringData(providerSectionName, L"Guid", iniFilePathPtr);
if (guidStr.size() != 38 || guidStr[0] != '{' || guidStr[37] != '}' || guidStr[9] != '-' || guidStr[14] != '-' || guidStr[19] != '-' || guidStr[24] != '-')
{
wprintf(L" ERROR: Section '[%s]', Property 'Guid' is missing and/or does not appear to be a GUID. Must the be format of: {2CB15D1D-5FC1-11D2-ABE1-00A0C911F518}", providerSectionName);
return E_FAIL;
}
provider.Name = providerList[i];
provider.Guid = StringToGuid(guidStr);
provider.Level = (BYTE)ReadIntData((LPWSTR)providerSectionName, L"Level", iniFilePathPtr, 5);
provider.MatchAnyKeyword = ReadIntData((LPWSTR)providerSectionName, L"MatchAnyKeyword", iniFilePathPtr, 0);
provider.MatchAllKeyword = ReadIntData((LPWSTR)providerSectionName, L"MatchAllKeyword", iniFilePathPtr, 0);
provider.ExeNamesFilter = ReadStringData(providerSectionName, L"ExeNamesFilter", iniFilePathPtr);
{
std::wstringstream ss(ReadStringData(providerSectionName, L"StackEventIdsFilter", iniFilePathPtr));
int x;
while (ss >> x)
{
provider.StackEventIds.push_back((USHORT)x);
if (ss.peek() == ',' || ss.peek() == ' ')
{
ss.ignore();
}
}
}
{
std::wstringstream ss(ReadStringData(providerSectionName, L"ExcludeEventIdsFilter", iniFilePathPtr));
int x;
while (ss >> x)
{
provider.ExcludeEventIds.push_back((USHORT)x);
if (ss.peek() == ',' || ss.peek() == ' ')
{
ss.ignore();
}
}
}
provider.EnableStacksForAllEventIds = ReadIntData((LPWSTR)providerSectionName, L"EnableStacksForAllEventIds", iniFilePathPtr, 0);
configuration.ProviderList.push_back(provider);
}
for (size_t i = 0; i < classicEventIdsStackList.size(); ++i)
{
CLASSIC_EVENT_ID classicEventId;
auto guidStr = ReadStringData(classicEventIdsStackList[i].c_str(), L"Guid", iniFilePathPtr);
if (guidStr.size() != 38 || guidStr[0] != '{' || guidStr[37] != '}' || guidStr[9] != '-' || guidStr[14] != '-' || guidStr[19] != '-' || guidStr[24] != '-')
{
wprintf(L" ERROR: Section '[%s]', Property 'Guid' is missing and/or does not appear to be a GUID. Must the be format of: {2CB15D1D-5FC1-11D2-ABE1-00A0C911F518}", classicEventIdsStackList[i].c_str());
return E_FAIL;
}
classicEventId.EventGuid = StringToGuid(guidStr);
auto typeVal = ReadIntData((LPWSTR)classicEventIdsStackList[i].c_str(), L"Type", iniFilePathPtr, 256);
classicEventId.Type = (UCHAR)typeVal;
if (typeVal > 255)
{
wprintf(L" ERROR: Section '[%s]', Property 'Type' has an invalid value, must be less than 255", classicEventIdsStackList[i].c_str());
return E_FAIL;
}
configuration.ClassicEventIdsStackList.push_back(classicEventId);
}
SessionName = (LPWSTR)configuration.SessionName.c_str(); // alive throughout the program
/* set working dir */
SetCurrentDirectoryW(configuration.DataDirectory.c_str());
WCHAR systemRoot[MAX_PATH] = L"";
GetWindowsDirectoryW(addr(systemRoot), MAX_PATH);
systemRoot[wcslen(systemRoot)] = L'\\';
configuration.VolumeMap.insert(std::make_pair(std::wstring(L"\\SystemRoot\\"), std::wstring(systemRoot)));
WCHAR volumePathName[32768];
WCHAR deviceName[MAX_PATH] = L"";
WCHAR volumeName[MAX_PATH] = L"";
auto findHandle = FindFirstVolumeW(addr(volumeName), (DWORD)size_of(volumeName));
if (findHandle == INVALID_HANDLE_VALUE)
{
wprintf(L"FindFirstVolumeW failed with error code %d\n", GetLastError());
return S_OK;
}
size_t index;
for (;;)
{
index = wcslen(volumeName) - 1;
if (volumeName[0] != L'\\' ||
volumeName[1] != L'\\' ||
volumeName[2] != L'?' ||
volumeName[3] != L'\\' ||
volumeName[index] != L'\\')
{
wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %d\n", ERROR_BAD_PATHNAME);
break;
}
volumeName[index] = L'\0';
if (QueryDosDeviceW(&volumeName[4], addr(deviceName), (DWORD)size_of(deviceName)) == 0)
{
wprintf(L"QueryDosDeviceW failed with error code %d\n", GetLastError());
break;
}
volumeName[index] = L'\\';
DWORD returnedLength = 0;
if (GetVolumePathNamesForVolumeNameW(volumeName, addr(volumePathName), (DWORD)size_of(volumePathName), &returnedLength) == 0)
{
wprintf(L"GetVolumePathNamesForVolumeNameW failed with error code %d\n", GetLastError());
continue;
}
deviceName[wcslen(deviceName)] = L'\\';
configuration.VolumeMap.insert(std::make_pair(std::wstring(deviceName), std::wstring(volumePathName)));
if (FindNextVolumeW(findHandle, addr(volumeName), (DWORD)size_of(volumePathName)) == 0)
{
break;
}
}
FindVolumeClose(findHandle);
return S_OK;
}