home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK10 / MFC / SRC / OLESVR.CP$ / olesvr
Encoding:
Text File  |  1992-03-19  |  30.3 KB  |  1,272 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library. 
  2. // Copyright (C) 1992 Microsoft Corporation 
  3. // All rights reserved. 
  4. //  
  5. // This source code is only intended as a supplement to the 
  6. // Microsoft Foundation Classes Reference and Microsoft 
  7. // QuickHelp documentation provided with the library. 
  8. // See these sources for detailed information regarding the 
  9. // Microsoft Foundation Classes product. 
  10.  
  11. #include "afxole.h"
  12. #pragma hdrstop
  13.  
  14. #include "oleptr_.h"
  15. #include <limits.h>
  16.  
  17. #include "shellapi.h"
  18.  
  19. #ifdef AFX_OLE_SEG
  20. #pragma code_seg(AFX_OLE_SEG)
  21. #endif
  22.  
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27.  
  28. #define OLEEXPORT FAR PASCAL _export
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // Helper class for locking out main message pump during callbacks
  32.  
  33. class LOCK_PUMP
  34. {
  35. public:
  36.     LOCK_PUMP()
  37.     {
  38. #ifdef _DEBUG
  39.         AfxGetApp()->EnablePump(FALSE);
  40. #endif
  41.     }
  42.  
  43.     ~LOCK_PUMP()
  44.     {
  45. #ifdef _DEBUG
  46.         AfxGetApp()->EnablePump(TRUE);
  47. #endif
  48.     }
  49. };
  50.  
  51. #define OLE_TRACE(string)   \
  52.     if (afxTraceFlags & 0x10)   \
  53.         TRACE(string)
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // OLEOBJECT callbacks mapping to COleServerItem virtual functions
  57.  
  58. inline COleServerItem * COleServerItem::FromLp(LPOLEOBJECT lpObject)
  59. {
  60.     ASSERT(lpObject != NULL);
  61.     COleServerItem* pItem;
  62.     pItem = (COleServerItem*) GetPtrFromFarPtr(lpObject, sizeof(CObject));
  63.     ASSERT(lpObject == &pItem->m_oleObject);
  64.     return pItem;
  65. }
  66.  
  67. // friend class to get access to COleServerItem protected implementations
  68. struct _afxOleServerItemImplementation
  69. {
  70.  
  71.     static LPVOID OLEEXPORT
  72.     QueryProtocol(LPOLEOBJECT lpObject, OLE_LPCSTR lpszProtocol)
  73.     {
  74.         LOCK_PUMP lock;
  75.         OLE_TRACE("COleServerItem::OnQueryProtocol()\n");
  76.         return COleServerItem::FromLp(lpObject)->OnQueryProtocol(lpszProtocol);
  77.     }
  78.  
  79.     static OLESTATUS OLEEXPORT
  80.     Release(LPOLEOBJECT lpObject)
  81.     {
  82.         LOCK_PUMP lock;
  83.         OLE_TRACE("COleServerItem::OnRelease()\n");
  84.         return COleServerItem::FromLp(lpObject)->OnRelease();
  85.     }
  86.  
  87.     static OLESTATUS OLEEXPORT
  88.     Show(LPOLEOBJECT lpObject, BOOL bTakeFocus)
  89.     {
  90.         LOCK_PUMP lock;
  91.         OLE_TRACE("COleServerItem::OnShow()\n");
  92.         return COleServerItem::FromLp(lpObject)->OnShow(bTakeFocus);
  93.     }
  94.  
  95.     static OLESTATUS OLEEXPORT
  96.     DoVerb(LPOLEOBJECT lpObject, UINT nVerb, BOOL bShow, BOOL bTakeFocus)
  97.     {
  98.         LOCK_PUMP lock;
  99.         OLE_TRACE("COleServerItem::OnDoVerb()\n");
  100.  
  101.         OLESTATUS status;
  102.         status = COleServerItem::FromLp(lpObject)->OnDoVerb(nVerb, bShow,
  103.             bTakeFocus);
  104. #ifdef _DEBUG
  105.         if ((afxTraceFlags & 0x10) && status != OLE_OK)
  106.             TRACE("COleServerItem::OnDoVerb(%d) failed\n", nVerb);
  107. #endif
  108.         return status;
  109.     }
  110.  
  111.     static OLESTATUS OLEEXPORT
  112.     GetData(LPOLEOBJECT lpObject, OLECLIPFORMAT nFormat,
  113.         LPHANDLE lphDataReturn)
  114.     {
  115.         LOCK_PUMP lock;
  116.         OLE_TRACE("COleServerItem::OnGetData()\n");
  117.         OLESTATUS status;
  118.         status = COleServerItem::FromLp(lpObject)->OnGetData(nFormat, lphDataReturn);
  119. #ifdef _DEBUG
  120.         if ((afxTraceFlags & 0x10) && status != OLE_OK)
  121.             TRACE("COleServerItem::OnGetData() failed to get format 0x%x\n",
  122.                     nFormat);
  123. #endif
  124.         return status;
  125.     }
  126.  
  127.     static OLESTATUS OLEEXPORT
  128.     SetData(LPOLEOBJECT lpObject, OLECLIPFORMAT nFormat, HANDLE hData)
  129.     {
  130.         LOCK_PUMP lock;
  131.         OLE_TRACE("COleServerItem::OnSetData()\n");
  132.         return COleServerItem::FromLp(lpObject)->OnSetData(nFormat, hData);
  133.     }
  134.  
  135.     static OLESTATUS OLEEXPORT
  136.     SetTargetDevice(LPOLEOBJECT lpObject, HANDLE hData)
  137.     {
  138.         LOCK_PUMP lock;
  139.         OLE_TRACE("COleServerItem::OnSetTargetDevice()\n");
  140.  
  141.         OLESTATUS status;
  142.         status = COleServerItem::FromLp(lpObject)->OnSetTargetDevice(
  143.             (LPOLETARGETDEVICE)((hData == NULL) ? NULL : ::GlobalLock(hData)));
  144.  
  145.         if (hData != NULL)
  146.         {
  147.             ::GlobalUnlock(hData);
  148.             ::GlobalFree(hData);
  149.         }
  150.         return status;
  151.     }
  152.  
  153.     static OLESTATUS OLEEXPORT
  154.     SetBounds(LPOLEOBJECT lpObject, OLE_CONST RECT FAR* lpRect)
  155.     {
  156.         LOCK_PUMP lock;
  157.         OLE_TRACE("COleServerItem::SetBounds()\n");
  158.         return COleServerItem::FromLp(lpObject)->OnSetBounds((LPRECT)lpRect);
  159.     }
  160.  
  161.     static OLECLIPFORMAT OLEEXPORT
  162.     EnumFormats(LPOLEOBJECT lpObject, OLECLIPFORMAT nFormat)
  163.     {
  164.         OLECLIPFORMAT wNext;
  165.         LOCK_PUMP lock;
  166.         wNext = COleServerItem::FromLp(lpObject)->OnEnumFormats(nFormat);
  167. #ifdef _DEBUG
  168.         if (afxTraceFlags & 0x10)
  169.             TRACE("COleServerItem::OnEnumFormats(0x%x) returns 0x%x\n",
  170.                 nFormat, wNext);
  171. #endif
  172.         return wNext;
  173.     }
  174.  
  175.     static OLESTATUS OLEEXPORT
  176.     SetColorScheme(LPOLEOBJECT lpObject, OLE_CONST LOGPALETTE FAR* lpLogPalette)
  177.     {
  178.         LOCK_PUMP lock;
  179.         OLE_TRACE("COleServerItem::SetColorScheme()\n");
  180.         return COleServerItem::FromLp(lpObject)->
  181.                 OnSetColorScheme((LPLOGPALETTE)lpLogPalette);
  182.     }
  183.  
  184. };
  185.  
  186. static struct _OLEOBJECTVTBL NEAR objectVtbl =
  187. {
  188.     &_afxOleServerItemImplementation::QueryProtocol,
  189.     &_afxOleServerItemImplementation::Release,
  190.     &_afxOleServerItemImplementation::Show,
  191.     &_afxOleServerItemImplementation::DoVerb,
  192.     &_afxOleServerItemImplementation::GetData,
  193.     &_afxOleServerItemImplementation::SetData,
  194.     &_afxOleServerItemImplementation::SetTargetDevice,
  195.     &_afxOleServerItemImplementation::SetBounds,
  196.     &_afxOleServerItemImplementation::EnumFormats,
  197.     &_afxOleServerItemImplementation::SetColorScheme,
  198. };
  199.  
  200. //////////////////////////////////////////////////////////////////////////////
  201. // Server view of embedded OLEOBJECT (includes back pointer to OLECLIENT)
  202.  
  203. IMPLEMENT_DYNAMIC(COleServerItem, CObject)
  204.  
  205. COleServerItem::COleServerItem()
  206. {
  207.     m_oleObject.lpvtbl = &objectVtbl;
  208.     m_pDocument = NULL;
  209.     m_hPalette = NULL;
  210.     m_lpClient = NULL;  // will be set later
  211.     m_rectBounds.SetRectEmpty();
  212. }
  213.  
  214. COleServerItem::~COleServerItem()
  215. {
  216.     ASSERT(m_lpClient == NULL);     // must be released first
  217.     if (m_hPalette != NULL)
  218.         ::DeleteObject(m_hPalette);
  219. }
  220.  
  221. void
  222. COleServerItem::BeginRevoke()   // Start revoking the client connection
  223. {
  224.     ASSERT(m_lpClient != NULL);
  225.  
  226.     OLESTATUS status = ::OleRevokeObject(m_lpClient);
  227.     ASSERT(status == OLE_OK || status == OLE_WAIT_FOR_RELEASE);
  228.     // revoke will not be finished until OnRelease called
  229. }
  230.  
  231.  
  232. int
  233. COleServerItem::NotifyClient(OLE_NOTIFICATION wNotify)
  234. {
  235.     ASSERT(m_lpClient != NULL);
  236.     ASSERT(wNotify <= OLE_QUERY_RETRY); // last valid notification code
  237.  
  238. #ifdef _DEBUG
  239.     if (afxTraceFlags & 0x10)
  240.         TRACE("Notifying client item (wNotification = %d)\n", wNotify);
  241. #endif
  242.     return (*m_lpClient->lpvtbl->CallBack)(m_lpClient, wNotify, &m_oleObject);
  243. }
  244.  
  245. //////////////////////////////////////////////////////////////////////////////
  246. // Default implementations
  247.  
  248. OLESTATUS
  249. COleServerItem::OnRelease()
  250. {
  251.     ASSERT(m_lpClient != NULL);
  252.     m_lpClient = NULL;
  253.  
  254.     return OLE_OK;
  255. }
  256.  
  257.  
  258. OLESTATUS
  259. COleServerItem::OnSetTargetDevice(LPOLETARGETDEVICE /*lpTargetDevice*/)
  260. {
  261.     // default to ignore request
  262.     return OLE_OK;
  263. }
  264.  
  265.  
  266. BOOL
  267. COleServerItem::OnGetTextData(CString& /*rStringReturn*/)
  268. {
  269.     // default to not supported
  270.     return FALSE;
  271. }
  272.  
  273.  
  274. OLESTATUS
  275. COleServerItem::OnExtraVerb(UINT /*nVerb*/)
  276. {
  277.     return OLE_ERROR_DOVERB;    // Error in sending do verb, or invalid
  278. }
  279.  
  280.  
  281. // Overridables you do not have to override
  282. LPVOID
  283. COleServerItem::OnQueryProtocol(LPCSTR lpszProtocol) const
  284. {
  285.     if (_fstrcmp(lpszProtocol, "StdFileEditing") == 0)
  286.         return (LPVOID) &m_oleObject;
  287.  
  288.     return NULL;        // not supported
  289. }
  290.  
  291.  
  292. OLESTATUS
  293. COleServerItem::OnSetColorScheme(LPLOGPALETTE lpLogPalette)
  294. {
  295.     // save in item palette
  296.     HPALETTE hNewPal = ::CreatePalette(lpLogPalette);
  297.  
  298.     if (hNewPal == NULL)
  299.         return OLE_ERROR_PALETTE;
  300.  
  301.     if (m_hPalette != NULL)
  302.         ::DeleteObject(m_hPalette);
  303.     m_hPalette = hNewPal;
  304.     return OLE_OK;
  305. }
  306.  
  307. OLESTATUS
  308. COleServerItem::OnSetBounds(LPRECT lpRect)
  309. {
  310.     m_rectBounds = lpRect;
  311.     return OLE_OK;
  312. }
  313.  
  314.  
  315. OLESTATUS
  316. COleServerItem::OnDoVerb(UINT nVerb, BOOL bShow, BOOL bTakeFocus)
  317. {
  318.     OLESTATUS status;
  319.     if (nVerb == OLEVERB_PRIMARY)
  320.     {
  321.         status = OLE_OK;
  322.     }
  323.     else
  324.     {
  325.         status = OnExtraVerb(nVerb);
  326.     }
  327.  
  328.     if ((status == OLE_OK) && bShow)
  329.         status = OnShow(bTakeFocus);
  330.     return status;
  331. }
  332.  
  333.  
  334. // Clipboard formats
  335.  
  336. static UINT cfNative = ::RegisterClipboardFormat("Native");
  337. static UINT cfOwnerLink = ::RegisterClipboardFormat("OwnerLink");
  338. static UINT cfObjectLink = ::RegisterClipboardFormat("ObjectLink");
  339.  
  340. static UINT formats[] =
  341. {
  342.     cfNative,           // native data format
  343.     CF_METAFILEPICT,    // item rendered as a metafile
  344.     CF_TEXT,            // optionally supported if OnGetTextData implemented
  345.     NULL
  346. };
  347.  
  348. OLECLIPFORMAT
  349. COleServerItem::OnEnumFormats(OLECLIPFORMAT nFormat) const
  350. {
  351.     int index = 0;
  352.     if (nFormat != 0)
  353.     {
  354.         // find the last element
  355.         while (formats[index++] != nFormat)
  356.             ;
  357.     }
  358.     return (OLECLIPFORMAT)formats[index];
  359. }
  360.  
  361. HANDLE
  362. COleServerItem::GetNativeData()
  363. {
  364.     // get native data via serialization
  365.     CSharedFile memFile;
  366.  
  367.     TRY
  368.     {
  369.         CArchive    getArchive(&memFile, CArchive::store);
  370.         this->Serialize(getArchive);        // store to archive
  371.     }
  372.     CATCH (CNotSupportedException, e)
  373.     {
  374.         memFile.Close();
  375.         return NULL;        // not supported
  376.     }
  377.     AND_CATCH (CException, e)
  378.     {
  379.         memFile.Close();
  380.         THROW_LAST();       // will be caught in GetData
  381.     }
  382.     END_CATCH
  383.     return memFile.Detach();
  384. }
  385.  
  386. HANDLE
  387. COleServerItem::GetMetafileData()
  388. {
  389.     CMetaFileDC dc;
  390.     if (!dc.Create())
  391.         return NULL;
  392.  
  393.     if (m_hPalette)
  394.     {
  395.         ::SelectPalette(dc.m_hDC, m_hPalette, TRUE);
  396.         dc.RealizePalette();
  397.     }
  398.  
  399.     // Paint directly into the metafile.
  400.     if (!OnDraw(&dc))
  401.     {
  402.         OLE_TRACE("calling COleServerItem::OnDraw() failed\n");
  403.         return NULL;    // will destroy DC
  404.     }
  405.  
  406.     HMETAFILE hMF = (HMETAFILE)dc.Close();
  407.     if (hMF == NULL)
  408.         return NULL;
  409.  
  410.     HANDLE hPict;
  411.     if ((hPict = ::GlobalAlloc(GMEM_DDESHARE, sizeof(METAFILEPICT))) == NULL)
  412.     {
  413.         DeleteMetaFile(hMF);
  414.         return NULL;
  415.     }
  416.  
  417.     LPMETAFILEPICT lpPict;
  418.     if ((lpPict = (LPMETAFILEPICT)::GlobalLock(hPict)) == NULL)
  419.     {
  420.         DeleteMetaFile(hMF);
  421.         ::GlobalFree(hPict);
  422.         return NULL;
  423.     }
  424.  
  425.     lpPict->mm = MM_ANISOTROPIC;
  426.     lpPict->hMF = hMF;
  427.     lpPict->xExt = m_rectBounds.Width();
  428.     lpPict->yExt = m_rectBounds.Height();   // will be negative for HiMetric
  429.     ::GlobalUnlock(hPict);
  430.     return hPict;
  431. }
  432.  
  433.  
  434. OLESTATUS
  435. COleServerItem::OnGetData(OLECLIPFORMAT nFormat, LPHANDLE lphReturn)
  436. {
  437.     HANDLE hData = NULL;    // default to not supported
  438.  
  439.     TRY
  440.     {
  441.         if (nFormat == cfNative)
  442.         {
  443.             hData = GetNativeData();
  444.         }
  445.         else if (nFormat == CF_METAFILEPICT)
  446.         {
  447.             hData = GetMetafileData();
  448.         }
  449.         else if (nFormat == CF_TEXT) 
  450.         {
  451.             CString text;
  452.             if (OnGetTextData(text))
  453.             {
  454.                 // allocate a global block for the string
  455.                 hData = ::GlobalAlloc(GMEM_DDESHARE, text.GetLength() + 1);
  456.                 if (hData == NULL)
  457.                     AfxThrowMemoryException();
  458.  
  459.                 LPSTR  lpszText = (LPSTR)::GlobalLock(hData);
  460.                 ASSERT(lpszText != NULL);
  461.                 _fstrcpy(lpszText, (const char*) text);
  462.                 ::GlobalUnlock(hData);
  463.             }
  464.         }
  465.         else
  466.         {
  467.             TRACE("Warning: OLE get data, unknown format %d\n", nFormat);
  468.         }
  469.     }
  470.     CATCH (COleException, e)
  471.     {
  472.         return e->m_status;
  473.     }
  474.     AND_CATCH (CException, e)
  475.     {
  476.         // other exceptions
  477.         return OLE_ERROR_MEMORY;
  478.     }
  479.     END_CATCH
  480.  
  481.     if (hData == NULL)
  482.         return OLE_ERROR_FORMAT;        // not supported
  483.  
  484.     // return the data
  485.     *lphReturn = hData;
  486.     return OLE_OK;
  487. }
  488.  
  489.  
  490. OLESTATUS
  491. COleServerItem::OnSetData(OLECLIPFORMAT nFormat, HANDLE hData)
  492. {
  493.     if (nFormat != cfNative)
  494.     {
  495.         ::GlobalFree(hData);
  496.         return OLE_ERROR_FORMAT;    // Requested format is not available
  497.     }
  498.  
  499.     // set native data via serialization
  500.     CSharedFile memFile;
  501.     memFile.SetHandle(hData);
  502.  
  503.     TRY
  504.     {
  505.         CArchive    setArchive(&memFile, CArchive::load);
  506.         this->Serialize(setArchive);        // load me
  507.     }
  508.     CATCH (CException, e)
  509.     {
  510.         memFile.Close();
  511.         return OLE_ERROR_GENERIC;
  512.     }
  513.     END_CATCH
  514.  
  515.     return OLE_OK;
  516. }
  517.  
  518.  
  519. /////////////////////////////////////////////////////////////////////////////
  520. /////////////////////////////////////////////////////////////////////////////
  521. // COleServerDoc
  522.  
  523. inline COleServerDoc * COleServerDoc::FromLp(LPOLESERVERDOC lpServerDoc)
  524. {
  525.     COleServerDoc* pDoc;
  526.     pDoc = (COleServerDoc*) GetPtrFromFarPtr(lpServerDoc, sizeof(CObject));
  527.     ASSERT(lpServerDoc == &pDoc->m_oleServerDoc);
  528.     return pDoc;
  529. }
  530.  
  531. // friend class to get access to COleServerDoc protected implementations
  532. struct _afxOleServerDocImplementation
  533. {
  534.  
  535.     static OLESTATUS OLEEXPORT
  536.     Save(LPOLESERVERDOC lpServerDoc)
  537.     {
  538.         LOCK_PUMP lock;
  539.         OLE_TRACE("COleServerDoc::OnSave()\n");
  540.         return COleServerDoc::FromLp(lpServerDoc)->OnSave();
  541.     }
  542.  
  543.     static OLESTATUS OLEEXPORT
  544.     Close(LPOLESERVERDOC lpServerDoc)
  545.     {
  546.         LOCK_PUMP lock;
  547.         OLE_TRACE("COleServerDoc::OnClose()\n");
  548.         return COleServerDoc::FromLp(lpServerDoc)->OnClose();
  549.     }
  550.  
  551.     static OLESTATUS OLEEXPORT
  552.     SetHostNames(LPOLESERVERDOC lpServerDoc,
  553.         OLE_LPCSTR lpszClient, OLE_LPCSTR lpszDoc)
  554.     {
  555.         LOCK_PUMP lock;
  556.         OLE_TRACE("COleServerDoc::OnSetHostNames()\n");
  557.         OLESTATUS status = COleServerDoc::FromLp(lpServerDoc)->OnSetHostNames(
  558.             lpszClient, lpszDoc);
  559.         return status;
  560.     }
  561.  
  562.     static OLESTATUS OLEEXPORT
  563.     SetDocDimensions(LPOLESERVERDOC lpServerDoc, OLE_CONST RECT FAR* lpRect)
  564.     {
  565.         LOCK_PUMP lock;
  566.         OLE_TRACE("COleServerDoc::OnSetDocDimensions()\n");
  567.         return COleServerDoc::FromLp(lpServerDoc)->OnSetDocDimensions((LPRECT)lpRect);
  568.     }
  569.  
  570.     static OLESTATUS OLEEXPORT
  571.     Release(LPOLESERVERDOC lpServerDoc)
  572.     {
  573.         LOCK_PUMP lock;
  574.         OLE_TRACE("COleServerDoc::OnRelease()\n");
  575.         return COleServerDoc::FromLp(lpServerDoc)->OnRelease();
  576.     }
  577.  
  578.     static OLESTATUS OLEEXPORT
  579.     SetColorScheme(LPOLESERVERDOC lpServerDoc,
  580.         OLE_CONST LOGPALETTE FAR* lpLogPalette)
  581.     {
  582.         LOCK_PUMP lock;
  583.         OLE_TRACE("COleServerDoc::OnSetColorScheme()\n");
  584.         OLESTATUS status = COleServerDoc::FromLp(lpServerDoc)->OnSetColorScheme(
  585.             (LPLOGPALETTE)lpLogPalette);
  586.         return status;
  587.     }
  588.  
  589.     static OLESTATUS OLEEXPORT
  590.     Execute(LPOLESERVERDOC lpServerDoc, HANDLE hCommands)
  591.     {
  592.         LOCK_PUMP lock;
  593.         OLE_TRACE("COleServerDoc::OnExecute()\n");
  594.         LPVOID  lpCommands = ::GlobalLock(hCommands);
  595.         ASSERT(lpCommands != NULL);
  596.         OLESTATUS status;
  597.         status = COleServerDoc::FromLp(lpServerDoc)->OnExecute(lpCommands);
  598.         ::GlobalUnlock(hCommands);
  599.         return status;
  600.     }
  601.  
  602.     static OLESTATUS OLEEXPORT
  603.     GetObject(LPOLESERVERDOC lpServerDoc, OLE_LPCSTR lpszObjname,
  604.         LPOLEOBJECT FAR * lplpObject, LPOLECLIENT lpClient)
  605.     {
  606.         COleServerDoc* pDoc = COleServerDoc::FromLp(lpServerDoc);
  607.         COleServerItem* pItem;
  608.         LOCK_PUMP lock;
  609.  
  610.         TRY
  611.         {
  612.             if (lpszObjname == NULL || *lpszObjname == '\0')
  613.             {
  614.                 OLE_TRACE("calling COleServerDoc::OnGetDocument\n");
  615.                 pItem = pDoc->OnGetDocument();
  616.             }
  617.             else
  618.             {
  619. #ifdef _DEBUG
  620.                 if (afxTraceFlags & 0x10)
  621.                     TRACE("calling COleServerDoc::GetItem(%Fs)\n", lpszObjname);
  622. #endif
  623.                 pItem = pDoc->OnGetItem(lpszObjname);
  624.             }
  625.         }
  626.         CATCH (CException, e)
  627.         {
  628.             return COleException::Process(e);
  629.         }
  630.         END_CATCH
  631.  
  632.         if (pItem == NULL)
  633.             return OLE_ERROR_GENERIC;
  634.  
  635.         pDoc->AddItem(pItem, lpClient);     // attaches everything
  636.         *lplpObject = &pItem->m_oleObject;
  637.         return OLE_OK;
  638.     }
  639. };
  640.  
  641. static struct _OLESERVERDOCVTBL NEAR serverDocVtbl =
  642. {
  643.     &_afxOleServerDocImplementation::Save,
  644.     &_afxOleServerDocImplementation::Close,
  645.     &_afxOleServerDocImplementation::SetHostNames,
  646.     &_afxOleServerDocImplementation::SetDocDimensions,
  647.     &_afxOleServerDocImplementation::GetObject,
  648.     &_afxOleServerDocImplementation::Release,
  649.     &_afxOleServerDocImplementation::SetColorScheme,
  650.     &_afxOleServerDocImplementation::Execute,
  651. };
  652.  
  653. /////////////////////////////////////////////////////////////////////////////
  654. // COleServerDoc construction and other operations
  655.  
  656. COleServerDoc::COleServerDoc()
  657. {
  658.     m_oleServerDoc.lpvtbl = &serverDocVtbl;
  659.     m_pServer = NULL;
  660.     m_lhServerDoc = NULL;
  661.     m_hPalette = NULL;
  662.     m_bWaiting = FALSE;
  663. }
  664.  
  665. IMPLEMENT_DYNAMIC(COleServerDoc, CObject)
  666.  
  667. COleServerDoc::~COleServerDoc()
  668. {
  669.     if (IsOpen())
  670.         BeginRevoke();
  671.     if (m_hPalette != NULL)
  672.         ::DeleteObject(m_hPalette);
  673. }
  674.  
  675. void
  676. COleServerDoc::CheckAsync(OLESTATUS status)
  677.     // throw exception if not ok to continue
  678. {
  679.     ASSERT(!m_bWaiting);
  680.  
  681.     if (status == OLE_WAIT_FOR_RELEASE)
  682.     {
  683.         m_bWaiting = TRUE;
  684.         while (m_bWaiting)
  685.         {
  686.             OLE_TRACE("OLE Server Doc waiting for release\n");
  687.             AfxGetApp()->PumpMessage();
  688.         }
  689.         m_bWaiting = FALSE;
  690.  
  691.         return;     // assume it worked
  692.     }
  693.  
  694.     if (status == OLE_OK || status > OLE_WARN_DELETE_DATA)
  695.     {
  696.         // ok, or just a warning
  697.         return;
  698.     }
  699.  
  700.     // otherwise this error wasn't expected, so throw an exception
  701.     TRACE("Warning: COleServerDoc operation failed %d, throwing exception\n", status);
  702.     AfxThrowOleException(status);
  703. }
  704.  
  705. OLESTATUS
  706. COleServerDoc::BeginRevoke()
  707.     // do not wait for async completion
  708. {
  709.     ASSERT(IsOpen());
  710.     LHCLIENTDOC lh = m_lhServerDoc;
  711.     ASSERT(lh != NULL);
  712.     if (m_pServer != NULL)
  713.         m_pServer->RemoveDocument(this);
  714.     m_lhServerDoc = NULL;
  715.     OLESTATUS status = ::OleRevokeServerDoc(lh);
  716.     ASSERT(status == OLE_OK || status == OLE_WAIT_FOR_RELEASE);
  717.     // revoke will not be finished until OnRelease called
  718.     return status;
  719. }
  720.  
  721. void
  722. COleServerDoc::Revoke()
  723.     // wait for async completion
  724. {
  725.     ASSERT(IsOpen());
  726.     CheckAsync(BeginRevoke());
  727. }
  728.  
  729. /////////////////////////////////////////////////////////////////////////////
  730. // Interesting operations
  731.  
  732. BOOL
  733. COleServerDoc::Register(COleServer* pServer, LPCSTR lpszDoc)
  734. {
  735.     ASSERT(m_lhServerDoc == NULL);      // one time only
  736.     ASSERT(pServer != NULL);
  737.     ASSERT(pServer->IsOpen());
  738.  
  739.     LHSERVERDOC lhDoc;
  740.     if (::OleRegisterServerDoc(pServer->m_lhServer, lpszDoc,
  741.         &m_oleServerDoc, &lhDoc) != OLE_OK)
  742.     {
  743.         return FALSE;
  744.     }
  745.  
  746.     pServer->AddDocument(this, lhDoc);
  747.     ASSERT(m_lhServerDoc == lhDoc); // make sure it connected it
  748.     return TRUE;
  749. }
  750.  
  751. void
  752. COleServerDoc::NotifyRename(LPCSTR lpszNewName)
  753. {
  754.     ASSERT(IsOpen());
  755.     ASSERT(lpszNewName != NULL);
  756.     CheckAsync(::OleRenameServerDoc(m_lhServerDoc, lpszNewName));
  757. }
  758.  
  759. void
  760. COleServerDoc::NotifyRevert()
  761. {
  762.     ASSERT(IsOpen());
  763.     CheckAsync(::OleRevertServerDoc(m_lhServerDoc));
  764. }
  765.  
  766. void
  767. COleServerDoc::NotifySaved()
  768. {
  769.     ASSERT(IsOpen());
  770.     CheckAsync(::OleSavedServerDoc(m_lhServerDoc));
  771. }
  772.  
  773. void
  774. COleServerDoc::NotifyAllClients(OLE_NOTIFICATION wNotify)
  775. {
  776.     POSITION pos = GetStartPosition();
  777.     COleServerItem* pItem;
  778.  
  779.     while ((pItem = GetNextItem(pos)) != NULL)
  780.     {
  781.         pItem->NotifyClient(wNotify);
  782.     }
  783. }
  784.  
  785. void
  786. COleServerDoc::AddItem(COleServerItem* pItem, LPOLECLIENT lpClient)
  787. {
  788.     ASSERT_VALID(pItem);
  789.  
  790.     // Attach handle to un-attached item
  791.     ASSERT(pItem->m_lpClient == NULL);  // must be unattached !
  792.     ASSERT(pItem->m_pDocument == NULL); // must be unconnected !
  793.     pItem->m_lpClient = lpClient;
  794.     pItem->m_pDocument = this;
  795. }
  796.  
  797. /////////////////////////////////////////////////////////////////////////////
  798. // COleServerDoc standard implementation of overridables
  799.  
  800. OLESTATUS
  801. COleServerDoc::OnRelease()
  802. {
  803.     OLE_TRACE("COleServerDoc::OnRelease\n");
  804.     m_bWaiting = FALSE;
  805.     // close connection to OLE server doc
  806.     m_lhServerDoc = NULL;
  807.     return OLE_OK;
  808. }
  809.  
  810.  
  811. OLESTATUS
  812. COleServerDoc::OnSave()
  813. {
  814.     return OLE_OK;
  815. }
  816.  
  817.  
  818. OLESTATUS
  819. COleServerDoc::OnClose()
  820. {
  821.     ASSERT(IsOpen());
  822.     BeginRevoke();
  823.     return OLE_OK;
  824. }
  825.  
  826.  
  827. OLESTATUS
  828. COleServerDoc::OnExecute(LPVOID /*lpCommands*/) // DDE commands
  829. {
  830.     return OLE_ERROR_COMMAND;
  831. }
  832.  
  833.  
  834. OLESTATUS
  835. COleServerDoc::OnSetDocDimensions(LPRECT /*lpRect*/)
  836. {
  837.     return OLE_OK;      // default to ignore it
  838. }
  839.  
  840.  
  841. // Overridables you do not have to override
  842. OLESTATUS
  843. COleServerDoc::OnSetHostNames(LPCSTR /*lpszHost*/, LPCSTR /*lpszHostObj*/)
  844. {
  845.     return OLE_OK;
  846. }
  847.  
  848.  
  849. OLESTATUS
  850. COleServerDoc::OnSetColorScheme(LPLOGPALETTE lpLogPalette)
  851. {
  852.     // save in global document palette
  853.     HPALETTE hNewPal = ::CreatePalette(lpLogPalette);
  854.  
  855.     if (hNewPal == NULL)
  856.         return OLE_ERROR_PALETTE;
  857.  
  858.     if (m_hPalette != NULL)
  859.         ::DeleteObject(m_hPalette);
  860.     m_hPalette = hNewPal;
  861.     return OLE_OK;
  862. }
  863.  
  864. /////////////////////////////////////////////////////////////////////////////
  865. /////////////////////////////////////////////////////////////////////////////
  866. // COleServer
  867.  
  868. inline COleServer * COleServer::FromLp(LPOLESERVER lpServer)
  869. {
  870.     COleServer* pOleServer;
  871.     pOleServer = (COleServer*) GetPtrFromFarPtr(lpServer, sizeof(CObject));
  872.     ASSERT(lpServer == &pOleServer->m_oleServer);
  873.     return pOleServer;
  874. }
  875.  
  876. // friend class to get access to COleServer protected implementations
  877. struct _afxOleServerImplementation
  878. {
  879.     static OLESTATUS OLEEXPORT
  880.     Exit(LPOLESERVER lpServer)
  881.     {
  882.         LOCK_PUMP lock;
  883.         OLE_TRACE("COleServer::OnExit()\n");
  884.         return COleServer::FromLp(lpServer)->OnExit();
  885.     }
  886.  
  887.     static OLESTATUS OLEEXPORT
  888.     Release(LPOLESERVER lpServer)
  889.     {
  890.         LOCK_PUMP lock;
  891.         OLE_TRACE("COleServer::OnRelease()\n");
  892.         return COleServer::FromLp(lpServer)->OnRelease();
  893.     }
  894.  
  895.     static OLESTATUS OLEEXPORT
  896.     Execute(LPOLESERVER lpServer, HANDLE hCommands)
  897.     {
  898.         LOCK_PUMP lock;
  899.         OLE_TRACE("COleServer::Execute()\n");
  900.  
  901.         LPVOID  lpCommands = ::GlobalLock(hCommands);
  902.         ASSERT(lpCommands != NULL);
  903.         OLESTATUS status;
  904.         status = COleServer::FromLp(lpServer)->OnExecute(lpCommands);
  905.         ::GlobalUnlock(hCommands);
  906.         return status;
  907.     }
  908.  
  909.     static OLESTATUS OLEEXPORT
  910.     Open(LPOLESERVER lpServer, LHSERVERDOC lhServerDoc,
  911.         OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR * lplpServerDoc)
  912.     {
  913.         LOCK_PUMP lock;
  914.         OLE_TRACE("COleServer::OnOpenDoc()\n");
  915.  
  916.         COleServer* pServer = COleServer::FromLp(lpServer);
  917.         COleServerDoc* pDoc;
  918.  
  919.         TRY
  920.             pDoc = pServer->OnOpenDoc(lpszDoc);
  921.         CATCH (CException, e)
  922.             return COleException::Process(e);
  923.         END_CATCH
  924.  
  925.         if (pDoc == NULL)
  926.             return OLE_ERROR_GENERIC;
  927.         pServer->AddDocument(pDoc, lhServerDoc);
  928.         *lplpServerDoc = &pDoc->m_oleServerDoc;
  929.         return OLE_OK;
  930.     }
  931.  
  932.     static OLESTATUS OLEEXPORT
  933.     Create(LPOLESERVER lpServer, LHSERVERDOC lhServerDoc,
  934.         OLE_LPCSTR lpszClass, OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR * lplpServerDoc)
  935.     {
  936.         LOCK_PUMP lock;
  937.         OLE_TRACE("COleServer::OnCreateDoc()\n");
  938.  
  939.         COleServer* pServer = COleServer::FromLp(lpServer);
  940.         COleServerDoc* pDoc;
  941.  
  942.         TRY
  943.             pDoc = pServer->OnCreateDoc(lpszClass, lpszDoc);
  944.         CATCH (CException, e)
  945.             return COleException::Process(e);
  946.         END_CATCH
  947.  
  948.         if (pDoc == NULL)
  949.             return OLE_ERROR_GENERIC;
  950.  
  951.         pServer->AddDocument(pDoc, lhServerDoc);
  952.         *lplpServerDoc = &pDoc->m_oleServerDoc;
  953.         return OLE_OK;
  954.     }
  955.  
  956.     static OLESTATUS OLEEXPORT
  957.     CreateFromTemplate(LPOLESERVER lpServer, LHSERVERDOC lhServerDoc,
  958.         OLE_LPCSTR lpszClass, OLE_LPCSTR lpszDoc, OLE_LPCSTR lpszTemplate,
  959.         LPOLESERVERDOC FAR * lplpServerDoc)
  960.     {
  961.         LOCK_PUMP lock;
  962.         OLE_TRACE("COleServer::OnCreateDocFromTemplate()\n");
  963.  
  964.         COleServer* pServer = COleServer::FromLp(lpServer);
  965.         COleServerDoc* pDoc;
  966.  
  967.         TRY
  968.             pDoc = pServer->OnCreateDocFromTemplate(lpszClass,
  969.               lpszDoc, lpszTemplate);
  970.         CATCH (CException, e)
  971.             return COleException::Process(e);
  972.         END_CATCH
  973.  
  974.         if (pDoc == NULL)
  975.             return OLE_ERROR_GENERIC;
  976.         pServer->AddDocument(pDoc, lhServerDoc);
  977.         *lplpServerDoc = &pDoc->m_oleServerDoc;
  978.         return OLE_OK;
  979.     }
  980.  
  981.     static OLESTATUS OLEEXPORT
  982.     Edit(LPOLESERVER lpServer, LHSERVERDOC lhServerDoc,
  983.         OLE_LPCSTR lpszClass, OLE_LPCSTR lpszDoc, LPOLESERVERDOC FAR * lplpServerDoc)
  984.     {
  985.         LOCK_PUMP lock;
  986.         OLE_TRACE("COleServer::OnEditDoc()\n");
  987.  
  988.         COleServer* pServer = COleServer::FromLp(lpServer);
  989.         COleServerDoc* pDoc;
  990.  
  991.         TRY
  992.             pDoc = pServer->OnEditDoc(lpszClass, lpszDoc);
  993.         CATCH (CException, e)
  994.             return COleException::Process(e);
  995.         END_CATCH
  996.  
  997.         if (pDoc == NULL)
  998.             return OLE_ERROR_GENERIC;
  999.         pServer->AddDocument(pDoc, lhServerDoc);
  1000.         *lplpServerDoc = &pDoc->m_oleServerDoc;
  1001.         return OLE_OK;
  1002.     }
  1003. };
  1004.  
  1005. static struct _OLESERVERVTBL NEAR serverVtbl =
  1006. {
  1007.     &_afxOleServerImplementation::Open,
  1008.     &_afxOleServerImplementation::Create,
  1009.     &_afxOleServerImplementation::CreateFromTemplate,
  1010.     &_afxOleServerImplementation::Edit,
  1011.     &_afxOleServerImplementation::Exit,
  1012.     &_afxOleServerImplementation::Release,
  1013.     &_afxOleServerImplementation::Execute,
  1014. };
  1015.  
  1016. //////////////////////////////////////////////////////////////////////////////
  1017. // COleServer construction etc
  1018.  
  1019. COleServer::COleServer(BOOL bLaunchEmbedded)
  1020. {
  1021.     m_oleServer.lpvtbl = &serverVtbl;
  1022.     m_lhServer = NULL;
  1023.  
  1024.     m_cOpenDocuments = 0;
  1025.     m_bLaunchEmbedded = bLaunchEmbedded;
  1026. }
  1027.  
  1028. IMPLEMENT_DYNAMIC(COleServer, CObject)
  1029.  
  1030. COleServer::~COleServer()
  1031. {
  1032.     if (IsOpen())
  1033.         BeginRevoke();          // server death
  1034. }
  1035.  
  1036. void
  1037. COleServer::BeginRevoke()
  1038. {
  1039.     ASSERT(IsOpen());
  1040.     LHSERVER lhServer = m_lhServer;
  1041.  
  1042.     if (lhServer != NULL)
  1043.     {
  1044.         m_lhServer = NULL;      // closed for all intensive purposes
  1045.         OLESTATUS status = ::OleRevokeServer(lhServer);
  1046.         ASSERT(status == OLE_OK || status == OLE_WAIT_FOR_RELEASE);
  1047.     }
  1048.     // NOTE: will return before the Revoke is acknowledged
  1049. }
  1050.  
  1051. BOOL
  1052. COleServer::Register(LPCSTR lpszClass, BOOL bMultiInstance)
  1053. {
  1054.     ASSERT(m_lhServer == NULL);     // one time only
  1055.     ASSERT(lpszClass != NULL);
  1056.  
  1057.     OLE_SERVER_USE use = bMultiInstance ? OLE_SERVER_MULTI : OLE_SERVER_SINGLE;
  1058.     return ::OleRegisterServer(lpszClass, &m_oleServer, &m_lhServer,
  1059.         AfxGetInstanceHandle(), use) == OLE_OK;
  1060. }
  1061.  
  1062. //////////////////////////////////////////////////////////////////////////////
  1063. // COleServer manages COleServerDocs
  1064.  
  1065. void COleServer::AddDocument(COleServerDoc* pDoc, LHSERVERDOC lhServerDoc)
  1066. {
  1067.     // Attach handle to un-open server document
  1068.     ASSERT_VALID(pDoc);
  1069.     ASSERT(pDoc->m_lhServerDoc == NULL);    // must be unregistered !
  1070.     ASSERT(pDoc->m_pServer == NULL);        // must be dis-connected
  1071.     ASSERT(lhServerDoc != NULL);
  1072.  
  1073.     // connect to server
  1074.     pDoc->m_lhServerDoc = lhServerDoc;
  1075.     pDoc->m_pServer = this;
  1076.     m_cOpenDocuments++;
  1077. }
  1078.  
  1079. void COleServer::RemoveDocument(COleServerDoc* pDoc)
  1080. {
  1081.     ASSERT(pDoc != NULL);
  1082.     ASSERT(pDoc->m_pServer == this);
  1083.     ASSERT(m_cOpenDocuments > 0);
  1084.  
  1085.     pDoc->m_pServer = NULL;
  1086.     m_cOpenDocuments--;
  1087. }
  1088.  
  1089. //////////////////////////////////////////////////////////////////////////////
  1090. // COleServer default implementation of overridables
  1091.  
  1092. COleServerDoc* COleServer::OnOpenDoc(LPCSTR /*lpszDoc*/)
  1093. {
  1094.     return NULL;
  1095. }
  1096.  
  1097. COleServerDoc* COleServer::OnCreateDocFromTemplate(LPCSTR /*lpszClass*/,
  1098.     LPCSTR /*lpszDoc*/, LPCSTR /*lpszTemplate*/)
  1099. {
  1100.     return NULL;
  1101. }
  1102.  
  1103. OLESTATUS COleServer::OnExecute(LPVOID /*lpCommands*/)  // DDE commands
  1104. {
  1105.     return OLE_ERROR_COMMAND;
  1106. }
  1107.  
  1108. OLESTATUS COleServer::OnExit()
  1109. {
  1110.     if (IsOpen())
  1111.     {
  1112.         OLE_TRACE("COleServer::OnExit() Revoking server\n");
  1113.         BeginRevoke();
  1114.     }
  1115.     return OLE_OK;
  1116. }
  1117.  
  1118. OLESTATUS COleServer::OnRelease()
  1119. {
  1120.     CWnd* pMainWnd = AfxGetApp()->m_pMainWnd;
  1121.  
  1122.     if (IsOpen() && m_bLaunchEmbedded)
  1123.     {
  1124.         // there is a chance we should be shutting down
  1125.         // shut down if no open documents, or if main window is invisible
  1126.         if (m_cOpenDocuments == 0 || 
  1127.             (pMainWnd != NULL && !pMainWnd->IsWindowVisible()))
  1128.         {
  1129.             OLE_TRACE("COleServer::OnRelease() Revoking server\n");
  1130.             BeginRevoke();
  1131.         }
  1132.     }
  1133.  
  1134.     // if someone has already revoked us
  1135.     if (!IsOpen())
  1136.     {
  1137.         TRACE("COleServer::OnRelease() terminating server app\n");
  1138.         OLE_TRACE("\tcalling ::PostQuitMessage\n");
  1139.         ::PostQuitMessage(0);
  1140.     }
  1141.  
  1142.     return OLE_OK;
  1143. }
  1144.  
  1145. //////////////////////////////////////////////////////////////////////////////
  1146. // Special register for server in case user does not run REGLOAD
  1147.  
  1148. BOOL AfxOleRegisterServerName(LPCSTR lpszClass, LPCSTR lpszLocalClassName)
  1149. {
  1150.     ASSERT(lpszClass != NULL && *lpszClass != '\0');
  1151.     LONG    lSize;
  1152.     char    szBuffer[OLE_MAXNAMESIZE];
  1153.  
  1154.     if (lpszLocalClassName == NULL || *lpszLocalClassName == '\0')
  1155.     {
  1156.         TRACE("Warning: no localized class name provided for server,"
  1157.             " using %Fs\n", lpszClass);
  1158.         lpszLocalClassName = lpszClass;
  1159.     }
  1160.  
  1161.     lSize = OLE_MAXNAMESIZE;
  1162.     if (::RegQueryValue(HKEY_CLASSES_ROOT, lpszClass, szBuffer,
  1163.         &lSize) == ERROR_SUCCESS)
  1164.     {
  1165.         // don't replace an existing localized name
  1166.         TRACE("Server already has localized class name (%s)\n", szBuffer);
  1167.     }
  1168.     else
  1169.     {
  1170.         // set localized (user visible) class name
  1171.         if (::RegSetValue(HKEY_CLASSES_ROOT, lpszClass, REG_SZ,
  1172.           lpszLocalClassName, _fstrlen(lpszLocalClassName)) != ERROR_SUCCESS)
  1173.             return FALSE;
  1174.     }
  1175.  
  1176.     // set the path name for the server for "StdFileEditing" to this app
  1177.  
  1178.     // get name/path of executable
  1179.     char szPathName[256];
  1180.     ::GetModuleFileName(AfxGetInstanceHandle(), szPathName,
  1181.         sizeof(szPathName)-1);
  1182.  
  1183.     wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\server",
  1184.         (LPCSTR)lpszClass);
  1185.     if (::RegSetValue(HKEY_CLASSES_ROOT, szBuffer, REG_SZ,
  1186.       szPathName, strlen(szPathName)) != ERROR_SUCCESS)
  1187.         return FALSE;
  1188.  
  1189.     // if there are no verbs, throw in the default "Edit" verb
  1190.     // (Note: we hard code the English "Edit" so you should have
  1191.     //   a .REG file for localized verb names)
  1192.  
  1193.     char szOldVerb[256];
  1194.     wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb",
  1195.         (LPCSTR)lpszClass);
  1196.     lSize = OLE_MAXNAMESIZE;
  1197.     if (::RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szOldVerb,
  1198.         &lSize) != ERROR_SUCCESS)
  1199.     {
  1200.         // no verbs, add "Edit"
  1201.         if (::RegSetValue(HKEY_CLASSES_ROOT, szBuffer, REG_SZ,
  1202.           "", 0) != ERROR_SUCCESS)
  1203.             return FALSE;
  1204.  
  1205.         strcat(szBuffer, "\\0");    // backslash + zero
  1206.         if (::RegSetValue(HKEY_CLASSES_ROOT, szBuffer, REG_SZ,
  1207.           "Edit", 4) != ERROR_SUCCESS)
  1208.             return FALSE;
  1209.     }
  1210.  
  1211.     // all set
  1212.     return TRUE;
  1213. }
  1214.  
  1215. //////////////////////////////////////////////////////////////////////////////
  1216. // Diagnostics
  1217.  
  1218. #ifdef _DEBUG
  1219. void COleServerItem::AssertValid() const
  1220. {
  1221.     CObject::AssertValid();
  1222.  
  1223.     // must be completely detached or completely attached
  1224.     ASSERT((m_pDocument == NULL && m_lpClient == NULL) ||
  1225.         (m_pDocument != NULL && m_lpClient != NULL));
  1226. }
  1227.  
  1228. void COleServerItem::Dump(CDumpContext& dc) const
  1229. {
  1230.     CObject::Dump(dc);
  1231.  
  1232.     // shallow dump
  1233.     dc << "\n\tm_pDocument = " << (void*)m_pDocument;
  1234.     dc << "\n\tm_lpClient = " << m_lpClient;
  1235.     dc << "\n\tm_hPalette = " << m_hPalette;
  1236.     dc << "\n\tm_rectBounds (HIMETRIC) = " << m_rectBounds;
  1237. }
  1238.  
  1239.  
  1240. void COleServerDoc::AssertValid() const
  1241. {
  1242.     CObject::AssertValid();
  1243.     ASSERT(!m_bWaiting);    // waiting is an internal state
  1244. }
  1245.  
  1246. void COleServerDoc::Dump(CDumpContext& dc) const
  1247. {
  1248.     CObject::Dump(dc);
  1249.     dc << "\n\tm_pServer = " << (void*)m_pServer;
  1250.     dc << "\n\tm_lhServerDoc = " << m_lhServerDoc;
  1251.     dc << "\n\tm_bWaiting = " << m_bWaiting;
  1252. }
  1253.  
  1254. void COleServer::AssertValid() const
  1255. {
  1256.     CObject::AssertValid();
  1257.     ASSERT(m_cOpenDocuments >= 0);
  1258. }
  1259.  
  1260. void COleServer::Dump(CDumpContext& dc) const
  1261. {
  1262.     CObject::Dump(dc);
  1263.     dc << "\n\tm_lhServer = " << m_lhServer;
  1264.     dc << "\n\tm_bLaunchEmbedded = " << m_bLaunchEmbedded;
  1265.     dc << "\n\tm_cOpenDocuments = " << m_cOpenDocuments;
  1266. }
  1267.  
  1268. #endif //_DEBUG
  1269.  
  1270.  
  1271. //////////////////////////////////////////////////////////////////////////////
  1272.