Aracılığıyla paylaş


Özel Vekil Yazma

Sistem tarafından sağlanan vekil çoğu durum için fazlasıyla yeterli olsa da, özel vekil yazmanın faydalı olabileceği bazı durumlar vardır. Aşağıda bazı örnekler verilmiştir:

  • Özelleştirilmiş bir vekil, sistem vekilinde bulunmayan bazı iyileştirmeler veya semantik özellikler sağlayabilir.
  • İşlem içi DLL, istemciyle aynı işlemde olmasına bağlı olan bir kod içeriyorsa, sistem vekilinde çalışıyorsa DLL sunucusu düzgün çalışmaz. Özel bir vekil, bununla başa çıkmak için belirli bir DLL'ye uyarlanabilir.
  • Sistem vekili, hem ücretsiz hem de apartman modeli DLL'lerini yükleyebilmesi için karma iş parçacığı modelini destekler. Özel bir vekil, verimlilik nedeniyle yalnızca daire DLL'lerini yüklemek veya yüklenmesine izin verilen DLL türü için bir komut satırı bağımsız değişkenini kabul etmek üzere uyarlanabilir.
  • Özel bir vekil, sistem vekilinin almadığı ek komut satırı parametreleri alabilir.
  • Sistem vekili, CoInitializeSecurityçağırır ve kayıt defterindeki AppID anahtarı altında bulunan mevcut güvenlik ayarlarını kullanmasını söyler. Özel bir vekil başka bir güvenlik bağlamı kullanabilir.
  • Uzak erişilebilir olmayan arabirimler (güncel OCX'ler gibi) sistem vekiliyle çalışmaz. Özel bir vekil, DLL'nin arabirimlerini kendi uygulamasıyla sarmalayabilir ve arabirimin uzaktan erişilebilir olmasına izin veren bir IDL tanımıyla ara sunucu/saplama DLL'leri kullanabilir.

Ana vekil iş parçacığı genellikle aşağıdaki kurulum adımlarını gerçekleştirmelidir:

  1. İş parçacığını başlatmak ve iş parçacığı modelini ayarlamak için CoInitializeEx çağırın.
  2. Sunucuda çalıştırılacak DLL sunucularının AppID kayıt defteri anahtarındaki güvenlik ayarlarını kullanabilmesini istiyorsanız, EOAC_APPID özelliğiyle coInitializeSecurityçağırın. Aksi takdirde eski güvenlik ayarları kullanılır.
  3. Vekil arabirimi COM'a kaydetmek için CoRegisterSurrogateçağırın.
  4. İstenen CLSID için ISurrogate::LoadDllServerçağırın.
  5. Ana iş parçacığını, CoFreeUnusedLibraries'ü düzenli aralıklarla çağırmak için bir döngüye yerleştirin.
  6. COM ISurrogate::FreeSurrogateçağırdığında, tüm sınıf fabrikalarını iptal edin ve çıkın.

Yedek işlem, ISurrogate arabirimini uygulamalıdır. Yeni bir vekil başlatıldığında ve CoInitializeExçağrıldıktan sonra bu arabirim kaydedilmelidir. Önceki adımlarda belirtildiği gibi, ISurrogate arabiriminde COM’un çağırdığı iki yöntem vardır: LoadDllServer, mevcut vekillere yeni DLL sunucularını dinamik olarak yüklemek için; ve FreeSurrogate, vekili serbest bırakmak için.

COM'un bir yük isteğiyle çağırdığı LoadDllServeruygulaması, önce IUnknown, IClassFactoryve IMarshaldestekleyen bir sınıf fabrikası nesnesi oluşturmalı ve sonra nesneyi istenen CLSID için sınıf fabrikası olarak kaydetmek için CoRegisterClassObject çağırmalıdır.

Vekil işlem tarafından kaydedilen sınıf fabrikası, DLL sunucusu tarafından uygulanan gerçek sınıf fabrikası değildir, ancak IClassFactory ve IMarshaldestekleyen vekil işlem tarafından uygulanan genel bir sınıf fabrikasıdır. Bu, kaydedilen DLL sunucusunun değil, vekilin sınıf fabrikası olduğundan, vekilin sınıf fabrikasının kayıtlı CLSID için nesnenin bir örneğini oluşturmak için gerçek sınıf fabrikasını kullanması gerekir. Vekilin IClassFactory::CreateInstance aşağıdaki örneğe benzer olmalıdır:

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;
}
 

CoGetClassObject çağrısı yalnızca IClassFactorydeğil, kayıtlı sınıf fabrikasından herhangi bir arabirim isteyebileceğinden, vekilin sınıf fabrikası da IMarshaldesteklemelidir. Ayrıca, genel sınıf fabrikası yalnızca IUnknown ve IClassFactorydesteklediğinden, diğer arabirimlere yönelik istekler gerçek nesneye yönlendirilmelidir. Bu nedenle, aşağıdakine benzer bir MarshalInterface yöntemi olmalıdır:

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;
 

Bir DLL sunucusunu barındıran vekilin, CoRegisterClassObjectçağrısıyla DLL sunucusunun sınıf nesnelerini yayımlaması gerekir. DLL vekilleri için tüm sınıf fabrikaları REGCLS_SURROGATE olarak kaydedilmelidir. REGCLS_SINGLUSE ve REGCLS_MULTIPLEUSE, aracılara yüklenen DLL sunucuları için kullanılmamalıdır.

Bunun gerekli olduğu durumlarda vekil işlem oluşturmaya yönelik bu yönergelerin takip edilmesi uygun davranışı güvence altına almalıdır.

DLL Vekilleri