5

In our application, we need to use a COM dll (namely msdia100.dll) which was not registered in the system before.

Earler, we have just called the DLL by calling its DllRegisterServer via this code:

// Register DIA DLL required by Breakpad
std::string diaLibPath = "msdia100";    
HMODULE diaLib = LoadLibrary(diaLibPath.c_str());
if( diaLib == NULL )
{
    errors << "Cannot load DLL " << diaLibPath << endl;
    return;
}

typedef HRESULT ( __stdcall * regServer_t )(void);

regServer_t regServer = (regServer_t)GetProcAddress(diaLib, "DllRegisterServer");
if( regServer == NULL )
{
    errors << "Cannot get method DllRegisterServer from " << diaLibPath << endl;
    FreeLibrary(diaLib);
    return;
}
if( regServer() != S_OK )
{
    errors << "Cannot call DllRegisterServer from " << diaLibPath << endl;
}
FreeLibrary(diaLib);

This doesn't work anymore on Windows 7 (maybe also Vista, didn't tried) because to call this function, it needs Administrator privileges.

All solutions to this problem I have found where about getting those Admin rights. That is no possible solution for us because our application must also work if the user is not able to get those Admin rights.

It is also no solution for us to suddenly need an installer for our application which registeres this DLL.

So, what possibilities are there? How can I use this DLL without Admin rights? Do I have to recode COM which works without the need to register a DLL first?


The code where I uses this lib looks like this:

CComPtr<IDiaDataSource> data_source;
if (FAILED(data_source.CoCreateInstance(CLSID_DiaSource))) {
  fprintf(stderr, "CoCreateInstance CLSID_DiaSource failed "
          "(msdia80.dll unregistered?)\n");
  return false;
}

(Btw., for those who are interested: That is part of Google Breakpad.)

Albert
  • 65,406
  • 61
  • 242
  • 386
  • This is a very silly problem. I have to say, trying to find a workaround for what you are explicitly denied to do without consent from your user is not taking the security concerns of your user seriously. This is not just an innocent workaround, this is running code that the user has no way of ever being able to guess could run. Get your user to trust you first, you're not getting close to that with this approach. – Hans Passant Mar 18 '10 at 00:57
  • 5
    nobugz: There's no security concern with running a COM object that you can't get permission to register. Registration requires admin rights because it's global state, not because it's a potential security problem (like with device drivers). As long as the COM object is running as the user it's no different than if it were part of the EXE. – Gabe Mar 18 '10 at 01:06
  • 2
    nobugz I disagree. It's not a silly problem. He is not trying to workaround a security restriction and register the DLL. He's trying to use code in a COM DLL without it being registered. Think about it. If it was a normal DLL that exported a couple of C functions he could call those functions. That's all he wants to do. – richb Mar 18 '10 at 01:09

2 Answers2

8

A simple approach is to use LoadLibrary("msdia100.dll") to load the DLL directly. Then use GetProcAddress("DllGetClassObject"). You can then use IClassFactory to do the equivalent of CoCreateInstance.

So something like the following. (Disclaimer: I haven't compiled this...)

HRESULT CoCreateDiaDataSource(CComPtr<IDiaDataSource>& data_source)
{
    HMODULE hmodule = LoadLibrary("MSDIA100");
    if (!hmodule)
        return HRESULT_FROM_WIN32(GetLastError()); // library not found

    BOOL (WINAPI*DllGetClassObject)(REFCLSID,REFIID,LPVOID*) =
        (BOOL(WINAPI*)(REFCLSID,REFIID,LPVOID*))GetProcAddress(hmodule, "DllGetClassObject");

    if (!DllGetClassObject) 
        return HRESULT_FROM_WIN32(GetLastError());

    CComPtr<IClassFactory> pClassFactory;
    HRESULT hr = DllGetClassObject(CLSID_DiaSource, IID_IClassFactory, &pClassFactory);
    if (FAILED(hr))
        return hr;

    hr = pClassFactory->CreateInstance(NULL, IID_IDiaDataSource, (void**)&data_source);
    if (FAILED(hr))
        return hr;

    return S_OK;
}

Notes:

  1. In the LoadLibrary call, you may have to supply a path. I don't know where MSDIA100.DLL normally lives.

  2. I don't know what MSDIA100.DLL does. Not all COM DLLs will work with this method, particularly if they rely on COM free threaded marshalling and horrible stuff like that. However, most COM DLLs are simple apartment threaded and work fine in my experience.

Axalo
  • 2,953
  • 4
  • 25
  • 39
richb
  • 4,716
  • 5
  • 24
  • 22
  • Thanks a lot for this hint! I added some code snippet in my initial question where I use this lib. How would it look like? – Albert Mar 18 '10 at 00:21
  • Thanks a lot! Sorry if I don't put the "accepted" mark right now as I don't have time to test this until next week. – Albert Mar 18 '10 at 16:27
  • I deliver msdia100.dll together with my EXE (so it is in the same directory). LoadLibrary should find it there if I don't specify a path, shouldn't it? – Albert Mar 19 '10 at 10:39
  • msdia is a lib from MS to read debugging information (from pdb or exe) and to get debugging information for some mini coredump. Google Breakpad uses it. – Albert Mar 19 '10 at 10:41
5

I think you should try Registration free COM. See: https://web.archive.org/web/20060626025853/http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dndotnet/html/rfanetwalk.asp

[edit] In addition, I found back a link to a discussion where it is claimed that just LoadLibrary will do. Can't confirm that it works from my own experience however. See: https://web.archive.org/web/20100418223007fw_/http://www.eggheadcafe.com/forumarchives/win32programmerole/Dec2005/post25120399.asp

mirh
  • 514
  • 8
  • 14
  • Registration free COM really seems too complicated for us. Also because we want to avoid these manifests (we only had problems with them). But the discussion is really interesting. It seems that I could call CoRegisterClassObject(CLSCTX_INPROC_SERVER) somehow and it would work without having it registered. Can you maybe say how the command would look like? (I added some information in the initial question.) – Albert Mar 18 '10 at 00:17
  • Don't avoid "the manifests". Learn how they work and can help you. The can be, and are, extremely helpful. – Chris Becke Mar 18 '10 at 05:17
  • Well, this is a cross platform application and we are planning to get away from any MS dependencies as far as possible. We have many troubles esp with MSVC in our cross build environment on Linux. The plan is to get rid of MSVC after all and move to mingw as the main build system for Windows. We would like a solution which works pretty much on all systems and takes the less work to maintain as possible (i.e. the less extra work for some specific system). Windows right now is already by far on the top in required work to maintain. And I am not sure if we would have less work with Manifests. – Albert Mar 18 '10 at 16:33