home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / ipserver.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  12.9 KB  |  489 lines

  1. //=--------------------------------------------------------------------------=
  2. // IPServer.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1997 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implements all exported DLL functions for the program, as well as a few
  13. // others that will be used by same
  14. //
  15. #include "IPServer.H"
  16. #include "LocalSrv.H"
  17.  
  18. #include "AutoObj.H"
  19. #include "ClassF.H"
  20. #include "CtrlObj.H"
  21. #include "Globals.H"
  22. #include "Unknown.H"
  23. #include "Util.H"
  24.  
  25. //=--------------------------------------------------------------------------=
  26. // Private module level data
  27. //
  28. // for ASSERT and FAIL
  29. //
  30. SZTHISFILE
  31.  
  32.  
  33. //=--------------------------------------------------------------------------=
  34. // These are used for reflection in OLE Controls.  Not that big of a hit that
  35. // we mind defining them for all servers, including automation or generic
  36. // COM.
  37. //
  38. char g_szReflectClassName [] = "CtlFrameWork_ReflectWindow";
  39. BYTE g_fRegisteredReflect = FALSE;
  40.  
  41.  
  42. //=--------------------------------------------------------------------------=
  43. // allow controls to register for DLL_THREAD_ATTACH and DLL_THREAD_DETACH 
  44. //
  45. THRDNFYPROC g_pfnThreadProc = NULL;
  46.  
  47. extern "C" void SetLibraryThreadProc(THRDNFYPROC pfnThreadNotify)
  48. {
  49.     if ((g_pfnThreadProc = pfnThreadNotify) == NULL)
  50.         DisableThreadLibraryCalls((HMODULE)g_hInstance);
  51. }
  52.  
  53.  
  54. // ref count for LockServer
  55. //
  56. LONG  g_cLocks;
  57.  
  58.  
  59. // private routines for this file.
  60. //
  61. int       IndexOfOleObject(REFCLSID);
  62. HRESULT   RegisterAllObjects(void);
  63. HRESULT   UnregisterAllObjects(void);
  64.  
  65. //=--------------------------------------------------------------------------=
  66. // DllMain
  67. //=--------------------------------------------------------------------------=
  68. // yon standard LibMain.
  69. //
  70. // Parameters and Output:
  71. //    - see SDK Docs on DllMain
  72. //
  73. // Notes:
  74. //
  75. BOOL WINAPI DllMain
  76. (
  77.     HANDLE hInstance,
  78.     DWORD  dwReason,
  79.     void  *pvReserved
  80. )
  81. {
  82.     int i;
  83.  
  84.     switch (dwReason) {
  85.       // set up some global variables, and get some OS/Version information
  86.       // set up.
  87.       //
  88.       case DLL_PROCESS_ATTACH:
  89.         {
  90.         DWORD dwVer = GetVersion();
  91.         DWORD dwWinVer;
  92.  
  93.         //  swap the two lowest bytes of dwVer so that the major and minor version
  94.         //  numbers are in a usable order.
  95.         //  for dwWinVer: high byte = major version, low byte = minor version
  96.         //     OS               Sys_WinVersion  (as of 5/2/95)
  97.         //     =-------------=  =-------------=
  98.         //     Win95            0x035F   (3.95)
  99.         //     WinNT ProgMan    0x0333   (3.51)
  100.         //     WinNT Win95 UI   0x0400   (4.00)
  101.         //
  102.         dwWinVer = (UINT)(((dwVer & 0xFF) << 8) | ((dwVer >> 8) & 0xFF));
  103.         g_fSysWinNT = FALSE;
  104.         g_fSysWin95 = FALSE;
  105.         g_fSysWin95Shell = FALSE;
  106.  
  107.         if (dwVer < 0x80000000) {
  108.             g_fSysWinNT = TRUE;
  109.             g_fSysWin95Shell = (dwWinVer >= 0x0334);
  110.         } else  {
  111.             g_fSysWin95 = TRUE;
  112.             g_fSysWin95Shell = TRUE;
  113.         }
  114.  
  115.         // initialize a critical seciton for our apartment threading support
  116.         //
  117.         InitializeCriticalSection(&g_CriticalSection);
  118.  
  119.         // create an initial heap for everybody to use.
  120.         // currently, we're going to let the system make things thread-safe,
  121.         // which will make them a little slower, but hopefully not enough
  122.         // to notice
  123.         //
  124.         g_hHeap = GetProcessHeap();
  125.         if (!g_hHeap) {
  126.             FAIL("Couldn't get Process Heap.  Not good!");
  127.             return FALSE;
  128.         }
  129.  
  130.         g_hInstance = (HINSTANCE)hInstance;
  131.  
  132.         // give the user a chance to initialize whatever
  133.         //
  134.         InitializeLibrary();
  135.  
  136.         // if they didn't ask for thread notifications then optimize by turning
  137.         // them off for our DLL.
  138.         //
  139.         if (!g_pfnThreadProc)
  140.             DisableThreadLibraryCalls((HMODULE)hInstance);
  141.         }
  142.         break;
  143.  
  144.       case DLL_THREAD_ATTACH:
  145.       case DLL_THREAD_DETACH:
  146.         if (g_pfnThreadProc)
  147.             g_pfnThreadProc(hInstance, dwReason, pvReserved);
  148.         break;
  149.  
  150.       // do  a little cleaning up!
  151.       //
  152.       case DLL_PROCESS_DETACH:
  153.  
  154.         // clean up our critical seciton
  155.         //
  156.         DeleteCriticalSection(&g_CriticalSection);
  157.  
  158.         // unregister all the registered window classes.
  159.         //
  160.         i = 0;
  161.  
  162.         while (!ISEMPTYOBJECT(i)) {
  163.             if (g_ObjectInfo[i].usType == OI_CONTROL) {
  164.                 if (CTLWNDCLASSREGISTERED(i))
  165.                     UnregisterClass(WNDCLASSNAMEOFCONTROL(i), g_hInstance);
  166.             }
  167.             i++;
  168.         }
  169.  
  170.         // clean up our parking window.
  171.         //
  172.         if (g_hwndParking) {
  173.             DestroyWindow(g_hwndParking);
  174.             UnregisterClass("CtlFrameWork_Parking", g_hInstance);
  175.             --g_cLocks;
  176.         }
  177.  
  178.         // clean up after reflection, if appropriate.
  179.         //
  180.         if (g_fRegisteredReflect)
  181.             UnregisterClass(g_szReflectClassName, g_hInstance);
  182.  
  183.         // give the user a chance to do some cleaning up
  184.         //
  185.         UninitializeLibrary();
  186.         break;
  187.     }
  188.  
  189.     return TRUE;
  190. }
  191.  
  192.  
  193.  
  194. //=--------------------------------------------------------------------------=
  195. // DllRegisterServer
  196. //=--------------------------------------------------------------------------=
  197. // registers the Automation server
  198. //
  199. // Output:
  200. //    HRESULT
  201. //
  202. // Notes:
  203. //
  204. STDAPI DllRegisterServer
  205. (
  206.     void
  207. )
  208. {
  209.     HRESULT hr;
  210.  
  211.     hr = RegisterAllObjects();
  212.     RETURN_ON_FAILURE(hr);
  213.  
  214.     // call user registration function.
  215.     //
  216.     return (RegisterData())? S_OK : E_FAIL;
  217. }
  218.  
  219.  
  220.  
  221. //=--------------------------------------------------------------------------=
  222. // DllUnregisterServer
  223. //=--------------------------------------------------------------------------=
  224. // unregister's the Automation server
  225. //
  226. // Output:
  227. //    HRESULT
  228. //
  229. // Notes:
  230. //
  231. STDAPI DllUnregisterServer
  232. (
  233.     void
  234. )
  235. {
  236.     HRESULT hr;
  237.  
  238.     hr = UnregisterAllObjects();
  239.     RETURN_ON_FAILURE(hr);
  240.  
  241.     // call user unregistration function
  242.     //
  243.     return (UnregisterData()) ? S_OK : E_FAIL;
  244. }
  245.  
  246.  
  247. //=--------------------------------------------------------------------------=
  248. // DllCanUnloadNow
  249. //=--------------------------------------------------------------------------=
  250. // we are being asked whether or not it's okay to unload the DLL.  just check
  251. // the lock counts on remaining objects ...
  252. //
  253. // Output:
  254. //    HRESULT        - S_OK, can unload now, S_FALSE, can't.
  255. //
  256. // Notes:
  257. //
  258. STDAPI DllCanUnloadNow
  259. (
  260.     void
  261. )
  262. {
  263.     // if there are any objects lying around, then we can't unload.  The
  264.     // controlling CUnknownObject class that people should be inheriting from
  265.     // takes care of this
  266.     //
  267.     return (g_cLocks) ? S_FALSE : S_OK;
  268. }
  269.  
  270.  
  271. //=--------------------------------------------------------------------------=
  272. // DllGetClassObject
  273. //=--------------------------------------------------------------------------=
  274. // creates a ClassFactory object, and returns it.
  275. //
  276. // Parameters:
  277. //    REFCLSID        - CLSID for the class object
  278. //    REFIID          - interface we want class object to be.
  279. //    void **         - pointer to where we should ptr to new object.
  280. //
  281. // Output:
  282. //    HRESULT         - S_OK, CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY,
  283. //                      E_INVALIDARG, E_UNEXPECTED
  284. //
  285. // Notes:
  286. //
  287. STDAPI DllGetClassObject
  288. (
  289.     REFCLSID rclsid,
  290.     REFIID   riid,
  291.     void   **ppvObjOut
  292. )
  293. {
  294.     HRESULT hr;
  295.     void   *pv;
  296.     int     iIndex;
  297.  
  298.     // arg checking
  299.     //
  300.     if (!ppvObjOut)
  301.         return E_INVALIDARG;
  302.  
  303.     // first of all, make sure they're asking for something we work with.
  304.     //
  305.     iIndex = IndexOfOleObject(rclsid);
  306.     if (iIndex == -1)
  307.         return CLASS_E_CLASSNOTAVAILABLE;
  308.  
  309.     // create the blank object.
  310.     //
  311.     pv = (void *)new CClassFactory(iIndex);
  312.     if (!pv)
  313.         return E_OUTOFMEMORY;
  314.  
  315.     // QI for whatever the user has asked for.
  316.     //
  317.     hr = ((IUnknown *)pv)->QueryInterface(riid, ppvObjOut);
  318.     ((IUnknown *)pv)->Release();
  319.  
  320.     return hr;
  321. }
  322. //=--------------------------------------------------------------------------=
  323. // IndexOfOleObject
  324. //=--------------------------------------------------------------------------=
  325. // returns the index in our global table of objects of the given CLSID.  if
  326. // it's not a supported object, then we return -1
  327. //
  328. // Parameters:
  329. //    REFCLSID     - [in] duh.
  330. //
  331. // Output:
  332. //    int          - >= 0 is index into global table, -1 means not supported
  333. //
  334. // Notes:
  335. //
  336. int IndexOfOleObject
  337. (
  338.     REFCLSID rclsid
  339. )
  340. {
  341.     int x = 0;
  342.  
  343.     // an object is creatable if it's CLSID is in the table of all allowable object
  344.     // types.
  345.     //
  346.     while (!ISEMPTYOBJECT(x)) {
  347.         if (OBJECTISCREATABLE(x)) {
  348.             if (rclsid == CLSIDOFOBJECT(x))
  349.                 return x;
  350.         }
  351.         x++;
  352.     }
  353.  
  354.     return -1;
  355. }
  356.  
  357. //=--------------------------------------------------------------------------=
  358. // RegisterAllObjects
  359. //=--------------------------------------------------------------------------=
  360. // registers all the objects for the given automation server.
  361. //
  362. // Parameters:
  363. //    none
  364. //
  365. // Output:
  366. //    HERSULT        - S_OK, E_FAIL
  367. //
  368. // Notes:
  369. //
  370. HRESULT RegisterAllObjects
  371. (
  372.     void
  373. )
  374. {
  375.     ITypeLib *pTypeLib;
  376.     HRESULT hr;
  377.     DWORD   dwPathLen;
  378.     char    szTmp[MAX_PATH];
  379.     int     x = 0;
  380.  
  381.     // loop through all of our creatable objects [those that have a clsid in
  382.     // our global table] and register them.
  383.     //
  384.     while (!ISEMPTYOBJECT(x)) {
  385.         if (!OBJECTISCREATABLE(x)) {
  386.             x++;
  387.             continue;
  388.         }
  389.  
  390.         // depending on the object type, register different pieces of information
  391.         //
  392.         switch (g_ObjectInfo[x].usType) {
  393.  
  394.           // for both simple co-creatable objects and proeprty pages, do the same
  395.           // thing
  396.           //
  397.           case OI_UNKNOWN:
  398.           case OI_PROPERTYPAGE:
  399.             RegisterUnknownObject(NAMEOFOBJECT(x), CLSIDOFOBJECT(x));
  400.             break;
  401.  
  402.           case OI_AUTOMATION:
  403.             RegisterAutomationObject(g_szLibName, NAMEOFOBJECT(x), VERSIONOFOBJECT(x), 
  404.                                      *g_pLibid, CLSIDOFOBJECT(x));
  405.             break;
  406.  
  407.           case OI_CONTROL:
  408.             RegisterControlObject(g_szLibName, NAMEOFOBJECT(x), VERSIONOFOBJECT(x),
  409.                                   *g_pLibid, CLSIDOFOBJECT(x), OLEMISCFLAGSOFCONTROL(x),
  410.                                   BITMAPIDOFCONTROL(x));
  411.             break;
  412.  
  413.         }
  414.         x++;
  415.     }
  416.  
  417.     // Load and register our type library.
  418.     //
  419.     if (g_fServerHasTypeLibrary) {
  420.         dwPathLen = GetModuleFileName(g_hInstance, szTmp, MAX_PATH);
  421.         MAKE_WIDEPTR_FROMANSI(pwsz, szTmp);
  422.         hr = LoadTypeLib(pwsz, &pTypeLib);
  423.         RETURN_ON_FAILURE(hr);
  424.         hr = RegisterTypeLib(pTypeLib, pwsz, NULL);
  425.         pTypeLib->Release();
  426.         RETURN_ON_FAILURE(hr);
  427.     }
  428.  
  429.     return S_OK;
  430. }
  431.  
  432. //=--------------------------------------------------------------------------=
  433. // UnregisterAllObjects
  434. //=--------------------------------------------------------------------------=
  435. // un-registers all the objects for the given automation server.
  436. //
  437. // Parameters:
  438. //    none
  439. //
  440. // Output:
  441. //    HRESULT        - S_OK
  442. //
  443. // Notes:
  444. //
  445. HRESULT UnregisterAllObjects
  446. (
  447.     void
  448. )
  449. {
  450.     int x = 0;
  451.  
  452.     // loop through all of our creatable objects [those that have a clsid in
  453.     // our global table] and register them.
  454.     //
  455.     while (!ISEMPTYOBJECT(x)) {
  456.         if (!OBJECTISCREATABLE(x)) {
  457.             x++;
  458.             continue;
  459.         }
  460.  
  461.         switch (g_ObjectInfo[x].usType) {
  462.  
  463.           case OI_UNKNOWN:
  464.           case OI_PROPERTYPAGE:
  465.             UnregisterUnknownObject(CLSIDOFOBJECT(x));
  466.             break;
  467.  
  468.           case OI_CONTROL:
  469.             UnregisterControlObject(g_szLibName, NAMEOFOBJECT(x), VERSIONOFOBJECT(x), 
  470.                                     CLSIDOFOBJECT(x));
  471.     
  472.           case OI_AUTOMATION:
  473.             UnregisterAutomationObject(g_szLibName, NAMEOFOBJECT(x), VERSIONOFOBJECT(x), 
  474.                                        CLSIDOFOBJECT(x));
  475.             break;
  476.  
  477.         }
  478.         x++;
  479.     }
  480.  
  481.     // if we've got one, unregister our type library [this isn't an API function
  482.     // -- we've implemented this ourselves]
  483.     //
  484.     if (g_pLibid)
  485.         UnregisterTypeLibrary(*g_pLibid);
  486.  
  487.     return S_OK;
  488. }
  489.