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 / dcdserve / dcdserve.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-30  |  28.8 KB  |  876 lines

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