void Flush()

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();
                        }
                    }
                }