|
|
1.1 root 1: /*************************************************************************
2: **
3: ** OLE 2 Server Sample Code
4: **
5: ** svrbase.c
6: **
7: ** This file contains all interfaces, methods and related support
8: ** functions for the basic OLE Object (Server) application. The
9: ** basic OLE Object application supports embedding an object and
10: ** linking to a file-based or embedded object as a whole. The basic
11: ** Object application includes the following implementation objects:
12: **
13: ** ClassFactory (aka. ClassObject) Object (see file classfac.c)
14: ** exposed interfaces:
15: ** IClassFactory interface
16: **
17: ** ServerDoc Object
18: ** exposed interfaces:
19: ** IUnknown
20: ** IOleObject interface
21: ** IPersistStorage interface
22: ** IDataObject interface
23: **
24: ** ServerApp Object
25: ** exposed interfaces:
26: ** IUnknown
27: **
28: ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
29: **
30: *************************************************************************/
31:
32:
33: #include "outline.h"
34: #include <regdb.h>
35: #include <enumfetc.h>
36: #include <geticon.h>
37:
38: OLEDBGDATA
39:
40: extern LPOUTLINEAPP g_lpApp;
41: extern IOleObjectVtbl g_SvrDoc_OleObjectVtbl;
42: extern IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl;
43:
44: #if defined( INPLACE_SVR )
45: extern IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl;
46: extern IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl;
47: #endif // INPLACE_SVR
48:
49: #if defined( SVR_TREATAS )
50: extern IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl;
51: #endif // SVR_TREATAS
52:
53:
54: // REVIEW: should use string resource for messages
55: extern char ErrMsgSaving[];
56: extern char ErrMsgFormatNotSupported[];
57: static char ErrMsgPSSaveFail[] = "PSSave failed";
58: extern char g_szUpdateCntrDoc[] = "&Update %s";
59: extern char g_szExitNReturnToCntrDoc[] = "E&xit && Return to %s";
60:
61:
62: /*************************************************************************
63: ** ServerDoc::IOleObject interface implementation
64: *************************************************************************/
65:
66: // IOleObject::QueryInterface method
67:
68: STDMETHODIMP SvrDoc_OleObj_QueryInterface(
69: LPOLEOBJECT lpThis,
70: REFIID riid,
71: LPVOID FAR* lplpvObj
72: )
73: {
74: LPSERVERDOC lpServerDoc =
75: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
76:
77: return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj);
78: }
79:
80:
81: // IOleObject::AddRef method
82:
83: STDMETHODIMP_(ULONG) SvrDoc_OleObj_AddRef(LPOLEOBJECT lpThis)
84: {
85: LPSERVERDOC lpServerDoc =
86: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
87:
88: OleDbgAddRefMethod(lpThis, "IOleObject");
89:
90: return OleDoc_AddRef((LPOLEDOC)lpServerDoc);
91: }
92:
93:
94: // IOleObject::Release method
95:
96: STDMETHODIMP_(ULONG) SvrDoc_OleObj_Release(LPOLEOBJECT lpThis)
97: {
98: LPSERVERDOC lpServerDoc =
99: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
100:
101: OleDbgReleaseMethod(lpThis, "IOleObject");
102:
103: return OleDoc_Release((LPOLEDOC)lpServerDoc);
104: }
105:
106:
107: // IOleObject::SetClientSite method
108:
109: STDMETHODIMP SvrDoc_OleObj_SetClientSite(
110: LPOLEOBJECT lpThis,
111: LPOLECLIENTSITE lpclientSite
112: )
113: {
114: LPSERVERDOC lpServerDoc =
115: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
116: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
117:
118: OLEDBG_BEGIN2("SvrDoc_OleObj_SetClientSite\r\n")
119:
120: // SetClientSite is only valid to call on an embedded object
121: if (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) {
122: OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED);
123: OLEDBG_END2
124: return ResultFromScode(E_UNEXPECTED);
125: }
126:
127: /* if we currently have a client site ptr, then release it. */
128: if (lpServerDoc->m_lpOleClientSite)
129: OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite);
130:
131: lpServerDoc->m_lpOleClientSite = (LPOLECLIENTSITE) lpclientSite;
132: // OLE2NOTE: to be able to hold onto clientSite pointer, we must AddRef it
133: if (lpclientSite)
134: lpclientSite->lpVtbl->AddRef(lpclientSite);
135:
136: OLEDBG_END2
137: return NOERROR;
138: }
139:
140:
141: // IOleObject::GetClientSite method
142:
143: STDMETHODIMP SvrDoc_OleObj_GetClientSite(
144: LPOLEOBJECT lpThis,
145: LPOLECLIENTSITE FAR* lplpClientSite
146: )
147: {
148: LPSERVERDOC lpServerDoc =
149: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
150:
151: OleDbgOut2("SvrDoc_OleObj_GetClientSite\r\n");
152:
153: /* OLE2NOTE: we MUST AddRef this interface pointer to give the
154: ** caller a personal copy of the pointer
155: */
156: lpServerDoc->m_lpOleClientSite->lpVtbl->AddRef(
157: lpServerDoc->m_lpOleClientSite
158: );
159: *lplpClientSite = lpServerDoc->m_lpOleClientSite;
160:
161: return NOERROR;
162:
163: }
164:
165:
166: // IOleObject::SetHostNames method
167:
168: STDMETHODIMP SvrDoc_OleObj_SetHostNames(
169: LPOLEOBJECT lpThis,
170: LPCSTR szContainerApp,
171: LPCSTR szContainerObj
172: )
173: {
174: LPSERVERDOC lpServerDoc =
175: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
176: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
177:
178: OleDbgOut2("SvrDoc_OleObj_SetHostNames\r\n");
179:
180: lstrcpy((LPSTR)lpServerDoc->m_szContainerApp, szContainerApp);
181: lstrcpy((LPSTR)lpServerDoc->m_szContainerObj, szContainerObj);
182:
183: /* The Window title for an embedded object is constructed as
184: ** follows:
185: ** <server app name> - <obj short type> in <cont. doc name>
186: **
187: ** here we construct the current document title portion of the
188: ** name which follows the '-'. OutlineDoc_SetTitle prepends the
189: ** "<server app name> - " to the document title.
190: */
191: // REVIEW: this string should be loaded from string resource
192: wsprintf(lpOutlineDoc->m_szFileName, "%s in %s",
193: (LPSTR)SHORTUSERTYPENAME, (LPSTR)lpServerDoc->m_szContainerObj);
194:
195: lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
196: OutlineDoc_SetTitle(lpOutlineDoc);
197:
198: /* OLE2NOTE: update the application menus correctly for an embedded
199: ** object. the changes include:
200: ** 1 Remove File/New and File/Open (SDI ONLY)
201: ** 2 Change File/Save As.. to File/Save Copy As..
202: ** 3 Change File menu so it contains "Update" instead of "Save"
203: ** 4 Change File/Exit to File/Exit & Return to <client doc>"
204: */
205: ServerDoc_UpdateMenu(lpServerDoc);
206:
207: return NOERROR;
208: }
209:
210:
211: // IOleObject::Close method
212:
213: STDMETHODIMP SvrDoc_OleObj_Close(
214: LPOLEOBJECT lpThis,
215: DWORD dwSaveOption
216: )
217: {
218: LPSERVERDOC lpServerDoc =
219: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
220: BOOL fStatus;
221:
222: OLEDBG_BEGIN2("SvrDoc_OleObj_Close\r\n")
223:
224: // REVIEW: dwSaveOption not yet supported
225:
226: /* OLE2NOTE: the OLE 2.0 user model is that embedded objects should
227: ** always be saved when closed WITHOUT any prompting to the
228: ** user. this is the recommendation irregardless of whether the
229: ** object is activated in-place or open in its own window.
230: ** this is a CHANGE from the OLE 1.0 user model where it
231: ** was the guideline that servers always prompt to save changes.
232: ** thus OLE 2.0 compound document oriented container's should
233: ** always pass dwSaveOption==OLECLOSE_SAVEIFDIRTY. it is
234: ** possible that for programmatic uses a container may want to
235: ** specify a different dwSaveOption. the implementation of
236: ** various save options can be tricky, particularly considering
237: ** cases involving in-place activation. the following would be
238: ** reasonable behavior:
239: **
240: ** (1) OLECLOSE_SAVEIFDIRTY: if dirty, save. close.
241: ** (2) OLECLOSE_NOSAVE: close.
242: ** (3) OLECLOSE_PROMPTSAVE:
243: ** (a) object visible, but not in-place:
244: ** if not dirty, close.
245: ** switch(prompt)
246: ** case IDYES: save. close.
247: ** case IDNO: close.
248: ** case IDCANCEL: return OLE_E_PROMPTSAVECANCELLED
249: ** (b) object invisible (includes UIDeactivated object)
250: ** if dirty, save. close.
251: ** NOTE: NO PROMPT. it is not appropriate to prompt
252: ** if the object is not visible.
253: ** (c) object is in-place active:
254: ** if dirty, save. close.
255: ** NOTE: NO PROMPT. it is not appropriate to prompt
256: ** if the object is active in-place.
257: */
258:
259: fStatus = OutlineDoc_Close((LPOUTLINEDOC)lpServerDoc, dwSaveOption);
260: OleDbgAssertSz(fStatus == TRUE, "SvrDoc_OleObj_Close failed\r\n");
261:
262: OLEDBG_END2
263: return (fStatus ? NOERROR : ResultFromScode(E_FAIL));
264: }
265:
266:
267: // IOleObject::SetMoniker method
268:
269: STDMETHODIMP SvrDoc_OleObj_SetMoniker(
270: LPOLEOBJECT lpThis,
271: DWORD dwWhichMoniker,
272: LPMONIKER lpmk
273: )
274: {
275: LPSERVERDOC lpServerDoc =
276: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
277: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
278: LPMONIKER lpmkFull;
279: HRESULT hrErr;
280: SCODE sc;
281:
282: OLEDBG_BEGIN2("SvrDoc_OleObj_SetMoniker\r\n")
283:
284: /* only our container should call IOleObject::SetMoniker. if we
285: ** don't have a ClientSite assigned then ignore this attempt to
286: ** set our moniker.
287: */
288: if (lpServerDoc->m_lpOleClientSite == NULL) {
289: sc = E_FAIL;
290: goto error;
291: }
292:
293: /* retrieve our full, absolute moniker from our container. the
294: ** moniker passed to the current method is either the relative
295: ** moniker of the object or the moniker of our container. we
296: ** require the full moniker in order to register as running.
297: */
298: hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->GetMoniker(
299: lpServerDoc->m_lpOleClientSite,
300: OLEGETMONIKER_ONLYIFTHERE,
301: OLEWHICHMK_OBJFULL,
302: &lpmkFull
303: );
304: if (hrErr != NOERROR) {
305: sc = GetScode(hrErr);
306: goto error;
307: }
308:
309: /* Register the document as running with the new moniker and
310: ** notify any clients that our moniker has changed.
311: */
312: OleDoc_DocRenamedUpdate(lpOleDoc, lpmkFull);
313:
314: if (lpmkFull)
315: OleStdRelease((LPUNKNOWN)lpmkFull);
316:
317: OLEDBG_END2
318: return NOERROR;
319:
320: error:
321: OLEDBG_END2
322: return ResultFromScode(sc);
323: }
324:
325:
326: // IOleObject::GetMoniker method
327:
328: STDMETHODIMP SvrDoc_OleObj_GetMoniker(
329: LPOLEOBJECT lpThis,
330: DWORD dwAssign,
331: DWORD dwWhichMoniker,
332: LPMONIKER FAR* lplpmk
333: )
334: {
335: LPSERVERDOC lpServerDoc =
336: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
337: HRESULT hrErr;
338: SCODE sc;
339:
340: OLEDBG_BEGIN2("SvrDoc_OleObj_GetMoniker\r\n")
341:
342: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
343: *lplpmk = NULL;
344:
345: if (lpServerDoc->m_lpOleClientSite != NULL) {
346: OleDbgAssert(((LPOUTLINEDOC)lpServerDoc)->m_docInitType==DOCTYPE_EMBEDDED);
347:
348: /* document is an embedded object. retrieve our moniker from
349: ** our container.
350: */
351: OLEDBG_BEGIN2("IOleClientSite::GetMoniker called\r\n")
352: hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->GetMoniker(
353: lpServerDoc->m_lpOleClientSite,
354: dwAssign,
355: dwWhichMoniker,
356: lplpmk
357: );
358: OLEDBG_END2
359:
360: } else if (((LPOUTLINEDOC)lpServerDoc)->m_docInitType == DOCTYPE_FROMFILE) {
361:
362: // document is a file-based document => return a FileMoniker
363: hrErr = CreateFileMoniker(
364: ((LPOUTLINEDOC)lpServerDoc)->m_szFileName,
365: lplpmk
366: );
367:
368: } else {
369: // document is either New or not yet fully initialized => no moniker
370: sc = E_FAIL;
371: goto error;
372: }
373:
374: OLEDBG_END2
375: return hrErr;
376:
377: error:
378: OLEDBG_END2
379: return ResultFromScode(sc);
380: }
381:
382:
383: // IOleObject::InitFromData method
384:
385: STDMETHODIMP SvrDoc_OleObj_InitFromData(
386: LPOLEOBJECT lpThis,
387: LPDATAOBJECT lpDataObject,
388: BOOL fCreation,
389: DWORD reserved
390: )
391: {
392: LPSERVERDOC lpServerDoc =
393: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
394:
395: OLEDBG_BEGIN2("SvrDoc_OleObj_InitFromData\r\n")
396:
397: // REVIEW: NOT YET IMPLEMENTED
398:
399: OLEDBG_END2
400: return ResultFromScode(E_NOTIMPL);
401: }
402:
403:
404: // IOleObject::GetClipboardData method
405:
406: STDMETHODIMP SvrDoc_OleObj_GetClipboardData(
407: LPOLEOBJECT lpThis,
408: DWORD reserved,
409: LPDATAOBJECT FAR* lplpDataObject
410: )
411: {
412: LPSERVERDOC lpServerDoc =
413: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
414:
415: OLEDBG_BEGIN2("SvrDoc_OleObj_GetClipboardData\r\n")
416:
417: // REVIEW: NOT YET IMPLEMENTED
418:
419: OLEDBG_END2
420: return ResultFromScode(E_NOTIMPL);
421: }
422:
423:
424: // IOleObject::DoVerb method
425:
426: STDMETHODIMP SvrDoc_OleObj_DoVerb(
427: LPOLEOBJECT lpThis,
428: LONG lVerb,
429: LPMSG lpmsg,
430: LPOLECLIENTSITE lpActiveSite,
431: LONG lindex,
432: HWND hwndParent,
433: LPCRECT lprcPosRect
434: )
435: {
436: LPSERVERDOC lpServerDoc =
437: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
438: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
439: SCODE sc = S_OK;
440:
441: OLEDBG_BEGIN2("SvrDoc_OleObj_DoVerb\r\n")
442:
443: switch (lVerb) {
444:
445: default:
446: /* OLE2NOTE: when an unknown verb number is given, the
447: ** server must take careful action:
448: ** 1. if it is one of the specially defined OLEIVERB
449: ** (negative numbered) verbs, the app should return an
450: ** error (E_NOTIMPL) and perform no action.
451: **
452: ** 2. if the verb is a application specific verb
453: ** (positive numbered verb), then the app should
454: ** return the special scode (OLEOBJ_S_INVALIDVERB). BUT,
455: ** we should still perform our normal primary verb action.
456: */
457: if (lVerb < 0) {
458: OLEDBG_END2
459: return ResultFromScode(E_NOTIMPL);
460: } else {
461: sc = OLEOBJ_S_INVALIDVERB;
462: }
463:
464: // deliberatly fall through to Primary Verb
465:
466: case 0:
467: case OLEIVERB_SHOW:
468:
469: #if defined( INPLACE_SVR )
470: /* OLE2NOTE: if our window is already open (visible) then
471: ** we should simply surface the open window. if not,
472: ** then we can do our primary action of in-place
473: ** activation.
474: */
475: if ( lpServerDoc->m_lpOleClientSite
476: && ! (IsWindowVisible(lpOutlineDoc->m_hWndDoc) &&
477: ! lpServerDoc->m_fInPlaceActive) ) {
478: ServerDoc_DoInPlaceActivate(
479: lpServerDoc, lVerb, lpmsg, lpActiveSite);
480: }
481: #endif // INPLACE_SVR
482:
483: OutlineDoc_ShowWindow(lpOutlineDoc);
484: break;
485:
486: case 1:
487: case OLEIVERB_OPEN:
488: #if defined( INPLACE_SVR )
489: ServerDoc_DoInPlaceDeactivate(lpServerDoc);
490: #endif // INPLACE_SVR
491: OutlineDoc_ShowWindow(lpOutlineDoc);
492: break;
493:
494:
495: case OLEIVERB_HIDE:
496: #if defined( INPLACE_SVR )
497: if (lpServerDoc->m_fInPlaceActive) {
498:
499: SvrDoc_IPObj_UIDeactivate(
500: (LPOLEINPLACEOBJECT)&lpServerDoc->m_OleInPlaceObject);
501:
502: #if defined( SVR_INSIDEOUT )
503: /* OLE2NOTE: an inside-out style in-place server will
504: ** NOT hide its window in UIDeactive (an outside-in
505: ** style object will hide its window in
506: ** UIDeactivate). thus we need to explicitly hide
507: ** our window now.
508: */
509: ServerDoc_DoInPlaceHide(lpServerDoc);
510: #endif // INSIEDOUT
511:
512: } else {
513: OleDoc_HideWindow((LPOLEDOC)lpServerDoc, FALSE /*fShutdown*/);
514: }
515: #endif // INPLACE_SVR
516: break;
517:
518: #if defined( INPLACE_SVR )
519: case OLEIVERB_UIACTIVATE:
520:
521: #if defined( SVR_INSIDEOUT )
522: /* OLE2NOTE: only an inside-out style object supports
523: ** INPLACEACTIVATE verb
524: */
525: case OLEIVERB_INPLACEACTIVATE:
526: #endif // INSIEDOUT
527: /* OLE2NOTE: if our window is already open (visible) then
528: ** we can NOT activate in-place.
529: */
530: if (IsWindowVisible(lpOutlineDoc->m_hWndDoc) &&
531: ! lpServerDoc->m_fInPlaceActive ) {
532: sc = OLE_E_NOT_INPLACEACTIVE;
533: } else {
534: sc = GetScode( ServerDoc_DoInPlaceActivate(
535: lpServerDoc, lVerb, lpmsg, lpActiveSite) );
536: if (SUCCEEDED(sc))
537: OutlineDoc_ShowWindow(lpOutlineDoc);
538: }
539: break;
540: #endif // INPLACE_SVR
541: }
542:
543: OLEDBG_END2
544: return ResultFromScode(sc);
545: }
546:
547:
548: // IOleObject::EnumVerbs method
549:
550: STDMETHODIMP SvrDoc_OleObj_EnumVerbs(
551: LPOLEOBJECT lpThis,
552: LPENUMOLEVERB FAR* lplpenumOleVerb
553: )
554: {
555: OleDbgOut2("SvrDoc_OleObj_EnumVerbs\r\n");
556:
557: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
558: *lplpenumOleVerb = NULL;
559:
560: // Tell OLE to enumerate our verbs using the REGDB
561: return ResultFromScode(OLE_S_USEREG);
562: }
563:
564:
565: // IOleObject::Update method
566:
567: STDMETHODIMP SvrDoc_OleObj_Update(LPOLEOBJECT lpThis)
568: {
569: OleDbgOut2("SvrDoc_OleObj_Update\r\n");
570:
571: /* OLE2NOTE: a server-only app is always "up-to-date".
572: ** a container-app which contains links where the link source
573: ** has changed since the last update of the link would be
574: ** considered "out-of-date". the "Update" method instructs the
575: ** object to get an update from any out-of-date links.
576: */
577:
578: return NOERROR;
579: }
580:
581:
582: // IOleObject::IsUpToDate method
583:
584: STDMETHODIMP SvrDoc_OleObj_IsUpToDate(LPOLEOBJECT lpThis)
585: {
586: OleDbgOut2("SvrDoc_OleObj_IsUpToDate\r\n");
587:
588: /* OLE2NOTE: a server-only app is always "up-to-date".
589: ** a container-app which contains links where the link source
590: ** has changed since the last update of the link would be
591: ** considered "out-of-date".
592: */
593: return NOERROR;
594: }
595:
596:
597: // IOleObject::GetUserClassID method
598:
599: STDMETHODIMP SvrDoc_OleObj_GetUserClassID(
600: LPOLEOBJECT lpThis,
601: LPCLSID lpClassID
602: )
603: {
604: LPSERVERDOC lpServerDoc =
605: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
606:
607: OleDbgOut2("SvrDoc_OleObj_GetClassID\r\n");
608:
609: /* OLE2NOTE: we must be carefull to return the correct CLSID here.
610: ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
611: ** operation then we need to return the class of the object
612: ** written in the storage of the object. otherwise we would
613: ** return our own class id.
614: */
615: return ServerDoc_GetClassID(lpServerDoc, lpClassID);
616: }
617:
618:
619: // IOleObject::GetUserType method
620:
621: STDMETHODIMP SvrDoc_OleObj_GetUserType(
622: LPOLEOBJECT lpThis,
623: DWORD dwFormOfType,
624: LPSTR FAR* lpszUserType
625: )
626: {
627: OleDbgOut2("SvrDoc_OleObj_GetUserType\r\n");
628:
629: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
630: *lpszUserType = NULL;
631:
632: // Tell OLE to enumerate our verbs using the REGDB
633: return ResultFromScode(OLE_S_USEREG);
634:
635: #if defined( LATER )
636: LPSERVERDOC lpServerDoc =
637: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
638:
639: /* OLE2NOTE: we must be carefull to return the correct UserType here.
640: ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
641: ** operation then we need to return the UserType of the object
642: ** written in the storage of the object. otherwise we would
643: ** return our own UserType.
644: */
645: return ServerDoc_GetUserType(lpServerDoc, dwFormOfType, lpszUserType);
646: #endif
647: }
648:
649:
650: // IOleObject::SetExtent method
651:
652: STDMETHODIMP SvrDoc_OleObj_SetExtent(
653: LPOLEOBJECT lpThis,
654: DWORD dwDrawAspect,
655: LPSIZEL lplgrc
656: )
657: {
658: OleDbgOut2("SvrDoc_OleObj_SetExtent\r\n");
659:
660: /* SVROUTL does NOT allow the object's size to be set by its
661: ** container. the size of the ServerDoc object is determined by
662: ** the data contained within the document.
663: */
664: return ResultFromScode(S_FALSE);
665: }
666:
667:
668: // IOleObject::GetExtent method
669:
670: STDMETHODIMP SvrDoc_OleObj_GetExtent(
671: LPOLEOBJECT lpThis,
672: DWORD dwDrawAspect,
673: LPSIZEL lpsizel
674: )
675: {
676: LPOLEDOC lpOleDoc =
677: (LPOLEDOC)((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
678:
679: OleDbgOut2("SvrDoc_OleObj_GetExtent\r\n");
680:
681: if (dwDrawAspect == DVASPECT_CONTENT
682: || dwDrawAspect == DVASPECT_THUMBNAIL
683: || dwDrawAspect == DVASPECT_DOCPRINT)
684: {
685: OleDoc_GetExtent(lpOleDoc, lpsizel);
686: return NOERROR;
687: }
688:
689: #if defined( LATER )
690:
691: else if (dwDrawAspect == DVASPECT_THUMBNAIL)
692: {
693: /* as our thumbnail we will render only the first page of the
694: ** document. calculate extents of our thumbnail rendering.
695: **
696: ** OLE2NOTE: thumbnails are most often used by applications in
697: ** FindFile or FileOpen type dialogs to give the user a
698: ** quick view of the contents of the file or object.
699: */
700: OleDoc_GetThumbnailExtent(lpOleDoc, lpsizel);
701: return NOERROR;
702: }
703: #endif
704:
705: else
706: {
707: return ResultFromScode(E_INVALIDARG);
708: }
709: }
710:
711:
712: // IOleObject::Advise method
713:
714: STDMETHODIMP SvrDoc_OleObj_Advise(
715: LPOLEOBJECT lpThis,
716: LPADVISESINK lpAdvSink,
717: LPDWORD lpdwConnection
718: )
719: {
720: LPSERVERDOC lpServerDoc =
721: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
722: HRESULT hrErr;
723: SCODE sc;
724:
725: OLEDBG_BEGIN2("SvrDoc_OleObj_Advise\r\n");
726:
727: if (lpServerDoc->m_lpOleAdviseHldr == NULL &&
728: CreateOleAdviseHolder(&lpServerDoc->m_lpOleAdviseHldr) != NOERROR) {
729: sc = E_OUTOFMEMORY;
730: goto error;
731: }
732:
733: OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n")
734: hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->Advise(
735: lpServerDoc->m_lpOleAdviseHldr,
736: lpAdvSink,
737: lpdwConnection
738: );
739: OLEDBG_END2
740:
741: OLEDBG_END2
742: return hrErr;
743:
744: error:
745: OLEDBG_END2
746: return ResultFromScode(sc);
747: }
748:
749:
750: // IOleObject::Unadvise method
751:
752: STDMETHODIMP SvrDoc_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection)
753: {
754: LPSERVERDOC lpServerDoc =
755: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
756: HRESULT hrErr;
757: SCODE sc;
758:
759: OLEDBG_BEGIN2("SvrDoc_OleObj_Unadvise\r\n");
760:
761: if (lpServerDoc->m_lpOleAdviseHldr == NULL) {
762: sc = E_FAIL;
763: goto error;
764: }
765:
766: OLEDBG_BEGIN2("IOleAdviseHolder::Unadvise called\r\n")
767: hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->Unadvise(
768: lpServerDoc->m_lpOleAdviseHldr,
769: dwConnection
770: );
771: OLEDBG_END2
772:
773: OLEDBG_END2
774: return hrErr;
775:
776: error:
777: OLEDBG_END2
778: return ResultFromScode(sc);
779: }
780:
781:
782: // IOleObject::EnumAdvise method
783:
784: STDMETHODIMP SvrDoc_OleObj_EnumAdvise(
785: LPOLEOBJECT lpThis,
786: LPENUMSTATDATA FAR* lplpenumAdvise
787: )
788: {
789: LPSERVERDOC lpServerDoc =
790: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
791: HRESULT hrErr;
792: SCODE sc;
793:
794: OLEDBG_BEGIN2("SvrDoc_OleObj_EnumAdvise\r\n");
795:
796: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
797: *lplpenumAdvise = NULL;
798:
799: if (lpServerDoc->m_lpOleAdviseHldr == NULL) {
800: sc = E_FAIL;
801: goto error;
802: }
803:
804: OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n")
805: hrErr = lpServerDoc->m_lpOleAdviseHldr->lpVtbl->EnumAdvise(
806: lpServerDoc->m_lpOleAdviseHldr,
807: lplpenumAdvise
808: );
809: OLEDBG_END2
810:
811: OLEDBG_END2
812: return hrErr;
813:
814: error:
815: OLEDBG_END2
816: return ResultFromScode(sc);
817: }
818:
819:
820: // IOleObject::GetMiscStatus method
821:
822: STDMETHODIMP SvrDoc_OleObj_GetMiscStatus(
823: LPOLEOBJECT lpThis,
824: DWORD dwAspect,
825: DWORD FAR* lpdwStatus
826: )
827: {
828: LPSERVERDOC lpServerDoc =
829: ((struct CDocOleObjectImpl FAR*)lpThis)->lpServerDoc;
830: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
831:
832: OleDbgOut2("SvrDoc_OleObj_GetMiscStatus\r\n");
833:
834: *lpdwStatus = 0;
835:
836: /* OLE2NOTE: check if the data copied is compatible to be
837: ** linked by an OLE 1.0 container. it is compatible if
838: ** either the data is an untitled document, a file, or a
839: ** selection of data within a file. if the data is part of
840: ** an embedded object, then it is NOT compatible to be
841: ** linked by an OLE 1.0 container. if it is compatible then
842: ** we must include OLEMISC_CANLINKBYOLE1 as part of the
843: ** dwStatus flags transfered via CF_OBJECTDESCRIPTOR or
844: ** CF_LINKSRCDESCRIPTOR.
845: */
846: if (lpOutlineDoc->m_docInitType == DOCTYPE_NEW ||
847: lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE)
848: *lpdwStatus |= OLEMISC_CANLINKBYOLE1;
849:
850: #if defined( INPLACE_SVR )
851: if (dwAspect == DVASPECT_CONTENT)
852: *lpdwStatus |= (OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE);
853: #endif // INPLACE_SVR
854:
855: return NOERROR;
856: }
857:
858:
859: // IOleObject::SetColorScheme method
860:
861: STDMETHODIMP SvrDoc_OleObj_SetColorScheme(
862: LPOLEOBJECT lpThis,
863: LPLOGPALETTE lpLogpal
864: )
865: {
866: OleDbgOut2("SvrDoc_OleObj_SetColorScheme\r\n");
867:
868: // REVIEW: NOT YET IMPLEMENTED
869:
870: return ResultFromScode(E_NOTIMPL);
871: }
872:
873:
874: /*************************************************************************
875: ** ServerDoc::IPersistStorage interface implementation
876: *************************************************************************/
877:
878: // IPersistStorage::QueryInterface method
879:
880: STDMETHODIMP SvrDoc_PStg_QueryInterface(
881: LPPERSISTSTORAGE lpThis,
882: REFIID riid,
883: LPVOID FAR* lplpvObj
884: )
885: {
886: LPSERVERDOC lpServerDoc =
887: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
888:
889: return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj);
890: }
891:
892:
893: // IPersistStorage::AddRef method
894:
895: STDMETHODIMP_(ULONG) SvrDoc_PStg_AddRef(LPPERSISTSTORAGE lpThis)
896: {
897: LPSERVERDOC lpServerDoc =
898: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
899:
900: OleDbgAddRefMethod(lpThis, "IPersistStorage");
901:
902: return OleDoc_AddRef((LPOLEDOC)lpServerDoc);
903: }
904:
905:
906: // IPersistStorage::Release method
907:
908: STDMETHODIMP_(ULONG) SvrDoc_PStg_Release(LPPERSISTSTORAGE lpThis)
909: {
910: LPSERVERDOC lpServerDoc =
911: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
912:
913: OleDbgReleaseMethod(lpThis, "IPersistStorage");
914:
915: return OleDoc_Release((LPOLEDOC)lpServerDoc);
916: }
917:
918:
919: // IPersistStorage::GetClassID method
920:
921: STDMETHODIMP SvrDoc_PStg_GetClassID(
922: LPPERSISTSTORAGE lpThis,
923: LPCLSID lpClassID
924: )
925: {
926: LPSERVERDOC lpServerDoc =
927: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
928:
929: OleDbgOut2("SvrDoc_PStg_GetClassID\r\n");
930:
931: /* OLE2NOTE: we must be carefull to return the correct CLSID here.
932: ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
933: ** operation then we need to return the class of the object
934: ** written in the storage of the object. otherwise we would
935: ** return our own class id.
936: */
937: return ServerDoc_GetClassID(lpServerDoc, lpClassID);
938: }
939:
940:
941: // IPersistStorage::IsDirty method
942:
943: STDMETHODIMP SvrDoc_PStg_IsDirty(LPPERSISTSTORAGE lpThis)
944: {
945: LPSERVERDOC lpServerDoc =
946: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
947:
948: OleDbgOut2("SvrDoc_PStg_IsDirty\r\n");
949:
950: if (OutlineDoc_IsModified((LPOUTLINEDOC)lpServerDoc))
951: return NOERROR;
952: else
953: return ResultFromScode(S_FALSE);
954: }
955:
956:
957:
958: // IPersistStorage::InitNew method
959:
960: STDMETHODIMP SvrDoc_PStg_InitNew(
961: LPPERSISTSTORAGE lpThis,
962: LPSTORAGE lpStg
963: )
964: {
965: LPSERVERDOC lpServerDoc =
966: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
967: SCODE sc;
968:
969: OLEDBG_BEGIN2("SvrDoc_PStg_InitNew\r\n")
970:
971: #if defined( SVR_TREATAS )
972: {
973: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
974: CLSID clsid;
975: CLIPFORMAT cfFmt;
976: LPSTR lpszType;
977:
978: /* OLE2NOTE: if the Server is capable of supporting "TreatAs"
979: ** (aka. ActivateAs), it must read the class that is written
980: ** into the storage. if this class is NOT the app's own
981: ** class ID, then this is a TreatAs operation. the server
982: ** then must faithfully pretend to be the class that is
983: ** written into the storage. it must also faithfully write
984: ** the data back to the storage in the SAME format as is
985: ** written in the storage.
986: **
987: ** SVROUTL and ISVROTL can emulate each other. they have the
988: ** simplification that they both read/write the identical
989: ** format. thus for these apps no actual conversion of the
990: ** native bits is actually required.
991: */
992: lpServerDoc->m_clsidTreatAs = CLSID_NULL;
993: if (OleStdGetTreatAsFmtUserType(&CLSID_APP, lpStg, &clsid,
994: (CLIPFORMAT FAR*)&cfFmt, (LPSTR FAR*)&lpszType)) {
995:
996: if (cfFmt == lpOutlineApp->m_cfOutline) {
997: // We should perform TreatAs operation
998: if (lpServerDoc->m_lpszTreatAsType)
999: OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL);
1000:
1001: lpServerDoc->m_clsidTreatAs = clsid;
1002: ((LPOUTLINEDOC)lpServerDoc)->m_cfSaveFormat = cfFmt;
1003: lpServerDoc->m_lpszTreatAsType = lpszType;
1004:
1005: OleDbgOut3("SvrDoc_PStg_InitNew: TreateAs ==> '");
1006: OleDbgOutNoPrefix3(lpServerDoc->m_lpszTreatAsType);
1007: OleDbgOutNoPrefix3("'\r\n");
1008: } else {
1009: // ERROR: we ONLY support TreatAs for CF_OUTLINE format
1010: OleDbgOut("SvrDoc_PStg_InitNew: INVALID TreatAs Format\r\n");
1011: OleStdFreeString(lpszType, NULL);
1012: }
1013: }
1014: }
1015: #endif // SVR_TREATAS
1016:
1017: // set the doc to a new embedded object.
1018: if (! ServerDoc_InitNewEmbed(lpServerDoc)) {
1019: sc = E_FAIL;
1020: goto error;
1021: }
1022:
1023: lpServerDoc->m_dwStorageMode = STGMODE_NORMAL;
1024:
1025: OLEDBG_END2
1026: return NOERROR;
1027:
1028: error:
1029: OLEDBG_END2
1030: return ResultFromScode(sc);
1031: }
1032:
1033:
1034: // IPersistStorage::Load method
1035:
1036: STDMETHODIMP SvrDoc_PStg_Load(
1037: LPPERSISTSTORAGE lpThis,
1038: LPSTORAGE lpStg
1039: )
1040: {
1041: LPSERVERDOC lpServerDoc =
1042: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
1043: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
1044: SCODE sc;
1045:
1046: OLEDBG_BEGIN2("SvrDoc_PStg_Load\r\n")
1047:
1048: if (OutlineDoc_LoadFromStg((LPOUTLINEDOC)lpServerDoc, lpStg)) {
1049:
1050: ((LPOUTLINEDOC)lpServerDoc)->m_docInitType = DOCTYPE_EMBEDDED;
1051:
1052: lpServerDoc->m_dwStorageMode = STGMODE_NORMAL;
1053:
1054: /* OLE2NOTE: we need to check if the ConvertStg bit is on. if
1055: ** so, we need to clear the ConvertStg bit and mark the
1056: ** document as dirty so as to force a save when the document
1057: ** is closed. the actual conversion of the bits should be
1058: ** performed when the data is loaded from the IStorage*. in
1059: ** our case any conversion of data formats would be done in
1060: ** OutlineDoc_LoadFromStg function. in reality both SVROUTL
1061: ** and ISVROTL read and write the same format so no actual
1062: ** conversion of data bits is necessary.
1063: */
1064: if (GetConvertStg(lpStg) == NOERROR) {
1065: SetConvertStg(lpStg, FALSE);
1066:
1067: OleDbgOut3("SvrDoc_PStg_Load: ConvertStg==TRUE\r\n");
1068: OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE);
1069: }
1070:
1071: } else {
1072: sc = E_FAIL;
1073: goto error;
1074: }
1075:
1076: OLEDBG_END2
1077: return NOERROR;
1078:
1079: error:
1080: OLEDBG_END2
1081: return ResultFromScode(sc);
1082: }
1083:
1084:
1085: // IPersistStorage::Save method
1086:
1087: STDMETHODIMP SvrDoc_PStg_Save(
1088: LPPERSISTSTORAGE lpThis,
1089: LPSTORAGE lpStg,
1090: BOOL fSameAsLoad
1091: )
1092: {
1093: LPSERVERDOC lpServerDoc =
1094: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
1095: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
1096: BOOL fStatus;
1097: SCODE sc;
1098:
1099: OLEDBG_BEGIN2("SvrDoc_PStg_Save\r\n")
1100:
1101: fStatus = OutlineDoc_SaveSelToStg(
1102: (LPOUTLINEDOC)lpServerDoc,
1103: NULL,
1104: lpOutlineDoc->m_cfSaveFormat,
1105: lpStg,
1106: FALSE
1107: );
1108:
1109: lpServerDoc->m_fSaveWithSameAsLoad = fSameAsLoad;
1110:
1111: if (! fStatus) {
1112: OutlineApp_ErrorMessage(g_lpApp, ErrMsgPSSaveFail);
1113: sc = E_FAIL;
1114: goto error;
1115: }
1116:
1117: lpServerDoc->m_dwStorageMode = STGMODE_NOSCRIBBLE;
1118: OLEDBG_END2
1119: return NOERROR;
1120:
1121: error:
1122: OLEDBG_END2
1123: return ResultFromScode(sc);
1124: }
1125:
1126:
1127:
1128: // IPersistStorage::SaveCompleted method
1129:
1130: STDMETHODIMP SvrDoc_PStg_SaveCompleted(
1131: LPPERSISTSTORAGE lpThis,
1132: LPSTORAGE lpStgNew
1133: )
1134: {
1135: LPSERVERDOC lpServerDoc =
1136: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
1137: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
1138:
1139: OLEDBG_BEGIN2("SvrDoc_PStg_SaveCompleted\r\n")
1140:
1141: /* OLE2NOTE: because we are a pure server that loads all data into
1142: ** memory, we do not hold on to our storage. thus we do not have
1143: ** to remember the storage passed into SaveCompleted.
1144: ** a container/server application must hold on to its storage
1145: ** however. any application that holds onto its storage must now
1146: ** remember the storage if one is passed in. in addition a
1147: ** container/server application would have to call SaveCompleted
1148: ** for each of its contained compound document objects. if a new
1149: ** storage was given, then the container/server would have to
1150: ** open the corresponding new sub-storage for each compound
1151: ** document object and pass as an argument in the SaveCompleted
1152: ** call.
1153: */
1154:
1155: lpServerDoc->m_dwStorageMode = STGMODE_NORMAL;
1156:
1157: /* OLE2NOTE: it is only legal to perform a Save or SaveAs operation
1158: ** on an embedded object. if the document is a file-based document
1159: ** then we can not be changed to a IStorage-base object.
1160: **
1161: ** fSameAsLoad lpStgNew Type of Save Send OnSave
1162: ** ---------------------------------------------------------
1163: ** TRUE NULL SAVE YES
1164: ** TRUE ! NULL SAVE * YES
1165: ** FALSE ! NULL SAVE AS YES
1166: ** FALSE NULL SAVE COPY AS NO
1167: **
1168: ** * this is a strange case that is possible. it is inefficient
1169: ** for the caller; it would be better to pass lpStgNew==NULL for
1170: ** the Save operation.
1171: */
1172: if ( ((lpServerDoc->m_fSaveWithSameAsLoad && lpStgNew==NULL) || lpStgNew)
1173: && (lpOutlineDoc->m_docInitType != DOCTYPE_EMBEDDED) ) {
1174: OLEDBG_END2
1175: return ResultFromScode(E_INVALIDARG);
1176: }
1177:
1178: /* OLE2NOTE: inform any linking clients that the document has been
1179: ** saved. in addition, any currently active pseudo objects
1180: ** should also inform their clients. we should only broadcast an
1181: ** OnSave notification if a Save or SaveAs operation was
1182: ** performed. we do NOT want to send the notification if a
1183: ** SaveCopyAs operation was performed.
1184: */
1185: if ((lpServerDoc->m_fSaveWithSameAsLoad && lpStgNew==NULL) || lpStgNew) {
1186:
1187: // Clear dirty flag upon save or saveAs
1188: OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
1189:
1190: ServerDoc_SendAdvise (
1191: lpServerDoc,
1192: OLE_ONSAVE,
1193: NULL, /* lpmkDoc -- not relevant here */
1194: 0 /* advf -- not relevant here */
1195: );
1196: }
1197: OLEDBG_END2
1198: return NOERROR;
1199: }
1200:
1201:
1202: // IPersistStorage::HandsOffStorage method
1203:
1204: STDMETHODIMP SvrDoc_PStg_HandsOffStorage(LPPERSISTSTORAGE lpThis)
1205: {
1206: LPSERVERDOC lpServerDoc =
1207: ((struct CDocPersistStorageImpl FAR*)lpThis)->lpServerDoc;
1208:
1209: OLEDBG_BEGIN2("SvrDoc_PStg_HandsOffStorage\r\n")
1210:
1211: /* OLE2NOTE: because we are a pure server that loads all data into
1212: ** memory, we do not hold on to our storage. thus we do not have
1213: ** a storage to release (ie. to enter HandsOff Mode).
1214: ** a container/server application must hold on to its storage
1215: ** however. any application that holds onto its storage must now
1216: ** release its storage. when SaveCompleted is called, then a new
1217: ** storage will be given.
1218: */
1219:
1220: lpServerDoc->m_dwStorageMode = STGMODE_HANDSOFF;
1221:
1222: OLEDBG_END2
1223: return NOERROR;
1224: }
1225:
1226:
1227:
1228: #if defined( SVR_TREATAS )
1229:
1230: /*************************************************************************
1231: ** ServerDoc::IStdMarshalInfo interface implementation
1232: *************************************************************************/
1233:
1234: // IStdMarshalInfo::QueryInterface method
1235:
1236: STDMETHODIMP SvrDoc_StdMshl_QueryInterface(
1237: LPSTDMARSHALINFO lpThis,
1238: REFIID riid,
1239: LPVOID FAR* lplpvObj
1240: )
1241: {
1242: LPSERVERDOC lpServerDoc =
1243: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc;
1244:
1245: return OleDoc_QueryInterface((LPOLEDOC)lpServerDoc, riid, lplpvObj);
1246: }
1247:
1248:
1249: // IStdMarshalInfo::AddRef method
1250:
1251: STDMETHODIMP_(ULONG) SvrDoc_StdMshl_AddRef(LPSTDMARSHALINFO lpThis)
1252: {
1253: LPSERVERDOC lpServerDoc =
1254: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc;
1255:
1256: OleDbgAddRefMethod(lpThis, "IStdMarshalInfo");
1257:
1258: return OleDoc_AddRef((LPOLEDOC)lpServerDoc);
1259: }
1260:
1261:
1262: // IStdMarshalInfo::Release method
1263:
1264: STDMETHODIMP_(ULONG) SvrDoc_StdMshl_Release(LPSTDMARSHALINFO lpThis)
1265: {
1266: LPSERVERDOC lpServerDoc =
1267: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc;
1268:
1269: OleDbgReleaseMethod(lpThis, "IStdMarshalInfo");
1270:
1271: return OleDoc_Release((LPOLEDOC)lpServerDoc);
1272: }
1273:
1274:
1275: // IStdMarshalInfo::GetClassForHandler
1276:
1277: STDMETHODIMP SvrDoc_StdMshl_GetClassForHandler(
1278: LPSTDMARSHALINFO lpThis,
1279: DWORD dwDestContext,
1280: LPVOID pvDestContext,
1281: LPCLSID lpClassID
1282: )
1283: {
1284: LPSERVERDOC lpServerDoc =
1285: ((struct CDocStdMarshalInfoImpl FAR*)lpThis)->lpServerDoc;
1286:
1287: OleDbgOut2("SvrDoc_StdMshl_GetClassForHandler\r\n");
1288:
1289: // OLE2NOTE: we only handle LOCAL marshal context.
1290: if (dwDestContext != MSHCTX_LOCAL || pvDestContext != NULL)
1291: return ResultFromScode(E_INVALIDARG);
1292:
1293: /* OLE2NOTE: we must return our REAL clsid, NOT the clsid that we
1294: ** are pretending to be if a "TreatAs" is in effect.
1295: */
1296: *lpClassID = CLSID_APP;
1297: return NOERROR;
1298: }
1299: #endif // SVR_TREATAS
1300:
1301:
1302:
1303: /*************************************************************************
1304: ** ServerDoc Support Functions
1305: *************************************************************************/
1306:
1307:
1308: /* ServerDoc_Init
1309: * --------------
1310: *
1311: * Initialize the fields of a new ServerDoc object. The object is initially
1312: * not associated with a file or an (Untitled) document. This function sets
1313: * the docInitType to DOCTYPE_UNKNOWN. After calling this function the
1314: * caller should call:
1315: * 1.) OutlineDoc_InitNewFile to set the ServerDoc to (Untitled)
1316: * 2.) OutlineDoc_LoadFromFile to associate the ServerDoc with a file.
1317: * This function creates a new window for the document.
1318: *
1319: * NOTE: the window is initially created with a NIL size. it must be
1320: * sized and positioned by the caller. also the document is initially
1321: * created invisible. the caller must call OutlineDoc_ShowWindow
1322: * after sizing it to make the document window visible.
1323: */
1324: BOOL ServerDoc_Init(LPSERVERDOC lpServerDoc, BOOL fDataTransferDoc)
1325: {
1326: lpServerDoc->m_cPseudoObj = 0;
1327: lpServerDoc->m_lpOleClientSite = NULL;
1328: lpServerDoc->m_lpOleAdviseHldr = NULL;
1329: lpServerDoc->m_lpDataAdviseHldr = NULL;
1330:
1331: // initialy doc does not have any storage
1332: lpServerDoc->m_dwStorageMode = STGMODE_HANDSOFF;
1333: lpServerDoc->m_fSaveWithSameAsLoad = FALSE;
1334: lpServerDoc->m_szContainerApp[0] = '\0';
1335: lpServerDoc->m_szContainerObj[0] = '\0';
1336: lpServerDoc->m_nNextRangeNo = 0L;
1337: lpServerDoc->m_lrSrcSelOfCopy.m_nStartLine = -1;
1338: lpServerDoc->m_lrSrcSelOfCopy.m_nEndLine = -1;
1339: lpServerDoc->m_fDataChanged = FALSE;
1340: lpServerDoc->m_fSizeChanged = FALSE;
1341: lpServerDoc->m_fSendDataOnStop = FALSE;
1342:
1343: #if defined( SVR_TREATAS )
1344: lpServerDoc->m_clsidTreatAs = CLSID_NULL;
1345: lpServerDoc->m_lpszTreatAsType = NULL;
1346: #endif // SVR_TREATAS
1347:
1348: #if defined( INPLACE_SVR )
1349: lpServerDoc->m_hWndHatch =
1350: CreateHatchWindow(
1351: OutlineApp_GetWindow(g_lpApp),
1352: OutlineApp_GetInstance(g_lpApp)
1353: );
1354: if (!lpServerDoc->m_hWndHatch)
1355: return FALSE;
1356:
1357: lpServerDoc->m_fInPlaceActive = FALSE;
1358: lpServerDoc->m_fInPlaceVisible = FALSE;
1359: lpServerDoc->m_fUIActive = FALSE;
1360: lpServerDoc->m_lpIPData = NULL;
1361:
1362: INIT_INTERFACEIMPL(
1363: &lpServerDoc->m_OleInPlaceObject,
1364: &g_SvrDoc_OleInPlaceObjectVtbl,
1365: lpServerDoc
1366: );
1367: INIT_INTERFACEIMPL(
1368: &lpServerDoc->m_OleInPlaceActiveObject,
1369: &g_SvrDoc_OleInPlaceActiveObjectVtbl,
1370: lpServerDoc
1371: );
1372: #endif // INPLACE_SVR
1373:
1374: INIT_INTERFACEIMPL(
1375: &lpServerDoc->m_OleObject,
1376: &g_SvrDoc_OleObjectVtbl,
1377: lpServerDoc
1378: );
1379:
1380: INIT_INTERFACEIMPL(
1381: &lpServerDoc->m_PersistStorage,
1382: &g_SvrDoc_PersistStorageVtbl,
1383: lpServerDoc
1384: );
1385:
1386: #if defined( SVR_TREATAS )
1387:
1388: INIT_INTERFACEIMPL(
1389: &lpServerDoc->m_StdMarshalInfo,
1390: &g_SvrDoc_StdMarshalInfoVtbl,
1391: lpServerDoc
1392: );
1393: #endif // SVR_TREATAS
1394: return TRUE;
1395: }
1396:
1397:
1398: /* ServerDoc_InitNewEmbed
1399: * ----------------------
1400: *
1401: * Initialize the ServerDoc object to be a new embedded object document.
1402: * This function sets the docInitType to DOCTYPE_EMBED.
1403: */
1404: BOOL ServerDoc_InitNewEmbed(LPSERVERDOC lpServerDoc)
1405: {
1406: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
1407:
1408: OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN);
1409:
1410: lpOutlineDoc->m_docInitType = DOCTYPE_EMBEDDED;
1411:
1412: /* The Window title for an embedded object is constructed as
1413: ** follows:
1414: ** <server app name> - <obj short type> in <cont. doc name>
1415: **
1416: ** here we construct the current document title portion of the
1417: ** name which follows the '-'. OutlineDoc_SetTitle prepends the
1418: ** "<server app name> - " to the document title.
1419: */
1420: // REVIEW: this string should be loaded from string resource
1421: wsprintf(lpOutlineDoc->m_szFileName, "%s in %s",
1422: (LPSTR)SHORTUSERTYPENAME,
1423: (LPSTR)DEFCONTAINERNAME);
1424: lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
1425:
1426:
1427: /* OLE2NOTE: an embedding should be marked as initially dirty so
1428: ** that on close we always call IOleClientSite::SaveObject.
1429: */
1430: OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE);
1431:
1432: OutlineDoc_SetTitle(lpOutlineDoc);
1433:
1434: return TRUE;
1435: }
1436:
1437:
1438: /* ServerDoc_SendAdvise
1439: * --------------------
1440: *
1441: * This function sends an advise notification on behalf of a specific
1442: * doc object to all its clients.
1443: */
1444: void ServerDoc_SendAdvise(
1445: LPSERVERDOC lpServerDoc,
1446: WORD wAdvise,
1447: LPMONIKER lpmkDoc,
1448: DWORD dwAdvf
1449: )
1450: {
1451: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
1452: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
1453:
1454: switch (wAdvise) {
1455:
1456: case OLE_ONDATACHANGE:
1457:
1458: // inform clients that the data of the object has changed
1459:
1460: if (lpOutlineDoc->m_nDisableDraw == 0) {
1461: /* drawing is currently enabled. inform clients that
1462: ** the data of the object has changed
1463: */
1464:
1465: lpServerDoc->m_fDataChanged = FALSE;
1466:
1467: if (lpServerDoc->m_lpDataAdviseHldr) {
1468: OLEDBG_BEGIN2(
1469: "IDataAdviseHolder::SendOnDataChange called\r\n"
1470: );
1471: lpServerDoc->m_lpDataAdviseHldr->lpVtbl->SendOnDataChange(
1472: lpServerDoc->m_lpDataAdviseHldr,
1473: (LPDATAOBJECT)&lpOleDoc->m_DataObject,
1474: 0,
1475: dwAdvf
1476: );
1477: OLEDBG_END2
1478:
1479: /* OLE2NOTE: we must note the time of last change
1480: ** for our object in the RunningObjectTable.
1481: ** this is used as the basis to answer
1482: ** IOleObject::IsUpToDate.
1483: */
1484: OleStdNoteObjectChangeTime(lpOleDoc->m_dwRegROT);
1485: }
1486:
1487: #if defined( INPLACE_SVR )
1488: /* OLE2NOTE: if the ServerDoc is currently in-place UI active,
1489: ** then is it important to renegotiate the size for the
1490: ** in-place document window BEFORE sending OnDataChange
1491: ** (which will cause the window to repaint).
1492: */
1493: if (lpServerDoc->m_fSizeChanged) {
1494: lpServerDoc->m_fSizeChanged = FALSE;
1495: if (lpServerDoc->m_fInPlaceActive)
1496: ServerDoc_UpdateInPlaceWindowOnExtentChange(lpServerDoc);
1497: }
1498: #endif
1499:
1500: /* OLE2NOTE: we do NOT need to tell our pseudo objects to
1501: ** broadcast OnDataChange notification because
1502: ** they will do it automatically when an editing
1503: ** change in the document affects a PseudoObj.
1504: ** (see OutlineNameTable_AddLineUpdate,
1505: ** OutlineNameTable_DeleteLineUpdate,
1506: ** and ServerNameTable_EditLineUpdate)
1507: */
1508:
1509: } else {
1510: /* drawing is currently disabled. do not send
1511: ** notifications or call
1512: ** IOleInPlaceObject::OnPosRectChange until drawing
1513: ** is re-enabled.
1514: */
1515: }
1516: break;
1517:
1518: case OLE_ONCLOSE:
1519:
1520: // inform clients that the document is shutting down
1521:
1522: if (lpServerDoc->m_lpOleAdviseHldr) {
1523: OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n");
1524: lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnClose(
1525: lpServerDoc->m_lpOleAdviseHldr
1526: );
1527: OLEDBG_END2
1528: }
1529:
1530: /* OLE2NOTE: we do NOT need to tell our pseudo objects to
1531: ** broadcast OnClose notification because they will do
1532: ** it automatically when the pseudo object is closed.
1533: ** (see PseudoObj_Close)
1534: */
1535:
1536: break;
1537:
1538: case OLE_ONSAVE:
1539:
1540: // inform clients that the object has been saved
1541:
1542: OLEDBG_BEGIN3("ServerDoc_SendAdvise ONSAVE\r\n");
1543:
1544: if (lpServerDoc->m_lpOleAdviseHldr) {
1545: OLEDBG_BEGIN2("IOleAdviseHolder::SendOnSave called\r\n");
1546: lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnSave(
1547: lpServerDoc->m_lpOleAdviseHldr
1548: );
1549: OLEDBG_END2
1550: }
1551:
1552: /* OLE2NOTE: inform any clients of pseudo objects
1553: ** within our document, that our document has been
1554: ** saved.
1555: */
1556: ServerNameTable_InformAllPseudoObjectsDocSaved(
1557: (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
1558: lpmkDoc
1559: );
1560:
1561:
1562: if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) {
1563: /* OLE2NOTE: we must note the time this File-Based
1564: ** object has been saved in the RunningObjectTable.
1565: ** These change times are used as the basis for
1566: ** IOleObject::IsUpToDate. It is important to set
1567: ** the time of the file-based object following a
1568: ** save operation to exactly the time of the saved
1569: ** file. this helps IOleObject::IsUpToDate to give
1570: ** the correct answer after a file has been saved.
1571: */
1572: OleStdNoteFileChangeTime(
1573: lpOutlineDoc->m_szFileName, lpOleDoc->m_dwRegROT);
1574: }
1575: OLEDBG_END3
1576: break;
1577:
1578: case OLE_ONRENAME:
1579:
1580: // inform clients that the object's name has changed
1581:
1582: OLEDBG_BEGIN3("ServerDoc_SendAdvise ONRENAME\r\n");
1583:
1584: if (lpmkDoc && lpServerDoc->m_lpOleAdviseHldr) {
1585: OLEDBG_BEGIN2("IOleAdviseHolder::SendOnRename called\r\n");
1586: lpServerDoc->m_lpOleAdviseHldr->lpVtbl->SendOnRename(
1587: lpServerDoc->m_lpOleAdviseHldr,
1588: lpmkDoc
1589: );
1590: OLEDBG_END2
1591: }
1592:
1593: /* OLE2NOTE: inform any clients of pseudo objects
1594: ** within our document, that our document's
1595: ** Moniker has changed.
1596: */
1597: ServerNameTable_InformAllPseudoObjectsDocRenamed(
1598: (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, lpmkDoc);
1599:
1600: OLEDBG_END3
1601: break;
1602: }
1603: }
1604:
1605:
1606: /* ServerDoc_GetClassID
1607: ** --------------------
1608: ** Return the class ID corresponding to the bits in the storage.
1609: ** normally this will be our application's given CLSID. but if a
1610: ** "TreateAs (aka. ActivateAs)" operation is taking place, then our
1611: ** application needs to pretend to be the class of the object that
1612: ** we are emulating. this is also the class that will be written
1613: ** into the storage.
1614: */
1615: HRESULT ServerDoc_GetClassID(LPSERVERDOC lpServerDoc, LPCLSID lpclsid)
1616: {
1617: #if defined( SVR_TREATAS )
1618: if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL))
1619: *lpclsid = lpServerDoc->m_clsidTreatAs;
1620: else
1621: #endif // SVR_TREATAS
1622: *lpclsid = CLSID_APP;
1623:
1624: return NOERROR;
1625: }
1626:
1627:
1628: #if defined( LATER )
1629:
1630: /* ServerDoc_GetUserType
1631: ** ---------------------
1632: ** Return the UserType corresponding to the bits in the storage.
1633: ** normally this will be our application's given UserType. but if a
1634: ** "TreateAs (aka. ActivateAs)" operation is taking place, then our
1635: ** application needs to pretend to be the UserType of the object that
1636: ** we are emulating. this is also the class that will be written
1637: ** into the storage.
1638: */
1639: HRESULT ServerDoc_GetUserType(LPSERVERDOC lpServerDoc, LPCLSID lpclsid)
1640: {
1641: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
1642: *lpszUserType = NULL;
1643:
1644: #if defined( SVR_TREATAS )
1645: if (lpServerDoc->m_clsidTreatAs != CLSID_NULL)
1646: return OleStdGetUserType(&lpServerDoc->m_clsidTreatAs);
1647: else
1648: #endif // SVR_TREATAS
1649: return OleStdGetUserType(&CLSID_APP);
1650: }
1651:
1652: #endif // LATER
1653:
1654:
1655: /* ServerDoc_UpdateMenu
1656: * --------------------
1657: *
1658: * Update menu for embedding mode. the changes include:
1659: * 1 Remove File/New and File/Open (SDI ONLY)
1660: * 2 Change File/Save As.. to File/Save Copy As..
1661: * 3 Change File menu so it contains "Update" instead of "Save"
1662: * 4 Change File/Exit to File/Exit & Return to <client doc>"
1663: */
1664: void ServerDoc_UpdateMenu(LPSERVERDOC lpServerDoc)
1665: {
1666: char str[256];
1667: HWND hWndMain;
1668: HMENU hMenu;
1669:
1670: OleDbgOut2("ServerDoc_UpdateMenu\r\n");
1671:
1672: hWndMain=g_lpApp->m_hWndApp;
1673: hMenu=GetMenu(hWndMain);
1674:
1675: #if defined( SDI_VERSION )
1676: /* SDI ONLY: Remove File/New and File/Open */
1677: DeleteMenu(hMenu, IDM_F_NEW, MF_BYCOMMAND);
1678: DeleteMenu(hMenu, IDM_F_OPEN, MF_BYCOMMAND);
1679: #endif
1680:
1681: // Change File.Save As.. to File.Save Copy As.. */
1682: ModifyMenu(hMenu,IDM_F_SAVEAS, MF_STRING, IDM_F_SAVEAS, "Save Copy As..");
1683:
1684: // Change File.Save to "&Update <container doc>"
1685: wsprintf(str, g_szUpdateCntrDoc, lpServerDoc->m_szContainerObj);
1686: ModifyMenu(hMenu, IDM_F_SAVE, MF_STRING, IDM_F_SAVE, str);
1687:
1688: // Change File/Exit to File/Exit & Return to <container doc>" */
1689: wsprintf(str, g_szExitNReturnToCntrDoc, lpServerDoc->m_szContainerObj);
1690: ModifyMenu(hMenu, IDM_F_EXIT, MF_STRING, IDM_F_EXIT, str);
1691:
1692: DrawMenuBar(hWndMain);
1693: }
1694:
1695: #if defined( MDI_VERSION )
1696:
1697: // NOTE: ServerDoc_RestoreMenu is actually redundant because the
1698: // app is dying when the function is called. (In SDI, the
1699: // app will terminate when the ref counter of the server doc
1700: // is zero). However, it is important for MDI.
1701:
1702: /* ServerDoc_RestoreMenu
1703: * ---------------------
1704: *
1705: * Reset the menu to non-embedding mode
1706: */
1707: void ServerDoc_RestoreMenu(LPSERVERDOC lpServerDoc)
1708: {
1709: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
1710: HWND hWndMain;
1711: HMENU hMenu;
1712:
1713: OleDbgOut2("ServerDoc_RestoreMenu\r\n");
1714:
1715: hWndMain = lpOutlineApp->m_hWndApp;
1716: hMenu = GetMenu(hWndMain);
1717:
1718: /* Add back File/New, File/Open.. and File/Save */
1719: InsertMenu(hMenu, IDM_F_SAVEAS, MF_BYCOMMAND | MF_ENABLED | MF_STRING,
1720: IDM_F_NEW, "&New");
1721: InsertMenu(hMenu, IDM_F_SAVEAS, MF_BYCOMMAND | MF_ENABLED | MF_STRING,
1722: IDM_F_OPEN, "&Open...");
1723:
1724: /* Change File menu so it contains "Save As..." instead of */
1725: /* "Save Copy As..." */
1726: ModifyMenu(hMenu, IDM_F_SAVEAS, MF_STRING, IDM_F_SAVEAS, "Save &As..");
1727:
1728: /* Change File menu so it contains "Save" instead of "Update" */
1729: ModifyMenu(hMenu, IDM_F_SAVE, MF_STRING, IDM_F_SAVE, "&Save");
1730:
1731: /* Change File menu so it contains "Exit" */
1732: /* instead of just "Exit & Return to <client doc>" */
1733: ModifyMenu(hMenu, IDM_F_EXIT, MF_STRING, IDM_F_EXIT, "E&xit");
1734:
1735: DrawMenuBar (hWndMain);
1736: }
1737:
1738: #endif // MDI_VERSION
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.