Flylib.com

Books Software

 
 
 

Essential COM - page 80

, , ÷ , . ÷ . ÷ , ø ÷ ÷, . ÷ , ø DllCanUnloadNow . , ÷ 3 , ÷ ÷ , ÷ , ø ø :

// reasons to remain loaded
// причины оставаться загруженными
LONG g_cLocks = 0;
// called from AddRef + IClassFactory::LockServer(TRUE)
// вызвано из AddRef + IClassFactory::LockServer(TRUE)
void LockModule(void)
  { InterlockedIncrement(&g_cLocks); }
// called from Release + IClassFactory::LockServer(FALSE)
// вызвано из Release + IClassFactory::LockServer(FALSE)
void UnlockModule(void)
  { InterlockedDecrement(&g_cLocks); }

DllCanUnloadNow :

STDAPI DllCanUnloadNow() { return g_cLocks ? S_FALSE : S_OK; }

DllCanUnloadNow ÷, ø " " CoFreeUnusedLibraries .

÷ , - . - , ÷. ÷ , " ", , . ÷. ÷ Win32 Event, API- SetEvent :

void UnlockModule(void)
{
    if (InterlockedDecrement(&g_cLocks) ==0) {
        extern HANDLE g_heventShutdown;
        SetEvent(g_heventShutdown);
    }
}

÷ Windows MSG , API-. PostThreadMessage ÷ WM_QUIT :

void UnlockModule(void)
{
    if (InterlockedDecrement(&g_cLocks) == 0) {
        extern DWORD g_dwMainThreadID;
          // set from main thread
          // установлено из основного потока
        PostThreadMessage(g_dwMainThreadID, WNLQUIT, О, 0);
    }
}

STA , ÷ , API- PostQuitMessage :

void UnlockModule(void)
{
    if (InterlockedDecrement(&g_cLocks) == 0)
        PostQuitMessage(0);
}

.

÷ , ÷ . ÷ IClassFactory::LockServer(TRUE) . .

, , ø . :

STDMETHODIMP_(ULONG) MyClassObject::AddRef(void) {
    LockModule();
      // note outstanding reference
      // отмечаем неосвобожденную ссылку
    return 2;
      // non-heap-based object
      // объект, размещенный не в "куче"
}

STDMETHODIMP_(ULONG) MyClassObject::Release(void) {
    UnlockModule();
      // note destroyed reference
      // отмечаем уничтоженную ссылку
    return 1;
      // non-heap-based object
      // объект, размещенный не в "куче"
}

, DLL , ø , Release .

, ø AddRef Release . , ÷ COM , ÷ ÷ , - COM CoRegisterClassObject . , , ø COM . ÷, ÷ ÷÷ ÷ . ( self-imposed ) CoRevokeClassObject . , ÷ CoRevokeClassObject , ÷÷ , ÷ ÷, ÷ .

× ÷ ø , ø AddRef Release :

STDMETHODIMP_(ULONG) MyClassObject::AddRef(void) {
      // ignore outstanding reference
      // игнорируем неосвобожденную ссылку
    return 2;
      // non-heap-based object
      // объект, размещенный не в "куче"
}

STDMETHODIMP_(ULONG) MyClassObject::Release(void) {
      // ignore destroyed reference
      // игнорируем уничтоженную ссылку
    return 1;
      // non-heap-based object
      //объект, размещенный не в "куче"
}

÷, ÷ ÷÷ .

{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

÷, ÷ , , ÷ . ÷ . , ÷ , ø . ø AddRef Release , COM . ø ø , SCM . CoMarshalInterface . IExternalConnection , , ÷ ø , . , ÷ IExternalConnection , o :

STDMETHODIMP_(DWORD) MyClassObject::AddConnection(DWORD extconn, DWORD)
{
    DWORD res = 0;
    if (extconn & EXTCONN_STRONG) {
        LockModule();
          // note external reference
          // записываем внешнюю ссылку
        res = InterlockedIncrement(&m_cExtRef);
    }
    return res;
}

STDMETHODIMP_(DWORD) MyClassObject::ReleaseConnection(DWORD extconn, DWORD, 
                                                      BOOL bLastReleaseKillsStub)
{
    DWORD res = 0;
    if (extconn & EXTCONN_STRONG) {
        UnlockModule();
          // note external reference
          // записываем внешнюю ссылку
        res = InterlockedDecrement(&m_cExtRef);
        if (res == 0 & bLastReleaseKillsStub)
            CoDisconnectObject((IExternalConnection*)this, 0);
    }
    return res;
}

, ÷ ÷÷ , ø , , COM, .

IExternalConnection COM , ø ÷ . ø ÷ ø ø . LockServer IClassFactory , ø ÷ , ÷ ÷ . ø ÷ ø LockServer , . :

IClassFactory *pcf = 0;

HRESULT hr = CoGetClassObject(CLSID_You, CLSCTX_LOCAL_SERVER,
                              О, IID_IClassFactory, (void**)&pcf);
if (SUCCEEDED(hr))
    hr = pcf->LockServer(TRUE);
      // keep server running?
      // поддерживать выполнение сервера?

COM . , ÷ CoGetClassObject IClassFactory::LockServer . ÷ ÷ . , ø LockServer . ÷ :

IClassFactory *pcf = 0;
HRESULT hr = S_OK;
do {
    if (pcf) pcf->Release();
    hr = CoGetClassObject(CLSID_You, CLSCTX_LOCAL_SERVER,
                          0, IID_IClassFactory, (void**)&pcf);
    if (FAILED(hr))
        break;
    hr = pcf->LockServer(TRUE);
      // keep server running?
      // поддерживать выполнение сервера?
} while (FAILED(hr));

, ÷ ÷ , LockServer ø. ø - CoGetClassObject LockServer , LockServer ø, , ÷ . Windows NT 3.51 ÷ .

, ÷ IExternalConnection , COM Windows NT 4.0 . ø CoGetClass0bject SCM IClassFactory::LockServer . ÷ ø IClassFactory , COM ÷ ÷ . IClassFactory COM, ÷ Windows NT 4.0, IExternalConnection .

, . , ÷ ø , , ÷ ÷ ( shutdown sequence ) . × CoRevokeClassObject . , , UnlockModule , . , ÷ , SetEvent PostThreadMessage , , , CoRevokeClassObject , . , , ÷ - ÷ . COM API-:

ULONG CoAddRefServerProcess(void);
ULONG CoReleaseServerProcess(void);

÷÷ . COM, ÷ , ÷ ÷÷ . , CoReleaseServerProcess , ÷ , SCM, ÷ CLSID.

:

void LockModule(void)
{
    CoAddRefServerProcess();
      // COM maintains lock count
      // COM устанавливает счетчик блокировок
}

void UnlockModule(void)
{
    if (CoReleaseServerProcess() == 0)
        SetEvent(g_heventShutdown);
}

, ÷ - . ø .

CoAddRefServerProcess / CoReleaseServerProcess . , ÷ CoReleaseServerProcess RPC ÷ SCM. SCM ÷ , CoReleaseServerProcess COM, , ÷ ÷ , SCM ø ÷ ( CO_E_SERVER_STOPPING ). SCM ÷ , , . , COM, , ÷ ÷ CoReleaseServerProcess . × , CO_E_SERVER_STOPPING IClassFactory::Create Instance , IPersistFile::Load ÷, , ÷ ÷ - . :

STDMETHODIMP MyClassObject::CreateInstance(IUnknown *puo,
                                           REFIID riid, void **ppv)
{
    LockModule();
      // ensure we don't shut down while in call
      // убеждаемся в том, что не прекращаем работу
      // во время вызова
    HRESULT hr;
    *ppv = 0;
      // shutdown initiated?
      // процесс останова запущен?
    DWORD dw = WaitForSingleObject(g_heventShutdown, 0);
    if (dw == WAIT_OBJECT_0)
        hr = CO_E_SERVER_STOPPING;
    else {
          // normal CreateInstance implementation
          // нормальная реализация CreateInstance
    }
    UnlockModule();
    return hr;
}

÷ COM .