-
Notifications
You must be signed in to change notification settings - Fork 275
Open
Description
This suggestion was originally proposed in microsoft/cppwinrt#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
}
}jschroedl
Metadata
Metadata
Assignees
Labels
No labels