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

  1. // DrawServ.cpp : Implementation of WinMain
  2. //
  3. // This is a part of the ActiveX Template Library.
  4. // Copyright (C) 1996 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // ActiveX Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // ActiveX 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, 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.  
  182.     BOOL bDelete = ::DeleteService(hService);
  183.     ::CloseServiceHandle(hService);
  184.     ::CloseServiceHandle(hSCM);
  185.  
  186.     if (bDelete)
  187.         return TRUE;
  188.  
  189.     MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
  190.     return FALSE;
  191. }
  192.  
  193. ///////////////////////////////////////////////////////////////////////////////////////
  194. // Logging functions
  195. void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
  196. {
  197.     TCHAR    chMsg[256];
  198.     HANDLE  hEventSource;
  199.     LPTSTR  lpszStrings[1];
  200.     va_list pArg;
  201.  
  202.     va_start(pArg, pFormat);
  203.     _vstprintf(chMsg, pFormat, pArg);
  204.     va_end(pArg);
  205.  
  206.     lpszStrings[0] = chMsg;
  207.  
  208.     if (m_bService)
  209.     {
  210.         /* Get a handle to use with ReportEvent(). */
  211.         hEventSource = RegisterEventSource(NULL, m_szServiceName);
  212.         if (hEventSource)
  213.         {
  214.             /* Write to event log. */
  215.             ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
  216.             DeregisterEventSource(hEventSource);
  217.         }
  218.     }
  219.     else
  220.     {
  221.         // As we are not running as a service, just write the error to the console.
  222.         _putts(chMsg);
  223.     }
  224. }
  225.  
  226. //////////////////////////////////////////////////////////////////////////////////////////////
  227. // Service startup and registration
  228. inline void CServiceModule::Start()
  229. {
  230.     SERVICE_TABLE_ENTRY st[] =
  231.     {
  232.         { m_szServiceName, _ServiceMain },
  233.         { NULL, NULL }
  234.     };
  235.     if (!::StartServiceCtrlDispatcher(st))
  236.     {
  237.         m_bService = FALSE;
  238.         if (GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
  239.             Run();
  240.     }
  241. }
  242.  
  243.  
  244. inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
  245. {
  246.     // Register the control request handler
  247.     m_status.dwCurrentState = SERVICE_START_PENDING;
  248.     m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
  249.     if (m_hServiceStatus == NULL)
  250.     {
  251.         LogEvent(_T("Handler not installed"));
  252.         return;
  253.     }
  254.     SetServiceStatus(SERVICE_START_PENDING);
  255.  
  256.     m_status.dwWin32ExitCode = S_OK;
  257.     m_status.dwCheckPoint = 0;
  258.     m_status.dwWaitHint = 0;
  259.  
  260.     // When the Run function returns, the service has stopped.
  261.     Run();
  262.  
  263.     SetServiceStatus(SERVICE_STOPPED);
  264.     LogEvent(_T("Service stopped"));
  265. }
  266.  
  267. inline void CServiceModule::Handler(DWORD dwOpcode)
  268. {
  269.     switch (dwOpcode)
  270.     {
  271.     case SERVICE_CONTROL_STOP:
  272.         SetServiceStatus(SERVICE_STOP_PENDING);
  273.         PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  274.         break;
  275.     case SERVICE_CONTROL_PAUSE:
  276.         break;
  277.     case SERVICE_CONTROL_CONTINUE:
  278.         break;
  279.     case SERVICE_CONTROL_INTERROGATE:
  280.         break;
  281.     case SERVICE_CONTROL_SHUTDOWN:
  282.         break;
  283.     default:
  284.         LogEvent(_T("Bad service request"));
  285.     }
  286. }
  287.  
  288. void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
  289. {
  290.     _Module.ServiceMain(dwArgc, lpszArgv);
  291. }
  292. void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
  293. {
  294.     _Module.Handler(dwOpcode); 
  295. }
  296.  
  297. void CServiceModule::SetServiceStatus(DWORD dwState)
  298. {
  299.     m_status.dwCurrentState = dwState;
  300.     ::SetServiceStatus(m_hServiceStatus, &m_status);
  301. }
  302.  
  303. void CServiceModule::Run()
  304. {
  305.     HRESULT hr;
  306.  
  307.     _Module.dwThreadID = GetCurrentThreadId();
  308.  
  309. //  If you are running on NT 4.0 or higher you can use the following call
  310. //  instead to make your service free threaded.
  311. //  This means that calls come in on a random RPC thread
  312.     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  313.  
  314. //  Otherwise, for single threaded use
  315. //  hr = CoInitialize(NULL);
  316.  
  317.     _ASSERTE(SUCCEEDED(hr));
  318.  
  319. //  In NT 4.0 and higher where DCOM is supported you may wish to initialize
  320. //  the security layer.  The following code will give you a DCOM service which
  321. //  would allow ALL users access to objects
  322.     CSecurityDescriptor sd;
  323.     sd.InitializeFromThreadToken();
  324.  
  325.     hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
  326.         RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
  327.     _ASSERTE(SUCCEEDED(hr));
  328.  
  329. //  If you wish to have your object creatable remotely using DCOM use the following
  330.     hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
  331. //  Otherwise, only local activation
  332. //  hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
  333.     _ASSERTE(SUCCEEDED(hr));
  334.  
  335.     LogEvent(_T("Service started"));
  336.     SetServiceStatus(SERVICE_RUNNING);
  337.  
  338.     MSG msg;
  339.     while (GetMessage(&msg, 0, 0, 0))
  340.         DispatchMessage(&msg);
  341.  
  342.     _Module.RevokeClassObjects();
  343.  
  344.     CoUninitialize();
  345. }
  346.  
  347. /////////////////////////////////////////////////////////////////////////////
  348. //
  349. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
  350.     LPTSTR lpCmdLine, int /* nShowCmd */)
  351. {
  352.     _Module.Init(ObjectMap, hInstance, IDS_SERVICENAME);
  353.  
  354.     TCHAR szTokens[] = _T("-/");
  355.  
  356.     LPTSTR lpszToken = _tcstok(lpCmdLine, szTokens);
  357.     while (lpszToken != NULL)
  358.     {
  359.         if (_tcsicmp(lpszToken, _T("UnregServer"))==0)
  360.             return _Module.UnregisterServer();
  361.         if (_tcsicmp(lpszToken, _T("RegServer"))==0)
  362.             return _Module.RegisterServer(TRUE);
  363.         lpszToken = _tcstok(NULL, szTokens);
  364.     }
  365.  
  366.     _Module.Start();
  367.  
  368.     // When we get here, the service has been stopped
  369.     return _Module.m_status.dwWin32ExitCode;
  370. }
  371.