398 lines
10 KiB
C
398 lines
10 KiB
C
|
/*---------------------------------------------------------------------------
|
|||
|
| PERS.C
|
|||
|
| This file has the IPersistStorage and IPersistfile interface implementation.
|
|||
|
|
|
|||
|
| Created By: Vij Rajarajan (VijR)
|
|||
|
+---------------------------------------------------------------------------*/
|
|||
|
#define SERVERONLY
|
|||
|
#include <Windows.h>
|
|||
|
#include "mpole.h"
|
|||
|
#include "mplayer.h"
|
|||
|
#define STRSAFE_NO_DEPRECATE
|
|||
|
#include <strsafe.h>
|
|||
|
|
|||
|
#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
*************** IPersistStorage INTERFACE IMPLEMENTATION.
|
|||
|
**************************************************************************/
|
|||
|
//delegate to the common IUnknown implementation.
|
|||
|
STDMETHODIMP PSQueryInterface(
|
|||
|
LPPERSISTSTORAGE lpPersStg, // persist storage object ptr
|
|||
|
REFIID riidReq, // IID required
|
|||
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|||
|
)
|
|||
|
{
|
|||
|
return UnkQueryInterface((LPUNKNOWN)lpPersStg, riidReq, lplpUnk);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) PSAddRef(
|
|||
|
LPPERSISTSTORAGE lpPersStg // persist storage object ptr
|
|||
|
)
|
|||
|
{
|
|||
|
return UnkAddRef((LPUNKNOWN) lpPersStg);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) PSRelease (
|
|||
|
LPPERSISTSTORAGE lpPersStg // persist storage object ptr
|
|||
|
)
|
|||
|
{
|
|||
|
return UnkRelease((LPUNKNOWN) lpPersStg);
|
|||
|
}
|
|||
|
|
|||
|
STDMETHODIMP PSGetClassID (
|
|||
|
LPPERSISTSTORAGE lpPersStg,
|
|||
|
CLSID FAR* pClsid
|
|||
|
)
|
|||
|
{
|
|||
|
DPF("PSGetClassID\n");
|
|||
|
|
|||
|
/* Return the actual class ID that gets stored:
|
|||
|
*/
|
|||
|
*pClsid = gClsIDOLE1Compat;
|
|||
|
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP PSIsDirty (
|
|||
|
LPPERSISTSTORAGE lpPersStg
|
|||
|
)
|
|||
|
{DPF("PSIsDirty\n");
|
|||
|
|
|||
|
RETURN_RESULT( (fDocChanged && !(gfPlayingInPlace || gfOle2IPPlaying))
|
|||
|
? S_OK : S_FALSE);
|
|||
|
}
|
|||
|
|
|||
|
STDMETHODIMP PSInitNew (
|
|||
|
LPPERSISTSTORAGE lpPersStg,
|
|||
|
LPSTORAGE lpStorage
|
|||
|
)
|
|||
|
{
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
* PSLoad:
|
|||
|
* The Load method reads the embedded data from the "\1Ole10Native"
|
|||
|
* stream of the IStorage passed as an argument. This is because
|
|||
|
* we always pretend to be an OLE1 server when transferring data.
|
|||
|
* ItemSetData is called with this embedded data to to run the required
|
|||
|
* object.
|
|||
|
**************************************************************************/
|
|||
|
STDMETHODIMP PSLoad (
|
|||
|
LPPERSISTSTORAGE lpPersStg,
|
|||
|
LPSTORAGE lpStorage
|
|||
|
)
|
|||
|
{
|
|||
|
LPDOC lpdoc;
|
|||
|
SCODE error;
|
|||
|
LPSTREAM pstm;
|
|||
|
ULONG cbRead;
|
|||
|
DWORD size = 0;
|
|||
|
HGLOBAL hNative = NULL;
|
|||
|
LPTSTR lpnative = NULL;
|
|||
|
|
|||
|
DPF("\nPSLoad is being called\n");
|
|||
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
|
|||
|
|
|||
|
error = GetScode(IStorage_OpenStream(lpStorage, sz1Ole10Native,
|
|||
|
NULL, STGM_SALL, 0, &pstm));
|
|||
|
if (error == S_OK)
|
|||
|
{
|
|||
|
error = GetScode(IStream_Read(pstm, &size, 4, &cbRead));
|
|||
|
}
|
|||
|
if (error == S_OK)
|
|||
|
{
|
|||
|
hNative = GlobalAlloc(GMEM_DDESHARE |GMEM_ZEROINIT, (LONG)size);
|
|||
|
if (hNative)
|
|||
|
lpdoc->native = GLOBALLOCK(hNative);
|
|||
|
}
|
|||
|
|
|||
|
if(lpdoc->native )
|
|||
|
{
|
|||
|
error = GetScode(IStream_Read(pstm, lpdoc->native, size, &cbRead));
|
|||
|
|
|||
|
if (cbRead != size) error = E_FAIL; // REVIEW SCODE stream size error
|
|||
|
IStream_Release(pstm);
|
|||
|
}
|
|||
|
else error = E_OUTOFMEMORY;
|
|||
|
|
|||
|
if (error == S_OK)
|
|||
|
{
|
|||
|
error = ItemSetData((LPBYTE)lpdoc->native);
|
|||
|
fDocChanged = FALSE;
|
|||
|
lpdoc->doctype = doctypeEmbedded;
|
|||
|
}
|
|||
|
|
|||
|
if(hNative)
|
|||
|
{
|
|||
|
GLOBALUNLOCK(hNative);
|
|||
|
GLOBALFREE(hNative);
|
|||
|
}
|
|||
|
|
|||
|
RETURN_RESULT( error);
|
|||
|
}
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
* PSSave:
|
|||
|
* The Save method saves the native data in "\1Ole10Native" stream.
|
|||
|
* This is because we always pretend to be an OLE1 server when transferring
|
|||
|
* data. This ensures backward compatibility. GetLink is called to get
|
|||
|
* the embedding data.
|
|||
|
**************************************************************************/
|
|||
|
STDMETHODIMP PSSave (
|
|||
|
LPPERSISTSTORAGE lpPersStg,
|
|||
|
LPSTORAGE lpStorage,
|
|||
|
BOOL fSameAsLoad
|
|||
|
)
|
|||
|
{
|
|||
|
LPDOC lpdoc;
|
|||
|
SCODE error;
|
|||
|
LPSTREAM pstm = NULL;
|
|||
|
ULONG cbWritten;
|
|||
|
DWORD_PTR size;
|
|||
|
HGLOBAL hNative = NULL;
|
|||
|
LPTSTR lpnative = NULL;
|
|||
|
LPWSTR lpszUserType;
|
|||
|
|
|||
|
DPF("* in pssave *");
|
|||
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
|
|||
|
|
|||
|
#if 0
|
|||
|
// Allow saves if we're playing so that broken links can be fixed.
|
|||
|
if (fSameAsLoad && (gfOle2IPPlaying || gfPlayingInPlace))
|
|||
|
RETURN_RESULT(S_OK);
|
|||
|
#endif
|
|||
|
|
|||
|
//Mark as OLE1 mplayer object.
|
|||
|
#ifndef UNICODE
|
|||
|
lpszUserType = AllocateUnicodeString(gachClassRoot);
|
|||
|
#else
|
|||
|
lpszUserType = gachClassRoot;
|
|||
|
#endif
|
|||
|
|
|||
|
error = GetScode(WriteClassStg(lpStorage, &gClsIDOLE1Compat));
|
|||
|
|
|||
|
error = GetScode(WriteFmtUserTypeStg(lpStorage, cfMPlayer, lpszUserType));
|
|||
|
#ifndef UNICODE
|
|||
|
FreeUnicodeString(lpszUserType);
|
|||
|
#endif
|
|||
|
|
|||
|
if(error != S_OK)
|
|||
|
RETURN_RESULT(error);
|
|||
|
error = GetScode(IStorage_CreateStream(lpStorage, sz1Ole10Native,
|
|||
|
STGM_SALL | STGM_FAILIFTHERE, 0,0, &pstm));
|
|||
|
if (error == STG_E_FILEALREADYEXISTS)
|
|||
|
{
|
|||
|
error = GetScode(IStorage_OpenStream(lpStorage, sz1Ole10Native,
|
|||
|
NULL, STGM_SALL, 0,&pstm));
|
|||
|
DPF("*pssave--openstream*");
|
|||
|
}
|
|||
|
|
|||
|
if(pstm && (error == S_OK))
|
|||
|
hNative = GetLink();
|
|||
|
|
|||
|
if (hNative)
|
|||
|
{
|
|||
|
lpnative = GLOBALLOCK(hNative);
|
|||
|
size = GlobalSize(hNative);
|
|||
|
}
|
|||
|
else
|
|||
|
error = E_OUTOFMEMORY;
|
|||
|
|
|||
|
if (lpnative && (size != 0L))
|
|||
|
{
|
|||
|
error = GetScode(IStream_Write(pstm, &size, 4, &cbWritten));
|
|||
|
error = GetScode(IStream_Write(pstm, lpnative, (ULONG)size, &cbWritten));
|
|||
|
|
|||
|
DPF("\n*After pssave write");
|
|||
|
if (cbWritten != size) error = E_FAIL ; // REVIEW SCODE stream full error
|
|||
|
IStream_Release(pstm);
|
|||
|
}
|
|||
|
|
|||
|
CleanObject();
|
|||
|
GLOBALUNLOCK(hNative);
|
|||
|
GLOBALFREE(hNative);
|
|||
|
RETURN_RESULT(error);
|
|||
|
}
|
|||
|
|
|||
|
/* InPowerPointSlideView
|
|||
|
*
|
|||
|
* Check the class name of the container window to see if we're in PowerPoint.
|
|||
|
* This is to support the horrible hack to get around problem of PowerPoint
|
|||
|
* crashing if we delete an empty Media Clip.
|
|||
|
*
|
|||
|
*/
|
|||
|
STATICFN BOOL InPowerPointSlideView()
|
|||
|
{
|
|||
|
TCHAR ClassName[256];
|
|||
|
|
|||
|
if (GetClassName(ghwndCntr, ClassName, CHAR_COUNT(ClassName)) > 0)
|
|||
|
{
|
|||
|
if (lstrcmp(ClassName, TEXT("paneClassDC")) == 0)
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
STDMETHODIMP PSSaveCompleted (
|
|||
|
LPPERSISTSTORAGE lpPersStg,
|
|||
|
LPSTORAGE lpStorage
|
|||
|
)
|
|||
|
{
|
|||
|
LPDOC lpdoc;
|
|||
|
DPF("\n**pssavecompleted**");
|
|||
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
|
|||
|
|
|||
|
/* Win95 HOT bug #11142
|
|||
|
*
|
|||
|
* Stop PowerPoint crashing horribly:
|
|||
|
*/
|
|||
|
if ((gwDeviceID == 0) && InPowerPointSlideView())
|
|||
|
SendDocMsg(lpdoc, OLE_CHANGED);
|
|||
|
|
|||
|
// inform clients that the object has been saved
|
|||
|
return SendDocMsg (lpdoc, OLE_SAVED);
|
|||
|
}
|
|||
|
|
|||
|
STDMETHODIMP PSHandsOffStorage (
|
|||
|
LPPERSISTSTORAGE lpPersStg
|
|||
|
)
|
|||
|
{
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**************************************************************************
|
|||
|
************ IPersistFile INTERFACE IMPLEMENTATION.
|
|||
|
**************************************************************************/
|
|||
|
//delegate to common IUnknown implementation.
|
|||
|
STDMETHODIMP PFQueryInterface(
|
|||
|
LPPERSISTFILE lpPersFile, // persist storage object ptr
|
|||
|
REFIID riidReq, // IID required
|
|||
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|||
|
)
|
|||
|
{
|
|||
|
return UnkQueryInterface((LPUNKNOWN)lpPersFile, riidReq, lplpUnk);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) PFAddRef(
|
|||
|
LPPERSISTFILE lpPersFile // persist storage object ptr
|
|||
|
)
|
|||
|
{
|
|||
|
return UnkAddRef((LPUNKNOWN) lpPersFile);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP_(ULONG) PFRelease (
|
|||
|
LPPERSISTFILE lpPersFile // persist storage object ptr
|
|||
|
)
|
|||
|
{
|
|||
|
return UnkRelease((LPUNKNOWN) lpPersFile);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP PFGetClassID (
|
|||
|
LPPERSISTFILE lpPersFile,
|
|||
|
CLSID FAR* pCid
|
|||
|
)
|
|||
|
{
|
|||
|
DPF("\n* PFGetclassid");
|
|||
|
|
|||
|
/* The docs are confusing here, but apparently IPersist interfaces
|
|||
|
* should return the old class ID:
|
|||
|
*/
|
|||
|
*pCid = gClsIDOLE1Compat;
|
|||
|
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP PFIsDirty (
|
|||
|
LPPERSISTFILE lpPersFile
|
|||
|
)
|
|||
|
{
|
|||
|
RETURN_RESULT( gfDirty ? S_OK : S_FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//This will be called when the user does a "Insert->Create from file".
|
|||
|
//Open the file with OpenMciDevice and we will be ready to transfer the
|
|||
|
//object.
|
|||
|
STDMETHODIMP PFLoad (
|
|||
|
LPPERSISTFILE lpPersFile,
|
|||
|
LPCWSTR lpszFileName,
|
|||
|
DWORD grfMode
|
|||
|
)
|
|||
|
{
|
|||
|
size_t nLen;
|
|||
|
LPDOC lpdoc;
|
|||
|
TCHAR szFileName[256];
|
|||
|
|
|||
|
if(FAILED(StringCchLength(lpszFileName, 256, &nLen)))
|
|||
|
RETURN_RESULT(E_FAIL);
|
|||
|
|
|||
|
//Don't even attempt to deal with file names greater then 256
|
|||
|
//Don't worry about nonUnincode so casting as LPTSTR
|
|||
|
if(nLen > 255)
|
|||
|
RETURN_RESULT(E_FAIL);
|
|||
|
|
|||
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersFile)->lpdoc;
|
|||
|
DPF("\n***IN PFLOAD: "DTS"\n", lpszFileName);
|
|||
|
#if UNICODE
|
|||
|
lstrcpy(szFileName, lpszFileName);
|
|||
|
#else
|
|||
|
UnicodeToAnsiString(lpszFileName, szFileName, UNKNOWN_LENGTH);
|
|||
|
#endif
|
|||
|
if(OpenMciDevice(szFileName, NULL))
|
|||
|
RETURN_RESULT(S_OK);
|
|||
|
else
|
|||
|
RETURN_RESULT(E_FAIL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP PFSave (
|
|||
|
LPPERSISTFILE lpPersFile,
|
|||
|
LPCWSTR lpszFileName,
|
|||
|
BOOL fRemember
|
|||
|
)
|
|||
|
{
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP PFSaveCompleted (
|
|||
|
LPPERSISTFILE lpPersFile,
|
|||
|
LPCWSTR lpszFileName
|
|||
|
)
|
|||
|
{
|
|||
|
LPDOC lpdoc;
|
|||
|
|
|||
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersFile)->lpdoc;
|
|||
|
|
|||
|
// inform clients that the object has been saved
|
|||
|
return SendDocMsg(lpdoc, OLE_SAVED);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
STDMETHODIMP PFGetCurFile (
|
|||
|
LPPERSISTFILE lpPersFile,
|
|||
|
LPWSTR FAR* lplpszFileName
|
|||
|
)
|
|||
|
{
|
|||
|
RETURN_RESULT( E_NOTIMPL);
|
|||
|
}
|
|||
|
|