microsoft / microsoft/wil

Suggestion: Support functions for COM class & TypeLib registration

Open
#531 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
3k
Forks
300
Avg merge
19h 12m
Merged PRs (30d)
1

Description

This suggestion was originally proposed in https://github.com/microsoft/cppwinrt/issues/1492, but the response was then to move the request to the WIL project.

BACKGROUND: I've just started modernizing some existing ATL projects to C++/WinRT. One challenge I then faced was lack of inbuilt support for registration of COM classes and type libraries. It would be very helpful if either WinRT or WIL could be extended with either support functions or sample code to demonstrate "best practice" in this area.

My "ask" is basically to add code resembling the RegisterTypeLibrary and RegisterComClass functions below to the repo.

Suggested code to add to the repo
/** COM type library (un)registration function. */
void RegisterTypeLibrary(bool do_register, std::wstring tlb_path) {
    if (do_register) {
        // register typelib
        CComPtr<ITypeLib> tlb;
        HRESULT hr = LoadTypeLibEx(tlb_path.c_str(), REGKIND_REGISTER, &tlb);
        assert(SUCCEEDED(hr));
    } else {
        // unregister typelib
        CComPtr<ITypeLib> tlb;
        HRESULT hr = LoadTypeLibEx(tlb_path.c_str(), REGKIND_NONE, &tlb);
        assert(SUCCEEDED(hr));

        TLIBATTR* attrPtr = nullptr;
        hr = tlb->GetLibAttr(&attrPtr);
        assert(SUCCEEDED(hr));

        UnRegisterTypeLib(attrPtr->guid, attrPtr->wMajorVerNum, attrPtr->wMinorVerNum, attrPtr->lcid, attrPtr->syskind); // will fail if already unregistered

        tlb->ReleaseTLibAttr(attrPtr);
    }
}

/** COM class (un)registration function. */
void RegisterComClass(bool do_register, CLSID clsid, ::GUID tlbGuid, std::wstring dll_exe_path) {
    std::wstring clsid_str(38, L'\0');
    int ret = StringFromGUID2(clsid, clsid_str.data(), static_cast<int>(clsid_str.size() + 1));
    assert(ret == 39); ret; // includes zero-termination

    if (do_register) {
        // register COM class
        std::wstring file_ext = dll_exe_path.substr(dll_exe_path.find_last_of(L'.'));

        if (!_wcsicmp(file_ext.c_str(), L".exe")) {
            std::wstring key_path = L"CLSID\\" + clsid_str + L"\\LocalServer32";
            CRegKey key;
            LSTATUS res = key.Create(HKEY_CLASSES_ROOT, key_path.c_str());
            assert(res == ERROR_SUCCESS); res;

            key.SetStringValue(nullptr, dll_exe_path.c_str());
        } else if (!_wcsicmp(file_ext.c_str(), L".dll")) {
            std::wstring key_path = L"CLSID\\" + clsid_str + L"\\InprocServer32";
            CRegKey key;
            LSTATUS res = key.Create(HKEY_CLASSES_ROOT, key_path.c_str());
            assert(res == ERROR_SUCCESS); res;

            key.SetStringValue(nullptr, dll_exe_path.c_str());
        } else {
            wprintf(L"ERROR: Unsupported file extension.\n");
            abort();
        }

        {
            std::wstring key_path = L"CLSID\\" + clsid_str + L"\\TypeLib";
            CRegKey key;
            LSTATUS res = key.Create(HKEY_CLASSES_ROOT, key_path.c_str());
            assert(res == ERROR_SUCCESS); res;

            wchar_t tlb_str[39] = {};
            StringFromGUID2(tlbGuid, tlb_str, static_cast<int>(std::size(tlb_str)));
            key.SetStringValue(nullptr, tlb_str);
        }
    } else {
        // unregister COM class
        CRegKey parent;
        LSTATUS res = parent.Open(HKEY_CLASSES_ROOT, L"CLSID", KEY_READ | KEY_WRITE);
        assert(res == ERROR_SUCCESS); res;

        parent.RecurseDeleteKey(clsid_str.c_str()); // will fail if already unregistered
    }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the proposed RegisterTypeLibrary and RegisterComClass functions, including their LoadTypeLibEx and registry API usage. Then inspect the WIL repository for existing patterns that could define the supported API or sample location. Done means an agreed scope and an implemented, documented approach with validation for registration and unregistration.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.