|
|
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:
12: #include "afxole.h"
13: #pragma hdrstop
14:
15: #include "oleptr_.h"
16:
17: #ifdef AFX_OLE_SEG
18: #pragma code_seg(AFX_OLE_SEG)
19: #endif
20:
21: #ifdef _DEBUG
22: #undef THIS_FILE
23: static char BASED_CODE THIS_FILE[] = __FILE__;
24: #endif
25:
26: #define OLEEXPORT FAR PASCAL _export
27:
28: /////////////////////////////////////////////////////////////////////////////
29: #ifdef _DEBUG
30: // character strings to use for debug traces
31:
32: static char BASED_CODE szCHANGED[] = "OLE_CHANGED";
33: static char BASED_CODE szSAVED[] = "OLE_SAVED";
34: static char BASED_CODE szCLOSED[] = "OLE_CLOSED";
35: static char BASED_CODE szRENAMED[] = "OLE_RENAMED";
36: static char BASED_CODE szQUERY_PAINT[] = "OLE_QUERY_PAINT";
37: static char BASED_CODE szRELEASE[] = "OLE_RELEASE";
38: static char BASED_CODE szQUERY_RETRY[] = "OLE_QUERY_RETRY";
39:
40: static char FAR* BASED_CODE notifyStrings[] =
41: {
42: szCHANGED,
43: szSAVED,
44: szCLOSED,
45: szRENAMED,
46: szQUERY_PAINT,
47: szRELEASE,
48: szQUERY_RETRY,
49: };
50: #endif //_DEBUG
51:
52: // Standard protocol strings
53: static char BASED_CODE lpszStaticProtocol[] = "Static";
54: static char BASED_CODE lpszStdProtocol[] = "StdFileEditing";
55:
56: /////////////////////////////////////////////////////////////////////////////
57: // Client view of OLEOBJECT (includes OLECLIENT)
58:
59: IMPLEMENT_DYNAMIC(COleClientItem, CObject)
60:
61: inline COleClientItem *
62: COleClientItem::FromLp(LPOLECLIENT lpClient)
63: {
64: ASSERT(lpClient != NULL);
65: COleClientItem* pOleClient;
66: pOleClient = (COleClientItem*) GetPtrFromFarPtr(lpClient, sizeof(CObject));
67: ASSERT(lpClient == &pOleClient->m_oleClient);
68: return pOleClient;
69: }
70:
71: // friend class to get access to COleClientItem protected implementations
72: struct _afxOleClientItemImplementation
73: {
74: static int OLEEXPORT
75: Client_CallBack(LPOLECLIENT lpClient, OLE_NOTIFICATION wNotification,
76: LPOLEOBJECT lpObject)
77: {
78: COleClientItem* pOleClient = COleClientItem::FromLp(lpClient);
79: ASSERT(pOleClient != NULL);
80:
81: #ifdef _DEBUG
82: if (wNotification != OLE_QUERY_PAINT)
83: {
84: if (afxTraceFlags & 0x10)
85: TRACE("OLE Client_Callback %d [%Fs] for $%lx\n",
86: wNotification, (LPCSTR)notifyStrings[wNotification], lpObject);
87: }
88: #else
89: (void)lpObject; // not used
90: #endif
91: return pOleClient->ClientCallBack(wNotification);
92: }
93: };
94:
95: static struct _OLECLIENTVTBL NEAR clientVtbl =
96: {
97: &_afxOleClientItemImplementation::Client_CallBack
98: };
99:
100: // Many creation variants
101: COleClientItem::COleClientItem(COleClientDoc* pContainerDoc)
102: {
103: ASSERT(pContainerDoc != NULL);
104: ASSERT(pContainerDoc->IsOpen());
105:
106: m_oleClient.lpvtbl = &clientVtbl;
107: m_lpObject = NULL;
108: m_lastStatus = OLE_OK;
109: m_pDocument = pContainerDoc;
110: }
111:
112: COleClientItem::~COleClientItem()
113: {
114: if (m_lpObject != NULL)
115: {
116: // wait for object to be not busy
117: UINT nType = GetType();
118:
119: if (nType != OT_STATIC)
120: WaitForServer();
121: // release linked, delete others
122: CheckAsync((nType == OT_LINK) ?
123: ::OleRelease(m_lpObject) : ::OleDelete(m_lpObject));
124: }
125: }
126:
127: void COleClientItem::Release()
128: {
129: if (m_lpObject == NULL)
130: return;
131:
132: CheckAsync(::OleRelease(m_lpObject));
133:
134: // detach
135: m_lpObject = NULL;
136: }
137:
138: void COleClientItem::Delete()
139: {
140: if (m_lpObject == NULL)
141: return;
142:
143: CheckAsync(::OleDelete(m_lpObject));
144:
145: // detach
146: m_lpObject = NULL;
147: }
148:
149: //////////////////////////////////////////////////////////////////////////////
150: // Create error handling
151:
152: BOOL COleClientItem::CheckCreate(OLESTATUS status)
153: {
154: m_lastStatus = status;
155:
156: switch (status)
157: {
158: case OLE_OK:
159: ASSERT(m_lpObject != NULL);
160: return TRUE; // immediate create success
161:
162: case OLE_WAIT_FOR_RELEASE: // synchronous create
163: ASSERT(m_lpObject != NULL);
164: WaitForServer();
165: return (m_lastStatus == OLE_OK);
166:
167: // cases to treat as exceptions
168: case OLE_ERROR_PROTECT_ONLY:
169: case OLE_ERROR_MEMORY:
170: case OLE_ERROR_OBJECT:
171: case OLE_ERROR_OPTION:
172: TRACE("Warning: COleClientItem::Create?() failed %d\n", status);
173: AfxThrowOleException(status);
174: break;
175: }
176:
177: // the rest are non-exceptional conditions for create
178: TRACE("Warning: COleClientItem::Create?() failed %d, returning FALSE\n", status);
179: m_lpObject = NULL; // just in case
180: return FALSE; // create failed
181: }
182:
183:
184: void COleClientItem::CheckAsync(OLESTATUS status)
185: // special case for possible Async requests
186: {
187: if (status == OLE_WAIT_FOR_RELEASE)
188: {
189: ASSERT(m_lpObject != NULL);
190: WaitForServer();
191: status = m_lastStatus; // set by ASYNC release
192: ASSERT(status != OLE_WAIT_FOR_RELEASE);
193: }
194: CheckGeneral(status); // may throw an exception
195: }
196:
197: void COleClientItem::CheckGeneral(OLESTATUS status)
198: // set 'm_lastStatus'
199: // throw exception if not ok to continue
200: {
201: ASSERT(status != OLE_WAIT_FOR_RELEASE);
202: // Async must be handled as a special case before this
203:
204: m_lastStatus = status;
205: if (status == OLE_OK || status > OLE_WARN_DELETE_DATA)
206: {
207: // ok, or just a warning
208: return;
209: }
210:
211: // otherwise this error wasn't expected, so throw an exception
212: TRACE("Warning: COleClientItem operation failed %d, throwing exception\n", status);
213: AfxThrowOleException(status);
214: }
215:
216:
217: //////////////////////////////////////////////////////////////////////////////
218: // Create variants for real OLEOBJECTs
219:
220: // From clipboard
221: BOOL COleClientItem::CanPaste(OLEOPT_RENDER renderopt,
222: OLECLIPFORMAT cfFormat)
223: {
224: return ::OleQueryCreateFromClip(lpszStdProtocol,
225: renderopt, cfFormat) == OLE_OK ||
226: ::OleQueryCreateFromClip(lpszStaticProtocol,
227: renderopt, cfFormat) == OLE_OK;
228: }
229:
230: BOOL COleClientItem::CanPasteLink(OLEOPT_RENDER renderopt,
231: OLECLIPFORMAT cfFormat)
232: {
233: return ::OleQueryLinkFromClip(lpszStdProtocol,
234: renderopt, cfFormat) == OLE_OK;
235: }
236:
237:
238: BOOL COleClientItem::CreateFromClipboard(LPCSTR lpszObjname,
239: OLEOPT_RENDER renderopt, OLECLIPFORMAT cfFormat)
240: {
241: ASSERT(m_lpObject == NULL); // one time only
242: ASSERT(m_pDocument != NULL);
243: ASSERT(m_pDocument->IsOpen());
244: ASSERT(lpszObjname != NULL);
245:
246: return CheckCreate(::OleCreateFromClip(lpszStdProtocol,
247: &m_oleClient, m_pDocument->m_lhClientDoc, lpszObjname,
248: &m_lpObject, renderopt, cfFormat));
249: }
250:
251: BOOL COleClientItem::CreateStaticFromClipboard(LPCSTR lpszObjname,
252: OLEOPT_RENDER renderopt, OLECLIPFORMAT cfFormat)
253: {
254: ASSERT(m_lpObject == NULL); // one time only
255: ASSERT(m_pDocument != NULL);
256: ASSERT(m_pDocument->IsOpen());
257: ASSERT(lpszObjname != NULL);
258:
259: return CheckCreate(::OleCreateFromClip(lpszStaticProtocol,
260: &m_oleClient, m_pDocument->m_lhClientDoc, lpszObjname,
261: &m_lpObject, renderopt, cfFormat));
262: }
263:
264: BOOL COleClientItem::CreateLinkFromClipboard(LPCSTR lpszObjname,
265: OLEOPT_RENDER renderopt, OLECLIPFORMAT cfFormat)
266: {
267: ASSERT(m_lpObject == NULL); // one time only
268: ASSERT(m_pDocument != NULL);
269: ASSERT(m_pDocument->IsOpen());
270: ASSERT(lpszObjname != NULL);
271:
272: return CheckCreate(::OleCreateLinkFromClip(lpszStdProtocol,
273: &m_oleClient, m_pDocument->m_lhClientDoc, lpszObjname,
274: &m_lpObject, renderopt, cfFormat));
275: }
276:
277:
278: // create from a protocol name or other template
279: BOOL COleClientItem::CreateNewObject(LPCSTR lpszClass, LPCSTR lpszObjname,
280: OLEOPT_RENDER renderopt, OLECLIPFORMAT cfFormat)
281: {
282: ASSERT(m_lpObject == NULL); // one time only
283: ASSERT(m_pDocument != NULL);
284: ASSERT(m_pDocument->IsOpen());
285: ASSERT(lpszClass != NULL);
286: ASSERT(lpszObjname != NULL);
287:
288: return CheckCreate(::OleCreate(lpszStdProtocol,
289: &m_oleClient, lpszClass,
290: m_pDocument->m_lhClientDoc, lpszObjname,
291: &m_lpObject, renderopt, cfFormat));
292: }
293:
294: // create invisible
295: BOOL COleClientItem::CreateInvisibleObject(LPCSTR lpszClass, LPCSTR lpszObjname,
296: OLEOPT_RENDER renderopt, OLECLIPFORMAT cfFormat, BOOL bActivate)
297: {
298: ASSERT(m_lpObject == NULL); // one time only
299: ASSERT(m_pDocument != NULL);
300: ASSERT(m_pDocument->IsOpen());
301: ASSERT(lpszClass != NULL);
302: ASSERT(lpszObjname != NULL);
303:
304: return CheckCreate(::OleCreateInvisible(lpszStdProtocol,
305: &m_oleClient, lpszClass,
306: m_pDocument->m_lhClientDoc, lpszObjname,
307: &m_lpObject, renderopt, cfFormat, bActivate));
308: }
309:
310:
311: /////////////////////////////////////////////////////////////////////////////
312: // More advanced creation
313:
314: BOOL COleClientItem::CreateCloneFrom(COleClientItem* pSrcObject,
315: LPCSTR lpszObjname)
316: {
317: ASSERT(m_lpObject == NULL); // one time only
318: ASSERT(pSrcObject != NULL);
319: ASSERT(m_pDocument != NULL);
320: ASSERT(m_pDocument->IsOpen());
321: ASSERT(lpszObjname != NULL);
322:
323: return CheckCreate(::OleClone(pSrcObject->m_lpObject,
324: &m_oleClient, m_pDocument->m_lhClientDoc, lpszObjname,
325: &m_lpObject));
326: }
327:
328:
329: /////////////////////////////////////////////////////////////////////////////
330: // Default implementations
331:
332: int COleClientItem::ClientCallBack(OLE_NOTIFICATION wNotification)
333: {
334: switch (wNotification)
335: {
336: case OLE_CHANGED: // OLE linked item updated
337: case OLE_SAVED: // OLE server document saved
338: case OLE_CLOSED: // OLE server document closed
339: OnChange(wNotification);
340: break;
341: case OLE_RENAMED:
342: OnRenamed();
343: break;
344: case OLE_RELEASE:
345: OnRelease();
346: break;
347: default:
348: // ignore it (eg: QueryPaint and QueryRetry)
349: break;
350: }
351:
352: return TRUE; // return TRUE in general
353: }
354:
355: void COleClientItem::OnRenamed()
356: {
357: // ignore normally
358: }
359:
360: void COleClientItem::OnRelease()
361: {
362: ASSERT(m_lpObject != NULL);
363: // default will store the release error
364: m_lastStatus = ::OleQueryReleaseError(m_lpObject);
365: ASSERT(m_lastStatus != OLE_WAIT_FOR_RELEASE);
366:
367: if (m_lastStatus != OLE_OK)
368: {
369: // operation failed
370: #ifdef _DEBUG
371: TRACE("Warning: COleClientItem::OnRelease with error %d ($%lx)\n", m_lastStatus,
372: m_lpObject);
373: #endif
374: return;
375: }
376:
377: // Success
378: OLE_RELEASE_METHOD nWhyReleased = ::OleQueryReleaseMethod(m_lpObject);
379:
380: if (nWhyReleased == OLE_DELETE)
381: m_lpObject = NULL; // detach
382: }
383:
384: /////////////////////////////////////////////////////////////////////////////
385: // COleClientItem - attributes
386:
387:
388: UINT COleClientItem::GetType()
389: {
390: ASSERT(m_lpObject != NULL);
391: LONG lType;
392:
393: CheckGeneral(::OleQueryType(m_lpObject, &lType));
394: ASSERT(lType == OT_LINK || lType == OT_EMBEDDED || lType == OT_STATIC);
395: return (UINT)lType;
396: }
397:
398:
399: CString COleClientItem::GetName()
400: {
401: ASSERT(m_lpObject != NULL);
402: char szT[OLE_MAXNAMESIZE];
403:
404: UINT cb = OLE_MAXNAMESIZE;
405: CheckGeneral(::OleQueryName(m_lpObject, szT, &cb));
406:
407: ASSERT(cb == strlen(szT));
408: return CString(szT);
409: }
410:
411:
412: BOOL COleClientItem::GetSize(LPPOINT lpSize)
413: {
414: ASSERT(m_lpObject != NULL);
415:
416: m_lastStatus = ::OleQuerySize(m_lpObject, (DWORD FAR*)lpSize);
417: if (m_lastStatus == OLE_ERROR_BLANK)
418: return FALSE; // no size set yet
419: CheckGeneral(m_lastStatus); // may throw exception
420: return TRUE;
421: }
422:
423: BOOL COleClientItem::GetBounds(LPRECT lpBounds)
424: {
425: ASSERT(m_lpObject != NULL);
426:
427: m_lastStatus = ::OleQueryBounds(m_lpObject, lpBounds);
428: if (m_lastStatus == OLE_ERROR_BLANK)
429: return FALSE; // no size set yet
430: CheckGeneral(m_lastStatus); // may throw exception
431: return TRUE;
432: }
433:
434: BOOL COleClientItem::IsOpen()
435: {
436: ASSERT(m_lpObject != NULL);
437:
438: m_lastStatus = ::OleQueryOpen(m_lpObject);
439: if (m_lastStatus == OLE_ERROR_NOT_OPEN)
440: return FALSE; // not open
441: CheckGeneral(m_lastStatus); // may throw exception
442: return TRUE;
443: }
444:
445: /////////////////////////////////////////////////////////////////////////////
446: // Data exchange plus helpers
447:
448: HANDLE
449: COleClientItem::GetData(OLECLIPFORMAT nFormat, BOOL& bMustDelete)
450: {
451: HANDLE hData = NULL;
452:
453: CheckGeneral(::OleGetData(m_lpObject, nFormat, &hData));
454:
455: ASSERT(hData != NULL);
456: bMustDelete = (m_lastStatus == OLE_WARN_DELETE_DATA);
457: return hData;
458: }
459:
460:
461: void
462: COleClientItem::SetData(OLECLIPFORMAT nFormat, HANDLE hData)
463: {
464: ASSERT(m_lpObject != NULL);
465: CheckAsync(::OleSetData(m_lpObject, nFormat, hData));
466: }
467:
468: void
469: COleClientItem::RequestData(OLECLIPFORMAT nFormat)
470: {
471: ASSERT(m_lpObject != NULL);
472: CheckAsync(::OleRequestData(m_lpObject, nFormat));
473: }
474:
475: /////////////////////////////////////////////////////////////////////////////
476: // Rare or implementation specific attributes
477:
478: BOOL
479: COleClientItem::IsEqual(COleClientItem* pObject)
480: {
481: ASSERT(m_lpObject != NULL);
482: ASSERT(pObject != NULL);
483: ASSERT(pObject->m_lpObject != NULL);
484:
485: m_lastStatus = ::OleEqual(m_lpObject, pObject->m_lpObject);
486: if (m_lastStatus == OLE_ERROR_NOT_EQUAL)
487: return FALSE; // FALSE => not equal
488: CheckGeneral(m_lastStatus); // may throw exception
489: return TRUE; // otherwise equal
490: }
491:
492: HANDLE
493: COleClientItem::GetLinkFormatData()
494: // Return global HANDLE of block containing link information
495: // will return NULL if error or not appropriate type
496: // Both link formats are: "szClass0szDocument0szItem00" */
497: {
498: OLECLIPFORMAT cf = NULL;
499:
500: // first determine the format of the link data
501: switch (GetType())
502: {
503: default:
504: return NULL; // Static or other (i.e. no link format)
505: case OT_EMBEDDED:
506: cf = (OLECLIPFORMAT)::RegisterClipboardFormat("OwnerLink");
507: break;
508: case OT_LINK:
509: cf = (OLECLIPFORMAT)::RegisterClipboardFormat("ObjectLink");
510: break;
511: }
512: ASSERT(cf != NULL);
513:
514: // now get the link data
515: BOOL bMustDelete;
516: HANDLE h;
517: if ((h = GetData(cf, bMustDelete)) == NULL)
518: return NULL;
519: ASSERT(!bMustDelete); // must not have to delete clip format data
520: return h;
521: }
522:
523:
524: /////////////////////////////////////////////////////////////////////////////
525: // Special link attributes
526:
527: OLEOPT_UPDATE COleClientItem::GetLinkUpdateOptions()
528: {
529: ASSERT(m_lpObject != NULL);
530: OLEOPT_UPDATE updateOpt;
531:
532: CheckGeneral(::OleGetLinkUpdateOptions(m_lpObject, &updateOpt));
533: return updateOpt;
534: }
535:
536: void
537: COleClientItem::SetLinkUpdateOptions(OLEOPT_UPDATE updateOpt)
538: {
539: ASSERT(m_lpObject != NULL);
540:
541: CheckAsync(::OleSetLinkUpdateOptions(m_lpObject, updateOpt));
542: }
543:
544: /////////////////////////////////////////////////////////////////////////////
545: // COleClientItem - general operations
546:
547: BOOL
548: COleClientItem::Draw(CDC *pDC, LPRECT lpBounds, LPRECT lpWBounds,
549: CDC* pFormatDC)
550: {
551: ASSERT(m_lpObject != NULL);
552: ASSERT(pDC != NULL);
553: // pFormatDC may be null
554:
555: m_lastStatus = ::OleDraw(m_lpObject, pDC->m_hDC, lpBounds,
556: lpWBounds, pFormatDC->GetSafeHdc());
557:
558: if (m_lastStatus == OLE_ERROR_ABORT || m_lastStatus == OLE_ERROR_DRAW ||
559: m_lastStatus == OLE_ERROR_BLANK)
560: return FALSE; // expected errors
561:
562: CheckGeneral(m_lastStatus); // may throw exception
563: return TRUE; // it worked
564: }
565:
566: void
567: COleClientItem::Activate(UINT nVerb, BOOL bShow, BOOL bTakeFocus,
568: CWnd* pWndContainer, LPRECT lpBounds)
569: {
570: ASSERT(m_lpObject != NULL);
571:
572: CheckAsync(::OleActivate(m_lpObject, nVerb, bShow,
573: bTakeFocus, pWndContainer->GetSafeHwnd(), lpBounds));
574: }
575:
576: /////////////////////////////////////////////////////////////////////////////
577: // more advanced operations
578:
579: void
580: COleClientItem::Rename(LPCSTR lpszNewname)
581: {
582: ASSERT(m_lpObject != NULL);
583: ASSERT(lpszNewname != NULL);
584: CheckGeneral(::OleRename(m_lpObject, lpszNewname));
585: }
586:
587: void
588: COleClientItem::CopyToClipboard()
589: {
590: ASSERT(m_lpObject != NULL);
591:
592: CheckGeneral(::OleCopyToClipboard(m_lpObject));
593: }
594:
595: void
596: COleClientItem::SetTargetDevice(HANDLE hData)
597: {
598: ASSERT(m_lpObject != NULL);
599: ASSERT(hData != NULL);
600: CheckAsync(::OleSetTargetDevice(m_lpObject, hData));
601: }
602:
603: /////////////////////////////////////////////////////////////////////////////
604: // Embedded COleClient operations
605:
606: void
607: COleClientItem::SetHostNames(LPCSTR lpszHost, LPCSTR lpszHostObj)
608: {
609: ASSERT(m_lpObject != NULL);
610: ASSERT(lpszHost != NULL);
611: ASSERT(lpszHostObj != NULL);
612:
613: CheckAsync(::OleSetHostNames(m_lpObject, lpszHost, lpszHostObj));
614: }
615:
616: void
617: COleClientItem::SetBounds(LPRECT lpRect)
618: {
619: ASSERT(m_lpObject != NULL);
620: CheckAsync(::OleSetBounds(m_lpObject, lpRect));
621: }
622:
623: void
624: COleClientItem::SetColorScheme(LPLOGPALETTE lpLogPalette)
625: {
626: ASSERT(m_lpObject != NULL);
627: CheckAsync(::OleSetColorScheme(m_lpObject, lpLogPalette));
628: }
629:
630: /////////////////////////////////////////////////////////////////////////////
631: // Linked COleClient operations
632:
633: void
634: COleClientItem::UpdateLink()
635: {
636: ASSERT(m_lpObject != NULL);
637:
638: CheckAsync(::OleUpdate(m_lpObject));
639: }
640:
641: void COleClientItem::CloseLink()
642: {
643: if (m_lpObject == NULL)
644: return;
645:
646: CheckAsync(::OleClose(m_lpObject));
647: // Does not detach since this can be reactivated later
648: }
649:
650: void
651: COleClientItem::ReconnectLink()
652: {
653: ASSERT(m_lpObject != NULL);
654: CheckAsync(::OleReconnect(m_lpObject));
655: }
656:
657: BOOL COleClientItem::FreezeLink(LPCSTR lpszFrozenName)
658: {
659: ASSERT(m_lpObject != NULL);
660: ASSERT(m_pDocument != NULL);
661: ASSERT(m_pDocument->IsOpen());
662: ASSERT(lpszFrozenName != NULL);
663:
664: ASSERT(GetType() == OT_LINK);
665:
666: LPOLEOBJECT lpOriginalObject = m_lpObject;
667: m_lpObject = NULL;
668: if (!CheckCreate(::OleObjectConvert(lpOriginalObject,
669: lpszStaticProtocol,
670: &m_oleClient, m_pDocument->m_lhClientDoc, lpszFrozenName,
671: &m_lpObject)))
672: {
673: m_lpObject = lpOriginalObject;
674: return FALSE;
675: }
676: ASSERT(GetType() == OT_STATIC);
677:
678: // copy from link worked - now get rid of the original
679: ASSERT(m_lpObject != lpOriginalObject);
680: ASSERT(m_lpObject != NULL);
681:
682: LPOLEOBJECT lpNewObject = m_lpObject;
683: m_lpObject = lpOriginalObject;
684: ASSERT(GetType() == OT_LINK);
685: Delete();
686:
687: ASSERT(m_lpObject == NULL);
688: m_lpObject = lpNewObject;
689: ASSERT(GetType() == OT_STATIC);
690:
691: return TRUE;
692: }
693:
694: /////////////////////////////////////////////////////////////////////////////
695: /////////////////////////////////////////////////////////////////////////////
696: // _COleStream - implementation class connecting OLESTREAM and CArchive
697:
698: struct _COleStream : public _OLESTREAM
699: {
700: CArchive* m_pArchive;
701: _COleStream(CArchive& ar);
702: };
703:
704: static UINT CalcSize(DWORD cbTotal, const void FAR* lpStart)
705: {
706: // return size to read/write (16K max unless limited by segment bounds)
707: DWORD cbThisSeg = 0x10000 - _AFX_FP_OFF(lpStart);
708: DWORD cb = min(cbThisSeg, cbTotal);
709: return (cb > 16384) ? 16384 : (UINT)cb;
710: }
711:
712: // class for static exports
713: struct _afxOleStreamImplementation
714: {
715: static DWORD OLEEXPORT
716: Get(LPOLESTREAM lpStream, void FAR* lpBuffer, DWORD dwCount)
717: {
718: register _COleStream* pStream =
719: (_COleStream*)GetPtrFromFarPtr(lpStream, 0);
720: ASSERT(((LPVOID)pStream) == (LPVOID)lpStream); // no near/far mismatch
721:
722: DWORD dwToRead = dwCount;
723: while (dwToRead > 0)
724: {
725: UINT nRead = CalcSize(dwToRead, lpBuffer);
726: pStream->m_pArchive->Read(lpBuffer, nRead);
727: dwToRead -= nRead;
728: lpBuffer = ((BYTE _huge*)lpBuffer) + nRead;
729: }
730: return dwCount;
731: }
732:
733: static DWORD OLEEXPORT
734: Put(LPOLESTREAM lpStream, OLE_CONST void FAR* lpBuffer, DWORD dwCount)
735: {
736: register _COleStream* pStream =
737: (_COleStream*)GetPtrFromFarPtr(lpStream, 0);
738: ASSERT(((LPVOID)pStream) == (LPVOID)lpStream); // no near/far mismatch
739:
740: DWORD dwToWrite = dwCount;
741: while (dwToWrite > 0)
742: {
743: UINT nWrite = CalcSize(dwToWrite, lpBuffer);
744: pStream->m_pArchive->Write(lpBuffer, nWrite);
745: dwToWrite -= nWrite;
746: lpBuffer = ((OLE_CONST BYTE _huge*)lpBuffer) + nWrite;
747: }
748: return dwCount;
749: }
750: };
751:
752: static struct _OLESTREAMVTBL NEAR streamVtbl =
753: {
754: &_afxOleStreamImplementation::Get,
755: &_afxOleStreamImplementation::Put
756: };
757:
758: _COleStream::_COleStream(CArchive& ar)
759: {
760: m_pArchive = &ar;
761: lpstbl = &streamVtbl; // OLE VTable setup
762: }
763:
764: /////////////////////////////////////////////////////////////////////////////
765: // COleClientItem - serialization
766:
767: void COleClientItem::Serialize(CArchive& ar)
768: {
769: ASSERT(GetDocument() != NULL); // must 'SetDocument' first
770: _COleStream oleStream(ar);
771:
772: if (ar.IsStoring())
773: {
774: ASSERT(m_lpObject != NULL);
775: ar << (WORD) GetType();
776: ar << GetName(); // save our document name
777:
778: // Save object
779: CheckGeneral(::OleSaveToStream(m_lpObject, &oleStream));
780: }
781: else
782: {
783: ASSERT(m_lpObject == NULL);
784:
785: WORD nType;
786: ar >> nType;
787: LPCSTR lpszProtocol;
788:
789: if (nType == OT_LINK || nType == OT_EMBEDDED)
790: {
791: lpszProtocol = lpszStdProtocol;
792: }
793: else if (nType == OT_STATIC)
794: {
795: lpszProtocol = lpszStaticProtocol;
796: }
797: else
798: {
799: // unknown type (i.e. bad file format)
800: AfxThrowOleException(OLE_ERROR_GENERIC);
801: }
802:
803: CString name;
804: ar >> name; // document name
805: if (!CheckCreate(::OleLoadFromStream(&oleStream, lpszProtocol,
806: &m_oleClient, m_pDocument->m_lhClientDoc, name, &m_lpObject)))
807: {
808: // throw an exception regardless
809: AfxThrowOleException(GetLastStatus());
810: }
811: }
812: }
813:
814: /////////////////////////////////////////////////////////////////////////////
815: // COleClientDoc - wrapper for LHCLIENTDOC
816:
817: IMPLEMENT_DYNAMIC(COleClientDoc, CObject)
818:
819: COleClientDoc::COleClientDoc()
820: {
821: m_lhClientDoc = NULL; // not open
822: }
823:
824: void
825: COleClientDoc::Revoke()
826: {
827: if (!IsOpen())
828: return;
829: LHCLIENTDOC lh = m_lhClientDoc;
830: ASSERT(lh != NULL);
831: m_lhClientDoc = NULL;
832: CheckGeneral(::OleRevokeClientDoc(lh));
833: }
834:
835: COleClientDoc::~COleClientDoc()
836: {
837: Revoke();
838: }
839:
840: void COleClientDoc::CheckGeneral(OLESTATUS status) const
841: // throw exception if not ok to continue
842: {
843: ASSERT(status != OLE_WAIT_FOR_RELEASE);
844:
845: if (status == OLE_OK || status > OLE_WARN_DELETE_DATA)
846: {
847: // ok, or just a warning
848: return;
849: }
850:
851: // otherwise this error wasn't expected, so throw an exception
852: TRACE("Warning: COleClientDoc operation failed %d, throwing exception\n", status);
853: AfxThrowOleException(status);
854: }
855:
856: BOOL
857: COleClientDoc::Register(LPCSTR lpszClass, LPCSTR lpszDoc)
858: {
859: ASSERT(m_lhClientDoc == NULL); // one time only
860: return ::OleRegisterClientDoc(lpszClass, lpszDoc,
861: 0L /*reserved*/, &m_lhClientDoc) == OLE_OK;
862: }
863:
864: void
865: COleClientDoc::NotifyRename(LPCSTR lpszNewName)
866: {
867: ASSERT(IsOpen());
868: ASSERT(lpszNewName != NULL);
869:
870: CheckGeneral(::OleRenameClientDoc(m_lhClientDoc, lpszNewName));
871: }
872:
873: void
874: COleClientDoc::NotifyRevert()
875: {
876: ASSERT(IsOpen());
877:
878: CheckGeneral(::OleRevertClientDoc(m_lhClientDoc));
879: }
880:
881: void
882: COleClientDoc::NotifySaved()
883: {
884: ASSERT(IsOpen());
885:
886: CheckGeneral(::OleSavedClientDoc(m_lhClientDoc));
887: }
888:
889: /////////////////////////////////////////////////////////////////////////////
890: // Diagnostics
891:
892: #ifdef _DEBUG
893: void COleClientItem::AssertValid() const
894: {
895: CObject::AssertValid();
896: ASSERT(m_pDocument != NULL);
897: }
898:
899: void COleClientItem::Dump(CDumpContext& dc) const
900: {
901: CObject::Dump(dc);
902:
903: // shallow dump
904: dc << "\n\tm_pDocument = " << (void*) m_pDocument;
905: dc << "\n\tm_lpObject = " << m_lpObject;
906: dc << "\n\tm_lastStatus = " << (int)m_lastStatus;
907: }
908:
909:
910: void COleClientDoc::AssertValid() const
911: {
912: CObject::AssertValid();
913: ASSERT(m_lhClientDoc != NULL);
914: // only valid if truely open
915: }
916:
917: void COleClientDoc::Dump(CDumpContext& dc) const
918: {
919: CObject::Dump(dc);
920: dc << "\n\tm_lhClientDoc = " << m_lhClientDoc;
921: }
922:
923: #endif //_DEBUG
924:
925:
926: /////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.