|
|
1.1 root 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: //////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.