/*+---------------------------------------------------------------------------- USAGE: serverCOM /REGSERVER - Installs registry entries for the server. serverCOM /UNREGSERVER - Removes registry entries for the server. serverCOM -Embedding - Server was auto-started by OLE. COMMENTS: The server program must be installed before running the client. Run serverCOM.exe /REGSERVER to install the server program. -----------------------------------------------------------------------------*/ #include #include #include "account.h" void PrintErrorMessage(HRESULT hr); HRESULT RegisterClassFactory(); HRESULT RevokeClassFactory(); //Prototypes for local functions HRESULT RegisterLocalServer(REFCLSID rclsid); HRESULT RegisterProxyDll(const char *pszProxyDll); HRESULT UnregisterLocalServer(REFCLSID rclsid); HRESULT UnregisterProxyDll(const char *pszProxyDll); extern "C" const CLSID CLSID_Account; long g_LockCount = 0; long g_ObjectCount = 0; //+--------------------------------------------------------------------------- // // Function: DecrementLockCount // // Synopsis: Decrements the lock count. The lock count controls the // registration of the class factory in the class table. // DecrementLockCount revokes the class factory when the // lock count is zero. // // Called By: ~CAccount, IClassFactory::LockServer(FALSE). // // See Also: ObjectCreated, ObjectDestroyed, IncrementLockCount. // //---------------------------------------------------------------------------- void DecrementLockCount() { //Decrement the lock count. if(InterlockedDecrement(&g_LockCount) == 0) { //When the lock count is decremented to zero, //revoke the class factory. RevokeClassFactory(); } } //+--------------------------------------------------------------------------- // // Function: IncrementLockCount // // Synopsis: Increments the lock count. The lock count controls the // registration of the class factory in the class table. // If necessary, IncrementLockCount will reregister the class // factory in the class table. // // Called By: CAccount, IClassFactory::LockServer(TRUE). // // See Also: DecrementLockCount, ObjectCreated, ObjectDestroyed. // //---------------------------------------------------------------------------- void IncrementLockCount() { if(g_LockCount == 0) { //Increment the lock count. InterlockedIncrement(&g_LockCount); //Reregister the class factory if necessary. RegisterClassFactory(); } else { //Increment the lock count. InterlockedIncrement(&g_LockCount); } } //+--------------------------------------------------------------------------- // // Function: main // // Synopsis: Main entry point for the server application. This function // initializes the server and processes the message loop. // //---------------------------------------------------------------------------- int _cdecl main(int argc, char *argv[]) { HRESULT hr = S_OK; int i; BOOL fRegisterServer = FALSE; BOOL fUnregisterServer = FALSE; BOOL fEmbedding = FALSE; BOOL fHelp = FALSE; MSG msg; // Parse each item, skip the command name for (i = 1; i < argc; i++) { if (stricmp( argv[i], "-Embedding" ) == 0) { //This server has been activated by OLE. fEmbedding = TRUE; } else if (stricmp( argv[i], "/REGSERVER" ) == 0) { fRegisterServer = TRUE; } else if (stricmp( argv[i], "/UNREGSERVER" ) == 0) { fUnregisterServer = TRUE; } else { fHelp = TRUE; } } if(fHelp == TRUE) { printf("USAGE: server /REGSERVER - Installs server in the registry.\n"); printf(" server /UNREGSERVER - Removes server from the registry.\n"); printf(" server -Embedding - Server was auto-started by OLE.\n"); return 0; } else if(fUnregisterServer == TRUE) { hr = UnregisterLocalServer(CLSID_Account); if(FAILED(hr)) { printf("Failed to remove local server from the registry.\n"); PrintErrorMessage(hr); } hr = UnregisterProxyDll("account.dll"); if(FAILED(hr)) { printf("Failed to remove proxy DLL from the registry.\n"); PrintErrorMessage(hr); } return 0; } //Install the local server in the registry. hr = RegisterLocalServer(CLSID_Account); if(FAILED(hr)) { printf("Failed to install local server in the registry.\n"); PrintErrorMessage(hr); } //Install the proxy DLL in the registry. hr = RegisterProxyDll("account.dll"); if(FAILED(hr)) { printf("Failed to install proxy DLL in the registry.\n"); PrintErrorMessage(hr); } if(fRegisterServer == TRUE) return 0; // // Initialize OLE before calling any other OLE functions. // hr = CoInitialize(NULL); if(SUCCEEDED(hr)) { hr = RegisterClassFactory(); if(SUCCEEDED(hr)) { printf("Waiting for client to connect...\n"); // Main message loop. We will remain in the message loop // until we get a WM_QUIT message. while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } //If the class factory is still registered in the //class table, revoke it before we shut down. RevokeClassFactory(); } else { printf("Failed to register class factory.\n"); PrintErrorMessage(hr); } CoUninitialize(); } else { printf("CoInitialize failed.\n"); PrintErrorMessage(hr); } return 0; } //+--------------------------------------------------------------------------- // // Function: ObjectCreated // // Synopsis: Increments the object count controlling the main message loop // of the server process. // // Called By: CAccount, CAccountFactory. // // See Also: DecrementLockCount, IncrementLockCount, ObjectDestroyed. // //---------------------------------------------------------------------------- void ObjectCreated() { InterlockedIncrement(&g_ObjectCount); } //+--------------------------------------------------------------------------- // // Function: ObjectDestroyed // // Synopsis: Decrements the object count controlling the main message loop // of the server process. When the object count is decremented // to zero, we post a WM_QUIT message. The main message loop will // exit and terminate the server process. // // Called By: ~CAccount, ~CAccountFactory. // // See Also: DecrementLockCount, IncrementLockCount, ObjectCreated. // //---------------------------------------------------------------------------- void ObjectDestroyed() { if(InterlockedDecrement(&g_ObjectCount) == 0) { //When the last object is released, post a quit message. PostQuitMessage(0); } } //+--------------------------------------------------------------------------- // // Function: RegisterLocalServer // // Synopsis: Creates a registry key for a local server. // // Parameters: rclsid - Supplies the class ID of the local server. // //---------------------------------------------------------------------------- HRESULT RegisterLocalServer(REFCLSID rclsid) { HRESULT hr; LONG error; HKEY hKeyCLSID; // key for ...\Classes\CLSID HKEY hKeyClassID; HKEY hKey; // current key DWORD dwDisposition; char szServer[MAX_PATH]; char szClassID[39]; unsigned long length; length = GetModuleFileNameA(0, szServer, sizeof(szServer)); if(length == 0) { hr = HRESULT_FROM_WIN32(GetLastError()); return hr; } //create the CLSID key error = RegCreateKeyExA( HKEY_CLASSES_ROOT, "CLSID", 0, "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKeyCLSID, &dwDisposition); if(!error) { //convert the class ID to a registry key name. sprintf(szClassID, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", rclsid.Data1, rclsid.Data2, rclsid.Data3, rclsid.Data4[0], rclsid.Data4[1], rclsid.Data4[2], rclsid.Data4[3], rclsid.Data4[4], rclsid.Data4[5], rclsid.Data4[6], rclsid.Data4[7]); //create key for the server class error = RegCreateKeyExA(hKeyCLSID, szClassID, 0, "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKeyClassID, &dwDisposition); if(!error) { //create LocalServer32 key. error = RegCreateKeyExA(hKeyClassID, "LocalServer32", 0, "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, &dwDisposition); if(!error) { //Set the server name. error = RegSetValueExA(hKey, "", 0, REG_SZ, (const unsigned char *)szServer, strlen(szServer) + 1); RegFlushKey(hKey); RegCloseKey(hKey); } RegCloseKey(hKeyClassID); } RegCloseKey(hKeyCLSID); } if(!error) hr = S_OK; else hr = HRESULT_FROM_WIN32(error); return hr; } //+--------------------------------------------------------------------------- // // Function: RegisterProxyDll // // Synopsis: Creates registry entries for the interfaces contained in a // proxy DLL. // // Parameters: pszProxyDll - Supplies the filename of the proxy DLL. // // Notes: RegisterProxyDll calls the DllRegisterServer function // exported from the proxy DLL. // //---------------------------------------------------------------------------- HRESULT RegisterProxyDll(const char *pszProxyDll) { HRESULT hr; HINSTANCE hProxyDll; HRESULT (STDAPICALLTYPE *pfnDllRegisterServer)(); hProxyDll = LoadLibraryA(pszProxyDll); if(hProxyDll != 0) { pfnDllRegisterServer = (HRESULT (STDAPICALLTYPE *)()) GetProcAddress(hProxyDll, "DllRegisterServer"); if(pfnDllRegisterServer != 0) hr = (*pfnDllRegisterServer)(); else hr = HRESULT_FROM_WIN32(GetLastError()); FreeLibrary(hProxyDll); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; } //+--------------------------------------------------------------------------- // // Function: UnregisterLocalServer // // Synopsis: Removes the registry key for a local server. // // Parameters: rclsid - Supplies the class ID of the local server. // //---------------------------------------------------------------------------- HRESULT UnregisterLocalServer(REFCLSID rclsid) { HRESULT hr; HKEY hKeyCLSID; HKEY hKeyClassID; long error; char szClassID[39]; //open the CLSID key error = RegOpenKeyExA( HKEY_CLASSES_ROOT, "CLSID", 0, KEY_ALL_ACCESS, &hKeyCLSID); if(!error) { //convert the class ID to a registry key name. sprintf(szClassID, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", rclsid.Data1, rclsid.Data2, rclsid.Data3, rclsid.Data4[0], rclsid.Data4[1], rclsid.Data4[2], rclsid.Data4[3], rclsid.Data4[4], rclsid.Data4[5], rclsid.Data4[6], rclsid.Data4[7]); //open registry key for class ID string error = RegOpenKeyExA( hKeyCLSID, szClassID, 0, KEY_ALL_ACCESS, &hKeyClassID); if(!error) { //delete LocalServer32 key. error = RegDeleteKeyA(hKeyClassID, "LocalServer32"); RegCloseKey(hKeyClassID); } error = RegDeleteKeyA(hKeyCLSID, szClassID); RegCloseKey(hKeyCLSID); } if(!error) hr = S_OK; else hr = HRESULT_FROM_WIN32(error); return hr; } //+--------------------------------------------------------------------------- // // Function: UnregisterProxyDll // // Synopsis: Removes registry entries for the interfaces contained in a // proxy DLL. // // Parameters: pszProxyDll - Supplies the filename of the proxy DLL. // // Notes: UnregisterProxyDll calls the DllUnregisterServer function // exported from the proxy DLL. // //---------------------------------------------------------------------------- HRESULT UnregisterProxyDll(const char *pszProxyDll) { HRESULT hr; HINSTANCE hProxyDll; HRESULT (STDAPICALLTYPE *pfnDllUnregisterServer)(); hProxyDll = LoadLibraryA(pszProxyDll); if(hProxyDll != 0) { pfnDllUnregisterServer = (HRESULT (STDAPICALLTYPE *)()) GetProcAddress(hProxyDll, "DllUnregisterServer"); if(pfnDllUnregisterServer != 0) hr = (*pfnDllUnregisterServer)(); else hr = HRESULT_FROM_WIN32(GetLastError()); FreeLibrary(hProxyDll); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; }