2010-03-17 3 views
4

Dans notre application, nous devons utiliser une DLL COM (à savoir msdia100.dll) qui n'était pas enregistrée dans le système auparavant.Windows/C++: comment utiliser une DLL COM qui n'est pas enregistrée

earler, nous venons d'appeler la DLL en appelant sa DllRegisterServer via ce 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); 

Cela ne fonctionne plus sur Windows 7 (peut-être Vista, n'a pas essayé) car d'appeler cette fonction, il a besoin de privilèges d'administrateur.

Toutes les solutions à ce problème, j'ai trouvé où obtenir ces droits d'administrateur. Ce n'est pas une solution possible pour nous car notre application doit également fonctionner si l'utilisateur n'est pas en mesure d'obtenir ces droits d'administrateur.

Il n'est également pas une solution pour nous d'avoir soudainement besoin d'un programme d'installation pour notre application qui enregistre cette DLL.

Alors, quelles sont les possibilités? Comment puis-je utiliser cette DLL sans droits d'administrateur? Dois-je recoder COM qui fonctionne sans avoir besoin d'enregistrer une DLL en premier?


Le code où j'utilise cette lib ressemble à ceci:

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

(BTW, pour ceux qui sont intéressés.. Cela fait partie de Google Breakpad)

+0

Ceci est un problème très stupide. Je dois dire, essayer de trouver une solution de contournement pour ce que vous êtes explicitement refusé de faire sans le consentement de votre utilisateur ne prend pas au sérieux les préoccupations de sécurité de votre utilisateur. Ce n'est pas seulement une solution de contournement innocente, c'est le code en cours d'exécution que l'utilisateur n'a aucun moyen de pouvoir deviner. Demandez à votre utilisateur de vous faire confiance d'abord, vous ne vous en approchez pas avec cette approche. –

+5

nobugz: Il n'y a pas de problème de sécurité avec l'exécution d'un objet COM que vous ne pouvez pas obtenir l'autorisation d'enregistrer.L'enregistrement nécessite des droits d'administrateur parce que c'est un état global, et non parce qu'il s'agit d'un problème de sécurité potentiel (comme avec les pilotes de périphériques). Tant que l'objet COM s'exécute en tant qu'utilisateur, il n'est pas différent de s'il faisait partie du fichier EXE. – Gabe

+2

nobugz Je ne suis pas d'accord. Ce n'est pas un problème stupide. Il n'essaie pas de contourner une restriction de sécurité et d'enregistrer la DLL. Il essaie d'utiliser du code dans une DLL COM sans qu'il soit enregistré. Penses-y. Si c'était une DLL normale qui exportait quelques fonctions C, il pouvait appeler ces fonctions. C'est tout ce qu'il veut faire. – richb

Répondre

5

Je pense que vous devrait essayer Inscription gratuite COM. Voir: http://msdn.microsoft.com/en-us/library/ms973913.aspx

[modifier] De plus, je trouve de nouveau un lien vers une discussion où on prétend que tout LoadLibrary fera. Je ne peux pas confirmer que cela fonctionne de ma propre expérience cependant. Voir: http://www.eggheadcafe.com/forumarchives/win32programmerole/Dec2005/post25120399.asp

+0

+1, article vraiment intéressant. –

+0

Inscription gratuite COM semble vraiment trop compliqué pour nous. Aussi parce que nous voulons éviter ces manifestes (nous avons seulement eu des problèmes avec eux). Mais la discussion est vraiment intéressante. Il semble que je pourrais appeler CoRegisterClassObject (CLSCTX_INPROC_SERVER) d'une manière ou d'une autre et cela fonctionnerait sans l'avoir enregistré. Pouvez-vous dire à quoi ressemblerait la commande? (J'ai ajouté quelques informations dans la question initiale.) – Albert

+0

Ne pas éviter "les manifestes". Apprenez comment ils fonctionnent et peuvent vous aider. Le peut être, et est, extrêmement utile. –

8

Une approche simple consiste à utiliser LoadLibrary ("msdia100.dll") pour charger la DLL directement. Ensuite, utilisez GetProcAddress ("DllGetClassObject"). Vous pouvez ensuite utiliser IClassFactory pour faire l'équivalent de CoCreateInstance.

Donc quelque chose comme ce qui suit. (Avertissement: Je ne l'ai pas compilé ce ...)

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. Dans l'appel LoadLibrary, vous pouvez avoir à fournir un chemin. Je ne sais pas où MSDIA100.DLL vit normalement.

  2. Je ne sais pas ce que MSDIA100.DLL fait. Toutes les DLLs COM ne fonctionneront pas avec cette méthode, en particulier si elles s'appuient sur le marshalling threading gratuit COM et des trucs horribles comme ça. Cependant, la plupart des DLL COM sont des threads d'appartement simples et fonctionnent très bien dans mon expérience.

+0

Merci beaucoup pour cet indice! J'ai ajouté un extrait de code dans ma question initiale où j'utilise cette lib. À quoi ressemblerait-il? – Albert

+0

J'ai ajouté un exemple de code pour vous. – richb

+0

Merci beaucoup! Désolé si je ne mets pas la marque "acceptée" dès maintenant car je n'ai pas le temps de la tester jusqu'à la semaine prochaine. – Albert

Questions connexes