home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / remote.srv / service.cpp < prev    next >
C/C++ Source or Header  |  1996-04-11  |  31KB  |  957 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  File Name 
  4. //      SERVICE.CPP
  5. //
  6. //  Description
  7. //      This is the file where the entry point is (WinMain).
  8. //      Here we also implement the registration and unregistration of
  9. //      the RPC server.
  10. //      The server register its services with NAMED PIPES as the exposed
  11. //      protocol sequence for RPC calls. This server can only be run on
  12. //      Windows NT platforms. Windows 95 does not support the creation of
  13. //      named pipes.
  14. //      This is where we register the NT service with the Service control
  15. //      manager and where the service control handler is implemented
  16. //
  17. //      The WinMain, function can take certain paramenters from the command
  18. //      line to control the action of the executable
  19. //
  20. //      Argument        Action
  21. //      ========        ======
  22. //      <None>          If normally started by the Service control manager,
  23. //                      the WINDS NT Service starts and it is ready to accept
  24. //                      request from WINDS MAPI service providers and from
  25. //                      the WINDS administrator.
  26. //                      If started as an application, a message dialog will
  27. //                      come up to allow interactive install and removal of
  28. //                      the service.
  29. //
  30. //      APP             Start the service as an APPLICATION EXECUTABLE, as
  31. //                      opposed to an NT SERVICE. This is useful for
  32. //                      debugging the WINDS server.
  33. //
  34. //      INSTALL         Adds the WINDS NT Service to the Service Control
  35. //                      Manager list, modify the registry entries and starts
  36. //                      the NT services normally.
  37. //
  38. //      REMOVE          Remove the WINDS NT service from the Service
  39. //                      control list, and stops the WINDS service, halting
  40. //                      services WINDS MAPI providers and WINDS administrators
  41. //
  42. //  Author
  43. //      Irving De la Cruz
  44. //
  45. //  Revision: 1.7
  46. //
  47. // Written for Microsoft Windows Developer Support
  48. // Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
  49. //
  50. #include "_WINDS.H"
  51. #include <WINDOWSX.H>
  52. #include "WRAP3D.H"
  53. #include <RPC.H>
  54. #include "WINDS.H"     // Header file generated by the MIDL compiler
  55. #include "WDSADM.H"    // Header file generated by the MIDL compiler
  56. #include "COMMON.H"
  57.  
  58. extern "C"
  59. {
  60.     BOOL WINAPI InitRPCServer
  61.                         ();
  62.     BOOL WINAPI TerminateAllRPCServer
  63.                         ();
  64.     void WINAPI RegisterWindsPrivateClass
  65.                         ();
  66.     void WindsServiceMain
  67.                         (DWORD                      dwArgc,
  68.                          LPTSTR *                   pszArgv);
  69.     void WindsServiceCtrlHandler
  70.                         (DWORD                      dwControlCode);
  71.     void WINAPI TerminateService
  72.                         (HRESULT                    hErrror);
  73.     HRESULT WINAPI SendStatusToSCM
  74.                         (DWORD                      dwServiceState,
  75.                          HRESULT                    hError,
  76.                          DWORD                      dwCheckPoint,
  77.                          DWORD                      dwWait);
  78.     HRESULT WINAPI InstallWindsService
  79.                         (DWORD                      dwStartType,
  80.                          LPTSTR                     szFullPathToServiceExe,
  81.                          BOOL                       fStartImmediately);
  82.     HRESULT WINAPI RemoveWindsService
  83.                         ();
  84.     HRESULT WINAPI InitWindsService
  85.                         ();
  86.     void WINAPI PauseWindsService
  87.                         ();
  88.     void WINAPI ResumeWindsService
  89.                         ();
  90.     void WINAPI StopWindsService
  91.                         ();
  92.     BOOL CALLBACK GenericDlgProc
  93.                         (HWND                       hDlg, 
  94.                          UINT                       message, 
  95.                          WPARAM                     wParam, 
  96.                          LPARAM                     lParam);
  97.     BOOL CALLBACK InstallDlgProc
  98.                         (HWND                       hDlg, 
  99.                          UINT                       message, 
  100.                          WPARAM                     wParam, 
  101.                          LPARAM                     lParam);
  102.     LRESULT CALLBACK PrivateDlgClassProc
  103.                         (HWND                       hDlg, 
  104.                          UINT                       message, 
  105.                          WPARAM                     wParam, 
  106.                          LPARAM                     lParam);
  107.  
  108.     TCHAR g_szAppTitle[] = TEXT("WINDS Messaging Host");
  109.     HINSTANCE ghInstance = NULL;
  110.     HANDLE ghHeap = NULL;
  111.     IOTHREADINFO     g_IOInfo = { 0 };
  112.     TCHAR            g_szDataFile[MAX_PATH] = { 0 };
  113.     HRESULT          g_hServerState = HRESULT_FROM_WIN32(ERROR_BUSY);
  114.     CRITICAL_SECTION g_csIOInfo;
  115.     CRITICAL_SECTION g_csNotifLinks;
  116.     CRITICAL_SECTION g_csServiceState;
  117.     CRITICAL_SECTION g_csPipeID;
  118.     DWORD g_dwNextPipeID = MIN_PIPE_NUMBER;
  119.  
  120.     SERVICE_STATUS_HANDLE   g_ssHandle = NULL;
  121.     HANDLE                  g_hTerminateEvent = NULL;
  122.     LPVOID                  g_pctl3d = NULL;
  123. };
  124.  
  125. CObjectList GlobalObjectMap;
  126.  
  127. #define WINDS_SERVICE_NAME          TEXT("WINDS Messaging Host")
  128. #define WINDS_SERVICE_NAME_SHORT    TEXT("WindsMessagingHost")
  129. #define WINDS_SERVICE_EXECUTABLE    TEXT("\\WINDSSRV.EXE")
  130.  
  131. ///////////////////////////////////////////////////////////////////////////////
  132. //    WindsServiceMain()
  133. //
  134. //    Parameters
  135. //      { Refer to Win32 API documentation on ServiceMain }
  136. //
  137. //    Purpose
  138. //      
  139. //    Return Value
  140. //      None
  141. //      
  142. void WindsServiceMain (DWORD dwArgc, LPTSTR * pszArgv)
  143. {
  144.     g_ssHandle = RegisterServiceCtrlHandler (WINDS_SERVICE_NAME,
  145.                                              (LPHANDLER_FUNCTION)WindsServiceCtrlHandler);
  146.     if (NULL == g_ssHandle)
  147.     {
  148.         TraceResult ("WindsServiceMain: Failed to register the control handle", HRESULT_FROM_WIN32(GetLastError()));
  149.         return;
  150.     }
  151.     HRESULT hResult = SendStatusToSCM (SERVICE_START_PENDING, S_OK, 1, 5);
  152.     if (hResult)
  153.     {
  154.         TerminateService (hResult);
  155.         return;
  156.     }
  157.     g_hTerminateEvent = CreateEvent (0, TRUE, FALSE, 0);
  158.     if (NULL == g_hTerminateEvent)
  159.     {
  160.         hResult = HRESULT_FROM_WIN32(GetLastError());
  161.         TraceResult ("WindsServiceMain: Failed to create terminate event", hResult);
  162.         TerminateService (hResult);
  163.         return;
  164.     }
  165.  
  166.     hResult = SendStatusToSCM (SERVICE_START_PENDING, S_OK, 2, 1);
  167.     if (!hResult)
  168.     {
  169.         hResult = InitWindsService();
  170.         if (!hResult)
  171.         {
  172.             hResult = SendStatusToSCM (SERVICE_RUNNING, S_OK, 0, 0);
  173.             // If an error occured, terminate the service
  174.             if (hResult)
  175.             {
  176.                 StopWindsService();
  177.             }
  178.         }
  179.     }
  180.     if (S_OK == hResult)
  181.     {
  182.         WaitForSingleObject (g_hTerminateEvent, INFINITE);
  183.     }
  184.     TerminateService (hResult);
  185.  
  186. }
  187.  
  188. ///////////////////////////////////////////////////////////////////////////////
  189. //    TerminateService()
  190. //
  191. //    Parameters
  192. //
  193. //    Purpose
  194. //      
  195. //    Return Value
  196. //      None
  197. //      
  198. void WINAPI TerminateService (HRESULT hError)
  199. {
  200.     if (g_hTerminateEvent)
  201.     {
  202.         CloseHandle (g_hTerminateEvent);
  203.     }
  204.     if (g_ssHandle)
  205.     {
  206.         SendStatusToSCM (SERVICE_STOPPED, hError, 0, 0);
  207.     }
  208. }
  209.  
  210. ///////////////////////////////////////////////////////////////////////////////
  211. //    SendStatusToSCM()
  212. //
  213. //    Parameters
  214. //
  215. //    Purpose
  216. //      
  217. //    Return Value
  218. //      None
  219. //      
  220. HRESULT WINAPI SendStatusToSCM (DWORD   dwServiceState,
  221.                                 HRESULT hError,
  222.                                 DWORD   dwCheckPoint,
  223.                                 DWORD   dwWait)
  224. {
  225.     SERVICE_STATUS ssStatus = { 0 };
  226.     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  227.     ssStatus.dwCurrentState = dwServiceState;
  228.     if (SERVICE_START_PENDING == dwServiceState)
  229.     {
  230.         ssStatus.dwControlsAccepted = 0;
  231.     }
  232.     else
  233.     {
  234.         ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  235.                                       SERVICE_ACCEPT_PAUSE_CONTINUE |
  236.                                       SERVICE_ACCEPT_SHUTDOWN;
  237.     }
  238.     if (hError)
  239.     {
  240.         ssStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  241.         ssStatus.dwServiceSpecificExitCode = (DWORD)hError;
  242.     }
  243.     ssStatus.dwCheckPoint = dwCheckPoint;
  244.     ssStatus.dwWaitHint = (dwWait * 1000);
  245.     
  246.     HRESULT hResult = S_OK;
  247.     if (!SetServiceStatus (g_ssHandle, &ssStatus))
  248.     {
  249.         hResult = HRESULT_FROM_WIN32(GetLastError());
  250.         TraceResult ("SendStatusToSCM: Failed to set service status", hResult);
  251.     }
  252.     return hResult;
  253. }
  254.  
  255. ///////////////////////////////////////////////////////////////////////////////
  256. //    WindsServiceCtrlHandler()
  257. //
  258. //    Parameters
  259. //
  260. //    Purpose
  261. //      
  262. //    Return Value
  263. //      None
  264. //      
  265. void WindsServiceCtrlHandler (DWORD dwControlCode)
  266. {
  267.     switch (dwControlCode)
  268.     {
  269.         case SERVICE_CONTROL_SHUTDOWN :
  270.         case SERVICE_CONTROL_STOP :
  271.             SendStatusToSCM (SERVICE_STOP_PENDING, S_OK, 1, 10);
  272.             StopWindsService();
  273.             SendStatusToSCM (SERVICE_STOPPED, S_OK, 0, 0);
  274.             break;
  275.  
  276.         case SERVICE_CONTROL_PAUSE :
  277.             SendStatusToSCM (SERVICE_PAUSE_PENDING, S_OK, 1, 1);
  278.             PauseWindsService();
  279.             SendStatusToSCM (SERVICE_PAUSED, S_OK, 0, 0);
  280.             break;
  281.  
  282.         case SERVICE_CONTROL_CONTINUE :
  283.             SendStatusToSCM (SERVICE_CONTINUE_PENDING, S_OK, 1, 1);
  284.             ResumeWindsService();
  285.             SendStatusToSCM (SERVICE_RUNNING, S_OK, 0, 0);
  286.             break;
  287.  
  288.         case SERVICE_CONTROL_INTERROGATE :
  289.             SendStatusToSCM (0, S_OK, 0, 0);
  290.             break;
  291.     }
  292. }
  293.  
  294. ///////////////////////////////////////////////////////////////////////////////
  295. //    InitWindsService()
  296. //
  297. //    Parameters
  298. //
  299. //    Purpose
  300. //      
  301. //    Return Value
  302. //      
  303. HRESULT WINAPI InitWindsService()
  304. {
  305.     HRESULT hResult = S_OK;
  306.     LoadSettingsFromRegistry();
  307.     SaveSettingsToRegistry();
  308.  
  309.     InitializeCriticalSection (&g_csIOInfo);
  310.     InitializeCriticalSection (&g_csPipeID);
  311.     InitializeCriticalSection (&g_csNotifLinks);
  312.     InitializeCriticalSection (&g_csServiceState);
  313.  
  314.     g_IOInfo.hResumeEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  315.     if (!g_IOInfo.hResumeEvent)
  316.     {
  317.         hResult = HRESULT_FROM_WIN32(GetLastError());
  318.         TraceResult ("InitWindsService: Failed to create sync object (EVENT)", hResult);
  319.         return FALSE;
  320.     }
  321.  
  322.     DWORD dwThreadID;
  323.     HANDLE hThread = CreateThread (NULL,
  324.                                    0,
  325.                                    (LPTHREAD_START_ROUTINE)WorkingIOProc,
  326.                                    NULL,
  327.                                    0,
  328.                                    &dwThreadID);
  329.     if (!hThread)
  330.     {
  331.         hResult = HRESULT_FROM_WIN32(GetLastError());
  332.         TraceResult ("InitWindsService: Failed to create I/O thread", hResult);
  333.         ReleaseSyncObj();
  334.         return hResult;
  335.     }
  336.     TraceDebugger ("InitWindsService: IO thread spawned. ID: %X", dwThreadID);
  337.     SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST);
  338.     CloseHandle (hThread);
  339.     
  340.     HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  341.  
  342.     if (InitRPCServer())
  343.     {
  344.         EnterCriticalSection (&g_csIOInfo);
  345.         SetEvent (g_IOInfo.hResumeEvent);
  346.         g_IOInfo.Action           = IO_OPEN_STORAGE_FILE;
  347.         g_IOInfo.hActionCompleted = hWaitEvent;
  348.         g_IOInfo.phLastError      = &hResult;
  349.         LeaveCriticalSection (&g_csIOInfo);
  350.         WaitForSingleObject (hWaitEvent, INFINITE);
  351.     }
  352.     else
  353.     {
  354.         TraceMessage ("InitWindsService: Failed to initialize the RPC server");
  355.         hResult = E_FAIL;
  356.     }
  357.     CloseHandle (hWaitEvent);
  358.  
  359.     EnterCriticalSection (&g_csIOInfo);
  360.     SetEvent (g_IOInfo.hResumeEvent);
  361.     g_IOInfo.Action            = IO_LOAD_MAILBOX_NAMES;
  362.     g_IOInfo.hActionCompleted  = NULL;
  363.     g_IOInfo.phLastError       = NULL;
  364.     LeaveCriticalSection (&g_csIOInfo);
  365.  
  366.     return hResult;
  367. }
  368.  
  369. ///////////////////////////////////////////////////////////////////////////////
  370. //    PauseWindsService()
  371. //
  372. //    Parameters
  373. //
  374. //    Purpose
  375. //      
  376. //    Return Value
  377. //      
  378. void WINAPI PauseWindsService()
  379. {
  380.     EnterCriticalSection (&g_csServiceState);
  381.     g_hServerState = HRESULT_FROM_WIN32(ERROR_SERVICE_CANNOT_ACCEPT_CTRL);
  382.     LeaveCriticalSection (&g_csServiceState);
  383. }
  384.  
  385. ///////////////////////////////////////////////////////////////////////////////
  386. //    ResumeWindsService()
  387. //
  388. //    Parameters
  389. //
  390. //    Purpose
  391. //      
  392. //    Return Value
  393. //      
  394. void WINAPI ResumeWindsService()
  395. {
  396.     EnterCriticalSection (&g_csServiceState);
  397.     g_hServerState = S_OK;
  398.     LeaveCriticalSection (&g_csServiceState);
  399. }
  400.  
  401. ///////////////////////////////////////////////////////////////////////////////
  402. //    StopWindsService()
  403. //
  404. //    Parameters
  405. //
  406. //    Purpose
  407. //      
  408. //    Return Value
  409. //      
  410. void WINAPI StopWindsService()
  411. {
  412.     HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  413.  
  414.     PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
  415.                                                                  HEAP_ZERO_MEMORY,
  416.                                                                  sizeof(WINDS_NOTIFICATION));
  417.     if (pNotif)
  418.     {
  419.         pNotif->Event = SERVER_IS_SHUTTING_DOWN;
  420.         EnterCriticalSection (&g_csIOInfo);
  421.         SetEvent (g_IOInfo.hResumeEvent);
  422.         g_IOInfo.Action           = IO_SENT_SHUTDOWN_NOTIFICATION;
  423.         g_IOInfo.hActionCompleted = hWaitEvent;
  424.         g_IOInfo.pNotif           = pNotif;
  425.         g_IOInfo.phLastError      = NULL;
  426.         LeaveCriticalSection (&g_csIOInfo);
  427.         WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  428.     }
  429.     else
  430.     {
  431.         TraceMessage ("StopWindsService: Failed to create structure for shutdown notification");
  432.     }
  433.     TerminateAllRPCServer();
  434.     RemoveAllNotifLinks();
  435.     
  436.     EnterCriticalSection (&g_csIOInfo);
  437.     // Resume the thread so that it terminate ifself properly
  438.     SetEvent (g_IOInfo.hResumeEvent);
  439.     g_IOInfo.fAppIsTerminating = TRUE;
  440.     g_IOInfo.hActionCompleted  = hWaitEvent;
  441.     LeaveCriticalSection (&g_csIOInfo);
  442.     WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  443.     
  444.     CloseHandle (hWaitEvent);
  445.     
  446.     UnInitTraces ();
  447.     
  448.     ReleaseSyncObj();
  449. }
  450.  
  451. ///////////////////////////////////////////////////////////////////////////////
  452. //    InstallWindsService()
  453. //
  454. //    Parameters
  455. //
  456. //    Purpose
  457. //      
  458. //    Return Value
  459. //      
  460. HRESULT WINAPI InstallWindsService (DWORD   dwStartType,
  461.                                     LPTSTR  szFullPathToServiceExe,
  462.                                     BOOL    fStartImmediately)
  463. {
  464.     HRESULT hResult = S_OK;
  465.     SC_HANDLE schSCM, schWINDS;
  466.     schSCM = OpenSCManager (0, 0, SC_MANAGER_CREATE_SERVICE);
  467.     if (NULL == schSCM)
  468.     {
  469.         hResult = HRESULT_FROM_WIN32 (GetLastError());
  470.     }
  471.     else
  472.     {
  473. RestartInstall:
  474.         schWINDS = CreateService (schSCM,
  475.                                   WINDS_SERVICE_NAME_SHORT,
  476.                                   WINDS_SERVICE_NAME,
  477.                                   SERVICE_ALL_ACCESS,
  478.                                   SERVICE_WIN32_OWN_PROCESS,
  479.                                   dwStartType,
  480.                                   SERVICE_ERROR_NORMAL,
  481.                                   szFullPathToServiceExe,
  482.                                   NULL,
  483.                                   NULL,
  484.                                   NULL,
  485.                                   NULL,
  486.                                   NULL);
  487.         if (NULL == schWINDS)
  488.         {
  489.             hResult = HRESULT_FROM_WIN32 (GetLastError());
  490.         }
  491.         else
  492.         {
  493.             if (fStartImmediately)
  494.             {
  495.                 StartService (schWINDS, 0, NULL);
  496.             }
  497.             CloseServiceHandle (schWINDS);
  498.         }
  499.         if (HRESULT_FROM_WIN32 (ERROR_SERVICE_EXISTS) == hResult)
  500.         {
  501.             RemoveWindsService();
  502.             goto RestartInstall;
  503.         }
  504.         CloseServiceHandle (schSCM);
  505.     }
  506.     TraceResult ("InstallWindsService", hResult);
  507.     return hResult;
  508. }
  509.  
  510. ///////////////////////////////////////////////////////////////////////////////
  511. //    RemoveWindsService()
  512. //
  513. //    Parameters
  514. //
  515. //    Purpose
  516. //      
  517. //    Return Value
  518. //      
  519. HRESULT WINAPI RemoveWindsService()
  520. {
  521.     HRESULT hResult = S_OK;
  522.     SC_HANDLE schSCM, schWINDS;
  523.     schSCM = OpenSCManager (0, 0, SC_MANAGER_CREATE_SERVICE);
  524.     if (NULL == schSCM)
  525.     {
  526.         hResult = HRESULT_FROM_WIN32 (GetLastError());
  527.     }
  528.     else
  529.     {
  530.         schWINDS = OpenService (schSCM,
  531.                                 WINDS_SERVICE_NAME_SHORT,
  532.                                 SERVICE_ALL_ACCESS);
  533.         if (NULL == schWINDS)
  534.         {
  535.             hResult = HRESULT_FROM_WIN32 (GetLastError());
  536.         }
  537.         else
  538.         {
  539.             SERVICE_STATUS ssState;
  540.             ControlService (schWINDS, SERVICE_CONTROL_STOP, &ssState);
  541.             DeleteService (schWINDS);
  542.             CloseServiceHandle (schWINDS);
  543.         }
  544.         CloseServiceHandle (schSCM);
  545.     }
  546.     TraceResult ("RemoveWindsService", hResult);
  547.     return hResult;
  548. }
  549.  
  550. ///////////////////////////////////////////////////////////////////////////////
  551. //    WinMain()
  552. //
  553. //    Parameters
  554. //      { Refer to Win32 SDK documentation }
  555. //      
  556. //    Purpose
  557. //      This is the entry function. The application will start executing here.
  558. //      
  559. //    Return Value
  560. //      Return code of the application to the system.
  561. //      
  562. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
  563. {
  564.     InitTraces (TRACES_NO_ASSERT_DIALOG | TRACES_NO_COM_OUTPUT);
  565.     //InitTraces (TRACES_NO_ASSERT_DIALOG);
  566.     ghInstance = hInstance;
  567.     ghHeap = GetProcessHeap();
  568.  
  569.     if (0 == lstrcmpi ("APP", pszCmdLine))
  570.     {
  571.         // Check for other instances of this application running. If one is found,
  572.         // bring it to the foreground
  573.         HWND hOtherInstance = FindWindow (MAINDLGCLASS, NULL);
  574.         if (NULL != hOtherInstance)
  575.         {
  576.             HWND hChildWnd = GetLastActivePopup (hOtherInstance);
  577.             if (hChildWnd != hOtherInstance)
  578.             {
  579.                 BringWindowToTop (hOtherInstance);
  580.             }
  581.             else
  582.             {
  583.                 SetForegroundWindow (hOtherInstance);
  584.             }
  585.             return 1;
  586.         }
  587.  
  588.         RegisterWindsPrivateClass();
  589.  
  590.         if (S_OK != InitWindsService())
  591.         {
  592.             return -1;
  593.         }
  594.     
  595.         DialogBoxParam (ghInstance, MAKEINTRESOURCE(IDD_WINDS_APP), NULL, GenericDlgProc, (LPARAM)TRUE);
  596.     
  597.         StopWindsService();
  598.  
  599.         return 0;
  600.     }
  601.  
  602.     if (0 == lstrcmpi ("INSTALL", pszCmdLine))
  603.     {
  604.         TCHAR szFullPath[_MAX_PATH] = { 0 };
  605.         GetCurrentDirectory (_MAX_PATH, szFullPath);
  606.         lstrcat (szFullPath, WINDS_SERVICE_EXECUTABLE);
  607.         if (S_OK != InstallWindsService (SERVICE_AUTO_START, szFullPath, TRUE))
  608.         {
  609.             return -1;
  610.         }
  611.         return 0;
  612.     }
  613.  
  614.     if (0 == lstrcmpi ("REMOVE", pszCmdLine))
  615.     {
  616.         if (S_OK != RemoveWindsService())
  617.         {
  618.             return -1;
  619.         }
  620.         return 0;
  621.     }
  622.  
  623.     SERVICE_TABLE_ENTRY ServiceTable[] =
  624.     {
  625.         { WINDS_SERVICE_NAME,
  626.           (LPSERVICE_MAIN_FUNCTION)WindsServiceMain,
  627.         },
  628.         { NULL, NULL }
  629.     };
  630.  
  631.     if (FALSE == StartServiceCtrlDispatcher (ServiceTable))
  632.     {
  633.         if (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT == GetLastError())
  634.         {
  635.             RegisterWindsPrivateClass();
  636.             DialogBoxParam (ghInstance, MAKEINTRESOURCE(IDD_WINDS_DIALOG), NULL, GenericDlgProc, (LPARAM)FALSE);
  637.         }
  638.     }
  639.     return 0;
  640. }
  641.  
  642. ///////////////////////////////////////////////////////////////////////////////
  643. //    InitRPCServer()
  644. //
  645. //    Parameters
  646. //
  647. //    Purpose
  648. //
  649. //    Return Value
  650. //
  651. BOOL WINAPI InitRPCServer()
  652. {
  653.     #define MAX_NUM_OF_CALLS    65536
  654.     RPC_STATUS status = RpcServerUseProtseqEp ((WINDS_RPC_STRING)WINDS_RPC_PROTOCOL,
  655.                                                MAX_NUM_OF_CALLS,
  656.                                                (WINDS_RPC_STRING)WINDS_PROVIDERS_RPC_ENDPOINT,
  657.                                                NULL);  // Security descriptor
  658.     if (status)
  659.     {
  660.         TraceMessage ("InitRPCServer: RpcServerUseProtseqEp failed (PROVIDER)");
  661.         goto ErrorExit;
  662.     }
  663.  
  664.     status = RpcServerRegisterIf (WINDSREM_v1_6_s_ifspec,   // Interface to register
  665.                                   NULL,                     // MgrTypeUuid
  666.                                   NULL);                    // MgrEpv; null means use default
  667.     if (status)
  668.     {
  669.         TraceMessage ("InitRPCServer: RpcServerRegisterIf failed (PROVIDER)");
  670.         goto ErrorExit;
  671.     }
  672.  
  673.     status = RpcServerUseProtseqEp ((WINDS_RPC_STRING)WINDS_RPC_PROTOCOL,
  674.                                     MAX_NUM_OF_CALLS,
  675.                                     (WINDS_RPC_STRING)WINDS_ADMIN_RPC_ENDPOINT,
  676.                                     NULL);  // Security descriptor
  677.     if (status)
  678.     {
  679.         TraceMessage ("InitRPCServer: RpcServerUseProtseqEp failed (ADMIN)");
  680.         goto ErrorExit;
  681.     }
  682.     
  683.     status = RpcServerRegisterIf (WINDSADM_v1_0_s_ifspec,   // Interface to register
  684.                                   NULL,                     // MgrTypeUuid
  685.                                   NULL);                    // MgrEpv; null means use default
  686.     if (status)
  687.     {
  688.         TraceMessage ("InitRPCServer: RpcServerRegisterIf failed (ADMIN)");
  689.         goto ErrorExit;
  690.     }
  691.  
  692.     status = RpcServerListen (1, MAX_NUM_OF_CALLS, TRUE);
  693.     if (status)
  694.     {
  695.         TraceMessage ("InitRPCServer: RpcServerListen failed");
  696.         goto ErrorExit;
  697.     }
  698. ErrorExit:
  699.     if (status)
  700.     {
  701.         TraceResult ("InitRPCServer", MAKE_HRESULT(1, FACILITY_RPC, status));
  702.         return FALSE;
  703.     }
  704.     return TRUE;
  705. }
  706.  
  707. ///////////////////////////////////////////////////////////////////////////////
  708. //    TerminateAllRPCServer()
  709. //
  710. //    Parameters
  711. //
  712. //    Purpose
  713. //
  714. //    Return Value
  715. //
  716. BOOL WINAPI TerminateAllRPCServer()
  717. {
  718.     RPC_STATUS status = RpcMgmtStopServerListening (NULL);
  719.     if (status)
  720.     {
  721.         TraceMessage ("TerminateRPCServer: RpcMgmtStopServerListening failed");
  722.     }
  723.     else
  724.     {
  725.         status = RpcServerUnregisterIf (NULL, NULL, FALSE);
  726.         if (status)
  727.         {
  728.             TraceMessage ("TerminateRPCServer: RpcServerUnregisterIf failed");
  729.         }
  730.     }
  731.     if (status)
  732.     {
  733.         TraceResult ("TerminateRPCServer", MAKE_HRESULT(1, FACILITY_RPC, status));
  734.         return FALSE;
  735.     }
  736.     return TRUE;
  737. }
  738.  
  739. ///////////////////////////////////////////////////////////////////////////////
  740. //    GetServiceState()
  741. //
  742. //    Parameters
  743. //
  744. //    Purpose
  745. //
  746. //    Return Value
  747. //
  748. HRESULT WINAPI GetServiceState()
  749. {
  750.     HRESULT hServiceState;
  751.     EnterCriticalSection (&g_csServiceState);
  752.     hServiceState = g_hServerState;
  753.     LeaveCriticalSection (&g_csServiceState);
  754.     return hServiceState;
  755. }
  756.  
  757. ///////////////////////////////////////////////////////////////////////////////
  758. //    PrivateDlgClassProc()
  759. //
  760. //    Parameters
  761. //      { Refer to Win32 API documentation on dialog procedures }
  762. //
  763. //    Purpose
  764. //      
  765. //    Return Value
  766. //      
  767. LRESULT CALLBACK PrivateDlgClassProc (HWND    hDlg, 
  768.                                       UINT    message, 
  769.                                       WPARAM  wParam, 
  770.                                       LPARAM  lParam)
  771. {
  772.     return DefDlgProc (hDlg, message, wParam, lParam);
  773. }
  774.  
  775. ///////////////////////////////////////////////////////////////////////////////
  776. //    RegisterWindsPrivateClass()
  777. //
  778. //    Parameters
  779. //
  780. //    Purpose
  781. //      
  782. //    Return Value
  783. //      
  784. void WINAPI RegisterWindsPrivateClass()
  785. {
  786.     WNDCLASS wc = { 0 };
  787.     // Register the class for this application
  788.     wc.hInstance        = ghInstance;
  789.     wc.hCursor          = LoadCursor (NULL, IDC_ARROW);
  790.     wc.lpfnWndProc      = PrivateDlgClassProc;
  791.     wc.cbWndExtra       = DLGWINDOWEXTRA;
  792.     wc.hIcon            = LoadIcon (ghInstance, MAKEINTRESOURCE (IDI_WINDSSERVICE));
  793.     wc.lpszClassName    = MAINDLGCLASS;
  794.     if (!RegisterClass (&wc))
  795.     {
  796.         TraceResult ("RegisterWindsPrivateClass: Failed to register the main class", HRESULT_FROM_WIN32(GetLastError()));
  797.     }
  798. }
  799.  
  800. ///////////////////////////////////////////////////////////////////////////////
  801. //    GenericDlgProc()
  802. //
  803. //    Parameters
  804. //      { Refer to Win32 API documentation on dialog procedures }
  805. //
  806. //    Purpose
  807. //      
  808. //    Return Value
  809. //      TRUE if message was handled, FALSE if we don't handle the message
  810. //      
  811. BOOL CALLBACK GenericDlgProc (HWND    hDlg, 
  812.                               UINT    message, 
  813.                               WPARAM  wParam, 
  814.                               LPARAM  lParam)
  815. {
  816.     HRESULT hResult;
  817.     switch (message)
  818.     {
  819.         case WM_INITDIALOG :
  820.             if (TRUE == lParam)
  821.             {
  822.                 ShowWindow (hDlg, SW_MINIMIZE);
  823.             }
  824.             else
  825.             {
  826.                 if (!g_pctl3d)
  827.                 {
  828.                     BOOL f;
  829.                     g_pctl3d = CTL3D_Initialize(ghInstance);
  830.                     CTL3D_AutoSubclass(g_pctl3d, ghInstance, &f);
  831.                 }
  832.                 CenterDialogBox (hDlg);
  833.             }
  834.             return TRUE;
  835.  
  836.         case WM_COMMAND :
  837.             switch (LOWORD(wParam))
  838.             {
  839.                 case IDOK :
  840.                 case IDCANCEL :
  841.                     PostMessage (hDlg, WM_SYSCOMMAND, SC_CLOSE, 0);
  842.                     return TRUE;
  843.  
  844.                 case IDC_INSTALL_SERVICE :
  845.                     DialogBox (ghInstance, MAKEINTRESOURCE(IDD_INSTALL_OPTIONS), hDlg, InstallDlgProc);
  846.                     break;
  847.  
  848.                 case IDC_REMOVE_SERVICE :
  849.                     hResult = RemoveWindsService();
  850.                     if (S_OK == hResult)
  851.                     {
  852.                         MessageBox (hDlg,
  853.                                     TEXT("Service successfully removed"),
  854.                                     TEXT("WINDS Services - Remove"),
  855.                                     MB_OK | MB_ICONEXCLAMATION);
  856.                     }
  857.                     else
  858.                     {
  859.                         MessageBox (hDlg,
  860.                                     TEXT("Failed to remove the service"),
  861.                                     TEXT("WINDS Services - Remove"),
  862.                                     MB_OK | MB_ICONSTOP);
  863.                     }
  864.                     break;
  865.             }
  866.             break;
  867.  
  868.         case WM_SYSCOMMAND:
  869.             if (wParam == SC_CLOSE)
  870.             {
  871.                 CTL3D_Uninitialize(g_pctl3d);
  872.                 g_pctl3d = NULL;
  873.                 EndDialog (hDlg, TRUE);
  874.                 return TRUE;
  875.             }
  876.             break;
  877.     }
  878.     return FALSE;
  879. }
  880.  
  881. ///////////////////////////////////////////////////////////////////////////////
  882. //    InstallDlgProc()
  883. //
  884. //    Parameters
  885. //      { Refer to Win32 API documentation on dialog procedures }
  886. //
  887. //    Purpose
  888. //      
  889. //    Return Value
  890. //      TRUE if message was handled, FALSE if we don't handle the message
  891. //      
  892. BOOL CALLBACK InstallDlgProc (HWND    hDlg, 
  893.                               UINT    message, 
  894.                               WPARAM  wParam, 
  895.                               LPARAM  lParam)
  896. {
  897.     TCHAR szFullPath[_MAX_PATH];
  898.     DWORD dwStart;
  899.     BOOL fStartNow;
  900.     switch (message)
  901.     {
  902.         case WM_INITDIALOG :
  903.             CenterDialogBox (hDlg);
  904.             Edit_LimitText (GetDlgItem (hDlg, IDC_SERVICE_FILEPATH), _MAX_PATH - 1);
  905.             GetCurrentDirectory (_MAX_PATH, szFullPath);
  906.             lstrcat (szFullPath, WINDS_SERVICE_EXECUTABLE);
  907.             SetWindowText (GetDlgItem (hDlg, IDC_SERVICE_FILEPATH), szFullPath);
  908.             Button_SetCheck (GetDlgItem (hDlg, IDC_AUTO_START), BST_CHECKED);
  909.             Button_SetCheck (GetDlgItem (hDlg, IDC_START_NOW), BST_CHECKED);
  910.             return TRUE;
  911.  
  912.         case WM_COMMAND :
  913.             switch (LOWORD(wParam))
  914.             {
  915.                 case IDOK :
  916.                     GetWindowText (GetDlgItem (hDlg, IDC_SERVICE_FILEPATH), szFullPath, _MAX_PATH);
  917.                     if (BST_CHECKED == Button_GetCheck (GetDlgItem (hDlg, IDC_AUTO_START)))
  918.                     {
  919.                         dwStart = SERVICE_AUTO_START;
  920.                     }
  921.                     else
  922.                     {
  923.                         dwStart = SERVICE_DEMAND_START;
  924.                     }
  925.                     if (BST_CHECKED == Button_GetCheck (GetDlgItem (hDlg, IDC_START_NOW)))
  926.                     {
  927.                         fStartNow = TRUE;
  928.                     }
  929.                     else
  930.                     {
  931.                         fStartNow = FALSE;
  932.                     }
  933.                     if (lstrlen (szFullPath) && S_OK == InstallWindsService (dwStart, szFullPath, fStartNow))
  934.                     {
  935.                         MessageBox (hDlg,
  936.                                     TEXT("Service successfully installed"),
  937.                                     TEXT("WINDS Services - Install"),
  938.                                     MB_OK | MB_ICONEXCLAMATION);
  939.                     }
  940.                     else
  941.                     {
  942.                         MessageBox (hDlg,
  943.                                     TEXT("Failed to install the service"),
  944.                                     TEXT("WINDS Services - Install"),
  945.                                     MB_OK | MB_ICONSTOP);
  946.                     }
  947.                     // Fall through
  948.                 case IDCANCEL :
  949.                     EndDialog (hDlg, TRUE);
  950.                     return TRUE;
  951.             }
  952.     }
  953.     return FALSE;
  954. }
  955.  
  956. // End of file for SERVICE.CPP
  957.