Bagikan melalui


Menulis Pengganti Kustom

Meskipun pengganti yang disediakan sistem akan lebih dari memadai untuk sebagian besar situasi, ada beberapa kasus di mana membuat pengganti kustom dapat bernilai. Berikut ini adalah beberapa contoh:

  • 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.
  • Surrogat sistem mendukung model pemrograman ulir campuran sehingga dapat memuat DLL model bebas 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 menerima parameter baris perintah tambahan yang tidak diterima oleh 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 diakses dari jarak jauh (seperti untuk OCX terbaru) tidak akan berfungsi dengan surrogat sistem. Pengganti kustom dapat membungkus antarmuka DLL dengan implementasinya sendiri dan menggunakan DLL proksi/stub dengan definisi IDL yang dapat diakses dari jarak jauh yang akan memungkinkan antarmuka tersebut 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. PanggilCoRegisterSurrogate untuk mendaftarkan antarmuka pengganti ke COM.
  4. Panggil ISurrogate::LoadDllServer untuk CLSID yang diminta.
  5. Tempatkan utas utama dalam loop untuk memanggil CoFreeUnusedLibraries secara berkala.
  6. Ketika COM memanggil ISurrogate::FreeSurrogate, batalkan semua fabrik kelas dan keluar.

Proses pengganti harus menerapkan antarmuka ISurrogate . Antarmuka ini harus didaftarkan ketika proses pengganti baru dimulai dan setelah memanggil CoInitializeEx. Seperti yang ditunjukkan dalam langkah-langkah sebelumnya, antarmuka ISurrogate memiliki dua metode yang dipanggil COM: LoadDllServer, untuk memuat server DLL baru secara dinamis 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 dari pengganti, bukan server DLL yang sedang didaftarkan, pabrik kelas pengganti perlu menggunakan pabrik kelas sebenarnya untuk membuat instance dari objek untuk CLSID yang terdaftar. Pengganti IClassFactory::CreateInstance seharusnya 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 fabrik kelas generik hanya mendukung IUnknown dan IClassFactory, permintaan untuk antarmuka lain perlu diarahkan ke objek yang sebenarnya. Dengan demikian, harus ada metode MarshalInterface yang serupa 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 dalam proses surrogate.

Mengikuti panduan ini untuk membuat proses pengganti ketika diperlukan harus memastikan perilaku yang benar.

Pengganti DLL