WUA API empty download URL for cumulative updates

NAVEENKUMAR K 1 Reputation point
2022-03-21T10:57:10.503+00:00

I am using a C++ program which uses WUA API to scan for updates against Microsoft Update Catalog. Things were working fine for quite a while, but in recent days, I am seeing certain KB articles are not providing download URL. These are especially cumulative updates.

I have verified Microsoft Update Catalog for same KB article, but there I can find the updates available and able to download from there. Please help on this.

Client operating system: Windows 10 version 21H1 (OS Build 19043.1586)

Code snippet:

include <wuapi.h>

include <comdef.h>

include <atlbase.h>

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);

IUpdateSession          *lpUpdateSession;
HRESULT hr = CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&lpUpdateSession);

if(hr != S_OK)
{
    _tprintf( _T("%s - 0x%X\n"), _T("Failed to create update session.\n\n"), hr);
    return -1;
}

IUpdateSearcher         *lpUpdateSearcher;
if((hr = lpUpdateSession->CreateUpdateSearcher(&lpUpdateSearcher)) != S_OK)
{
    _tprintf( _T("Failed to create searcher 0x%X\n\n"),hr);
    return -1;
}

IUpdateServiceManager   *lpUpdateServiceManager;
if((hr = CoCreateInstance(CLSID_UpdateServiceManager, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateServiceManager, (LPVOID*)&lpUpdateServiceManager)) != S_OK)
{
    _tprintf( _T("Created Update service Manager failed 0x%X\n\n"),hr);
    return -1;
}

lpUpdateSession->put_ClientApplicationID(bstr_t("MyApp"));

IUpdateSearcher         *pSearcher;
hr = lpUpdateSession->CreateUpdateSearcher(&pSearcher);
pSearcher->put_ServiceID(bstr_t("7971f918-a847-4430-9279-4a52d1efe18d")); //Microsoft Update Catalog
pSearcher->put_ServerSelection(ssOthers);

BSTR bstrSearchCriteria = bstr_t("");
_TCHAR tszCriteria[1024] = _T("");
bstrSearchCriteria = bstr_t("Type='Software'");

ISearchResult           *pSearchResult;
if((hr=pSearcher->Search(bstrSearchCriteria, &pSearchResult))!= S_OK)
{
    _tprintf( _T("Failed to perform Search: 0x%X\n"),hr);
    return -1;
}
IUpdateCollection *pUpdateCollection;
pSearchResult->get_Updates(&pUpdateCollection);

long lFoundUpdateCount = 0;
pUpdateCollection->get_Count(&lFoundUpdateCount);

_tprintf( _T("Found %ld updates.\n"), lFoundUpdateCount );
for ( long l = 0; l < lFoundUpdateCount; l++ )
{
    IUpdate *lpUpdate = NULL;
    hr = pUpdateCollection->get_Item(l, &lpUpdate);
    if (hr == S_OK)
    {
        //KB Article ID
        CComQIPtr<IStringCollection> lpKBArticles;
        hr = lpUpdate->get_KBArticleIDs(&lpKBArticles);
        if(SUCCEEDED(hr) && lpKBArticles != NULL)
        {
            long lKBArticlesCount = 0;
            lpKBArticles->get_Count(&lKBArticlesCount);
            for(long kb = 0; kb < lKBArticlesCount; kb++)
            {
                BSTR bstrKB;
                lpKBArticles->get_Item(kb, &bstrKB);
                _tprintf(_T("\nKB%s\n"), (const _TCHAR*)bstr_t(bstrKB) );
            }
        }

        //Installed/missing
        VARIANT_BOOL bInstalled;
        lpUpdate->get_IsInstalled(&bInstalled);
        if( bInstalled == VARIANT_FALSE )
        {
            _tprintf( _T("Missing\n") );
        }
        else
        {
            _tprintf( _T("Installed\n") );
        }

        //Download URL
        CComQIPtr<IUpdateCollection> BundledUpdate;
        if(lpUpdate->get_BundledUpdates(&BundledUpdate) == S_OK)
        {
            long count = -1;
            BundledUpdate->get_Count(&count);

            if (count == 0)
            {
                _tprintf( _T("Empty download URL\n"));
            }
            else
            {
                _tprintf( _T("DownloadURL(s):\n"));

                for(long update = 0; update < count; update++)
                {
                    CComQIPtr<IUpdateDownloadContentCollection> retVal;
                    CComQIPtr<IUpdateDownloadContent> retItem;
                    CComQIPtr<IUpdate> retUpdate;
                    BundledUpdate->get_Item(update, &retUpdate);
                    retUpdate->get_DownloadContents(&retVal);
                    hr = retVal->get_Item(0, &retItem);
                    if(hr != S_OK)
                    {
                        continue;
                    }

                    BSTR bstrDownloadURL;
                    retItem->get_DownloadUrl(&bstrDownloadURL);
                    _tprintf( _T("%s\n"), (const _TCHAR*)bstr_t(bstrDownloadURL));
                }
            }
        }
    }
}
return 0;

}

I am getting download URL for almost all patches, but 2 KB articles I am getting empty download URL. Below is sample output.

KB890830
Installed
DownloadURL(s):
http://download.windowsupdate.com/d/msdownload/update/software/uprl/2022/02/windows-kb890830-x64-v5.98_b56cfec6692828d2b240b0978e09fa22ddf23994.exe

KB5010472
Missing
DownloadURL(s):
http://download.windowsupdate.com/d/msdownload/update/software/updt/2022/01/windows10.0-kb5010472-x64-ndp48_07d328da3e495d688287607c0c4748cb4a327b90.cab

KB890830
Installed
DownloadURL(s):
http://download.windowsupdate.com/d/msdownload/update/software/uprl/2022/03/windows-kb890830-x64-v5.99_66336e634eff1ead4e953f09165eda1da29298fb.exe

KB5011487
Installed
Empty download URL

KB4023057
Installed
Empty download URL

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,427 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,540 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Xiaopo Yang - MSFT 11,501 Reputation points Microsoft Vendor
    2022-05-05T01:39:53.927+00:00

    Hello @NAVEENKUMAR K , "Those are non-bundled updates. So, they should just do something like:"

    #include <wuapi.h>  
    #include <comdef.h>  
    #include <atlbase.h>  
    int _tmain(int argc, _TCHAR* argv[])  
    {  
        CoInitialize(NULL);  
      
        IUpdateSession* lpUpdateSession;  
        HRESULT hr = CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&lpUpdateSession);  
        if (hr != S_OK)  
        {  
            _tprintf(_T("%s - 0x%X\n"), _T("Failed to create update session.\n\n"), hr);  
            return -1;  
        }  
        /*IUpdateSearcher* lpUpdateSearcher;  
        if ((hr = lpUpdateSession->CreateUpdateSearcher(&lpUpdateSearcher)) != S_OK)  
        {  
            _tprintf(_T("Failed to create searcher 0x%X\n\n"), hr);  
            return -1;  
        }  
        IUpdateServiceManager* lpUpdateServiceManager;  
        if ((hr = CoCreateInstance(CLSID_UpdateServiceManager, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateServiceManager, (LPVOID*)&lpUpdateServiceManager)) != S_OK)  
        {  
            _tprintf(_T("Created Update service Manager failed 0x%X\n\n"), hr);  
            return -1;  
        }*/  
        lpUpdateSession->put_ClientApplicationID(bstr_t("MyApp"));  
        IUpdateSearcher* pSearcher;  
        hr = lpUpdateSession->CreateUpdateSearcher(&pSearcher);  
        pSearcher->put_ServiceID(bstr_t("7971f918-a847-4430-9279-4a52d1efe18d")); //Microsoft Update Catalog  
        //pSearcher->put_ServerSelection(ssOthers);  
        pSearcher->put_ServerSelection(ssWindowsUpdate);  
        BSTR bstrSearchCriteria = bstr_t("");  
        _TCHAR tszCriteria[1024] = _T("");  
        bstrSearchCriteria = bstr_t("Type='Software'");  
        ISearchResult* pSearchResult;  
        if ((hr = pSearcher->Search(bstrSearchCriteria, &pSearchResult)) != S_OK)  
        {  
            _tprintf(_T("Failed to perform Search: 0x%X\n"), hr);  
            return -1;  
        }  
        IUpdateCollection* pUpdateCollection;  
        pSearchResult->get_Updates(&pUpdateCollection);  
        long lFoundUpdateCount = 0;  
        pUpdateCollection->get_Count(&lFoundUpdateCount);  
        _tprintf(_T("Found %ld updates.\n"), lFoundUpdateCount);  
        for (long l = 0; l < lFoundUpdateCount; l++)  
        {  
            IUpdate* lpUpdate = NULL;  
            hr = pUpdateCollection->get_Item(l, &lpUpdate);  
            if (hr == S_OK)  
            {  
                //KB Article ID  
                CComQIPtr<IStringCollection> lpKBArticles;  
                hr = lpUpdate->get_KBArticleIDs(&lpKBArticles);  
                if (SUCCEEDED(hr) && lpKBArticles != NULL)  
                {  
                    long lKBArticlesCount = 0;  
                    lpKBArticles->get_Count(&lKBArticlesCount);  
                    for (long kb = 0; kb < lKBArticlesCount; kb++)  
                    {  
                        BSTR bstrKB;  
                        lpKBArticles->get_Item(kb, &bstrKB);  
                        _tprintf(_T("\nKB%s\n"), (const _TCHAR*)bstr_t(bstrKB));  
                    }  
                }  
                //Installed/missing  
                VARIANT_BOOL bInstalled;  
                lpUpdate->get_IsInstalled(&bInstalled);  
                if (bInstalled == VARIANT_FALSE)  
                {  
                    _tprintf(_T("Missing\n"));  
                }  
                else  
                {  
                    _tprintf(_T("Installed\n"));  
                }  
                //Download URL  
                /*CComQIPtr<IUpdateCollection> BundledUpdate;  
                if (lpUpdate->get_BundledUpdates(&BundledUpdate) == S_OK)  
                {  
                    long count = -1;  
                    BundledUpdate->get_Count(&count);  
                    if (count == 0)  
                    {  
                        _tprintf(_T("Empty download URL\n"));  
                    }  
                    else  
                    {  
                        _tprintf(_T("DownloadURL(s):\n"));  
                        for (long update = 0; update < count; update++)  
                        {  
                            CComQIPtr<IUpdateDownloadContentCollection> retVal;  
                            CComQIPtr<IUpdateDownloadContent> retItem;  
                            CComQIPtr<IUpdate> retUpdate;  
                            BundledUpdate->get_Item(update, &retUpdate);  
                            retUpdate->get_DownloadContents(&retVal);  
                            hr = retVal->get_Item(0, &retItem);  
                            if (hr != S_OK)  
                            {  
                                continue;  
                            }  
                            BSTR bstrDownloadURL;  
                            retItem->get_DownloadUrl(&bstrDownloadURL);  
                            _tprintf(_T("%s\n"), (const _TCHAR*)bstr_t(bstrDownloadURL));  
                        }  
                    }  
                }*/  
      
                //Download URL  
                long bundledUpdateCount{};  
      
                // Is it a bundled update?  
                CComQIPtr<IUpdateCollection> bundledUpdates;  
                if (lpUpdate->get_BundledUpdates(&bundledUpdates) == S_OK)  
                {  
                    bundledUpdates->get_Count(&bundledUpdateCount);  
                }  
      
                if (bundledUpdateCount > 0)  
                {  
                    _tprintf(_T("This is a bundled update.  We will iterate each update.\n"));  
      
                    _tprintf(_T("DownloadURL(s):\n"));  
      
                    for (long update = 0; update < bundledUpdateCount; update++)  
                    {  
                        CComQIPtr<IUpdateDownloadContentCollection> retVal;  
                        CComQIPtr<IUpdateDownloadContent> retItem;  
                        CComQIPtr<IUpdate> retUpdate;  
                        bundledUpdates->get_Item(update, &retUpdate);  
                        retUpdate->get_DownloadContents(&retVal);  
                        hr = retVal->get_Item(0, &retItem);  
                        if (hr != S_OK)  
                        {  
                            continue;  
                        }  
                        BSTR bstrDownloadURL;  
                        retItem->get_DownloadUrl(&bstrDownloadURL);  
                        _tprintf(_T("%s\n"), (const _TCHAR*)bstr_t(bstrDownloadURL));  
                    }  
      
                    _tprintf(_T("\n"));  
                }  
                else  
                {  
                    _tprintf(_T("This is not a bundled update.\n"));  
      
                    _tprintf(_T("DownloadURL(s):\n"));  
      
                    CComQIPtr<IUpdateDownloadContentCollection> retVal;  
                    CComQIPtr<IUpdateDownloadContent> retItem;  
                    lpUpdate->get_DownloadContents(&retVal);  
                    hr = retVal->get_Item(0, &retItem);  
                    if (hr != S_OK)  
                    {  
                        continue;  
                    }  
                    BSTR bstrDownloadURL;  
                    retItem->get_DownloadUrl(&bstrDownloadURL);  
                    _tprintf(_T("%s\n\n"), (const _TCHAR*)bstr_t(bstrDownloadURL));  
                }  
      
            }  
        }  
        return 0;  
    }  
    

    198949-image.png