//+------------------------------------------------------------------- // // File: srvmain.cxx // // Contents: Server entry points. // // Classes: none // // History: 23-Nov-92 Rickhi Created // //-------------------------------------------------------------------- #include #pragma hdrstop extern "C" { #include "wterm.h" #include #include } // globals LONG g_Usage = 0; DWORD gTlsIndex = TlsAlloc(); //+------------------------------------------------------------------- // // typedef: SCLASSDATA - class data stored in TLS. // //+------------------------------------------------------------------- typedef struct tagSCLASSDATA { ULONG cClasses; SCLASSINFO *pClsInfo; } SCLASSDATA; //+------------------------------------------------------------------- // // Function: RememberClasses // // Synopsis: Stores the class info for this thread in TLS. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- HRESULT RememberClasses(SCLASSINFO *pClsInfo, ULONG cClasses) { SCLASSDATA *pClsData = (SCLASSDATA *) new BYTE[sizeof(SCLASSDATA)]; if (pClsData) { pClsData->cClasses = cClasses; pClsData->pClsInfo = pClsInfo; TlsSetValue(gTlsIndex, pClsData); return S_OK; } return E_OUTOFMEMORY; } //+------------------------------------------------------------------- // // Function: RecallClasses // // Synopsis: retrieves the class info for this thread from TLS. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- void RecallClasses(SCLASSINFO **ppClsInfo, ULONG *pcClasses) { SCLASSDATA *pClsData = (SCLASSDATA *) TlsGetValue(gTlsIndex); if (pClsData) { *pcClasses = pClsData->cClasses; *ppClsInfo = pClsData->pClsInfo; } else { *pcClasses = 0; *ppClsInfo = NULL; } } //+------------------------------------------------------------------- // // Function: ForgetClasses // // Synopsis: removes the class info for this thread from TLS. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- void ForgetClasses() { SCLASSDATA *pClsData = (SCLASSDATA *) TlsGetValue(gTlsIndex); if (pClsData) { delete pClsData; TlsSetValue(gTlsIndex, NULL); } } //+------------------------------------------------------------------- // // Function: RegisterAllClasses // // Synopsis: loops, registering each class specified by the server. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- void RegisterAllClasses(SCLASSINFO *pClsInfo, ULONG cClasses) { // store the class info in TLS so we can get it back later // in GlobalRefs. if (FAILED(RememberClasses(pClsInfo, cClasses))) return; HRESULT hr; for (ULONG i=0; iclsid, pClsInfo->pCF, pClsInfo->dwCtx, pClsInfo->dwClsReg, &pClsInfo->dwReg); if (FAILED(hr)) { Display(TEXT("ERROR: failed CoRegisterClassObject %x\n"), hr); } } if (FAILED(hr)) { Display(TEXT("ERROR: failed CoResumeClassObjects %x\n"), hr); } } //+------------------------------------------------------------------- // // Function: RevokeAllClasses // // Synopsis: loops, revoking each class specified by the server. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- void RevokeAllClasses() { // first, get the class information from TLS SCLASSINFO *pClsInfo; ULONG cClasses; RecallClasses(&pClsInfo, &cClasses); // now revoke each of the registered classes for (ULONG i=0; idwReg != 0) { ULONG ulRef = CoRevokeClassObject(pClsInfo->dwReg); Display(TEXT("Revoked ClassObject\n")); pClsInfo->dwReg = 0; } } } //+------------------------------------------------------------------- // // Function: ReleaseAllClasses // // Synopsis: loops, releasing each class factory object. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- void ReleaseAllClasses() { // first, get the class information from TLS SCLASSINFO *pClsInfo; ULONG cClasses; RecallClasses(&pClsInfo, &cClasses); // now release each of the class factories for (ULONG i=0; ipCF->Release(); Display(TEXT("CF RefCnt = %x\n"), ulRef); } // now remove the class information from TLS ForgetClasses(); } //+------------------------------------------------------------------------- // // Function: GlobalRefs // // Synopsis: keeps track of global reference couting. Revokes all the // classes when the global count reaches 0. // // History: 06-Aug-92 Ricksa Created // //-------------------------------------------------------------------------- void GlobalRefs(BOOL fAddRef) { if (fAddRef) { g_Usage = CoAddRefServerProcess(); Display(TEXT("Object Count: %ld\n"), g_Usage); } else { if (0 == (g_Usage = CoReleaseServerProcess())) { // No more objects so we can quit Display(TEXT("Object Server Exiting\n")); PostMessage((HWND)g_hMain, WM_TERM_WND, 0, 0); } } } //+------------------------------------------------------------------- // // Function: SrvMain // // Synopsis: Special entry point for registing just 1 class. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- int SrvMain( HANDLE hInstance, REFCLSID rclsid, DWORD dwClsReg, TCHAR *pszAppName, IClassFactory *pCF) { SCLASSINFO clsinfo; clsinfo.clsid = rclsid; clsinfo.dwCtx = CLSCTX_LOCAL_SERVER, clsinfo.dwClsReg = dwClsReg; clsinfo.pCF = pCF; clsinfo.dwReg = 0; STHREADINFO ThrdInfo; ThrdInfo.hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL); ThrdInfo.hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL); ThrdInfo.hInstance = (HINSTANCE)hInstance; ThrdInfo.dwTid = GetCurrentThreadId(); ThrdInfo.pszWindow = pszAppName; ThrdInfo.dwFlags = SRVF_THREADMODEL_UNKNOWN; ThrdInfo.cClasses = 1; ThrdInfo.pClsInfo = &clsinfo; return SrvMain2(&ThrdInfo); } //+------------------------------------------------------------------- // // Function: SrvMain2 // // Synopsis: Main entry point for registering classes, entering modal // loop, and cleaning up on exit. // // History: 21-Nov-92 SarahJ Created // //-------------------------------------------------------------------- int SrvMain2(STHREADINFO *pThrdInfo) { MakeTheWindow(pThrdInfo->hInstance, pThrdInfo->pszWindow); // Initialize the OLE libraries DWORD dwThreadMode = COINIT_APARTMENTTHREADED; if (pThrdInfo->dwFlags & SRVF_THREADMODEL_UNKNOWN) { // Look up the thread mode from the win.ini file. TCHAR buffer[80]; int len; len = GetProfileString( TEXT("OleSrv"), TEXT("ThreadMode"), TEXT("MultiThreaded"), buffer, sizeof(buffer) ); if (lstrcmp(buffer, TEXT("ApartmentThreaded")) != 0) dwThreadMode = COINIT_MULTITHREADED; } else if (pThrdInfo->dwFlags & SRVF_THREADMODEL_MULTI) { dwThreadMode = COINIT_MULTITHREADED; } HRESULT hr = CoInitializeEx(NULL, dwThreadMode); if (SUCCEEDED(hr)) { // registe all the classes RegisterAllClasses(pThrdInfo->pClsInfo, pThrdInfo->cClasses); } else { Display(TEXT("ERROR: failed OleInitialize %x\n"), hr); } if (pThrdInfo->dwFlags & SRVF_REGISTER_RESUME) { hr = CoResumeClassObjects(); } // notify the main thread we are running now SetEvent(pThrdInfo->hEventRun); // Message processing loop MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } // revoke the classes again incase we missed any (eg. no instances // were created, the user just closed the app). RevokeAllClasses(); // release the classes ReleaseAllClasses(); // Tell OLE we are going away. CoUninitialize(); // notify the main thread that we are done SetEvent(pThrdInfo->hEventDone); return (msg.wParam); /* Returns the value from PostQuitMessage */ }