Bagikan melalui


Menulis Pengganti Kustom

Meskipun pengganti yang disediakan sistem akan lebih dari memadai untuk sebagian besar situasi, ada beberapa kasus di mana menulis pengganti kustom bisa berharga. Berikut adalah beberapa contohnya:

  • Pengganti kustom dapat memberikan beberapa pengoptimalan atau semantik yang tidak ada di pengganti sistem.
  • Jika DLL dalam proses berisi kode yang bergantung pada berada dalam proses yang sama dengan klien, server DLL tidak akan berfungsi dengan benar jika berjalan di pengganti sistem. Pengganti kustom dapat disesuaikan dengan DLL tertentu untuk menangani hal ini.
  • Pengganti sistem mendukung model mixed-threading sehingga dapat memuat DLL model gratis dan apartemen. Pengganti kustom mungkin disesuaikan untuk memuat HANYA DLL apartemen karena alasan efisiensi atau untuk menerima argumen baris perintah untuk jenis DLL yang diizinkan untuk dimuat.
  • Pengganti kustom dapat mengambil parameter baris perintah tambahan yang tidak dilakukan pengganti sistem.
  • Pengganti sistem memanggil CoInitializeSecurity dan memberi tahunya untuk menggunakan pengaturan keamanan yang ada yang ditemukan di bawah kunci AppID di registri. Pengganti kustom dapat menggunakan konteks keamanan lain.
  • Antarmuka yang tidak dapat diremobilitas (seperti untuk OCX terbaru) tidak akan berfungsi dengan pengganti sistem. Pengganti kustom dapat membungkus antarmuka DLL dengan implementasinya sendiri dan menggunakan DLL proksi/stub dengan definisi IDL yang dapat diremotable yang akan memungkinkan antarmuka untuk di-remote.

Utas pengganti utama biasanya harus melakukan langkah-langkah penyiapan berikut:

  1. Panggil CoInitializeEx untuk menginisialisasi utas dan mengatur model utas.
  2. Jika Anda ingin server DLL yang dijalankan di server dapat menggunakan pengaturan keamanan di kunci registri AppID , panggil CoInitializeSecurity dengan kemampuan EOAC_APPID. Jika tidak, pengaturan keamanan warisan akan digunakan.
  3. Panggil CoRegisterSurrogate untuk mendaftarkan antarmuka pengganti ke COM.
  4. Panggil ISurrogate::LoadDllServer untuk CLSID yang diminta.
  5. Letakkan utas utama dalam perulangan untuk memanggil CoFreeUnusedLibraries secara berkala.
  6. Ketika COM memanggil ISurrogate::FreeSurrogate, cabut semua pabrik kelas dan keluar.

Proses pengganti harus menerapkan antarmuka ISurrogate. Antarmuka ini harus didaftarkan ketika pengganti baru dimulai dan setelah memanggil CoInitializeEx. Seperti yang ditunjukkan dalam langkah-langkah sebelumnya, antarmuka ISurrogate memiliki dua metode yang dipanggil COM: LoadDllServer, untuk secara dinamis memuat server DLL baru ke pengganti yang ada; dan FreeSurrogate, untuk membebaskan pengganti.

Implementasi LoadDllServer, yang dipanggil COM dengan permintaan beban, harus terlebih dahulu membuat objek pabrik kelas yang mendukung IUnknown, IClassFactory, dan IMarshal, lalu memanggil CoRegisterClassObject untuk mendaftarkan objek sebagai pabrik kelas untuk CLSID yang diminta.

Pabrik kelas yang terdaftar oleh proses pengganti bukanlah pabrik kelas aktual yang diterapkan oleh server DLL tetapi merupakan pabrik kelas generik yang diterapkan oleh proses pengganti yang mendukung IClassFactory dan IMarshal. Karena ini adalah pabrik kelas pengganti, daripada server DLL yang sedang didaftarkan, pabrik kelas pengganti perlu menggunakan pabrik kelas nyata untuk membuat instans objek untuk CLSID terdaftar. IClassFactory::CreateInstance pengganti akan terlihat seperti contoh berikut:

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

Pabrik kelas pengganti juga harus mendukung IMarshal karena panggilan ke CoGetClassObject dapat meminta antarmuka apa pun dari pabrik kelas terdaftar, bukan hanya IClassFactory. Selanjutnya, karena pabrik kelas generik hanya mendukung IUnknown dan IClassFactory, permintaan untuk antarmuka lain harus diarahkan ke objek nyata. Dengan demikian, harus ada metode MarshalInterface yang harus mirip dengan yang berikut:

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;
 

Pengganti yang menampung server DLL harus menerbitkan objek kelas server DLL dengan panggilan ke CoRegisterClassObject. Semua pabrik kelas untuk pengganti DLL harus terdaftar sebagai REGCLS_SURROGATE. REGCLS_SINGLUSE dan REGCLS_MULTIPLEUSE tidak boleh digunakan untuk server DLL yang dimuat ke pengganti.

Mengikuti panduan ini untuk membuat proses pengganti ketika perlu melakukannya harus memastikan perilaku yang tepat.

Pengganti DLL