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