home *** CD-ROM | disk | FTP | other *** search
/ PC Press 1997 July / Sezamfile97_2.iso / windows / program / activex / axtsamp.exe / TSBRANCH.EXE / STOSERVE / STOSERVE.CPP < prev    next >
C/C++ Source or Header  |  1996-12-29  |  16KB  |  517 lines

  1. /*+==========================================================================
  2.   File:      STOSERVE.CPP
  3.  
  4.   Summary:   Main implementation file for a DLL COM Component server
  5.              providing a Paper-related COM Component: DllPaper. Access to
  6.              Class Factories is provided in this module.  This module also
  7.              supports self registration and unregistration for the server.
  8.              STOSERVE and its managed COPaper COM objects are thread-safe.
  9.  
  10.              For a comprehensive tutorial code tour of STOSERVE's contents
  11.              and offerings see the tutorial STOSERVE.HTM file. For more
  12.              specific technical details on the internal workings see the
  13.              comments dispersed throughout the STOSERVE source code. For
  14.              more details see STOCLIEN.HTM in the main tutorial directory.
  15.  
  16.   Classes:   none.
  17.  
  18.   Functions: DllMain, DllGetClassObject, DllCanUnloadNow, DllRegisterServer,
  19.              DllUnregisterServer.
  20.  
  21.   Origin:    6-10-96: atrent - Editor-inheritance from CONSERVE.CPP in
  22.                the CONSERVE Tutorial Code Sample.
  23.  
  24. ----------------------------------------------------------------------------
  25.   This file is part of the Microsoft ActiveX Tutorial Code Samples.
  26.  
  27.   Copyright (C) Microsoft Corporation, 1997.  All rights reserved.
  28.  
  29.   This source code is intended only as a supplement to Microsoft
  30.   Development Tools and/or on-line documentation.  See these other
  31.   materials for detailed information regarding Microsoft code samples.
  32.  
  33.   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  34.   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  35.   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  36.   PARTICULAR PURPOSE.
  37. ==========================================================================+*/
  38.  
  39. /*---------------------------------------------------------------------------
  40.   We include WINDOWS.H for all Win32 applications.
  41.   We include OLE2.H because we will be calling the COM/OLE Libraries.
  42.   We include INITGUID.H only once (here) in the entire DLL because we
  43.     will be defining GUIDs and want them as constants in the data segment.
  44.   We include APPUTIL.H because we will be building this DLL using
  45.     the convenient Virtual Window and Dialog classes and other
  46.     utility functions in the APPUTIL Library (ie, APPUTIL.LIB).
  47.   We include IPAPER.H and PAPRGUID.H for the common Paper-related
  48.     Interface class, GUID, and CLSID specifications.
  49.   We include STOSERVE.H because it has the _DLLEXPORT_ controlled import
  50.     and export specifications.
  51.   We include SERVER.H because it has internal class declarations for
  52.     the server's control object.
  53.   We include FACTORY.H because it has the necessary internal class factory
  54.     declarations for this DLL component server.
  55. ---------------------------------------------------------------------------*/
  56. #include <windows.h>
  57. #include <ole2.h>
  58. #include <initguid.h>
  59. #include <apputil.h>
  60. #include <ipaper.h>
  61. #include <papguids.h>
  62. #define _DLLEXPORT_
  63. #include "stoserve.h"
  64. #include "server.h"
  65. #include "factory.h"
  66.  
  67.  
  68. // Global variable definitions. Some Initialized in DllMain() below.
  69.  
  70. // We encapsulate the control of this COM server (eg, lock and object
  71. // counting) in a server control C++ object. Here is it's global pointer.
  72. CServer* g_pServer = NULL;
  73.  
  74.  
  75. /*F+F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  76.   Function: UnicodeOk
  77.  
  78.   Summary:  Checks if the platform will handle unicode versions of
  79.             Win32 string API calls.
  80.  
  81.   Args:     void
  82.  
  83.   Returns:  BOOL
  84.               TRUE if unicode support; FALSE if not.
  85. ------------------------------------------------------------------------F-F*/
  86. BOOL UnicodeOk(void)
  87. {
  88.   BOOL bOk = TRUE;
  89.   TCHAR szUserName[MAX_STRING_LENGTH];
  90.   DWORD dwSize = MAX_STRING_LENGTH;
  91.  
  92.   if (!GetUserName(szUserName, &dwSize))
  93.     bOk = ERROR_CALL_NOT_IMPLEMENTED == GetLastError() ? FALSE : TRUE;
  94.  
  95.   return bOk;
  96. }
  97.  
  98.  
  99. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  100.   Function: DllMain
  101.  
  102.   Summary:  Just as WinMain is for an EXE application, this DllMain
  103.             function is the main entry point for this DLL.  It is called
  104.             when the DLL is loaded by a process, and when new threads are
  105.             created by a process that has already loaded this DLL.
  106.             DllMain is also called when threads of a process that has
  107.             loaded the DLL exit cleanly and when the process itself
  108.             unloads the DLL.
  109.  
  110.             If you want to use C runtime libraries, keep this function
  111.             named "DllMain" and you won't have to do anything special to
  112.             initialize the runtime libraries.
  113.  
  114.             When fdwReason == DLL_PROCESS_ATTACH, the return value is used
  115.             to determine if the DLL should remain loaded, or should be
  116.             immediately unloaded depending upon whether the DLL could be
  117.             initialized properly.  For all other values of fdwReason, the
  118.             return value is ignored.
  119.  
  120.   Args:     HINSTANCE hDLLInst,
  121.               Instance handle of the DLL.
  122.             DWORD fdwReason,
  123.               Process attach/detach or thread attach/detach.
  124.               Reason for calling.
  125.             LPVOID lpvReserved)
  126.               Reserved and not used.
  127.  
  128.   Returns:  BOOL,
  129.               Return value is used only when fdwReason == DLL_PROCESS_ATTACH.
  130.               TRUE  -  Used to signify that the DLL should remain loaded.
  131.               FALSE -  Used to signify that the DLL should be
  132.                 immediately unloaded.
  133. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  134. BOOL WINAPI DllMain(
  135.               HINSTANCE hDllInst,
  136.               DWORD fdwReason,
  137.               LPVOID lpvReserved)
  138. {
  139.   BOOL bResult = TRUE;
  140.  
  141.   // Dispatch this main call based on the reason it was called.
  142.   switch (fdwReason)
  143.   {
  144.     case DLL_PROCESS_ATTACH:
  145.       // The DLL is being loaded for the first time by a given process.
  146.       // Perform per-process initialization here.  If the initialization
  147.       // is successful, return TRUE; if unsuccessful, return FALSE.
  148.       bResult = FALSE;
  149.       if (UnicodeOk())
  150.       {
  151.         // Instantiate the CServer utility class.
  152.         g_pServer = new CServer;
  153.         if (NULL != g_pServer)
  154.         {
  155.           // Remember the DLL Instance handle.
  156.           g_pServer->m_hDllInst = hDllInst;
  157.           bResult = TRUE;
  158.         }
  159.       }
  160.       break;
  161.  
  162.     case DLL_PROCESS_DETACH:
  163.       // The DLL is being unloaded by a given process.  Do any
  164.       // per-process clean up here, such as undoing what was done in
  165.       // DLL_PROCESS_ATTACH.  The return value is ignored.
  166.       DELETE_POINTER(g_pServer);
  167.       break;
  168.  
  169.     case DLL_THREAD_ATTACH:
  170.       // A thread is being created in a process that has already loaded
  171.       // this DLL.  Perform any per-thread initialization here.  The
  172.       // return value is ignored.
  173.       break;
  174.  
  175.     case DLL_THREAD_DETACH:
  176.       // A thread is exiting cleanly in a process that has already
  177.       // loaded this DLL.  Perform any per-thread clean up here.  The
  178.       // return value is ignored.
  179.       break;
  180.  
  181.     default:
  182.       break;
  183.   }
  184.  
  185.   return (bResult);
  186. }
  187.  
  188.  
  189. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  190.   Function: DllGetClassObject
  191.  
  192.   Summary:  The standard exported function that the COM service library
  193.             uses to obtain an object class of the class factory for a
  194.             specified component provided by this server DLL.
  195.  
  196.   Args:     REFCLSID rclsid,
  197.               [in] The CLSID of the requested Component.
  198.             REFIID riid,
  199.               [in] GUID of the requested interface on the Class Factory.
  200.             PPVOID ppv)
  201.               [out] Address of the caller's pointer variable that will
  202.               receive the requested interface pointer.
  203.  
  204.   Returns:  HRESULT
  205.               E_FAIL if requested component isn't supported.
  206.               E_OUTOFMEMORY if out of memory.
  207.               Error code out of the QueryInterface.
  208. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  209. STDAPI DllGetClassObject(
  210.          REFCLSID rclsid,
  211.          REFIID riid,
  212.          PPVOID ppv)
  213. {
  214.   HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  215.   IUnknown* pCob = NULL;
  216.  
  217.   if (CLSID_DllPaper == rclsid)
  218.   {
  219.     hr = E_OUTOFMEMORY;
  220.     pCob = new CFPaper(NULL, g_pServer);
  221.   }
  222.  
  223.   if (NULL != pCob)
  224.   {
  225.     g_pServer->ObjectsUp();
  226.     hr = pCob->QueryInterface(riid, ppv);
  227.     if (FAILED(hr))
  228.     {
  229.       g_pServer->ObjectsDown();
  230.       DELETE_POINTER(pCob);
  231.     }
  232.   }
  233.  
  234.   return hr;
  235. }
  236.  
  237.  
  238. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  239.   Function: DllCanUnloadNow
  240.  
  241.   Summary:  The standard exported function that the COM service library
  242.             uses to determine if this server DLL can be unloaded.
  243.  
  244.   Args:     void.
  245.  
  246.   Returns:  HRESULT
  247.               S_OK if this DLL server can be unloaded.
  248.               S_FALSE if this DLL can not be unloaded.
  249. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  250. STDAPI DllCanUnloadNow(void)
  251. {
  252.   HRESULT hr;
  253.  
  254.   // We return S_OK if there are no longer any living objects AND
  255.   // there are no outstanding client locks on this server.
  256.   hr = g_pServer->CanUnloadNow();
  257.  
  258.   return hr;
  259. }
  260.  
  261.  
  262. /*F+F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  263.   Function: SetRegKeyValue
  264.  
  265.   Summary:  Internal utility function to set a Key, Subkey, and value
  266.             in the system Registry under HKEY_CLASSES_ROOT.
  267.  
  268.   Args:     LPTSTR pszKey,
  269.             LPTSTR pszSubkey,
  270.             LPTSTR pszValue)
  271.  
  272.   Returns:  BOOL
  273.               TRUE if success; FALSE if not.
  274. ------------------------------------------------------------------------F-F*/
  275. BOOL SetRegKeyValue(
  276.        LPTSTR pszKey,
  277.        LPTSTR pszSubkey,
  278.        LPTSTR pszValue)
  279. {
  280.   BOOL bOk = FALSE;
  281.   LONG ec;
  282.   HKEY hKey;
  283.   TCHAR szKey[MAX_STRING_LENGTH];
  284.  
  285.   lstrcpy(szKey, pszKey);
  286.  
  287.   if (NULL != pszSubkey)
  288.   {
  289.     lstrcat(szKey, TEXT("\\"));
  290.     lstrcat(szKey, pszSubkey);
  291.   }
  292.  
  293.   ec = RegCreateKeyEx(
  294.          HKEY_CLASSES_ROOT,
  295.          szKey,
  296.          0,
  297.          NULL,
  298.          REG_OPTION_NON_VOLATILE,
  299.          KEY_ALL_ACCESS,
  300.          NULL,
  301.          &hKey,
  302.          NULL);
  303.  
  304.   if (NULL != pszValue && ERROR_SUCCESS == ec)
  305.   {
  306.     ec = RegSetValueEx(
  307.            hKey,
  308.            NULL,
  309.            0,
  310.            REG_SZ,
  311.            (BYTE *)pszValue,
  312.            (lstrlen(pszValue)+1)*sizeof(TCHAR));
  313.     if (ERROR_SUCCESS == ec)
  314.       bOk = TRUE;
  315.     RegCloseKey(hKey);
  316.   }
  317.  
  318.   return bOk;
  319. }
  320.  
  321.  
  322. /*F+F++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  323.   Function: AddRegNamedValue
  324.  
  325.   Summary:  Internal utility function to add a named data value to an
  326.             existing Key (with optional Subkey) in the system Registry
  327.             under HKEY_CLASSES_ROOT.
  328.  
  329.   Args:     LPTSTR pszKey,
  330.             LPTSTR pszSubkey,
  331.             LPTSTR pszValueName,
  332.             LPTSTR pszValue)
  333.  
  334.   Returns:  BOOL
  335.               TRUE if success; FALSE if not.
  336. ------------------------------------------------------------------------F-F*/
  337. BOOL AddRegNamedValue(
  338.        LPTSTR pszKey,
  339.        LPTSTR pszSubkey,
  340.        LPTSTR pszValueName,
  341.        LPTSTR pszValue)
  342. {
  343.   BOOL bOk = FALSE;
  344.   LONG ec;
  345.   HKEY hKey;
  346.   TCHAR szKey[MAX_STRING_LENGTH];
  347.  
  348.   lstrcpy(szKey, pszKey);
  349.  
  350.   if (NULL != pszSubkey)
  351.   {
  352.     lstrcat(szKey, TEXT("\\"));
  353.     lstrcat(szKey, pszSubkey);
  354.   }
  355.  
  356.   ec = RegOpenKeyEx(
  357.          HKEY_CLASSES_ROOT,
  358.          szKey,
  359.          0,
  360.          KEY_ALL_ACCESS,
  361.          &hKey);
  362.  
  363.   if (NULL != pszValue && ERROR_SUCCESS == ec)
  364.   {
  365.     ec = RegSetValueEx(
  366.            hKey,
  367.            pszValueName,
  368.            0,
  369.            REG_SZ,
  370.            (BYTE *)pszValue,
  371.            (lstrlen(pszValue)+1)*sizeof(TCHAR));
  372.     if (ERROR_SUCCESS == ec)
  373.       bOk = TRUE;
  374.     RegCloseKey(hKey);
  375.   }
  376.  
  377.   return bOk;
  378. }
  379.  
  380.  
  381. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  382.   Function: DllRegisterServer
  383.  
  384.   Summary:  The standard exported function that can be called to command
  385.             this DLL server to register itself in the system registry.
  386.  
  387.   Args:     void.
  388.  
  389.   Returns:  HRESULT
  390.               NOERROR
  391. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  392. STDAPI DllRegisterServer(void)
  393. {
  394.   HRESULT  hr = NOERROR;
  395.   TCHAR    szID[GUID_SIZE+1];
  396.   TCHAR    szCLSID[GUID_SIZE+1];
  397.   TCHAR    szModulePath[MAX_PATH];
  398.  
  399.   // Obtain the path to this module's executable file for later use.
  400.   GetModuleFileName(
  401.     g_pServer->m_hDllInst,
  402.     szModulePath,
  403.     sizeof(szModulePath)/sizeof(TCHAR));
  404.  
  405.   /*-------------------------------------------------------------------------
  406.     Create registry entries for the DllPaper Component.
  407.   -------------------------------------------------------------------------*/
  408.   // Create some base key strings.
  409.   StringFromGUID2(CLSID_DllPaper, szID, GUID_SIZE);
  410.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  411.   lstrcat(szCLSID, szID);
  412.  
  413.   // Create ProgID keys.
  414.   SetRegKeyValue(
  415.     TEXT("DllPaper1.0"),
  416.     NULL,
  417.     TEXT("DllPaper Component - STOSERVE Code Sample"));
  418.   SetRegKeyValue(
  419.     TEXT("DllPaper1.0"),
  420.     TEXT("CLSID"),
  421.     szID);
  422.  
  423.   // Create VersionIndependentProgID keys.
  424.   SetRegKeyValue(
  425.     TEXT("DllPaper"),
  426.     NULL,
  427.     TEXT("DllPaper Component - STOSERVE Code Sample"));
  428.   SetRegKeyValue(
  429.     TEXT("DllPaper"),
  430.     TEXT("CurVer"),
  431.     TEXT("DllPaper1.0"));
  432.   SetRegKeyValue(
  433.     TEXT("DllPaper"),
  434.     TEXT("CLSID"),
  435.     szID);
  436.  
  437.   // Create entries under CLSID.
  438.   SetRegKeyValue(
  439.     szCLSID,
  440.     NULL,
  441.     TEXT("DllPaper Component - STOSERVE Code Sample"));
  442.   SetRegKeyValue(
  443.     szCLSID,
  444.     TEXT("ProgID"),
  445.     TEXT("DllPaper1.0"));
  446.   SetRegKeyValue(
  447.     szCLSID,
  448.     TEXT("VersionIndependentProgID"),
  449.     TEXT("DllPaper"));
  450.   SetRegKeyValue(
  451.     szCLSID,
  452.     TEXT("NotInsertable"),
  453.     NULL);
  454.   SetRegKeyValue(
  455.     szCLSID,
  456.     TEXT("InprocServer32"),
  457.     szModulePath);
  458.   AddRegNamedValue(
  459.     szCLSID,
  460.     TEXT("InprocServer32"),
  461.     TEXT("ThreadingModel"),
  462.     TEXT("Apartment"));
  463.  
  464.   return hr;
  465. }
  466.  
  467.  
  468. /*F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
  469.   Function: DllUnregisterServer
  470.  
  471.   Summary:  The standard exported function that can be called to command
  472.             this DLL server to unregister itself from the system Registry.
  473.  
  474.   Args:     void.
  475.  
  476.   Returns:  HRESULT
  477.               NOERROR
  478. F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F*/
  479. STDAPI DllUnregisterServer(void)
  480. {
  481.   HRESULT  hr = NOERROR;
  482.   TCHAR    szID[GUID_SIZE+1];
  483.   TCHAR    szCLSID[GUID_SIZE+1];
  484.   TCHAR    szTemp[GUID_SIZE+1];
  485.  
  486.   /*-------------------------------------------------------------------------
  487.     Delete registry entries for the Paper Component.
  488.   -------------------------------------------------------------------------*/
  489.   //Create some base key strings.
  490.   StringFromGUID2(CLSID_DllPaper, szID, GUID_SIZE);
  491.   lstrcpy(szCLSID, TEXT("CLSID\\"));
  492.   lstrcat(szCLSID, szID);
  493.  
  494.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("DllPaper\\CurVer"));
  495.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("DllPaper\\CLSID"));
  496.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("DllPaper"));
  497.  
  498.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("DllPaper1.0\\CLSID"));
  499.   RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("DllPaper1.0"));
  500.  
  501.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("ProgID"));
  502.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  503.  
  504.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("VersionIndependentProgID"));
  505.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  506.  
  507.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("NotInsertable"));
  508.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  509.  
  510.   wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("InprocServer32"));
  511.   RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
  512.  
  513.   RegDeleteKey(HKEY_CLASSES_ROOT, szCLSID);
  514.  
  515.   return hr;
  516. }
  517.