Delen via


Een aangepast surrogaat schrijven

Hoewel het door het systeem geleverde surrogaat meer dan voldoende is voor de meeste situaties, zijn er enkele gevallen waarin het schrijven van een aangepast surrogaat de moeite waard kan zijn. Hier volgen enkele voorbeelden:

  • Een aangepast surrogaat kan bepaalde optimalisaties of semantiek bieden die niet aanwezig zijn in het systeem surrogaat.
  • Als een IN-process DLL code bevat die afhankelijk is van hetzelfde proces als de client, werkt de DLL-server niet correct als deze wordt uitgevoerd in het systeem surrogaat. Een aangepaste surrogaat kan worden aangepast aan een specifieke DLL om hiermee om te gaan.
  • Het systeem-surrogaat ondersteunt een model met gemengde threading, zodat het zowel free-threaded als appartementmodel DLL's kan laden. Een aangepast vertegenwoordiger kan specifiek worden ontworpen om alleen DLL's voor appartementen te laden voor efficiëntie, of om een opdrachtregelargument te accepteren voor het type DLL dat geladen mag worden.
  • Een aangepaste surrogaat kan extra opdrachtregelparameters bevatten die het systeem surrogaat niet doet.
  • Het systeem surrogaat roept CoInitializeSecurity aan en geeft aan dat deze bestaande beveiligingsinstellingen moet gebruiken die zijn gevonden onder de AppID--sleutel in het register. Een aangepaste surrogaat kan een andere beveiligingscontext gebruiken.
  • Interfaces die niet extern kunnen worden gebruikt (zoals voor recente OCX's), werken niet met het systeem surrogaat. Een aangepaste surrogaat kan de interfaces van het DLL-bestand omwikkelen met een eigen implementatie en gebruikmaken van proxy-/stub-DLL's met een externe IDL-definitie die het mogelijk maakt de interface op afstand toegankelijk te maken.

De hoofd-surrogaatthread moet doorgaans de volgende installatiestappen uitvoeren:

  1. Roep CoInitializeEx aan om de thread te initialiseren en het threadingmodel in te stellen.
  2. Als u wilt dat de DLL-servers die op de server worden uitgevoerd, de beveiligingsinstellingen in de AppID registersleutel kunnen gebruiken, roept u CoInitializeSecurity- aan met de EOAC_APPID-functie. Anders worden verouderde beveiligingsinstellingen gebruikt.
  3. Roep CoRegisterSurrogate- aan om de surrogaatinterface te registreren bij COM.
  4. Roep ISurrogate::LoadDllServer aan voor de aangevraagde CLSID.
  5. Plaats de hoofdthread in een lus om regelmatig CoFreeUnusedLibraries aan te roepen.
  6. Wanneer COM ISurrogate::FreeSurrogateaanroept, herroept u alle class factories en sluit u af.

Een surrogaatproces moet de interface ISurrogate implementeren. Deze interface moet worden geregistreerd wanneer een nieuwe surrogaat wordt gestart en na het aanroepen van CoInitializeEx. Zoals aangegeven in de voorgaande stappen heeft de ISurrogate interface twee methoden die COM aanroept: LoadDllServer, om dynamisch nieuwe DLL-servers in bestaande surrogaten te laden; en FreeSurrogate, om het surrogaat vrij te maken.

De implementatie van LoadDllServer, die COM aanroept met een laadaanvraag, moet eerst een klasse factory-object maken dat ondersteuning biedt voor IUnknown, IClassFactoryen IMarshalen vervolgens CoRegisterClassObject aanroepen om het object te registreren als klassefactory voor de aangevraagde CLSID.

De klassefactory die door het surrogaatproces is geregistreerd, is niet de werkelijke klassefactory die door de DLL-server is geïmplementeerd, maar is een algemene klassefactory die wordt geïmplementeerd door het surrogaatproces dat ondersteuning biedt voor IClassFactory- en IMarshal. Omdat het de class factory van de surrogaat is en niet die van de DLL-server die wordt geregistreerd, moet de class factory van de surrogaat de echte class factory gebruiken om een exemplaar van het object voor de geregistreerde CLSID te maken. De IClassFactory::CreateInstance zou er als volgt uit moeten zien in het volgende voorbeeld:

STDMETHODIMP CSurrogateFactory::CreateInstance(
  IUnknown* pUnkOuter, 
  REFIID iid, 
  void** ppv)
{
    void* pcf;
    HRESULT hr;
 
    hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, &pcf);
    if ( FAILED(hr) )
        return hr;
    hr = ((IClassFactory*)pcf)->CreateInstance(pUnkOuter, iid, ppv);
    ((IClassFactory*)pcf)->Release();
    return hr;
}
 

De klassefabriek van de plaatsvervanger moet ook IMarshal ondersteunen, omdat een oproep naar CoGetClassObject elke interface van de geregistreerde klassefabriek kan aanvragen, niet alleen IClassFactory. Aangezien de generieke klassefactory alleen IUnknown- en IClassFactory-ondersteunt, moeten verzoeken voor andere interfaces naar het echte object worden omgeleid. Er moet dus een MarshalInterface methode zijn die vergelijkbaar moet zijn met het volgende:

STDMETHODIMP CSurrogateFactory::MarshalInterface(
  IStream *pStm,  
  REFIID riid, void *pv, 
  WORD dwDestContext, 
  void *pvDestContext, 
  DWORD mshlflags )
{   
    void * pCF = NULL;
    HRESULT hr;
 
    hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, riid, &pCF);
    if ( FAILED(hr) )
        return hr;   
    hr = CoMarshalInterface(pStm, riid, (IUnknown*)pCF, dwDestContext, pvDestContext,  mshlflags);
    ((IUnknown*)pCF)->Release();
    return S_OK;
 

De surrogaat die een DLL-server bevat, moet de klasseobjecten van de DLL-server publiceren met een aanroep naar CoRegisterClassObject. Alle klassefabrieken voor DLL-surrogaten moeten worden geregistreerd als REGCLS_SURROGATE. REGCLS_SINGLUSE en REGCLS_MULTIPLEUSE mogen niet worden gebruikt voor DLL-servers die in surrogaten zijn geladen.

Volg deze richtlijnen voor het opzetten van een surrogaatproces wanneer dit noodzakelijk is om het juiste gedrag te garanderen.

DLL-surrogaten