home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / atl / dcom / drawserv / drawserv.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  11KB  |  409 lines

  1. // DrawServ.cpp : Implementation of WinMain
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12. //
  13. // You will need the NT SUR Beta 2 SDK or VC 4.2 in order to build this
  14. // project.  This is because you will need MIDL 3.00.15 or higher and new
  15. // headers and libs.  If you have VC 4.2 installed, then everything should
  16. // already be configured correctly.
  17.  
  18. // Note: Proxy/Stub Information
  19. //      To build a separate proxy/stub DLL,
  20. //      run nmake -f DrawServps.mak in the project directory.
  21.  
  22. #include "predraw.h"
  23. #include "drawres.h"
  24. #include "initguid.h"
  25. #include "DrawServ.h"
  26. #include "DrawObj.h"
  27.  
  28. #define IID_DEFINED
  29. #include "DrawServ_i.c"
  30.  
  31.  
  32. #include <stdio.h>
  33.  
  34. CServiceModule _Module;
  35.  
  36. BEGIN_OBJECT_MAP(ObjectMap)
  37.     OBJECT_ENTRY(CLSID_CDrawServ, CDrawObj)
  38. END_OBJECT_MAP()
  39.  
  40.  
  41. // Although some of these functions are big they are declared inline since they are only used once
  42.  
  43. inline HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib)
  44. {
  45.     HRESULT hr = CoInitialize(NULL);
  46.     if (FAILED(hr))
  47.         return hr;
  48.  
  49.     // Remove any previous service since it may point to
  50.     // the incorrect file
  51.     Uninstall();
  52.     // Add service entries
  53.     UpdateRegistryFromResource(IDR_DrawServ, TRUE);
  54.     // Create service
  55.     Install();
  56.     // Add object entries
  57.     HRESULT hRes = CComModule::RegisterServer(bRegTypeLib);
  58.  
  59.     CoUninitialize();
  60.     return hRes;
  61. }
  62.  
  63. inline HRESULT CServiceModule::UnregisterServer()
  64. {
  65.     HRESULT hr = CoInitialize(NULL);
  66.     if (FAILED(hr))
  67.         return hr;
  68.  
  69.     // Remove service entries
  70.     UpdateRegistryFromResource(IDR_DrawServ, FALSE);
  71.     // Remove service
  72.     Uninstall();
  73.     // Remove object entries
  74.     CComModule::UnregisterServer();
  75.  
  76.     CoUninitialize();
  77.     return S_OK;
  78. }
  79.  
  80. inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID)
  81. {
  82.     CComModule::Init(p, h);
  83.  
  84.     m_bService = TRUE;
  85.  
  86.     LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));
  87.  
  88.     // set up the initial service status
  89.     m_hServiceStatus = NULL;
  90.     m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  91.     m_status.dwCurrentState = SERVICE_STOPPED;
  92.     m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  93.     m_status.dwWin32ExitCode = 0;
  94.     m_status.dwServiceSpecificExitCode = 0;
  95.     m_status.dwCheckPoint = 0;
  96.     m_status.dwWaitHint = 0;
  97. }
  98.  
  99. LONG CServiceModule::Unlock()
  100. {
  101.     LONG l = CComModule::Unlock();
  102.     if (l == 0 && !m_bService)
  103.         PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  104.     return l;
  105. }
  106.  
  107. BOOL CServiceModule::IsInstalled()
  108. {
  109.     BOOL bResult = FALSE;
  110.  
  111.     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  112.  
  113.     if (hSCM != NULL)
  114.     {
  115.         SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);
  116.         if (hService != NULL)
  117.         {
  118.             bResult = TRUE;
  119.             ::CloseServiceHandle(hService);
  120.         }
  121.         ::CloseServiceHandle(hSCM);
  122.     }
  123.     return bResult;
  124. }
  125.  
  126. inline BOOL CServiceModule::Install()
  127. {
  128.     if (IsInstalled())
  129.         return TRUE;
  130.  
  131.     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  132.     if (hSCM == NULL)
  133.     {
  134.         MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
  135.         return FALSE;
  136.     }
  137.  
  138.     // Get the executable file path
  139.     TCHAR szFilePath[_MAX_PATH];
  140.     ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
  141.  
  142.     SC_HANDLE hService = ::CreateService(
  143.         hSCM, m_szServiceName, m_szServiceName,
  144.         SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
  145.         SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
  146.         szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);
  147.  
  148.     if (hService == NULL)
  149.     {
  150.         ::CloseServiceHandle(hSCM);
  151.         MessageBox(NULL, _T("Couldn't create service"), m_szServiceName, MB_OK);
  152.         return FALSE;
  153.     }
  154.  
  155.     ::CloseServiceHandle(hService);
  156.     ::CloseServiceHandle(hSCM);
  157.     return TRUE;
  158. }
  159.  
  160. inline BOOL CServiceModule::Uninstall()
  161. {
  162.     if (!IsInstalled())
  163.         return TRUE;
  164.  
  165.     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  166.  
  167.     if (hSCM == NULL)
  168.     {
  169.         MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
  170.         return FALSE;
  171.     }
  172.  
  173.     SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE);
  174.  
  175.     if (hService == NULL)
  176.     {
  177.         ::CloseServiceHandle(hSCM);
  178.         MessageBox(NULL, _T("Couldn't open service"), m_szServiceName, MB_OK);
  179.         return FALSE;
  180.     }
  181.     SERVICE_STATUS status;
  182.     ::ControlService(hService, SERVICE_CONTROL_STOP, &status);
  183.  
  184.     BOOL bDelete = ::DeleteService(hService);
  185.     ::CloseServiceHandle(hService);
  186.     ::CloseServiceHandle(hSCM);
  187.  
  188.     if (bDelete)
  189.         return TRUE;
  190.  
  191.     MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
  192.     return FALSE;
  193. }
  194.  
  195. ///////////////////////////////////////////////////////////////////////////////////////
  196. // Logging functions
  197. void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
  198. {
  199.     TCHAR    chMsg[256];
  200.     HANDLE  hEventSource;
  201.     LPTSTR  lpszStrings[1];
  202.     va_list pArg;
  203.  
  204.     va_start(pArg, pFormat);
  205.     _vstprintf(chMsg, pFormat, pArg);
  206.     va_end(pArg);
  207.  
  208.     lpszStrings[0] = chMsg;
  209.  
  210.     if (m_bService)
  211.     {
  212.         /* Get a handle to use with ReportEvent(). */
  213.         hEventSource = RegisterEventSource(NULL, m_szServiceName);
  214.         if (hEventSource)
  215.         {
  216.             /* Write to event log. */
  217.             ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
  218.             DeregisterEventSource(hEventSource);
  219.         }
  220.     }
  221.     else
  222.     {
  223.         // As we are not running as a service, just write the error to the console.
  224.         _putts(chMsg);
  225.     }
  226. }
  227.  
  228. //////////////////////////////////////////////////////////////////////////////////////////////
  229. // Service startup and registration
  230. inline void CServiceModule::Start()
  231. {
  232.     SERVICE_TABLE_ENTRY st[] =
  233.     {
  234.         { m_szServiceName, _ServiceMain },
  235.         { NULL, NULL }
  236.     };
  237.     if (m_bService && !::StartServiceCtrlDispatcher(st))
  238.     {
  239.         m_bService = FALSE;
  240.     }
  241.     if (m_bService == FALSE)
  242.         Run();
  243. }
  244.  
  245.  
  246. inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
  247. {
  248.     // Register the control request handler
  249.     m_status.dwCurrentState = SERVICE_START_PENDING;
  250.     m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
  251.     if (m_hServiceStatus == NULL)
  252.     {
  253.         LogEvent(_T("Handler not installed"));
  254.         return;
  255.     }
  256.     SetServiceStatus(SERVICE_START_PENDING);
  257.  
  258.     m_status.dwWin32ExitCode = S_OK;
  259.     m_status.dwCheckPoint = 0;
  260.     m_status.dwWaitHint = 0;
  261.  
  262.     // When the Run function returns, the service has stopped.
  263.     Run();
  264.  
  265.     SetServiceStatus(SERVICE_STOPPED);
  266.     LogEvent(_T("Service stopped"));
  267. }
  268.  
  269. inline void CServiceModule::Handler(DWORD dwOpcode)
  270. {
  271.     switch (dwOpcode)
  272.     {
  273.     case SERVICE_CONTROL_STOP:
  274.         SetServiceStatus(SERVICE_STOP_PENDING);
  275.         PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  276.         break;
  277.     case SERVICE_CONTROL_PAUSE:
  278.         break;
  279.     case SERVICE_CONTROL_CONTINUE:
  280.         break;
  281.     case SERVICE_CONTROL_INTERROGATE:
  282.         break;
  283.     case SERVICE_CONTROL_SHUTDOWN:
  284.         break;
  285.     default:
  286.         LogEvent(_T("Bad service request"));
  287.     }
  288. }
  289.  
  290. void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
  291. {
  292.     _Module.ServiceMain(dwArgc, lpszArgv);
  293. }
  294. void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
  295. {
  296.     _Module.Handler(dwOpcode);
  297. }
  298.  
  299. void CServiceModule::SetServiceStatus(DWORD dwState)
  300. {
  301.     m_status.dwCurrentState = dwState;
  302.     ::SetServiceStatus(m_hServiceStatus, &m_status);
  303. }
  304.  
  305. void CServiceModule::Run()
  306. {
  307.     HRESULT hr;
  308.  
  309.     _Module.dwThreadID = GetCurrentThreadId();
  310.  
  311. //  If you are running on NT 4.0 or higher you can use the following call
  312. //  to make your service free threaded.
  313. //  This means that calls come in on a random RPC thread
  314.     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  315.  
  316. //  Otherwise, for single threaded use
  317. //  hr = CoInitialize(NULL);
  318.  
  319.     ATLASSERT(SUCCEEDED(hr));
  320.  
  321. //  In NT 4.0 and higher where DCOM is supported you may wish to initialize
  322. //  the security layer.  The following code will give you a DCOM service which
  323. //  would allow ALL users access to objects
  324.     CSecurityDescriptor sd;
  325.     sd.InitializeFromThreadToken();
  326.  
  327.     hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
  328.         RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
  329.     ATLASSERT(SUCCEEDED(hr));
  330.  
  331. //  If you wish to have your object creatable remotely using DCOM use the following
  332.     hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
  333. //  Otherwise, only local activation
  334. //  hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
  335.     ATLASSERT(SUCCEEDED(hr));
  336.  
  337.     LogEvent(_T("Service started"));
  338.     SetServiceStatus(SERVICE_RUNNING);
  339.  
  340.     MSG msg;
  341.     while (GetMessage(&msg, 0, 0, 0))
  342.         DispatchMessage(&msg);
  343.  
  344.     _Module.RevokeClassObjects();
  345.  
  346.     CoUninitialize();
  347. }
  348.  
  349. /////////////////////////////////////////////////////////////////////////////
  350. //
  351. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
  352.     LPTSTR lpCmdLine, int /* nShowCmd */)
  353. {
  354.     _Module.Init(ObjectMap, hInstance, IDS_SERVICENAME);
  355.     _Module.m_bService = TRUE;
  356.  
  357.     TCHAR szTokens[] = _T("-/");
  358.     LPTSTR lpszToken = _tcstok(lpCmdLine, szTokens);
  359.     while (lpszToken != NULL)
  360.     {
  361.         if (_tcsicmp(lpszToken, _T("UnregServer"))==0)
  362.             return _Module.UnregisterServer();
  363.  
  364.         if (_tcsicmp(lpszToken, _T("RegServer"))==0)
  365.             return _Module.RegisterServer(TRUE);
  366.  
  367.         if (_tcsicmp(lpszToken, _T("Embedding"))==0)
  368.             _Module.m_bService = FALSE;
  369.  
  370.         if (_tcsicmp(lpszToken, _T("LocalServer"))==0)
  371.         {
  372.             _Module.SetupAsLocalServer();
  373.             return 0;
  374.         }
  375.         lpszToken = _tcstok(NULL, szTokens);
  376.     }
  377.     _Module.Start();
  378.  
  379.     // When we get here, the service has been stopped
  380.     return _Module.m_status.dwWin32ExitCode;
  381. }
  382.  
  383. void CServiceModule::SetupAsLocalServer()
  384. {
  385.     USES_CONVERSION;
  386.     CRegKey keyClasses,key;
  387.     LPOLESTR pCLSID;
  388.  
  389.     Uninstall();
  390.  
  391.     if (keyClasses.Open(HKEY_CLASSES_ROOT, _T("CLSID")) != ERROR_SUCCESS)
  392.         return;
  393.  
  394.     _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap;
  395.     while (pEntry->pclsid != NULL)
  396.     {
  397.         StringFromCLSID(*pEntry->pclsid, &pCLSID);
  398.         if (key.Open(keyClasses, OLE2T(pCLSID)) == ERROR_SUCCESS)
  399.         {
  400.             TCHAR szModule[_MAX_PATH];
  401.             key.DeleteValue(_T("AppID"));
  402.             key.DeleteValue(_T("_LocalServer32"));
  403.             GetModuleFileName(GetModuleInstance(), szModule, _MAX_PATH);
  404.             key.SetKeyValue(_T("LocalServer32"), szModule, _T(""));
  405.         }
  406.         pEntry++;
  407.     }
  408. }
  409.