home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / tutsamp / aptserve / aptserve.cpp next >
Encoding:
C/C++ Source or Header  |  1997-08-30  |  32.3 KB  |  992 lines

  1. /*+==========================================================================
  2.   File:      APTSERVE.CPP
  3.  
  4.   Summary:   Based largely on the LOCSERVE.EXE source code, this module
  5.              implements the main framework for a Win32 .EXE application.
  6.              This application is meant to run hidden as a local multiple
  7.              Apartment COM server that offers the Car, UtilityCar, and
  8.              CruiseCar components.  Though this local server offers a
  9.              simple main window and menu system these are not seen during
  10.              normal operation.  This server can be run stand-alone for
  11.              debugging purposes by explicitly using the -embedding command
  12.              line switch and invoking APTSERVE prior to the client.
  13.  
  14.              This local server supports self-registration and this program
  15.              recognizes the -RegServer and -UnregServer command line
  16.              switches and has the appropriate functions (RegisterServer
  17.              and UnregisterServer) to register this local server in the
  18.              system Registry.
  19.  
  20.              For a comprehensive tutorial code tour of APTSERVE's
  21.              contents and offerings see the tutorial APTSERVE.HTM file.
  22.              For more specific technical details on the internal workings
  23.              see the comments dispersed throughout the APTSERVE source code.
  24.              For more details on the APTCLIEN.EXE that APTSERVE works with
  25.              see the APTCLIEN.HTM file in the main tutorial directory.
  26.  
  27.   Classes:   CMainWindow
  28.  
  29.   Functions: InitApplication, WinMain
  30.  
  31.   Origin:    3-20-96: atrent - Editor-inheritance from the LOCSERVE source.
  32.  
  33. ----------------------------------------------------------------------------
  34.   This file is part of the Microsoft COM Tutorial Code Samples.
  35.  
  36.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  37.  
  38.   This source code is intended only as a supplement to Microsoft
  39.   Development Tools and/or on-line documentation.  See these other
  40.   materials for detailed information regarding Microsoft code samples.
  41.  
  42.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  43.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  44.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  45.   PARTICULAR PURPOSE.
  46. ==========================================================================+*/
  47.  
  48. /*--------------------------------------------------------------------------
  49.   We include WINDOWS.H for all Win32 applications.
  50.   We include OLE2.H because we will make calls to the COM/OLE libraries.
  51.   We include INITGUID.H only once (here) in the entire app because we
  52.     will be defining GUIDs and want them as constants in the data segment.
  53.   We include APPUTIL.H because we will be building this application using
  54.     the convenient Virtual Window and Dialog classes and other
  55.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  56.   We include MICARS.H and CARGUIDS.H for the common car-related Interface
  57.     class, GUID, and CLSID specifications.
  58.   We include APTSERVE.H because it has class and resource definitions
  59.     specific to this APTSERVE application.
  60.   We include SERVER.H because it has internal class declarations for
  61.     the server's control object.
  62.   We include FACTORY.H because it has the necessary internal class factory
  63.     declarations for this component server.
  64. ---------------------------------------------------------------------------*/
  65. #include <windows.h>
  66. #include <ole2.h>
  67. #include <initguid.h>
  68. #include <apputil.h>
  69. #include <micars.h>
  70. #include <carguids.h>
  71. #include "aptserve.h"
  72. #include "server.h"
  73. #include "factory.h"
  74.  
  75.  
  76. // We encapsulate the control of this COM server (eg, lock and object
  77. // counting) in a server control C++ object.  Here is it's pointer.
  78. CServer*  g_pServer = NULL;
  79.  
  80. // Here is a pointer for use by the global Trace Message logging macros.
  81. CSendLog* g_pMsgLog = NULL;
  82.  
  83.  
  84. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  85.   Method:   CMainWindow::CMainWindow
  86.  
  87.   Summary:  CMainWindow Constructor.
  88.  
  89.   Args:     .
  90.  
  91.   Modifies: m_pMsgBox.
  92.  
  93.   Returns:  .
  94. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  95. CMainWindow::CMainWindow()
  96. {
  97.   // Null the Message object pointers.
  98.   m_pMsgBox = NULL;
  99.   m_pMsgLog = NULL;
  100. }
  101.  
  102.  
  103. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  104.   Method:   CMainWindow::~CMainWindow
  105.  
  106.   Summary:  CMainWindow Destructor.  Destruction of the main window
  107.             indicates that the application should quit and thus the
  108.             PostQuitMessage API is called.
  109.  
  110.   Args:     .
  111.  
  112.   Modifies: .
  113.  
  114.   Returns:  .
  115. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  116. CMainWindow::~CMainWindow()
  117. {
  118.   // CMainWindow is derived from CVirWindow which traps the WM_DESTROY
  119.   // message and causes a delete of CMainWindow which in turn causes this
  120.   // destructor to run. The WM_DESTROY results when the window is destoyed
  121.   // after a close of the window. Prior to exiting the main message loop:
  122.  
  123.   // Close down the factories (ie, Revoke and release the Class Factories).
  124.   if (NULL != g_pServer)
  125.     g_pServer->CloseFactories();
  126.  
  127.   LOGF1("L<%X>: Exiting APTSERVE local server application.",TID);
  128.  
  129.   // We delete the CMsgBox and CMsgLog objects that were made in
  130.   // Initinstance and the server control object, CServer.
  131.   DELETE_POINTER(g_pServer);
  132.   DELETE_POINTER(m_pMsgBox);
  133.   DELETE_POINTER(m_pMsgLog);
  134.  
  135.   // We then post a WM_QUIT message to cause an exit of the main thread's
  136.   // message loop and an exit of this instance of the application.
  137.   PostQuitMessage(0);
  138. }
  139.  
  140.  
  141. /*F+F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  142.   Function: SetRegKeyValue
  143.  
  144.   Summary:  Internal utility function to set a Key, Subkey, and value
  145.             in the system Registry under HKEY_CLASSES_ROOT.
  146.  
  147.   Args:     LPTSTR pszKey,
  148.             LPTSTR pszSubkey,
  149.             LPTSTR pszValue)
  150.  
  151.   Returns:  BOOL
  152.               TRUE if success; FALSE if not.
  153. ------------------------------------------------------------------------F-F*/
  154. BOOL SetRegKeyValue(
  155.        LPTSTR pszKey,
  156.        LPTSTR pszSubkey,
  157.        LPTSTR pszValue)
  158. {
  159.   BOOL bOk = FALSE;
  160.   LONG ec;
  161.   HKEY hKey;
  162.   TCHAR szKey[MAX_STRING_LENGTH];
  163.  
  164.   lstrcpy(szKey, pszKey);
  165.  
  166.   if (NULL != pszSubkey)
  167.   {
  168.     lstrcat(szKey, TEXT("\\"));
  169.     lstrcat(szKey, pszSubkey);
  170.   }
  171.  
  172.   ec = RegCreateKeyEx(
  173.          HKEY_CLASSES_ROOT,
  174.          szKey,
  175.          0,
  176.          NULL,
  177.          REG_OPTION_NON_VOLATILE,
  178.          KEY_ALL_ACCESS,
  179.          NULL,
  180.          &hKey,
  181.          NULL);
  182.  
  183.   if (ERROR_SUCCESS == ec)
  184.   {
  185.     if (NULL != pszValue)
  186.     {
  187.       ec = RegSetValueEx(
  188.              hKey,
  189.              NULL,
  190.              0,
  191.              REG_SZ,
  192.              (BYTE *)pszValue,
  193.              (lstrlen(pszValue)+1)*sizeof(TCHAR));
  194.     }
  195.     if (ERROR_SUCCESS == ec)
  196.       bOk = TRUE;
  197.     RegCloseKey(hKey);
  198.   }
  199.  
  200.   return bOk;
  201. }
  202.  
  203.  
  204. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  205.   Method:   CMainWindow::RegisterServer
  206.  
  207.   Summary:  Member function used by this server to register itself in the
  208.             system registry.
  209.  
  210.   Args:     void.
  211.  
  212.   Returns:  BOOL
  213.               TRUE
  214. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  215. BOOL CMainWindow::RegisterServer(void)
  216. {
  217.   BOOL  bOk = TRUE;
  218.   TCHAR szID[GUID_SIZE+1];
  219.   TCHAR szCLSID[GUID_SIZE+32];
  220.   TCHAR szModulePath[MAX_PATH];
  221.  
  222.   // Obtain the path to this module's executable file for later use.
  223.   GetModuleFileName(
  224.     g_pServer->m_hInstServer,
  225.     szModulePath,
  226.     sizeof(szModulePath)/sizeof(TCHAR));
  227.  
  228.   /*-------------------------------------------------------------------------
  229.     Create registry entries for the AptCar Component.
  230.   -------------------------------------------------------------------------*/
  231.   // Create some base key strings.
  232.   StringFromGUID2(CLSID_AptCar, szID, GUID_SIZE);
  233.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  234.   lstrcat(szCLSID, szID);
  235.  
  236.   // Create ProgID keys.
  237.   SetRegKeyValue(
  238.     TEXT("CTS.AptCar.1"),
  239.     NULL,
  240.     TEXT("AptCar Component - APTSERVE Code Sample"));
  241.   SetRegKeyValue(
  242.     TEXT("CTS.AptCar.1"),
  243.     TEXT("CLSID"),
  244.     szID);
  245.  
  246.   // Create VersionIndependentProgID keys.
  247.   SetRegKeyValue(
  248.     TEXT("CTS.AptCar"),
  249.     NULL,
  250.     TEXT("AptCar Component - APTSERVE Code Sample"));
  251.   SetRegKeyValue(
  252.     TEXT("CTS.AptCar"),
  253.     TEXT("CurVer"),
  254.     TEXT("CTS.AptCar.1"));
  255.   SetRegKeyValue(
  256.     TEXT("CTS.AptCar"),
  257.     TEXT("CLSID"),
  258.     szID);
  259.  
  260.   // Create entries under CLSID.
  261.   SetRegKeyValue(
  262.     szCLSID,
  263.     NULL,
  264.     TEXT("AptCar Component - APTSERVE Code Sample"));
  265.   SetRegKeyValue(
  266.     szCLSID,
  267.     TEXT("ProgID"),
  268.     TEXT("CTS.AptCar.1"));
  269.   SetRegKeyValue(
  270.     szCLSID,
  271.     TEXT("VersionIndependentProgID"),
  272.     TEXT("CTS.AptCar"));
  273.   SetRegKeyValue(
  274.     szCLSID,
  275.     TEXT("NotInsertable"),
  276.     NULL);
  277.   SetRegKeyValue(
  278.     szCLSID,
  279.     TEXT("LocalServer32"),
  280.     szModulePath);
  281.  
  282.   /*-------------------------------------------------------------------------
  283.     Create registry entries for the AptUtilityCar Component.
  284.   -------------------------------------------------------------------------*/
  285.   // Create some base key strings.
  286.   StringFromGUID2(CLSID_AptUtilityCar, szID, GUID_SIZE);
  287.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  288.   lstrcat(szCLSID, szID);
  289.  
  290.   // Create ProgID keys.
  291.   SetRegKeyValue(
  292.     TEXT("CTS.AptUtilityCar.1"),
  293.     NULL,
  294.     TEXT("AptUtilityCar Component - APTSERVE Code Sample"));
  295.   SetRegKeyValue(
  296.     TEXT("CTS.AptUtilityCar.1"),
  297.     TEXT("CLSID"),
  298.     szID);
  299.  
  300.   // Create VersionIndependentProgID keys.
  301.   SetRegKeyValue(
  302.     TEXT("CTS.AptUtilityCar"),
  303.     NULL,
  304.     TEXT("AptUtilityCar Component - APTSERVE Code Sample"));
  305.   SetRegKeyValue(
  306.     TEXT("CTS.AptUtilityCar"),
  307.     TEXT("CurVer"),
  308.     TEXT("CTS.AptUtilityCar.1"));
  309.   SetRegKeyValue(
  310.     TEXT("CTS.AptUtilityCar"),
  311.     TEXT("CLSID"),
  312.     szID);
  313.  
  314.   // Create entries under CLSID.
  315.   SetRegKeyValue(
  316.     szCLSID,
  317.     NULL,
  318.     TEXT("AptUtilityCar Component - APTSERVE Code Sample"));
  319.   SetRegKeyValue(
  320.     szCLSID,
  321.     TEXT("ProgID"),
  322.     TEXT("CTS.AptUtilityCar.1"));
  323.   SetRegKeyValue(
  324.     szCLSID,
  325.     TEXT("VersionIndependentProgID"),
  326.     TEXT("CTS.AptUtilityCar"));
  327.   SetRegKeyValue(
  328.     szCLSID,
  329.     TEXT("NotInsertable"),
  330.     NULL);
  331.   SetRegKeyValue(
  332.     szCLSID,
  333.     TEXT("LocalServer32"),
  334.     szModulePath);
  335.  
  336.   /*-------------------------------------------------------------------------
  337.     Create registry entries for the AptCruiseCar Component.
  338.   -------------------------------------------------------------------------*/
  339.   // Create some base key strings.
  340.   StringFromGUID2(CLSID_AptCruiseCar, szID, GUID_SIZE);
  341.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  342.   lstrcat(szCLSID, szID);
  343.  
  344.   // Create ProgID keys.
  345.   SetRegKeyValue(
  346.     TEXT("CTS.AptCruiseCar.1"),
  347.     NULL,
  348.     TEXT("AptCruiseCar Component - APTSERVE Code Sample"));
  349.   SetRegKeyValue(
  350.     TEXT("CTS.AptCruiseCar.1"),
  351.     TEXT("CLSID"),
  352.     szID);
  353.  
  354.   // Create VersionIndependentProgID keys.
  355.   SetRegKeyValue(
  356.     TEXT("CTS.AptCruiseCar"),
  357.     NULL,
  358.     TEXT("AptCruiseCar Component - APTSERVE Code Sample"));
  359.   SetRegKeyValue(
  360.     TEXT("CTS.AptCruiseCar"),
  361.     TEXT("CurVer"),
  362.     TEXT("CTS.AptCruiseCar.1"));
  363.   SetRegKeyValue(
  364.     TEXT("CTS.AptCruiseCar"),
  365.     TEXT("CLSID"),
  366.     szID);
  367.  
  368.   // Create entries under CLSID.
  369.   SetRegKeyValue(
  370.     szCLSID,
  371.     NULL,
  372.     TEXT("AptCruiseCar Component - APTSERVE Code Sample"));
  373.   SetRegKeyValue(
  374.     szCLSID,
  375.     TEXT("ProgID"),
  376.     TEXT("CTS.AptCruiseCar.1"));
  377.   SetRegKeyValue(
  378.     szCLSID,
  379.     TEXT("VersionIndependentProgID"),
  380.     TEXT("CTS.AptCruiseCar"));
  381.   SetRegKeyValue(
  382.     szCLSID,
  383.     TEXT("NotInsertable"),
  384.     NULL);
  385.   SetRegKeyValue(
  386.     szCLSID,
  387.     TEXT("LocalServer32"),
  388.     szModulePath);
  389.  
  390.   return bOk;
  391. }
  392.  
  393.  
  394. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  395.   Method:   CMainWindow::UnregisterServer
  396.  
  397.   Summary:  Member function used by this server to unregister itself from
  398.             the system Registry.
  399.  
  400.   Args:     void.
  401.  
  402.   Returns:  BOOL
  403.               TRUE
  404. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  405. BOOL CMainWindow::UnregisterServer(void)
  406. {
  407.   BOOL  bOk = TRUE;
  408.   TCHAR szID[GUID_SIZE+1];
  409.   TCHAR szCLSID[GUID_SIZE+32];
  410.   TCHAR szTemp[MAX_PATH+GUID_SIZE];
  411.  
  412.   /*-------------------------------------------------------------------------
  413.     Delete registry entries for the AptCar Component.
  414.   -------------------------------------------------------------------------*/
  415.   //Create some base key strings.
  416.   StringFromGUID2(CLSID_AptCar, szID, GUID_SIZE);
  417.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  418.   lstrcat(szCLSID, szID);
  419.  
  420.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCar\\CurVer"));
  421.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCar\\CLSID"));
  422.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCar"));
  423.  
  424.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCar.1\\CLSID"));
  425.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCar.1"));
  426.  
  427.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("ProgID"));
  428.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  429.  
  430.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("VersionIndependentProgID"));
  431.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  432.  
  433.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("NotInsertable"));
  434.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  435.  
  436.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("LocalServer32"));
  437.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  438.  
  439.   RegDeleteKey(HKEY_CLASSES_ROOT, szCLSID);
  440.  
  441.   /*-------------------------------------------------------------------------
  442.     Delete registry entries for the AptUtilityCar Component.
  443.   -------------------------------------------------------------------------*/
  444.   //Create some base key strings.
  445.   StringFromGUID2(CLSID_AptUtilityCar, szID, GUID_SIZE);
  446.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  447.   lstrcat(szCLSID, szID);
  448.  
  449.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptUtilityCar\\CurVer"));
  450.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptUtilityCar\\CLSID"));
  451.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptUtilityCar"));
  452.  
  453.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptUtilityCar.1\\CLSID"));
  454.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptUtilityCar.1"));
  455.  
  456.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("ProgID"));
  457.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  458.  
  459.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("VersionIndependentProgID"));
  460.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  461.  
  462.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("NotInsertable"));
  463.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  464.  
  465.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("LocalServer32"));
  466.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  467.  
  468.   RegDeleteKey(HKEY_CLASSES_ROOT, szCLSID);
  469.  
  470.   /*-------------------------------------------------------------------------
  471.     Delete registry entries for the AptCruiseCar Component.
  472.   -------------------------------------------------------------------------*/
  473.   //Create some base key strings.
  474.   StringFromGUID2(CLSID_AptCruiseCar, szID, GUID_SIZE);
  475.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  476.   lstrcat(szCLSID, szID);
  477.  
  478.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCruiseCar\\CurVer"));
  479.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCruiseCar\\CLSID"));
  480.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCruiseCar"));
  481.  
  482.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCruiseCar.1\\CLSID"));
  483.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("CTS.AptCruiseCar.1"));
  484.  
  485.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("ProgID"));
  486.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  487.  
  488.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("VersionIndependentProgID"));
  489.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  490.  
  491.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("NotInsertable"));
  492.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  493.  
  494.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("LocalServer32"));
  495.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  496.  
  497.   RegDeleteKey(HKEY_CLASSES_ROOT, szCLSID);
  498.  
  499.   return bOk;
  500. }
  501.  
  502.  
  503. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  504.   Method:   CMainWindow::DoMenu
  505.  
  506.   Summary:  Dispatch and handle the main menu commands.
  507.  
  508.   Args:     WPARAM wParam,
  509.               First message parameter (word sized).
  510.             LPARAM lParam)
  511.               Second message parameter (long sized).
  512.  
  513.   Modifies: ...
  514.  
  515.   Returns:  LRESULT
  516.               Standard Windows WindowProc return value.
  517. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  518. LRESULT CMainWindow::DoMenu(
  519.           WPARAM wParam,
  520.           LPARAM lParam)
  521. {
  522.   LRESULT lResult = FALSE;
  523.   HMENU hMenu  = ::GetMenu(m_hWnd);
  524.  
  525.   switch (LOWORD(wParam))
  526.   {
  527.     //----------------------------------------------------------------------
  528.     // Handle File Menu Commands.
  529.     //----------------------------------------------------------------------
  530.     case IDM_FILE_EXIT:
  531.       // The user commands us to exit this application so we tell the
  532.       // Main window to close itself.
  533.       ::PostMessage(m_hWnd, WM_CLOSE, 0, 0);
  534.       break;
  535.  
  536.     //----------------------------------------------------------------------
  537.     // Handle Log Menu Commands.
  538.     //----------------------------------------------------------------------
  539.     case IDM_LOG_LOGCLEAR:
  540.       // Clear the message log.
  541.       g_pMsgLog->Clear();
  542.       // Use macro to log messages.
  543.       LOGID(IDS_LOGTO_SERVER);
  544.       break;
  545.     case IDM_LOG_COPYCLIP:
  546.       // Copy trace message log to clipboard.
  547.       g_pMsgLog->Copy();
  548.       break;
  549.  
  550.     //----------------------------------------------------------------------
  551.     // Handle Help Menu Commands.
  552.     //----------------------------------------------------------------------
  553.     case IDM_HELP_ABOUT:
  554.       {
  555.         CAboutBox dlgAboutBox;
  556.         HWND hWnd = FindWindow(NULL, TEXT(CLIENT_WINDOW_TITLE));
  557.         if (NULL == hWnd)
  558.           hWnd = m_hWnd;
  559.  
  560.         LOGF1("L<%X>: === Help Menu: About APTSERVE.",TID);
  561.         // Show the standard About Box dialog for this EXE by telling the
  562.         // dialog C++ object to show itself by invoking its ShowDialog
  563.         // method.  Pass it this EXE instance and the parent window handle.
  564.         // Use a dialog resource ID for the dialog template stored in
  565.         // this EXE module's resources.
  566.         dlgAboutBox.ShowDialog(
  567.           m_hInst,
  568.           MAKEINTRESOURCE(IDM_HELP_ABOUT),
  569.           hWnd);
  570.       }
  571.       break;
  572.  
  573.     default:
  574.       // Defer all messages NOT handled here to the Default Window Proc.
  575.       lResult = ::DefWindowProc(m_hWnd, WM_COMMAND, wParam, lParam);
  576.       break;
  577.   }
  578.  
  579.   return(lResult);
  580. }
  581.  
  582.  
  583. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  584.   Method:   CMainWindow::InitInstance
  585.  
  586.   Summary:  Instantiates an instance of the main application window.
  587.             This method must be called only once, immediately after
  588.             window class construction.  We take care to delete 'this'
  589.             CMainWindow if we must return the error condition FALSE.
  590.  
  591.   Args:     HINSTANCE hInstance,
  592.               Handle of the application instance.
  593.             int nShow)
  594.               Command to pass to ShowWindow.
  595.  
  596.   Modifies: m_pMsgBox, m_pMsgLog.
  597.  
  598.   Returns:  BOOL.
  599.               TRUE if succeeded.
  600.               FALSE if failed.
  601. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  602. BOOL CMainWindow::InitInstance(
  603.        HINSTANCE hInstance,
  604.        int nShow)
  605. {
  606.   BOOL bOk = FALSE;
  607.   HWND hWnd;
  608.  
  609.   // Create the Message Box object.
  610.   m_pMsgBox = new CMsgBox;
  611.   m_pMsgLog = new CSendLog;
  612.  
  613.   if (NULL != m_pMsgBox && NULL != m_pMsgLog)
  614.   {
  615.     // Note, the Create method sets the m_hWnd member so we don't
  616.     // need to set it explicitly here first.
  617.  
  618.     // Here is the create of this window.  Size the window reasonably.
  619.     // Create sets both m_hInst and m_hWnd.
  620.     hWnd = Create(
  621.              TEXT(MAIN_WINDOW_CLASS_NAME_STR),
  622.              TEXT(MAIN_WINDOW_TITLE_STR),
  623.              WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
  624.                | WS_MAXIMIZEBOX | WS_THICKFRAME,
  625.              CW_USEDEFAULT,
  626.              CW_USEDEFAULT,
  627.              ::GetSystemMetrics(SM_CXSCREEN)*3/5,
  628.              ::GetSystemMetrics(SM_CYSCREEN)*3/5,
  629.              NULL,
  630.              NULL,
  631.              hInstance);
  632.     if (hWnd)
  633.     {
  634.       // Assign the server's copy of the main window handle.
  635.       g_pServer->m_hWndServer = m_hWnd;
  636.  
  637.       // Init the Message Box object.
  638.       if (m_pMsgBox->Init(m_hInst, m_hWnd))
  639.       {
  640.         bOk = TRUE;
  641.         // If the Client's Main window is found then set up logging to it.
  642.         hWnd = FindWindow(NULL, TEXT(CLIENT_WINDOW_TITLE));
  643.         if (NULL != hWnd)
  644.         {
  645.           // Tell the CSendLog object that we are logging to client.
  646.           m_pMsgLog->LogToServer(FALSE);
  647.           // Assign the global MsgLog pointer.
  648.           g_pMsgLog = m_pMsgLog;
  649.           m_pMsgLog->SetClient(m_hInst, m_hWnd, hWnd);
  650.           LOGID(IDS_LOGTO_CLIENT);
  651.         }
  652.         else
  653.         {
  654.           // If the client window can't be found then create and show the
  655.           // log display in this local server.
  656.  
  657.           // Indicate we are logging to our own server log facility.
  658.           m_pMsgLog->LogToServer(TRUE);
  659.  
  660.           // Ensure the new window is shown on screen and its content
  661.           // is painted.
  662.           ::ShowWindow(m_hWnd, nShow);
  663.           ::UpdateWindow(m_hWnd);
  664.  
  665.           // Create the Trace Message Log ListBox as a child window that
  666.           // fits the client area of the Main Window (the TRUE 3rd argument
  667.           // specifies such an inside child). If you want the Trace Message
  668.           // Log in a separate (but owned) window, then pass a FALSE
  669.           // instead for the 3rd argument.
  670.           if (m_pMsgLog->CreateServerLog(m_hInst, m_hWnd, TRUE))
  671.           {
  672.             // Assign the global MsgLog pointer.
  673.             g_pMsgLog = m_pMsgLog;
  674.             // Use macro to log an initial start messsage.
  675.             LOGID(IDS_LOGTO_SERVER);
  676.           }
  677.           else
  678.             bOk = FALSE;
  679.         }
  680.       }
  681.     }
  682.   }
  683.  
  684.   if (!bOk)
  685.   {
  686.     DELETE_POINTER(m_pMsgBox);
  687.     DELETE_POINTER(m_pMsgLog);
  688.   }
  689.  
  690.   return (bOk);
  691. }
  692.  
  693.  
  694. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  695.   Method:   CMainWindow::WindowProc
  696.  
  697.   Summary:  Main window procedure for this window object.  See CVirWindow
  698.             in the APPUTIL library (APPUTIL.CPP) for details on how this
  699.             method gets called by the global WindowProc.
  700.  
  701.   Args:     UINT uMsg,
  702.               Windows message that is "sent" to this window.
  703.             WPARAM wParam,
  704.               First message parameter (word sized).
  705.             LPARAM lParam)
  706.               Second message parameter (long sized).
  707.  
  708.   Modifies: ...
  709.  
  710.   Returns:  LRESULT
  711.               Standard Windows WindowProc return value.
  712. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  713. LRESULT CMainWindow::WindowProc(
  714.           UINT uMsg,
  715.           WPARAM wParam,
  716.           LPARAM lParam)
  717. {
  718.   LRESULT lResult = FALSE;
  719.  
  720.   switch (uMsg)
  721.   {
  722.     case WM_CREATE:
  723.       break;
  724.  
  725.     case WM_COMMAND:
  726.       // Dispatch and handle any Menu command messages received.
  727.       lResult = DoMenu(wParam, lParam);
  728.       break;
  729.  
  730.     case WM_CLOSE:
  731.       // The user selected Close on the main window's System menu
  732.       // or Exit on the File menu.
  733.     case WM_QUIT:
  734.       // If the app is being quit then close any associated help windows.
  735.     default:
  736.       // Defer all messages NOT handled here to the Default Window Proc.
  737.       lResult = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
  738.       break;
  739.   }
  740.  
  741.   return(lResult);
  742. }
  743.  
  744.  
  745. /*F+F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  746.   Function: UnicodeOk
  747.  
  748.   Summary:  Checks if the platform will handle unicode versions of
  749.             Win32 API calls.
  750.  
  751.   Args:     void
  752.  
  753.   Modifies: .
  754.  
  755.   Returns:  BOOL
  756.               TRUE if unicode support; FALSE if not.
  757. ------------------------------------------------------------------------F-F*/
  758. BOOL UnicodeOk(void)
  759. {
  760.   BOOL bOk = TRUE;
  761.   TCHAR szUserName[MAX_STRING_LENGTH];
  762.   DWORD dwSize = MAX_STRING_LENGTH;
  763.  
  764.   if (!GetUserName(szUserName, &dwSize))
  765.     bOk = ERROR_CALL_NOT_IMPLEMENTED == GetLastError() ? FALSE : TRUE;
  766.  
  767.   return bOk;
  768. }
  769.  
  770.  
  771. /*F+F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  772.   Function: InitApplication
  773.  
  774.   Summary:  Initializes the application and registers its main window class.
  775.  
  776.   Args:     HINSTANCE hInstance)
  777.               Handle to the first instance of the application.
  778.  
  779.   Modifies: .
  780.  
  781.   Returns:  BOOL.
  782.               TRUE if success.
  783.               FALSE if fail.
  784. ------------------------------------------------------------------------F-F*/
  785. BOOL InitApplication(
  786.        HINSTANCE hInstance)
  787. {
  788.   BOOL bOk;
  789.   // The window class for all instances of the main frame window.
  790.   WNDCLASSEX wcf;
  791.  
  792.   // Assign the appropriate values for this main frame window class.
  793.   wcf.cbSize        = sizeof(WNDCLASSEX);
  794.   wcf.cbClsExtra    = 0;            // No per-class extra data.
  795.   wcf.cbWndExtra    = 0;            // No per-window extra data.
  796.   wcf.hInstance     = hInstance;    // Application module instance.
  797.   wcf.lpfnWndProc   = &WindowProc;  // Global Window Procedure (defined in
  798.                                     // APPUTIL for all CVirWindows).
  799.   wcf.hCursor       = LoadCursor(NULL, IDC_ARROW); // Load app cursor.
  800.   wcf.hIcon         = (HICON) LoadIcon(            // Load app icon.
  801.                                 hInstance,
  802.                                 TEXT("AppIcon"));
  803.   wcf.hIconSm       = (HICON) LoadImage(           // Load small icon.
  804.                                 hInstance,
  805.                                 TEXT("AppIcon"),
  806.                                 IMAGE_ICON,
  807.                                 16, 16,
  808.                                 0);
  809.   wcf.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);  // Default backgnd color.
  810.   wcf.style         = CS_HREDRAW | CS_VREDRAW;     // Class style(s).
  811.   wcf.lpszClassName = TEXT(MAIN_WINDOW_CLASS_NAME_STR); // Class name.
  812.   wcf.lpszMenuName  = TEXT(MAIN_WINDOW_CLASS_MENU_STR); // Menu name.
  813.  
  814.   // Register the window class and return FALSE if unsuccesful.
  815.   bOk = RegisterClassEx(&wcf);
  816.  
  817.   return (bOk);
  818. }
  819.  
  820.  
  821. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  822.   Function: WinMain
  823.  
  824.   Summary:  The Windows main entry point function for this application.
  825.             Initializes the application, the COM Libraries, and starts
  826.             the main application message loop.
  827.  
  828.   Args:     HINSTANCE hInstance,
  829.               Instance handle; a new one for each invocation of this app.
  830.             HINSTANCE hPrevInstance,
  831.               Instance handle of the previous instance. NULL in Win32.
  832.             LPSTR lpCmdLine,
  833.               Windows passes a pointer to the application's
  834.               invocation command line.
  835.             int nCmdShow)
  836.               Bits telling the show state of the application.
  837.  
  838.   Returns:  int
  839.               msg.wParam (upon exit of message loop).
  840.               FALSE if this instance couldn't initialize and run.
  841. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  842. extern "C" int WINAPI WinMain(
  843.                         HINSTANCE hInstance,
  844.                         HINSTANCE hPrevInstance,
  845.                         LPSTR lpCmdLine,
  846.                         int nCmdShow)
  847. {
  848.   CMainWindow* pWin = NULL;
  849.   int iRun = TRUE;
  850.   MSG msg;
  851.  
  852.   // If we were compiled for UNICODE and the platform seems OK with this
  853.   // then proceed.  Else we error and exit the app.
  854.   if (UnicodeOk())
  855.   {
  856.     // Call to initialize the COM Library.  Use the SUCCEEDED macro
  857.     // to detect success.  If fail then exit app with error message.
  858.     // The default apartment model is assumed and used.
  859.     if (SUCCEEDED(CoInitialize(NULL)))
  860.     {
  861.       // If we succeeded in initializing the COM Library we proceed to
  862.       // initialize the application.  If we can't init the application
  863.       // then we signal shut down with an error message exit.
  864.       iRun = InitApplication(hInstance);
  865.       if (iRun)
  866.       {
  867.         // Assume we'll set iRun to TRUE when initialization is done.
  868.         iRun = FALSE;
  869.  
  870.         // We are still go for running so we try to create a nifty new
  871.         // CMainWindow object for this app instance.
  872.         pWin = new CMainWindow;
  873.         if (NULL != pWin)
  874.         {
  875.           // Setup the server control object.
  876.           g_pServer = new CServer;
  877.           if (NULL != g_pServer)
  878.           {
  879.             // Assign the server's instance handle.
  880.             g_pServer->m_hInstServer = hInstance;
  881.  
  882.             // Check command line for switches to register or unregister
  883.             // this server's managed components.   iRun will be set to 2
  884.             // to signal an immediate and quiet exit of this application
  885.             // if such registration or unregistration is requested.
  886.             if (0 == lstrcmpiA(lpCmdLine, "-RegServer")
  887.                 || 0 == lstrcmpiA(lpCmdLine, "/RegServer"))
  888.             {
  889.               if (pWin->RegisterServer())
  890.                 iRun = 2;
  891.             }
  892.             else if (0 == lstrcmpiA(lpCmdLine, "-UnregServer")
  893.                      || 0 == lstrcmpiA(lpCmdLine, "/UnregServer"))
  894.             {
  895.               if (pWin->UnregisterServer())
  896.                 iRun = 2;
  897.             }
  898.  
  899.             if (FALSE == iRun)
  900.             {
  901.               // If we did not process a command line switch that
  902.               // requires immediate exit, then initialize an instance of
  903.               // the new CMainWindow. This entails creating the main window.
  904.               if (pWin->InitInstance(hInstance, nCmdShow))
  905.               {
  906.                 LOGF2("L<%X>: CmdLine Switches= %s",TID,lpCmdLine);
  907.                 // Create and register the Class Factories.  But only do so
  908.                 // if this application has been launched by COM as indicated
  909.                 // by the -Embedding command line switch.
  910.                 if (0 == lstrcmpiA(lpCmdLine, "-Embedding")
  911.                     || 0 == lstrcmpiA(lpCmdLine, "/Embedding"))
  912.                   iRun = g_pServer->OpenFactories();
  913.               }
  914.             }
  915.           }
  916.         }
  917.       }
  918.  
  919.       switch (iRun)
  920.       {
  921.         case TRUE:
  922.           {
  923.             // If we initialized the app instance properly then we are still
  924.             // go for running.  We then start up the main message pump for
  925.             // the application.  The application will normally live hidden
  926.             // as a local server.
  927.             while (GetMessage(&msg, NULL, 0, 0))
  928.             {
  929.               TranslateMessage(&msg);
  930.               DispatchMessage(&msg);
  931.             }
  932.  
  933.             // We'll pass to the OS the reason why we exited the message
  934.             // loop.
  935.             iRun = msg.wParam;
  936.           }
  937.           break;
  938.  
  939.         case FALSE:
  940.           // We failed to initialize the application--issue an error
  941.           // messagebox.  Can't initialize or can't run stand-alone.
  942.           ErrorBox(hInstance, NULL, IDS_APPINITFAILED);
  943.  
  944.           // Delete the CMainWindow object.
  945.           DELETE_POINTER(pWin);
  946.  
  947.           // Pass the OS an error code of 1.
  948.           iRun = 1;
  949.           break;
  950.  
  951.         default:
  952.           // Pass the OS an error code of 0.
  953.           iRun = 0;
  954.           break;
  955.       }
  956.  
  957.       // We're exiting this app (either normally or by init failure) so
  958.       // shut down the COM Library.
  959.       CoUninitialize();
  960.     }
  961.     else
  962.     {
  963.       // We failed to Initialize the COM Library. Put up error message box
  964.       // saying that COM Library couldn't be initialized.  Parent window
  965.       // is desktop (ie, NULL). Exit the failed application (ie, by
  966.       // returning FALSE to WinMain).
  967.       ErrorBox(hInstance, NULL, IDS_COMINITFAILED);
  968.     }
  969.   }
  970.   else
  971.   {
  972.     // If we were compiled for UNICODE but the platform has problems with
  973.     // this then indicate an error and exit the app immediately.
  974.     CHAR szMsg[MAX_STRING_LENGTH];
  975.  
  976.     if (LoadStringA(
  977.           hInstance,
  978.           IDS_NOUNICODE,
  979.           szMsg,
  980.           MAX_STRING_LENGTH))
  981.     {
  982.       MessageBoxA(
  983.         NULL,
  984.         szMsg,
  985.         ERROR_TITLE_STR,
  986.         MB_OK | MB_ICONEXCLAMATION);
  987.     }
  988.   }
  989.  
  990.   return iRun;
  991. }
  992.