Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

387 lines
9.4 KiB

/*---------------------------------------------------------------------------
| 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 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
)
{
LPDOC lpdoc;
TCHAR szFileName[256];
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);
}