//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: api.cpp // // Contents: OLE2 api definitions. // // Classes: none // // Functions: OleRun // OleIsRunning // OleLockRunning // OleSetContainedObject // OleNoteObjectVisible // OleGetData // OleSetData // OleSave // ReadClassStg // WriteClassStg // WriteFmtUserTypeStg // ReadFmtUserTypeStg // ReadM1ClassStm (internal) // WriteM1ClassStm (internal) // ReadClassStm // WriteClassStm // ReleaseStgMedium // OleDuplicateData // ReadOleStg (internal) // WriteOleStg (internal) // GetDocumentBitStg (internal and unused) // GetConvertStg // SetConvertStg // ReadClipformatStm // WriteClipformatStm // WriteMonikerStm // ReadMonikerStm // OleDraw // CreateObjectDescriptor (internal (for now)) // // History: dd-mmm-yy Author Comment // 20-Feb-95 KentCe Buffer version of Read/WriteM1ClassStm. // 04-Jun-94 alexgo added CreateObjectDescriptor and // enhanced metafile support // 25-Jan-94 alexgo first pass at Cairo-style memory allocation // 11-Jan-94 chriswe fixed broken asserts // 11-Jan-94 alexgo added VDATEHEAP macros to every function // and fixed compile warnings // 08-Dec-93 ChrisWe added necessary casts to GlobalLock() calls // resulting from removing bogus GlobalLock() macros in // le2int.h // 21-Oct-93 Alex Gounares (alexgo) 32-bit port, commented // and substantial cleanup // (curts) 11/01/92 Added OleDuplicateMedium // (srinik) 06/22/92 Moved ReadStringStream, WriteStringStream // to "utstream.cpp" // (barrym) 06/02/92 Moved OleSave, ReadClassStg, // WriteClassStg, added // OleSaveCompleted, OleIsDirty // 28-May-92 Srini Koppolu (srinik) Original Author // //-------------------------------------------------------------------------- // REVIEW FINAL: probably want to change all pstm->Read into StRead(pstm...) // except if spec issue 313 is accepted in which case we change StRead into // pstm->Read. #include #pragma SEG(api) #define COMPOBJSTM_HEADER_SIZE 7 #ifndef _MAC FARINTERNAL_(HBITMAP) BmDuplicate(HBITMAP hold, DWORD FAR* lpdwSize, LPBITMAP lpBm); #endif NAME_SEG(Api) ASSERTDATA #define MAX_STR 512 #ifndef WIN32 // WIN16 uses remove() #include #endif DWORD gdwFirstDword = (DWORD)MAKELONG(COMPOBJ_STREAM_VERSION, BYTE_ORDER_INDICATOR); DWORD gdwOleVersion = MAKELONG(OLE_STREAM_VERSION, OLE_PRODUCT_VERSION); //+------------------------------------------------------------------------- // // Function: OleRun // // Synopsis: Calls IRunnableObject->Run on a given object // // Effects: Usually puts on object in the RunningObjectTable // // Arguments: [lpUnkown] -- Pointer to the object // // Requires: // // Returns: The HRESULT from the Run method. // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 21-Oct-93 alexgo ported to 32bit // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(OleRun) STDAPI OleRun(IUnknown FAR* lpUnknown) { OLETRACEIN((API_OleRun, PARAMFMT("lpUnknown= %p"), lpUnknown)); VDATEHEAP(); HRESULT hresult; IRunnableObject FAR* pRO; VDATEIFACE_LABEL(lpUnknown, errRtn, hresult); if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO) != NOERROR) { // if no IRunnableObject, assume already running hresult = NOERROR; goto errRtn; } hresult = pRO->Run(NULL); pRO->Release(); errRtn: OLETRACEOUT((API_OleRun, hresult)); return hresult; } //+------------------------------------------------------------------------- // // Function: OleIsRunning // // Synopsis: calls IRunnableObject->IsRunning on the given object // // Effects: Usually returns whether or not an object is in the // Running Object Table. // // Arguments: [lpOleObj] -- pointer to the object // // Requires: // // Returns: TRUE or FALSE (from IRO->IsRunning) // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 21-Oct-93 alexgo ported to 32bit // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(OleIsRunning) STDAPI_(BOOL) OleIsRunning(IOleObject FAR* lpOleObj) { OLETRACEIN((API_OleIsRunning, PARAMFMT("lpOleObj= %p"), lpOleObj)); VDATEHEAP(); IRunnableObject FAR* pRO; BOOL bRetval; GEN_VDATEIFACE_LABEL(lpOleObj, FALSE, errRtn, bRetval); if (lpOleObj->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO) != NOERROR) { // if no IRunnableObject, assume already running bRetval = TRUE; goto errRtn; } bRetval = pRO->IsRunning(); pRO->Release(); errRtn: OLETRACEOUTEX((API_OleIsRunning, RETURNFMT("%B"), bRetval)); return bRetval; } //+------------------------------------------------------------------------- // // Function: OleLockRunning // // Synopsis: calls IRunnableObject->LockRunning on the given object // // Effects: The object usually ends up calling CoLockObjectExternal // on itself // // Arguments: [lpUnknown] -- pointer to the object // [fLock] -- TRUE == lock running // FALSE == unlock running // [fLastUnlockCloses] -- if TRUE, IRO->LockRunning // is supposed to call IOO->Close // if this was the last unlock // // Requires: // // Returns: HRESULT from IRunnableObject->LockRunning() // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 21-Oct-93 alexgo 32bit port, changed GEN_VDATEIFACE // to VDATEIFACE to fix a bug // Notes: // //-------------------------------------------------------------------------- #pragma SEG(OleLockRunning) STDAPI OleLockRunning(LPUNKNOWN lpUnknown, BOOL fLock, BOOL fLastUnlockCloses) { OLETRACEIN((API_OleLockRunning, PARAMFMT("lpUnknown= %p, fLock= %B, fLastUnlockCloses= %B"), lpUnknown, fLock, fLastUnlockCloses)); VDATEHEAP(); IRunnableObject FAR* pRO; HRESULT hresult; VDATEIFACE_LABEL(lpUnknown, errRtn, hresult); if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO) != NOERROR) { // if no IRunnableObject, no locks hresult = NOERROR; goto errRtn; } hresult = pRO->LockRunning(fLock, fLastUnlockCloses); pRO->Release(); errRtn: OLETRACEOUT((API_OleLockRunning, hresult)); return hresult; } //+------------------------------------------------------------------------- // // Function: OleSetContainedObject // // Synopsis: calls IRunnableObject->SetContainedObject on the given object // // Effects: Usually has the effect of calling CoLockObjectExternal // (lpUnkown, !fContained, FALSE). // // Arguments: [lpUnknown] -- pointer to the object // [fContained] -- if TRUE, the object is an embedding // // Requires: // // Returns: HRESULT from the IRO->SetContainedObject call // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 21-Oct-92 alexgo 32bit port, changed GEN_VDATEIFACE to // VDATEIFACE to fix a bug // // Notes: Containers usually call OleSetContainedObject(..,TRUE) after // OleLoad or OleCreate. The basic idea is to tell OLE that // the object is an embedding. The real effect is to unlock // the object (since all objects start out locked) so that // other connections may determine it's fate while invisible. // OleNoteObjectVisible, for instance, would be called to lock // the object when it become visible. // // //-------------------------------------------------------------------------- #pragma SEG(OleSetContainedObject) STDAPI OleSetContainedObject(LPUNKNOWN lpUnknown, BOOL fContained) { OLETRACEIN((API_OleSetContainedObject, PARAMFMT("lpUnknown= %p, fContained= %B"), lpUnknown, fContained)); VDATEHEAP(); IRunnableObject FAR* pRO; HRESULT hresult; VDATEIFACE_LABEL(lpUnknown, errRtn, hresult); if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO) != NOERROR) { // if no IRunnableObject, assume container-ness doesn't matter hresult = NOERROR; goto errRtn; } hresult = pRO->SetContainedObject(fContained); pRO->Release(); errRtn: OLETRACEOUT((API_OleSetContainedObject, hresult)); return hresult; } //+------------------------------------------------------------------------- // // Function: OleNoteObjectVisible // // Synopsis: Simple calls CoLockObjectExternal // // Effects: // // Arguments: [lpUnknown] -- pointer to the object // [fVisible] -- if TRUE, then lock the object, // if false, then unlock // // Requires: // // Returns: HRESULT from CoLockObjectExternal // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 21-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(OleNoteObjectVisible) STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible) { OLETRACEIN((API_OleNoteObjectVisible, PARAMFMT("pUnknown= %p, fVisible= %B"), pUnknown, fVisible)); VDATEHEAP(); // NOTE: we as fLastUnlockReleases=TRUE here because there would // otherwise be no other way to fully release the stubmgr. This // means that objects can't use this mechanism to hold invisible // objects alive. HRESULT hr; hr = CoLockObjectExternal(pUnknown, fVisible, TRUE); OLETRACEOUT((API_OleNoteObjectVisible, hr)); return hr; } //+------------------------------------------------------------------------- // // Function: OleSave // // Synopsis: Writes the CLSID to the storage and calls IPersistStorage-> // Save() // // Effects: // // Arguments: [pPS] -- pointer to the IPersistStorage interface // on the object to be saved // [pstgSave] -- pointer to the storage to which the object // should be saved // [fSameAsLoad] -- FALSE indicates a SaveAs operation // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 22-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(OleSave) STDAPI OleSave( IPersistStorage FAR* pPS, IStorage FAR* pstgSave, BOOL fSameAsLoad ) { OLETRACEIN((API_OleSave, PARAMFMT("pPS= %p, pstgSave= %p, fSameAsLoad= %B"), pPS, pstgSave, fSameAsLoad)); VDATEHEAP(); HRESULT hresult; CLSID clsid; VDATEIFACE_LABEL(pPS, errRtn, hresult); VDATEIFACE_LABEL(pstgSave, errRtn, hresult); if (hresult = pPS->GetClassID(&clsid)) { goto errRtn; } if (hresult = WriteClassStg(pstgSave, clsid)) { goto errRtn; } if ((hresult = pPS->Save(pstgSave, fSameAsLoad)) == NOERROR) { hresult = pstgSave->Commit(0); } errRtn: OLETRACEOUT((API_OleSave, hresult)); return hresult; } //+------------------------------------------------------------------------- // // Function: ReadClassStg // // Synopsis: Calls IStorage->Stat to get the CLSID from the given storage // // Effects: // // Arguments: [pstg] -- pointer to the storage // [pclsid] -- place to return the CLSID // // Requires: // // Returns: HRESULT from the IS->Stat call // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 22-Oct-93 alexgo 32bit port, fixed bug with invalid // [pclsid] and error on IS->Stat // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(ReadClassStg) STDAPI ReadClassStg( IStorage FAR * pstg, LPCLSID pclsid) { OLETRACEIN((API_ReadClassStg, PARAMFMT("pstg= %p, pclsid= %p"), pstg, pclsid)); VDATEHEAP(); HRESULT hresult; STATSTG statstg; VDATEIFACE_LABEL(pstg, errRtn, hresult); VDATEPTROUT_LABEL(pclsid, CLSID, errRtn, hresult); if ((hresult = pstg->Stat(&statstg, STATFLAG_NONAME)) != NOERROR) { *pclsid = CLSID_NULL; goto errRtn; } *pclsid = statstg.clsid; errRtn: OLETRACEOUT((API_ReadClassStg, hresult)); return hresult; } //+------------------------------------------------------------------------- // // Function: WriteClassStg // // Synopsis: Calls IStorage->SetClass to store the CLSID in the given // storage // // Effects: // // Arguments: [pstg] -- pointer to the storage // [clsid] -- the CLSID to write into the storage // // Requires: // // Returns: HRESULT from the IS->SetClass call // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 22-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(WriteClassStg) STDAPI WriteClassStg( IStorage FAR * pstg, REFCLSID clsid) { OLETRACEIN((API_WriteClassStg, PARAMFMT("pstg= %p, clsid= %I"), pstg, &clsid)); VDATEHEAP(); HRESULT hr; VDATEIFACE_LABEL(pstg, errRtn, hr); // write clsid in storage (what is read above) hr = pstg->SetClass(clsid); errRtn: OLETRACEOUT((API_WriteClassStg, hr)); return hr; } //+------------------------------------------------------------------------- // // Function: ReadM1ClassStm // // Synopsis: Reads -1L, CLSID from the given stream // // Effects: // // Arguments: [pStm] -- pointer to the stream // [pclsid] -- where to put the clsid // // Requires: // // Returns: HRESULT from the ReadM1ClassStm. // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 24-Oct-93 alexgo 32bit port // 20-Feb-95 KentCe Convert to buffered stream reads. // // Notes: Internal API. // // Reads -1L and CLSID from stream swapping bytes on // big-endian machines // //-------------------------------------------------------------------------- STDAPI ReadM1ClassStm(LPSTREAM pStm, LPCLSID pclsid) { VDATEHEAP(); CStmBufRead StmRead; HRESULT error; StmRead.Init(pStm); error = ReadM1ClassStmBuf(StmRead, pclsid); if (error != NOERROR) *pclsid = CLSID_NULL; StmRead.Release(); return error; } //+------------------------------------------------------------------------- // // Function: WriteM1ClassStm // // Synopsis: Writes -1L, CLSID to the given stream // // Effects: // // Arguments: [pStm] -- pointer to the stream // [clsid] -- CLSID to be written // // Requires: // // Returns: HRESULT from the WriteM1ClassStm // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 11-Jan-84 alexgo changed dw from a DWORD to a LONG // 24-Oct-93 alexgo 32bit port // 20-Feb-95 KentCe Convert to buffered stream writes. // // Notes: Internal API. // // Writess -1L and CLSID from stream swapping bytes on // big-endian machines // //-------------------------------------------------------------------------- STDAPI WriteM1ClassStm(LPSTREAM pStm, REFCLSID clsid) { VDATEHEAP(); CStmBufWrite StmWrite; HRESULT error; VDATEIFACE( pStm ); StmWrite.Init(pStm); error = WriteM1ClassStmBuf(StmWrite, clsid); if (FAILED(error)) { goto errRtn; } error = StmWrite.Flush(); errRtn: StmWrite.Release(); return error; } //+------------------------------------------------------------------------- // // Function: ReadM1ClassStmBuf // // Synopsis: Reads -1L and CLSID from the given buffered stream. // // Arguments: [StmRead] -- Stream Read Object. // [pclsid] -- Where to put the clsid // // Returns: HRESULT from the StmRead.Read's // // // History: dd-mmm-yy Author Comment // 20-Feb-95 KentCe Convert to buffered stream reads. // 24-Oct-93 alexgo 32bit port // // Notes: Internal API. // // Reads -1L and CLSID from stream swapping bytes on // big-endian machines // //-------------------------------------------------------------------------- STDAPI ReadM1ClassStmBuf(CStmBufRead & StmRead, LPCLSID pclsid) { VDATEHEAP(); HRESULT error; LONG lValue; if ((error = StmRead.ReadLong(&lValue)) != NOERROR) { goto errRtn; } if (lValue == -1) { // have a GUID error = StmRead.Read((void FAR *)pclsid, sizeof(CLSID)); } else { // this is now an error; we don't allow string form // of clsid anymore error = ResultFromScode(E_UNSPEC); } errRtn: if (error != NOERROR) { *pclsid = CLSID_NULL; } return error; } //+------------------------------------------------------------------------- // // Function: WriteM1ClassStmBuf // // Synopsis: Writes -1L and CLSID to the given buffered stream. // // Arguments: [StmRead] -- Stream Write Object. // [pclsid] -- Where to read the clsid // // Returns: HRESULT from the StmWrite.Write's // // // History: dd-mmm-yy Author Comment // 20-Feb-95 KentCe Convert to buffered stream reads. // 24-Oct-93 alexgo 32bit port // // Notes: Internal API. // // Writess -1L and CLSID from stream swapping bytes on // big-endian machines // //-------------------------------------------------------------------------- STDAPI WriteM1ClassStmBuf(CStmBufWrite & StmWrite, REFCLSID clsid) { VDATEHEAP(); HRESULT error; // format is -1L followed by GUID if ((error = StmWrite.WriteLong(-1)) != NOERROR) return error; return StmWrite.Write((LPVOID)&clsid, sizeof(clsid)); } //+------------------------------------------------------------------------- // // Function: ReadClassStm // // Synopsis: Reads the CLSID from the given stream // // Effects: // // Arguments: [pStm] -- pointer to the stream // [pclsid] -- where to put the clsid // // Requires: // // Returns: HRESULT from the IStream->Read // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 24-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(ReadClassStm) // reads CLSID from stream swapping bytes on big-endian machines STDAPI ReadClassStm(LPSTREAM pStm, LPCLSID pclsid) { OLETRACEIN((API_ReadClassStm, PARAMFMT("pStm= %p, pclsid= %p"), pStm, pclsid)); VDATEHEAP(); HRESULT error; VDATEIFACE_LABEL( pStm, errRtn, error ); VDATEPTROUT_LABEL(pclsid, CLSID, errRtn, error); if ((error = StRead(pStm, (void FAR *)pclsid, sizeof(CLSID))) != NOERROR) *pclsid = CLSID_NULL; errRtn: OLETRACEOUT((API_ReadClassStm, error)); return error; } //+------------------------------------------------------------------------- // // Function: WriteClassStm // // Synopsis: Writes the class ID to the given stream // // Effects: // // Arguments: [pStm] -- pointer to the stream // [clsid] -- CLSID to write to the stream // // Requires: // // Returns: HRESULT from the IStream->Write call // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 24-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(WriteClassStm) // writes CLSID to stream swapping bytes on big-endian machines STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID clsid) { OLETRACEIN((API_WriteClassStm, PARAMFMT("pStm= %p, clsid= %I"), pStm, &clsid)); VDATEHEAP(); HRESULT hr; VDATEIFACE_LABEL( pStm, errRtn, hr); hr = pStm->Write(&clsid, sizeof(clsid), NULL); errRtn: OLETRACEOUT((API_WriteClassStm, hr)); return hr; } //+------------------------------------------------------------------------- // // Function: ReleaseStgMedium // // Synopsis: Releases any resources held by a storage medium // // Arguments: [pMedium] -- pointer to the storage medium // // Returns: nothing // // History: dd-mmm-yy Author Comment // 24-Oct-93 alexgo 32-bit port // 15-May-94 DavePl Added EMF support // //-------------------------------------------------------------------------- #pragma SEG(ReleaseStgMedium) STDAPI_(void) ReleaseStgMedium( LPSTGMEDIUM pMedium ) { OLETRACEIN((API_ReleaseStgMedium, PARAMFMT("pMedium= %p"), pMedium)); VDATEHEAP(); if (pMedium) { BOOL fPunkRel; //VDATEPTRIN rejects NULL VOID_VDATEPTRIN_LABEL( pMedium, STGMEDIUM, errRtn); fPunkRel = pMedium->pUnkForRelease != NULL; switch (pMedium->tymed) { case TYMED_HGLOBAL: if (pMedium->hGlobal != NULL && !fPunkRel) Verify(GlobalFree(pMedium->hGlobal) == 0); break; case TYMED_GDI: if (pMedium->hGlobal != NULL && !fPunkRel) DeleteObject(pMedium->hGlobal); break; case TYMED_ENHMF: if (pMedium->hEnhMetaFile != NULL && !fPunkRel) { Verify(DeleteEnhMetaFile(pMedium->hEnhMetaFile)); }; break; case TYMED_MFPICT: if (pMedium->hGlobal != NULL && !fPunkRel) { LPMETAFILEPICT pmfp; if ((pmfp = (LPMETAFILEPICT)GlobalLock(pMedium->hGlobal)) == NULL) break; DeleteMetaFile(pmfp->hMF); GlobalUnlock(pMedium->hGlobal); Verify(GlobalFree(pMedium->hGlobal) == 0); } break; case TYMED_FILE: if (pMedium->lpszFileName != NULL) { if (!IsValidPtrIn(pMedium->lpszFileName, 1)) break; if (!fPunkRel) { #ifdef WIN32 DeleteFile(pMedium->lpszFileName); #else #ifdef _MAC // the libraries are essentially small model on the MAC Verify(0==remove(pMedium->lpszFileName)); #else #ifdef OLD_AND_NICE_ASSEMBLER_VERSION // Win 3.1 specific code to call DOS to delete the file // given a far pointer to the file name extern void WINAPI DOS3Call(void); _asm { mov ah,41H push ds lds bx,pMedium lds dx,[bx].lpszFileName call DOS3Call pop ds } #else { OFSTRUCT of; OpenFile(pMedium->lpszFileName, &of, OF_DELETE); } #endif #endif #endif } // WARNING: there was a bug in the 16bit code that the filename // string was not being freed if pUnkForRelease was NULL. the // spec says it should delete the string, so we follow the spec // here. PubMemFree(pMedium->lpszFileName); pMedium->lpszFileName = NULL; } break; case TYMED_ISTREAM: if (pMedium->pstm != NULL && IsValidInterface(pMedium->pstm)) pMedium->pstm->Release(); break; case TYMED_ISTORAGE: if (pMedium->pstg != NULL && IsValidInterface(pMedium->pstg)) pMedium->pstg->Release(); break; case TYMED_NULL: break; default: AssertSz(FALSE, "Invalid medium in ReleaseStgMedium"); } if (pMedium->pUnkForRelease) { if (IsValidInterface(pMedium->pUnkForRelease)) pMedium->pUnkForRelease->Release(); pMedium->pUnkForRelease = NULL; } // NULL out to prevent unwanted use of just freed data. // Note: this must be done AFTER punkForRelease is called // because our special punkForRelease used in remoting // needs the tymed value. pMedium->tymed = TYMED_NULL; } errRtn: OLETRACEOUTEX((API_ReleaseStgMedium, NORETURN)); return; } #ifdef MAC_REVIEW This API must be written for MAC and PICT format. #endif //+------------------------------------------------------------------------- // // Function: OleDuplicateData // // Synopsis: Duplicates data from the given handle and clipboard format // // Effects: // // Arguments: [hSrc] -- handle to the data to be duplicated // [cfFormat] -- format of [hSrc] // [uiFlags] -- any flags (such a GMEM_MOVEABLE) for // memory allocation // // Requires: // // Returns: a HANDLE to the duplicated resource // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 30-May-94 alexgo added support for enhanced metafiles // 24-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(OleDuplicateData) STDAPI_(HANDLE) OleDuplicateData (HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags) { HANDLE hDup; OLETRACEIN((API_OleDuplicateData, PARAMFMT("hSrc= %h, cfFormat= %d, uiFlags= %x"), hSrc, cfFormat, uiFlags)); VDATEHEAP(); if (!hSrc) { hDup = NULL; goto errRtn; } switch( cfFormat ) { case CF_BITMAP: hDup = (HANDLE) BmDuplicate ((HBITMAP)hSrc, NULL, NULL); break; case CF_PALETTE: hDup = (HANDLE) UtDupPalette ((HPALETTE)hSrc); break; case CF_ENHMETAFILE: hDup = (HANDLE) CopyEnhMetaFile((HENHMETAFILE)hSrc, NULL); break; case CF_METAFILEPICT: if (uiFlags == NULL) { uiFlags = GMEM_MOVEABLE; } LPMETAFILEPICT lpmfpSrc; LPMETAFILEPICT lpmfpDst; if (!(lpmfpSrc = (LPMETAFILEPICT) GlobalLock (hSrc))) { hDup = NULL; goto errRtn; } if (!(hDup = UtDupGlobal (hSrc, uiFlags))) { GlobalUnlock(hSrc); hDup = NULL; goto errRtn; } if (!(lpmfpDst = (LPMETAFILEPICT) GlobalLock (hDup))) { GlobalUnlock(hSrc); GlobalFree (hDup); hDup = NULL; goto errRtn; } *lpmfpDst = *lpmfpSrc; lpmfpDst->hMF = CopyMetaFile (lpmfpSrc->hMF, NULL); GlobalUnlock (hSrc); GlobalUnlock (hDup); break; default: if (uiFlags == NULL) { uiFlags = GMEM_MOVEABLE; } hDup = UtDupGlobal (hSrc, uiFlags); } errRtn: OLETRACEOUTEX((API_OleDuplicateData, RETURNFMT("%h"), hDup)); return hDup; } //+------------------------------------------------------------------------- // // Function: BmDuplicate // // Synopsis: Duplicates a bitmap // // Effects: // // Arguments: [hold] -- the source bitmap // [lpdwSize] -- where to put the bitmap size // [lpBm] -- where to put the new bitmap // // Requires: // // Returns: A handle to the new bitmap // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 25-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(BmDuplicate) FARINTERNAL_(HBITMAP) BmDuplicate (HBITMAP hold, DWORD FAR* lpdwSize, LPBITMAP lpBm) { VDATEHEAP(); HBITMAP hnew = NULL; HANDLE hMem; LPVOID lpMem; DWORD dwSize; BITMAP bm; SIZE extents; extents.cx = extents.cy = 0; // REVIEW (davepl): The bitmap pointer here was being cast to LPOLESTR // for some reason. It's takes a void pointer! GetObject (hold, sizeof(BITMAP), &bm); dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) * ((DWORD) bm.bmPlanes); if (!(hMem = GlobalAlloc (GMEM_MOVEABLE, dwSize))) return NULL; if (!(lpMem = GlobalLock (hMem))) goto errRtn; GlobalUnlock (hMem); // REVIEW(davepl): This should probably use GetDIBits() instead GetBitmapBits (hold, dwSize, lpMem); if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel, NULL)) { if (!SetBitmapBits (hnew, dwSize, lpMem)) { DeleteObject (hnew); hnew = NULL; goto errRtn; } } if (lpdwSize) *lpdwSize = dwSize; if (lpBm) *lpBm = bm; if (hnew && GetBitmapDimensionEx(hold, &extents) && extents.cx && extents.cy) SetBitmapDimensionEx(hnew, extents.cx, extents.cy, NULL); errRtn: if (hMem) GlobalFree (hMem); return hnew; } //+------------------------------------------------------------------------- // // Function: ReadOleStg // // Synopsis: Internal API to read private OLE information from // the OLE_STREAM in the given storage // // Effects: // // Arguments: [pstg] -- pointer to the storage // [pdwFlags] -- where to put flags stored in the // the stream (may be NULL) // [pdwOptUpdate] -- where to put the update flags // (may be NULL) // [pdwReserved] -- where to put the reserved value // (may be NULL) // [ppmk] -- where to put the moniker // (may be NULL) // [ppstmOut] -- where to put the OLE_STREAM pointer // (may be NULL) // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(ReadOleStg) STDAPI ReadOleStg (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate, DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut) { OLETRACEIN((API_ReadOleStg, PARAMFMT("pdwFlags= %p, pdwOptUpdate= %p, pdwReserved= %p, ppmk= %p, ppstmOut= %p"), pdwFlags, pdwOptUpdate, pdwReserved, ppmk, ppstmOut)); VDATEHEAP(); HRESULT error; IStream FAR * pstm; DWORD dwBuf[4]; LPMONIKER pmk; LPOLESTR szClassName = OLE_STREAM; if (ppmk) { VDATEPTROUT_LABEL( ppmk, LPMONIKER, errNoFreeRtn, error); *ppmk = NULL; } if (ppstmOut){ VDATEPTROUT_LABEL( ppstmOut, LPSTREAM, errNoFreeRtn, error); *ppstmOut = NULL; } VDATEIFACE_LABEL( pstg, errNoFreeRtn, error); if ((error = pstg->OpenStream(szClassName, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstm)) != NOERROR) { // This error is OK for some callers (ex: default handler) // of this function. They depend on NOERROR or this error // code. So, don't change the error code. error = ReportResult(0, STG_E_FILENOTFOUND, 0, 0); goto errNoFreeRtn; } // read Ole version number, flags, Update options, reserved field if ((error = StRead (pstm, dwBuf, 4*sizeof(DWORD))) != NOERROR) goto errRtn; if (dwBuf[0] != gdwOleVersion) { error = ResultFromScode(DV_E_CLIPFORMAT); goto errRtn; } if (pdwFlags) *pdwFlags = dwBuf[1]; if (pdwOptUpdate) *pdwOptUpdate = dwBuf[2]; AssertSz(dwBuf[3] == NULL,"Reserved field in OLE STREAM is not NULL"); if (dwBuf[3] != NULL) { error = ResultFromScode(DV_E_CLIPFORMAT); goto errRtn; } if (pdwReserved) *pdwReserved = dwBuf[3]; if ((error = ReadMonikerStm (pstm, &pmk)) != NOERROR) goto errRtn; if (ppmk) *ppmk = pmk; else if (pmk) pmk->Release(); errRtn: if (pstm) { if ((error == NOERROR) && (ppstmOut != NULL)) *ppstmOut = pstm; else pstm->Release(); } errNoFreeRtn: OLETRACEOUT((API_ReadOleStg, error)); return error; } //+------------------------------------------------------------------------- // // Function: WriteOleStg // // Synopsis: Writes private OLE info into an OLE_STREAM in the given storage. // // Arguments: [pstg] [in] -- pointer to the storage // [pOleObj] [in] -- object from which to get info to write // (may be NULL) // [dwReserved] [in] -- reserved // [ppstmOut] [out] -- pointer to return the private stream // (may be NULL) // Returns: HRESULT // // History: dd-mmm-yy Author Comment // Oct 27, 93 alexgo 32bit port // Oct 23, 96 gopalk Changed to call WriteOleStgEx // //-------------------------------------------------------------------------- #pragma SEG(WriteOleStg) STDAPI WriteOleStg(LPSTORAGE pstg, IOleObject* pOleObj, DWORD dwReserved, LPSTREAM* ppstmOut) { OLETRACEIN((API_WriteOleStg, PARAMFMT("pstg=%p, pOleObj=%p, dwReserved=%x, ppstmOut=%p, "), pstg, pOleObj, dwReserved, ppstmOut)); // Local variable HRESULT error; do { // Validation Checks VDATEHEAP(); if(ppstmOut && !IsValidPtrOut(ppstmOut, sizeof(LPSTREAM))) { error = ResultFromScode(E_INVALIDARG); break; } if(!IsValidInterface(pstg)) { error = ResultFromScode(E_INVALIDARG); break; } if(pOleObj && !IsValidInterface(pOleObj)) { error = ResultFromScode(E_INVALIDARG); break; } // Call WriteOleStgEx error = WriteOleStgEx(pstg, pOleObj, dwReserved, 0, ppstmOut); } while(FALSE); OLETRACEOUT((API_WriteOleStg, error)); return error; } //+------------------------------------------------------------------------- // // Function: WriteOleStgEx (Internal) // // Synopsis: Writes private OLE info into an OLE_STREAM in the given storage. // // Arguments: [pstg] [in] -- pointer to the storage // [pOleObj] [in] -- object from which to get info to write // (may be NULL) // [dwReserved] [in] -- reserved // [ppstmOut] [out] -- pointer to return the private stream // (may be NULL) // [dwGivenFlags] [in] -- Additional object flags to be set // // Returns: HRESULT // // History: dd-mmm-yy Author Comment // Oct 23, 96 gopalk Creation // //-------------------------------------------------------------------------- STDAPI WriteOleStgEx(LPSTORAGE pstg, IOleObject* pOleObj, DWORD dwReserved, DWORD dwGivenFlags, LPSTREAM* ppstmOut) { // Local Variables HRESULT error = NOERROR; IStream* pstm = NULL; IOleLink* pLink; LPMONIKER pmk; DWORD dwUpdOpt; ULONG cbRead; DWORD objflags; ULARGE_INTEGER ularge_integer; LARGE_INTEGER large_integer; // Initialize out parameter if(ppstmOut) *ppstmOut = NULL; // Open or Create OLE_STREAM error = OpenOrCreateStream(pstg, OLE_STREAM, &pstm); if(error == NOERROR) { // Write Ole version error = pstm->Write(&gdwOleVersion, sizeof(DWORD), NULL); if(error == NOERROR) { // Read existing Objflags to preserve doc bit if(pstm->Read(&objflags, sizeof(DWORD), &cbRead) != NOERROR || cbRead != sizeof(DWORD)) objflags = 0; // Only preserve docbit objflags &= OBJFLAGS_DOCUMENT; // Set the given flags objflags |= dwGivenFlags; // Obtain link update options dwUpdOpt = 0L; if(pOleObj != NULL && pOleObj->QueryInterface(IID_IOleLink, (void **)&pLink) == NOERROR) { objflags |= OBJFLAGS_LINK; pLink->GetUpdateOptions(&dwUpdOpt); pLink->Release(); } // Seek to the Objflags field. We could be off due to the above read LISet32(large_integer, sizeof(DWORD)); error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL); if(error == NOERROR) { // Write Objflags and link update options DWORD dwBuf[3]; dwBuf[0] = objflags; dwBuf[1] = dwUpdOpt; Win4Assert(dwReserved == NULL); dwBuf[2] = 0L; error = pstm->Write(dwBuf, 3*sizeof(DWORD), NULL); if(error == NOERROR) { // Obtain object moniker pmk = NULL; if(pOleObj != NULL) { error = pOleObj->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJREL, &pmk); if(SUCCEEDED(error) && !IsValidInterface(pmk)) { Win4Assert(FALSE); pmk = NULL; } else if(FAILED(error) && pmk) { Win4Assert(FALSE); if(!IsValidInterface(pmk)) pmk = NULL; } // Write Object moniker error = WriteMonikerStm(pstm, pmk); if(pmk) pmk->Release(); // Truncate the stream to remove any existing data if(error == NOERROR) { LISet32(large_integer, 0); error = pstm->Seek(large_integer, STREAM_SEEK_CUR, &ularge_integer); if(error == NOERROR) pstm->SetSize(ularge_integer); } } } } } if(error==NOERROR && ppstmOut) *ppstmOut = pstm; else pstm->Release(); } return error; } //+------------------------------------------------------------------------- // // Function: SetBitOleStg // // Synopsis: internal function to write private OLE info into // OLE_STREAM on the given storage // // Effects: // // Arguments: [pstg] -- pointer to the storage // [mask] -- mask for old values // [value] -- values to write // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: writes (old_values & mask ) | value into the stream // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32-bit port, fixed bugs // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(SetBitOleStg) static INTERNAL SetBitOleStg(LPSTORAGE pstg, DWORD mask, DWORD value) { VDATEHEAP(); IStream FAR * pstm = NULL; HRESULT error; DWORD objflags = 0; LARGE_INTEGER large_integer; VDATEIFACE( pstg ); if (error = pstg->OpenStream(OLE_STREAM, NULL, STGM_SALL, 0, &pstm)) { if (STG_E_FILENOTFOUND != GetScode(error)) goto errRtn; if ((error = pstg->CreateStream(OLE_STREAM, STGM_SALL, 0, 0, &pstm)) != NOERROR) goto errRtn; DWORD dwBuf[5]; dwBuf[0] = gdwOleVersion; dwBuf[1] = objflags; dwBuf[2] = 0L; dwBuf[3] = 0L; dwBuf[4] = 0L; if ((error = pstm->Write(dwBuf, 5*sizeof(DWORD), NULL)) != NOERROR) goto errRtn; } // seek directly to word, read, modify, seek back and write. LISet32( large_integer, sizeof(DWORD) ); if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR) goto errRtn; if ((error = StRead(pstm, &objflags, sizeof(objflags))) != NOERROR) goto errRtn; objflags = (objflags & mask) | value; LISet32( large_integer, sizeof(DWORD) ); if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR) goto errRtn; error = pstm->Write(&objflags, sizeof(DWORD), NULL); errRtn:// close and return error code. if (pstm) pstm->Release(); return error; } //+------------------------------------------------------------------------- // // Function: GetFlagsOleStg // // Synopsis: Internal function to get the private ole flags from a // given storage // // Effects: // // Arguments: [pstg] -- pointer to the storage // [lpobjflags] -- where to put the flags // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port, fixed bugs (error return) // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(GetFlagsOleStg) static INTERNAL GetFlagsOleStg(LPSTORAGE pstg, LPDWORD lpobjflags) { VDATEHEAP(); IStream FAR * pstm = NULL; HRESULT error; LARGE_INTEGER large_integer; VDATEIFACE( pstg ); if ((error = pstg->OpenStream(OLE_STREAM, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstm)) != NOERROR) goto errRtn; // seek directly to word, read, modify, seek back and write. LISet32( large_integer, sizeof(DWORD) ); if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR) goto errRtn; error = StRead(pstm, lpobjflags, sizeof(*lpobjflags)); errRtn: if (pstm) pstm->Release(); return error; } //+------------------------------------------------------------------------- // // Function: GetDocumentBitStg // // Synopsis: returns the doc bit from the given storage // // Effects: // // Arguments: [pStg] -- pointer to the storage // // Requires: // // Returns: NOERROR if the doc bit is set, S_FALSE if not // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port // // Notes: // REVIEW32:: Nobody seems to use this function. Nuke it. // //-------------------------------------------------------------------------- #pragma SEG(GetDocumentBitStg) // get doc bit; return NOERROR if on; S_FALSE if off STDAPI GetDocumentBitStg(LPSTORAGE pStg) { OLETRACEIN((API_GetDocumentBitStg, PARAMFMT("pStg= %p"), pStg)); VDATEHEAP(); DWORD objflags; HRESULT error; if ((error = GetFlagsOleStg(pStg, &objflags)) == NOERROR) { if(!(objflags&OBJFLAGS_DOCUMENT)) { error = ResultFromScode(S_FALSE); } } OLETRACEOUT((API_GetDocumentBitStg, error)); return error; } //+------------------------------------------------------------------------- // // Function: SetDocumentBitStg // // Synopsis: Writes the document bit to the given storage // // Effects: // // Arguments: [pStg] -- pointer to the storage // [fDocument] -- TRUE, storage is a document, false // otherwise // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32-bit port // // Notes: // REVIEW32: nobody seems to use this function, nuke it // //-------------------------------------------------------------------------- #pragma SEG(SetDocumentBitStg) // set doc bit according to fDocument STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument) { OLETRACEIN((API_SetDocumentBitStg, PARAMFMT("pStg= %p, fDocument= %B"), pStg, fDocument)); VDATEHEAP(); HRESULT hr; hr = SetBitOleStg(pStg, fDocument ? -1L : ~OBJFLAGS_DOCUMENT, fDocument ? OBJFLAGS_DOCUMENT : 0); OLETRACEOUT((API_SetDocumentBitStg, hr)); return hr; } //+------------------------------------------------------------------------- // // Function: GetConvertStg // // Synopsis: Gets the convert bit from the given storage // // Effects: // // Arguments: [pStg] -- pointer to the storage // // Requires: // // Returns: NOERROR if set, S_FALSE if not // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(GetConvertStg) STDAPI GetConvertStg(LPSTORAGE pStg) { OLETRACEIN((API_GetConvertStg, PARAMFMT("pStg= %p"), pStg)); VDATEHEAP(); DWORD objflags; HRESULT error; if ((error = GetFlagsOleStg(pStg, &objflags)) != NOERROR) { goto errRtn; } if (objflags&OBJFLAGS_CONVERT) { error = NOERROR; } else { error = ResultFromScode(S_FALSE); } errRtn: OLETRACEOUT((API_GetConvertStg, error)); return error; } //+------------------------------------------------------------------------- // // Function: SetConvertStg // // Synopsis: Sets the convert bit in a storage // // Effects: // // Arguments: [pStg] -- pointer to the storage // [fConvert] -- convert bit // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(SetConvertStg) STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert) { OLETRACEIN((API_SetConvertStg, PARAMFMT("pStg= %p, fConvert= %B"), pStg, fConvert)); VDATEHEAP(); HRESULT hr; hr = SetBitOleStg(pStg, fConvert ? -1L : ~OBJFLAGS_CONVERT, fConvert ? OBJFLAGS_CONVERT : 0); OLETRACEOUT((API_SetConvertStg, hr)); return hr; } //+------------------------------------------------------------------------- // // Function: ReadClipformatStm // // Synopsis: Reads the clipboard format from the given stream // // Effects: If the clipboard format is a length followed by a // string, then the string is read and registered as a // clipboard format (and the new format number is returned). // // Arguments: [lpstream] -- pointer to the stream // [lpdwCf] -- where to put the clipboard format // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: the format of the stream must be one of the following: // 0 No clipboard format // -1 DWORD predefined windows clipboard format in // the second dword. // -2 DWORD predefined mac clipboard format in the // second dword. This may be obsolete or // irrelevant for us. REVIEW32 // num STRING clipboard format name string (prefaced // by length of string). // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port, fixed ifdef and NULL // pointer bugs // // 17-Mar-94 davepl Revereted to ANSI string reads // Notes: // //-------------------------------------------------------------------------- STDAPI ReadClipformatStm(LPSTREAM lpstream, DWORD FAR* lpdwCf) { VDATEHEAP(); HRESULT error; DWORD dwValue; VDATEIFACE(lpstream); VDATEPTROUT(lpdwCf, DWORD); if (error = StRead(lpstream, &dwValue, sizeof(DWORD))) { return error; } if (dwValue == NULL) { // NULL cf value *lpdwCf = NULL; } else if (dwValue == -1L) { // Then this is a NON-NULL predefined windows clipformat. // The clipformat values follows if (error = StRead(lpstream, &dwValue, sizeof(DWORD))) return error; *lpdwCf = dwValue; } else if (dwValue == -2L) { // Then this is a NON-NULL MAC clipboard format. // The clipformat value follows. For MAC the CLIPFORMAT // is 4 bytes if (error = StRead(lpstream, &dwValue, sizeof(DWORD))) { return error; } *lpdwCf = dwValue; return ResultFromScode(OLE_S_MAC_CLIPFORMAT); } else { char szACF[MAX_STR]; if (error = StRead(lpstream, szACF, dwValue)) { return error; } if (((*lpdwCf = (DWORD) SSRegisterClipboardFormatA(szACF))) == 0) { return ResultFromScode(DV_E_CLIPFORMAT); } } return NOERROR; } //+------------------------------------------------------------------------- // // Function: WriteClipformatStm // // Synopsis: Writes the clipboard format the given stream // // Arguments: [lpstream] -- pointer to the stream // [cf] -- the clipboard format // // Returns: HRESULT // // History: dd-mmm-yy Author Comment // 11-Jan-94 alexgo cast -1 to a DWORD to remove compile // warning // 27-Oct-93 alexgo 32bit port // 16-Mar-94 davepl Revereted to ANSI string writes // // Notes: see ReadClipformatStm for a description of the // data layout in the stream // //-------------------------------------------------------------------------- #pragma SEG(WriteClipformatStm) STDAPI WriteClipformatStm(LPSTREAM lpstream, CLIPFORMAT cf) { VDATEHEAP(); #ifdef _MAC AssertSz(0,"WriteClipformatStm NYI"); return ReportResult(0, E_NOTIMPL, 0, 0); #else HRESULT error; VDATEIFACE( lpstream ); //REVIEW32 where did 0xC000 come from??? Is this //portable to NT && Chicago??? Try to replace with a constant. //(although there don't seem to be any :( ) if (cf < 0xC000) { DWORD dwBuf[2]; DWORD dwSize = sizeof(DWORD); if (cf == NULL) { dwBuf[0] = NULL; } else { // write -1L, to indicate NON NULL predefined // clipboard format dwBuf[0] = (DWORD)-1L; dwBuf[1] = (DWORD)cf; dwSize += sizeof(DWORD); } if (error = StWrite(lpstream, dwBuf, dwSize)) { return error; } } else { // it is a registerd clipboard format char szACF[MAX_STR]; ULONG len; // Get the name of the clipboard format len = SSGetClipboardFormatNameA(cf, szACF, sizeof(szACF)); if (0 == len) { return ResultFromScode(E_UNSPEC); } ++len; // Account for NULL terminator if (error = StWrite(lpstream, &len, sizeof(len))) { return error; } // Write it (plus terminator) to the stream if (error = StWrite(lpstream, szACF, len)) { return error; } } return NOERROR; #endif // _MAC } //+------------------------------------------------------------------------- // // Function: WriteMonikerStm // // Synopsis: Writes the persistent state of the given moniker to the // given stream. Internal // // Effects: // // Arguments: [pstm] -- pointer to the stream // [pmk] -- pointer to the moniker // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(WriteMonikerStm) // write size long followed by persistent moniker STDAPI WriteMonikerStm (LPSTREAM pstm, LPMONIKER pmk) { VDATEHEAP(); DWORD cb = NULL; ULARGE_INTEGER dwBegin; ULARGE_INTEGER dwEnd; HRESULT error; LARGE_INTEGER large_integer; VDATEIFACE( pstm ); if (pmk == NULL) return pstm->Write(&cb, sizeof(DWORD), NULL); else { VDATEIFACE( pmk ); // get the begining position LISet32( large_integer, 0 ); if ((error = pstm->Seek (large_integer, STREAM_SEEK_CUR, &dwBegin)) != NOERROR) return error; // skip the moniker size DWORD LISet32( large_integer, 4); if ((error = pstm->Seek (large_integer, STREAM_SEEK_CUR, NULL)) != NOERROR) return error; if ((error = OleSaveToStream (pmk, pstm)) != NOERROR) return error; // get the end position LISet32( large_integer, 0); if ((error = pstm->Seek (large_integer, STREAM_SEEK_CUR, &dwEnd)) != NOERROR) return error; // moniker data size cb = dwEnd.LowPart - dwBegin.LowPart; // seek to the begining position LISet32( large_integer, dwBegin.LowPart); if ((error = pstm->Seek (large_integer, STREAM_SEEK_SET,NULL)) != NOERROR) return error; // write moniker info size if ((error = pstm->Write(&cb, sizeof(DWORD), NULL)) != NOERROR) return error; // seek to the end position LISet32( large_integer, dwEnd.LowPart); return pstm->Seek (large_integer, STREAM_SEEK_SET, NULL); } } //+------------------------------------------------------------------------- // // Function: ReadMonikerStm // // Synopsis: Reads a moniker from the given stream (inverse of // WriteMonikerStm) // // Effects: // // Arguments: [pstm] -- pointer to the stream // [ppmk] -- where to put the moniker // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 27-Oct-93 alexgo 32bit port // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(ReadMonikerStm) // read size long followed by persistent moniker STDAPI ReadMonikerStm (LPSTREAM pstm, LPMONIKER FAR* ppmk) { VDATEHEAP(); HRESULT error; DWORD cb; VDATEPTROUT( ppmk, LPMONIKER ); *ppmk = NULL; VDATEIFACE( pstm ); if ((error = StRead (pstm, &cb, sizeof(DWORD))) != NOERROR) return error; if (cb == NULL) return NOERROR; return OleLoadFromStream (pstm, IID_IMoniker, (LPLPVOID) ppmk); } //+------------------------------------------------------------------------- // // Function: OleDraw // // Synopsis: Calls IViewObject->Draw on the given object // // Effects: Draws something on the screen :) // // Arguments: [lpUnk] -- pointer to the object // [dwAspect] -- aspect to draw (NORMAL, ICON, etc) // [hdcDraw] -- the device context to use // [lprcBounds] -- the rectangle in which to draw // // Requires: // // Returns: HRESULT // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 01-Apr-94 alexgo fixed usage of MAKELONG (only // for 16bit) // 27-Oct-93 alexgo 32bit port // // Notes: // On Win32, RECT and RECTL are identical structures, thus there // is no need to convert from RECT to RECTL with MAKELONG. // //-------------------------------------------------------------------------- #pragma SEG(OleDraw) STDAPI OleDraw (LPUNKNOWN lpUnk, DWORD dwAspect, HDC hdcDraw, LPCRECT lprcBounds) { HRESULT error; IViewObject FAR* lpView; #ifndef WIN32 RECTL rclBounds; #endif //!WIN32 OLETRACEIN((API_OleDraw, PARAMFMT("lpUnk= %p, dwAspect= %x, hdcDraw= %h, lprcBounds= %tr"), lpUnk, dwAspect, hdcDraw, lprcBounds)); VDATEHEAP(); VDATEIFACE_LABEL( lpUnk, errRtn, error ); VDATEPTRIN_LABEL( lprcBounds, RECT, errRtn, error); #ifndef WIN32 rclBounds.left = MAKELONG(lprcBounds->left, 0); rclBounds.right = MAKELONG(lprcBounds->right, 0); rclBounds.top = MAKELONG(lprcBounds->top, 0); rclBounds.bottom = MAKELONG(lprcBounds->bottom, 0); lprcBounds = &rclBounds; #endif //!WIN32 if ((error = lpUnk->QueryInterface (IID_IViewObject, (LPLPVOID)&lpView)) != NOERROR) { error = ResultFromScode(DV_E_NOIVIEWOBJECT); goto errRtn; } error = lpView->Draw (dwAspect, DEF_LINDEX, 0, 0, 0, hdcDraw, (LPCRECTL)lprcBounds, 0, 0,0); lpView->Release(); errRtn: OLETRACEOUT((API_OleDraw, error)); return error; } //+---------------------------------------------------------------------------- // // Function: // CreateObjectDescriptor, static // // Synopsis: // Creates and initializes an OBJECTDESCRIPTOR from the given // parameters // // Arguments: // [clsid] -- the class ID of the object being transferred // [dwAspect] -- the display aspect drawn by the source of the // transfer // [psizel] -- pointer to the size of the object // [ppointl] -- pointer to the mouse offset in the object that // initiated a drag-drop transfer // [dwStatus] -- the OLEMISC status flags for the object // being transferred // [lpszFullUserTypeName] -- the full user type name of the // object being transferred // [lpszSrcOfCopy] -- a human readable name for the object // being transferred // // Returns: // If successful, A handle to the new OBJECTDESCRIPTOR; otherwise // NULL. // // Notes: // REVIEW, this seems generally useful for anyone using the // clipboard, or drag-drop; perhaps it should be exported. // // History: // 12/07/93 - ChrisWe - file inspection and cleanup // //----------------------------------------------------------------------------- #pragma SEG(CreateObjectDescriptor) INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect, const SIZEL FAR *psizel, const POINTL FAR *ppointl, DWORD dwStatus, LPOLESTR lpszFullUserTypeName, LPOLESTR lpszSrcOfCopy) { VDATEHEAP(); DWORD dwFullUserTypeNameBLen; // length of lpszFullUserTypeName in BYTES DWORD dwSrcOfCopyBLen; // length of lpszSrcOfCopy in BYTES HGLOBAL hMem; // handle to the object descriptor LPOBJECTDESCRIPTOR lpOD; // the new object descriptor // Get the length of Full User Type Name; Add 1 for the null terminator if (!lpszFullUserTypeName) dwFullUserTypeNameBLen = 0; else dwFullUserTypeNameBLen = (_xstrlen(lpszFullUserTypeName) + 1) * sizeof(OLECHAR); // Get the Source of Copy string and it's length; Add 1 for the null // terminator if (lpszSrcOfCopy) dwSrcOfCopyBLen = (_xstrlen(lpszSrcOfCopy) + 1) * sizeof(OLECHAR); else { // No src moniker so use user type name as source string. lpszSrcOfCopy = lpszFullUserTypeName; dwSrcOfCopyBLen = dwFullUserTypeNameBLen; } // allocate the memory where we'll put the object descriptor hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen + dwSrcOfCopyBLen); if (hMem == NULL) goto error; lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem); if (lpOD == NULL) goto error; // Set the FullUserTypeName offset and copy the string if (!lpszFullUserTypeName) { // zero offset indicates that string is not present lpOD->dwFullUserTypeName = 0; } else { lpOD->dwFullUserTypeName = sizeof(OBJECTDESCRIPTOR); _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwFullUserTypeName, (const void FAR *)lpszFullUserTypeName, dwFullUserTypeNameBLen); } // Set the SrcOfCopy offset and copy the string if (!lpszSrcOfCopy) { // zero offset indicates that string is not present lpOD->dwSrcOfCopy = 0; } else { lpOD->dwSrcOfCopy = sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen; _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwSrcOfCopy, (const void FAR *)lpszSrcOfCopy, dwSrcOfCopyBLen); } // Initialize the rest of the OBJECTDESCRIPTOR lpOD->cbSize = sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen + dwSrcOfCopyBLen; lpOD->clsid = clsid; lpOD->dwDrawAspect = dwAspect; lpOD->sizel = *psizel; lpOD->pointl = *ppointl; lpOD->dwStatus = dwStatus; GlobalUnlock(hMem); return(hMem); error: if (hMem) { GlobalUnlock(hMem); GlobalFree(hMem); } return(NULL); }