in include/wil/Tracelogging.h [3571:3671]
void Flush(wistd::function<void(PCWSTR, PCWSTR, PCSTR, UINT32*, UINT16)> flushCallback)
{
wistd::unique_ptr<ApiData> root;
if (m_root)
{
auto lock = m_lock.lock_exclusive();
root.swap(m_root);
}
while (root)
{
// First find the number of characters we need to allocate for each string, and the number of items in the counter array to allocate
size_t totalApiListLength = 1; // Init to 1 to account for null terminator
size_t totalSpecializationsLength = 1; // Init to 1 to account for null terminator
UINT16 numCounts = 0;
ProcessSingleNamespace(&root,
[&](wistd::unique_ptr<ApiData>& node)
{
// Get the length needed for the class string
const wchar_t* strAfterNamespace = GetClassStringPointer(node->className);
size_t classStrLen = wcslen(strAfterNamespace ? strAfterNamespace : node->className);
totalApiListLength += (classStrLen + wcslen(node->apiName) + 1); // We add 1 to account for the comma delimeter
if (node->specialization)
{
totalSpecializationsLength += strlen(node->specialization) + 1; // We add 1 to account for the comma delimeter
}
else
{
totalSpecializationsLength += 2; // '-' plus comma delimeter
}
numCounts++;
});
// Fill arrays with the API data, and then pass it to the callback function
wistd::unique_ptr<wchar_t[]> apiList(new(std::nothrow) wchar_t[totalApiListLength]);
wistd::unique_ptr<char[]> specializationList(new(std::nothrow) char[totalSpecializationsLength]);
wistd::unique_ptr<UINT32[]> countArray(new(std::nothrow) UINT32[numCounts]);
size_t nameSpaceLength = GetNameSpaceLength(root->className) + 1;
wistd::unique_ptr<wchar_t[]> nameSpace(new(std::nothrow) wchar_t[nameSpaceLength]);
if (!apiList || !specializationList || !countArray || !nameSpace)
{
return;
}
ZeroMemory(apiList.get(), totalApiListLength * sizeof(wchar_t));
ZeroMemory(specializationList.get(), totalSpecializationsLength * sizeof(char));
ZeroMemory(countArray.get(), numCounts * sizeof(UINT32));
ZeroMemory(nameSpace.get(), nameSpaceLength * sizeof(wchar_t));
StringCchCopyNW(nameSpace.get(), STRSAFE_MAX_CCH, root->className, nameSpaceLength - 1);
int countArrayIndex = 0;
wistd::unique_ptr<ApiData>* lastNamespaceNode = ProcessSingleNamespace(&root,
[&](wistd::unique_ptr<ApiData>& node)
{
countArray[countArrayIndex] = static_cast<UINT32>(::InterlockedExchangeNoFence(node->counterReference, 0));
// Prepend the portion of the apiName group string that's after the '.'. So for example, if the
// className is "Windows.System.Launcher", then we prepend "Launcher." to the apiName string.
const wchar_t* strAfterNamespace = GetClassStringPointer(node->className);
if (strAfterNamespace)
{
FAIL_FAST_IF_FAILED(StringCchCatW(apiList.get(), totalApiListLength, strAfterNamespace + 1));
FAIL_FAST_IF_FAILED(StringCchCatW(apiList.get(), totalApiListLength, L"."));
}
FAIL_FAST_IF_FAILED(StringCchCatW(apiList.get(), totalApiListLength, node->apiName));
if (node->specialization)
{
FAIL_FAST_IF_WIN32_ERROR(strncat_s(specializationList.get(), totalSpecializationsLength, node->specialization, strlen(node->specialization)) != 0);
}
else
{
FAIL_FAST_IF_WIN32_ERROR(strncat_s(specializationList.get(), totalSpecializationsLength, "-", 1) != 0);
}
if (countArrayIndex != (numCounts - 1))
{
FAIL_FAST_IF_FAILED(StringCchCatW(apiList.get(), totalApiListLength, L","));
FAIL_FAST_IF_WIN32_ERROR(strncat_s(specializationList.get(), totalSpecializationsLength, ",", 1) != 0);
}
countArrayIndex++;
});
// Call the callback function with the data we've collected for this namespace
flushCallback(nameSpace.get(), apiList.get(), specializationList.get(), countArray.get(), numCounts);
if (*lastNamespaceNode)
{
root.swap((*lastNamespaceNode)->next);
}
else
{
root.reset();
}
}
}