* Copyright 1999 Francis Beaudet
* Copyright 1999 Sylvain St-Germain
* Copyright 1999 Thuy Nguyen
+ * Copyright 2005 Mike McCormack
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTES
+ * The compound file implementation of IStorage used for create
+ * and manage substorages and streams within a storage object
+ * residing in a compound file object.
+ *
+ * MSDN
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/istorage_compound_file_implementation.asp
*/
#include <assert.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "winbase.h" /* for lstrlenW() and the likes */
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "windef.h"
+#include "winbase.h"
#include "winnls.h"
-#include "debugtools.h"
+#include "winuser.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
#include "storage32.h"
#include "ole2.h" /* For Write/ReadClassStm */
#include "winreg.h"
#include "wine/wingdi16.h"
-DEFAULT_DEBUG_CHANNEL(storage)
+WINE_DEFAULT_DEBUG_CHANNEL(storage);
#define FILE_BEGIN 0
-
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
#define OLESTREAM_ID 0x501
#define OLESTREAM_MAX_STR_LEN 255
/* OLESTREAM memory structure to use for Get and Put Routines */
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
-typedef struct
+typedef struct
{
DWORD dwOleID;
DWORD dwTypeID;
DWORD dwOleObjFileNameLength;
DWORD dwMetaFileWidth;
DWORD dwMetaFileHeight;
- CHAR strUnknown[8]; //don't know what is this 8 byts information in OLE stream.
+ CHAR strUnknown[8]; /* don't know what is this 8 byts information in OLE stream. */
DWORD dwDataLength;
BYTE *pData;
}OLECONVERT_OLESTREAM_DATA;
BYTE byUnknown1[28];
DWORD dwExtentX;
DWORD dwExtentY;
- DWORD dwSize;
+ DWORD dwSize;
BYTE *pData;
}OLECONVERT_ISTORAGE_OLEPRES;
ULONG storagePropertyIndex,
INT typeOfRelation);
-static HRESULT adjustPropertyChain(
+static HRESULT adjustPropertyChain(
StorageImpl *This,
StgProperty propertyToDelete,
StgProperty parentProperty,
StgProperty newProperty);
static LONG propertyNameCmp(
- OLECHAR *newProperty,
- OLECHAR *currentProperty);
+ const OLECHAR *newProperty,
+ const OLECHAR *currentProperty);
/***********************************************************************
* Declaration of miscellaneous functions...
*/
-static HRESULT validateSTGM(DWORD stgmValue);
+static HRESULT validateSTGM(DWORD stgmValue);
static DWORD GetShareModeFromSTGM(DWORD stgm);
static DWORD GetAccessModeFromSTGM(DWORD stgm);
static DWORD GetCreationModeFromSTGM(DWORD stgm);
-/*
- * Virtual function table for the IStorage32Impl class.
- */
-static ICOM_VTABLE(IStorage) Storage32Impl_Vtbl =
-{
- ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- StorageBaseImpl_QueryInterface,
- StorageBaseImpl_AddRef,
- StorageBaseImpl_Release,
- StorageBaseImpl_CreateStream,
- StorageBaseImpl_OpenStream,
- StorageImpl_CreateStorage,
- StorageBaseImpl_OpenStorage,
- StorageImpl_CopyTo,
- StorageImpl_MoveElementTo,
- StorageImpl_Commit,
- StorageImpl_Revert,
- StorageBaseImpl_EnumElements,
- StorageImpl_DestroyElement,
- StorageBaseImpl_RenameElement,
- StorageImpl_SetElementTimes,
- StorageBaseImpl_SetClass,
- StorageImpl_SetStateBits,
- StorageBaseImpl_Stat
-};
-
-/*
- * Virtual function table for the Storage32InternalImpl class.
- */
-static ICOM_VTABLE(IStorage) Storage32InternalImpl_Vtbl =
- {
- ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- StorageBaseImpl_QueryInterface,
- StorageBaseImpl_AddRef,
- StorageBaseImpl_Release,
- StorageBaseImpl_CreateStream,
- StorageBaseImpl_OpenStream,
- StorageImpl_CreateStorage,
- StorageBaseImpl_OpenStorage,
- StorageImpl_CopyTo,
- StorageImpl_MoveElementTo,
- StorageInternalImpl_Commit,
- StorageInternalImpl_Revert,
- StorageBaseImpl_EnumElements,
- StorageImpl_DestroyElement,
- StorageBaseImpl_RenameElement,
- StorageImpl_SetElementTimes,
- StorageBaseImpl_SetClass,
- StorageImpl_SetStateBits,
- StorageBaseImpl_Stat
-};
-
-/*
- * Virtual function table for the IEnumSTATSTGImpl class.
- */
-static ICOM_VTABLE(IEnumSTATSTG) IEnumSTATSTGImpl_Vtbl =
-{
- ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
- IEnumSTATSTGImpl_QueryInterface,
- IEnumSTATSTGImpl_AddRef,
- IEnumSTATSTGImpl_Release,
- IEnumSTATSTGImpl_Next,
- IEnumSTATSTGImpl_Skip,
- IEnumSTATSTGImpl_Reset,
- IEnumSTATSTGImpl_Clone
-};
-
-
+extern const IPropertySetStorageVtbl IPropertySetStorage_Vtbl;
*
* This method implements the common QueryInterface for all IStorage32
* implementations contained in this file.
- *
+ *
* See Windows documentation for more details on IUnknown methods.
*/
HRESULT WINAPI StorageBaseImpl_QueryInterface(
REFIID riid,
void** ppvObject)
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (ppvObject==0) )
return E_INVALIDARG;
-
+
/*
* Initialize the return parameter.
*/
*ppvObject = 0;
-
+
/*
* Compare the riid with the interface IDs implemented by this object.
*/
- if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
+ if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
{
*ppvObject = (IStorage*)This;
}
- else if (memcmp(&IID_IStorage, riid, sizeof(IID_IStorage)) == 0)
+ else if (memcmp(&IID_IStorage, riid, sizeof(IID_IStorage)) == 0)
{
*ppvObject = (IStorage*)This;
}
-
+ else if (memcmp(&IID_IPropertySetStorage, riid, sizeof(IID_IPropertySetStorage)) == 0)
+ {
+ *ppvObject = (IStorage*)&This->pssVtbl;
+ }
+
/*
* Check that we obtained an interface.
*/
if ((*ppvObject)==0)
return E_NOINTERFACE;
-
+
/*
* Query Interface always increases the reference count by one when it is
* successful
*/
- StorageBaseImpl_AddRef(iface);
+ IStorage_AddRef(iface);
return S_OK;
}
-
+
/************************************************************************
* Storage32BaseImpl_AddRef (IUnknown)
*
* This method implements the common AddRef for all IStorage32
* implementations contained in this file.
- *
+ *
* See Windows documentation for more details on IUnknown methods.
*/
-ULONG WINAPI StorageBaseImpl_AddRef(
+ULONG WINAPI StorageBaseImpl_AddRef(
IStorage* iface)
{
- ICOM_THIS(StorageBaseImpl,iface);
- This->ref++;
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) AddRef to %ld\n", This, ref);
- return This->ref;
+ return ref;
}
-
+
/************************************************************************
* Storage32BaseImpl_Release (IUnknown)
*
* This method implements the common Release for all IStorage32
* implementations contained in this file.
- *
+ *
* See Windows documentation for more details on IUnknown methods.
*/
-ULONG WINAPI StorageBaseImpl_Release(
+ULONG WINAPI StorageBaseImpl_Release(
IStorage* iface)
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
/*
* Decrease the reference count on this object.
*/
- This->ref--;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ReleaseRef to %ld\n", This, ref);
/*
* If the reference count goes down to 0, perform suicide.
*/
- if (This->ref==0)
+ if (ref == 0)
{
/*
- * Since we are using a system of base-classes, we want to call the
- * destructor of the appropriate derived class. To do this, we are
+ * Since we are using a system of base-classes, we want to call the
+ * destructor of the appropriate derived class. To do this, we are
* using virtual functions to implement the destructor.
*/
This->v_destructor(This);
-
- return 0;
}
-
- return This->ref;
+
+ return ref;
}
/************************************************************************
*
* See Windows documentation for more details on IStorage methods.
*/
-HRESULT WINAPI StorageBaseImpl_OpenStream(
+HRESULT WINAPI StorageBaseImpl_OpenStream(
IStorage* iface,
const OLECHAR* pwcsName, /* [string][in] */
void* reserved1, /* [unique][in] */
- DWORD grfMode, /* [in] */
- DWORD reserved2, /* [in] */
- IStream** ppstm) /* [out] */
+ DWORD grfMode, /* [in] */
+ DWORD reserved2, /* [in] */
+ IStream** ppstm) /* [out] */
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
IEnumSTATSTGImpl* propertyEnumeration;
StgStreamImpl* newStream;
StgProperty currentProperty;
ULONG foundPropertyIndex;
+ HRESULT res = STG_E_UNKNOWN;
+ DWORD parent_grfMode;
- TRACE("(%p, %s, %p, %lx, %ld, %p)\n",
+ TRACE("(%p, %s, %p, %lx, %ld, %p)\n",
iface, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm);
/*
* Perform a sanity check on the parameters.
*/
if ( (pwcsName==NULL) || (ppstm==0) )
- return E_INVALIDARG;
-
+ {
+ res = E_INVALIDARG;
+ goto end;
+ }
+
/*
* Initialize the out parameter
*/
- *ppstm = 0;
-
+ *ppstm = NULL;
+
/*
* Validate the STGM flags
*/
if ( FAILED( validateSTGM(grfMode) ))
- return STG_E_INVALIDFLAG;
+ {
+ res = STG_E_INVALIDFLAG;
+ goto end;
+ }
/*
* As documented.
*/
- if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
+ if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE ||
(grfMode & STGM_DELETEONRELEASE) ||
(grfMode & STGM_TRANSACTED) )
- return STG_E_INVALIDFUNCTION;
+ {
+ res = STG_E_INVALIDFUNCTION;
+ goto end;
+ }
+
+ /*
+ * Check that we're compatible with the parent's storage mode
+ */
+ parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )
+ {
+ res = STG_E_ACCESSDENIED;
+ goto end;
+ }
/*
* Create a property enumeration to search the properties
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct(
- This->ancestorStorage,
+ This->ancestorStorage,
This->rootPropertySetIndex);
-
+
/*
* Search the enumeration for the property with the given name
*/
propertyEnumeration,
pwcsName,
¤tProperty);
-
+
/*
* Delete the property enumeration since we don't need it anymore
*/
IEnumSTATSTGImpl_Destroy(propertyEnumeration);
-
+
/*
* If it was found, construct the stream object and return a pointer to it.
*/
- if ( (foundPropertyIndex!=PROPERTY_NULL) &&
+ if ( (foundPropertyIndex!=PROPERTY_NULL) &&
(currentProperty.propertyType==PROPTYPE_STREAM) )
{
newStream = StgStreamImpl_Construct(This, grfMode, foundPropertyIndex);
-
+
if (newStream!=0)
{
newStream->grfMode = grfMode;
*ppstm = (IStream*)newStream;
/*
- * Since we are returning a pointer to the interface, we have to
+ * Since we are returning a pointer to the interface, we have to
* nail down the reference.
*/
- StgStreamImpl_AddRef(*ppstm);
-
- return S_OK;
+ IStream_AddRef(*ppstm);
+
+ res = S_OK;
+ goto end;
}
-
- return E_OUTOFMEMORY;
+
+ res = E_OUTOFMEMORY;
+ goto end;
}
-
- return STG_E_FILENOTFOUND;
+
+ res = STG_E_FILENOTFOUND;
+
+end:
+ if (res == S_OK)
+ TRACE("<-- IStream %p\n", *ppstm);
+ TRACE("<-- %08lx\n", res);
+ return res;
}
/************************************************************************
* Storage32BaseImpl_OpenStorage (IStorage)
*
* This method will open a new storage object from the current storage.
- *
+ *
* See Windows documentation for more details on IStorage methods.
- */
-HRESULT WINAPI StorageBaseImpl_OpenStorage(
+ */
+HRESULT WINAPI StorageBaseImpl_OpenStorage(
IStorage* iface,
- const OLECHAR* pwcsName, /* [string][unique][in] */
- IStorage* pstgPriority, /* [unique][in] */
- DWORD grfMode, /* [in] */
- SNB snbExclude, /* [unique][in] */
- DWORD reserved, /* [in] */
- IStorage** ppstg) /* [out] */
-{
- ICOM_THIS(StorageBaseImpl,iface);
+ const OLECHAR* pwcsName, /* [string][unique][in] */
+ IStorage* pstgPriority, /* [unique][in] */
+ DWORD grfMode, /* [in] */
+ SNB snbExclude, /* [unique][in] */
+ DWORD reserved, /* [in] */
+ IStorage** ppstg) /* [out] */
+{
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
StorageInternalImpl* newStorage;
IEnumSTATSTGImpl* propertyEnumeration;
StgProperty currentProperty;
ULONG foundPropertyIndex;
+ HRESULT res = STG_E_UNKNOWN;
+ DWORD parent_grfMode;
- TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n",
- iface, debugstr_w(pwcsName), pstgPriority,
+ TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n",
+ iface, debugstr_w(pwcsName), pstgPriority,
grfMode, snbExclude, reserved, ppstg);
-
+
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (pwcsName==NULL) || (ppstg==0) )
- return E_INVALIDARG;
-
+ {
+ res = E_INVALIDARG;
+ goto end;
+ }
+
+ /* as documented */
+ if (snbExclude != NULL)
+ {
+ res = STG_E_INVALIDPARAMETER;
+ goto end;
+ }
+
/*
* Validate the STGM flags
*/
if ( FAILED( validateSTGM(grfMode) ))
- return STG_E_INVALIDFLAG;
+ {
+ res = STG_E_INVALIDFLAG;
+ goto end;
+ }
/*
* As documented.
*/
- if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
+ if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE ||
(grfMode & STGM_DELETEONRELEASE) ||
(grfMode & STGM_PRIORITY) )
- return STG_E_INVALIDFUNCTION;
+ {
+ res = STG_E_INVALIDFUNCTION;
+ goto end;
+ }
+
+ /*
+ * Check that we're compatible with the parent's storage mode
+ */
+ parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )
+ {
+ res = STG_E_ACCESSDENIED;
+ goto end;
+ }
/*
* Initialize the out parameter
*/
- *ppstg = 0;
-
+ *ppstg = NULL;
+
/*
* Create a property enumeration to search the properties
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct(
- This->ancestorStorage,
+ This->ancestorStorage,
This->rootPropertySetIndex);
-
+
/*
* Search the enumeration for the property with the given name
*/
propertyEnumeration,
pwcsName,
¤tProperty);
-
+
/*
* Delete the property enumeration since we don't need it anymore
*/
IEnumSTATSTGImpl_Destroy(propertyEnumeration);
-
+
/*
* If it was found, construct the stream object and return a pointer to it.
*/
- if ( (foundPropertyIndex!=PROPERTY_NULL) &&
+ if ( (foundPropertyIndex!=PROPERTY_NULL) &&
(currentProperty.propertyType==PROPTYPE_STORAGE) )
{
/*
*/
newStorage = StorageInternalImpl_Construct(
This->ancestorStorage,
+ grfMode,
foundPropertyIndex);
-
+
if (newStorage != 0)
{
*ppstg = (IStorage*)newStorage;
/*
- * Since we are returning a pointer to the interface,
+ * Since we are returning a pointer to the interface,
* we have to nail down the reference.
*/
StorageBaseImpl_AddRef(*ppstg);
-
- return S_OK;
+
+ res = S_OK;
+ goto end;
}
-
- return STG_E_INSUFFICIENTMEMORY;
+
+ res = STG_E_INSUFFICIENTMEMORY;
+ goto end;
}
-
- return STG_E_FILENOTFOUND;
+
+ res = STG_E_FILENOTFOUND;
+
+end:
+ TRACE("<-- %08lx\n", res);
+ return res;
}
/************************************************************************
* Storage32BaseImpl_EnumElements (IStorage)
*
- * This method will create an enumerator object that can be used to
+ * This method will create an enumerator object that can be used to
* retrieve informatino about all the properties in the storage object.
- *
+ *
* See Windows documentation for more details on IStorage methods.
- */
-HRESULT WINAPI StorageBaseImpl_EnumElements(
+ */
+HRESULT WINAPI StorageBaseImpl_EnumElements(
IStorage* iface,
- DWORD reserved1, /* [in] */
- void* reserved2, /* [size_is][unique][in] */
- DWORD reserved3, /* [in] */
- IEnumSTATSTG** ppenum) /* [out] */
+ DWORD reserved1, /* [in] */
+ void* reserved2, /* [size_is][unique][in] */
+ DWORD reserved3, /* [in] */
+ IEnumSTATSTG** ppenum) /* [out] */
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
IEnumSTATSTGImpl* newEnum;
- TRACE("(%p, %ld, %p, %ld, %p)\n",
+ TRACE("(%p, %ld, %p, %ld, %p)\n",
iface, reserved1, reserved2, reserved3, ppenum);
/*
*/
if ( (This==0) || (ppenum==0))
return E_INVALIDARG;
-
+
/*
* Construct the enumerator.
*/
* Don't forget to nail down a reference to the new object before
* returning it.
*/
- IEnumSTATSTGImpl_AddRef(*ppenum);
-
+ IEnumSTATSTG_AddRef(*ppenum);
+
return S_OK;
}
* Storage32BaseImpl_Stat (IStorage)
*
* This method will retrieve information about this storage object.
- *
+ *
* See Windows documentation for more details on IStorage methods.
- */
-HRESULT WINAPI StorageBaseImpl_Stat(
+ */
+HRESULT WINAPI StorageBaseImpl_Stat(
IStorage* iface,
- STATSTG* pstatstg, /* [out] */
- DWORD grfStatFlag) /* [in] */
+ STATSTG* pstatstg, /* [out] */
+ DWORD grfStatFlag) /* [in] */
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
StgProperty curProperty;
- BOOL readSuccessful;
+ BOOL readSuccessful;
+ HRESULT res = STG_E_UNKNOWN;
- TRACE("(%p, %p, %lx)\n",
+ TRACE("(%p, %p, %lx)\n",
iface, pstatstg, grfStatFlag);
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (pstatstg==0))
- return E_INVALIDARG;
+ {
+ res = E_INVALIDARG;
+ goto end;
+ }
/*
* Read the information from the property.
if (readSuccessful)
{
StorageUtl_CopyPropertyToSTATSTG(
- pstatstg,
- &curProperty,
+ pstatstg,
+ &curProperty,
grfStatFlag);
-
- return S_OK;
+
+ res = S_OK;
+ goto end;
+ }
+
+ res = E_FAIL;
+
+end:
+ if (res == S_OK)
+ {
+ TRACE("<-- STATSTG: pwcsName: %s, type: %ld, cbSize.Low/High: %ld/%ld, grfMode: %08lx, grfLocksSupported: %ld, grfStateBits: %08lx\n", debugstr_w(pstatstg->pwcsName), pstatstg->type, pstatstg->cbSize.u.LowPart, pstatstg->cbSize.u.HighPart, pstatstg->grfMode, pstatstg->grfLocksSupported, pstatstg->grfStateBits);
}
-
- return E_FAIL;
+ TRACE("<-- %08lx\n", res);
+ return res;
}
/************************************************************************
* Storage32BaseImpl_RenameElement (IStorage)
*
- * This method will rename the specified element.
+ * This method will rename the specified element.
*
* See Windows documentation for more details on IStorage methods.
- *
- * Implementation notes: The method used to rename consists of creating a clone
- * of the deleted StgProperty object setting it with the new name and to
+ *
+ * Implementation notes: The method used to rename consists of creating a clone
+ * of the deleted StgProperty object setting it with the new name and to
* perform a DestroyElement of the old StgProperty.
*/
HRESULT WINAPI StorageBaseImpl_RenameElement(
const OLECHAR* pwcsOldName, /* [in] */
const OLECHAR* pwcsNewName) /* [in] */
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
IEnumSTATSTGImpl* propertyEnumeration;
StgProperty currentProperty;
ULONG foundPropertyIndex;
- TRACE("(%p, %s, %s)\n",
+ TRACE("(%p, %s, %s)\n",
iface, debugstr_w(pwcsOldName), debugstr_w(pwcsNewName));
/*
return STG_E_FILEALREADYEXISTS;
}
- IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)propertyEnumeration);
+ IEnumSTATSTG_Reset((IEnumSTATSTG*)propertyEnumeration);
/*
* Search the enumeration for the old property name
/*
* Setup a new property for the renamed property
*/
- renamedProperty.sizeOfNameString =
+ renamedProperty.sizeOfNameString =
( lstrlenW(pwcsNewName)+1 ) * sizeof(WCHAR);
-
+
if (renamedProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
return STG_E_INVALIDNAME;
-
- lstrcpyW(renamedProperty.name, pwcsNewName);
-
+
+ strcpyW(renamedProperty.name, pwcsNewName);
+
renamedProperty.propertyType = currentProperty.propertyType;
renamedProperty.startingBlock = currentProperty.startingBlock;
- renamedProperty.size.s.LowPart = currentProperty.size.s.LowPart;
- renamedProperty.size.s.HighPart = currentProperty.size.s.HighPart;
-
+ renamedProperty.size.u.LowPart = currentProperty.size.u.LowPart;
+ renamedProperty.size.u.HighPart = currentProperty.size.u.HighPart;
+
renamedProperty.previousProperty = PROPERTY_NULL;
renamedProperty.nextProperty = PROPERTY_NULL;
-
+
/*
* Bring the dirProperty link in case it is a storage and in which
* case the renamed storage elements don't require to be reorganized.
*/
renamedProperty.dirProperty = currentProperty.dirProperty;
-
- /* call CoFileTime to get the current time
+
+ /* call CoFileTime to get the current time
renamedProperty.timeStampS1
renamedProperty.timeStampD1
renamedProperty.timeStampS2
renamedProperty.timeStampD2
- renamedProperty.propertyUniqueID
+ renamedProperty.propertyUniqueID
*/
-
- /*
+
+ /*
* Obtain a free property in the property chain
*/
renamedPropertyIndex = getFreeProperty(This->ancestorStorage);
-
+
/*
* Save the new property into the new property spot
- */
+ */
StorageImpl_WriteProperty(
This->ancestorStorage,
- renamedPropertyIndex,
+ renamedPropertyIndex,
&renamedProperty);
-
- /*
+
+ /*
* Find a spot in the property chain for our newly created property.
*/
updatePropertyChain(
(StorageImpl*)This,
- renamedPropertyIndex,
+ renamedPropertyIndex,
renamedProperty);
/*
- * At this point the renamed property has been inserted in the tree,
- * now, before to Destroy the old property we must zeroed it's dirProperty
- * otherwise the DestroyProperty below will zap it all and we do not want
+ * At this point the renamed property has been inserted in the tree,
+ * now, before to Destroy the old property we must zeroed it's dirProperty
+ * otherwise the DestroyProperty below will zap it all and we do not want
* this to happen.
* Also, we fake that the old property is a storage so the DestroyProperty
* will not do a SetSize(0) on the stream data.
- *
+ *
* This means that we need to tweek the StgProperty if it is a stream or a
* non empty storage.
*/
currentProperty.propertyType = PROPTYPE_STORAGE;
StorageImpl_WriteProperty(
This->ancestorStorage,
- foundPropertyIndex,
+ foundPropertyIndex,
¤tProperty);
- /*
- * Invoke Destroy to get rid of the ole property and automatically redo
- * the linking of it's previous and next members...
- */
- StorageImpl_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName);
+ /*
+ * Invoke Destroy to get rid of the ole property and automatically redo
+ * the linking of it's previous and next members...
+ */
+ IStorage_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName);
}
else
/************************************************************************
* Storage32BaseImpl_CreateStream (IStorage)
*
- * This method will create a stream object within this storage
+ * This method will create a stream object within this storage
*
* See Windows documentation for more details on IStorage methods.
*/
DWORD reserved2, /* [in] */
IStream** ppstm) /* [out] */
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
IEnumSTATSTGImpl* propertyEnumeration;
StgStreamImpl* newStream;
StgProperty currentProperty, newStreamProperty;
ULONG foundPropertyIndex, newPropertyIndex;
+ DWORD parent_grfMode;
- TRACE("(%p, %s, %lx, %ld, %ld, %p)\n",
- iface, debugstr_w(pwcsName), grfMode,
+ TRACE("(%p, %s, %lx, %ld, %ld, %p)\n",
+ iface, debugstr_w(pwcsName), grfMode,
reserved1, reserved2, ppstm);
/*
if (pwcsName == 0)
return STG_E_INVALIDNAME;
+ if (reserved1 || reserved2)
+ return STG_E_INVALIDPARAMETER;
+
/*
* Validate the STGM flags
*/
if ( FAILED( validateSTGM(grfMode) ))
return STG_E_INVALIDFLAG;
+ if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE)
+ return STG_E_INVALIDFLAG;
+
/*
* As documented.
*/
- if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
- (grfMode & STGM_DELETEONRELEASE) ||
- (grfMode & STGM_TRANSACTED) )
+ if ((grfMode & STGM_DELETEONRELEASE) ||
+ (grfMode & STGM_TRANSACTED))
return STG_E_INVALIDFUNCTION;
+ /*
+ * Check that we're compatible with the parent's storage mode
+ */
+ parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )
+ return STG_E_ACCESSDENIED;
+
/*
* Initialize the out parameter
*/
if (foundPropertyIndex != PROPERTY_NULL)
{
/*
- * An element with this name already exists
+ * An element with this name already exists
*/
- if (grfMode & STGM_CREATE)
+ if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
{
- IStorage_DestroyElement(iface, pwcsName);
+ IStorage_DestroyElement(iface, pwcsName);
}
- else
+ else
return STG_E_FILEALREADYEXISTS;
}
- /*
- * memset the empty property
+ /*
+ * memset the empty property
*/
memset(&newStreamProperty, 0, sizeof(StgProperty));
if (newStreamProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
return STG_E_INVALIDNAME;
- lstrcpyW(newStreamProperty.name, pwcsName);
+ strcpyW(newStreamProperty.name, pwcsName);
newStreamProperty.propertyType = PROPTYPE_STREAM;
newStreamProperty.startingBlock = BLOCK_END_OF_CHAIN;
- newStreamProperty.size.s.LowPart = 0;
- newStreamProperty.size.s.HighPart = 0;
+ newStreamProperty.size.u.LowPart = 0;
+ newStreamProperty.size.u.HighPart = 0;
newStreamProperty.previousProperty = PROPERTY_NULL;
newStreamProperty.nextProperty = PROPERTY_NULL;
newStreamProperty.dirProperty = PROPERTY_NULL;
- /* call CoFileTime to get the current time
+ /* call CoFileTime to get the current time
newStreamProperty.timeStampS1
newStreamProperty.timeStampD1
newStreamProperty.timeStampS2
/* newStreamProperty.propertyUniqueID */
/*
- * Get a free property or create a new one
+ * Get a free property or create a new one
*/
newPropertyIndex = getFreeProperty(This->ancestorStorage);
/*
* Save the new property into the new property spot
- */
+ */
StorageImpl_WriteProperty(
This->ancestorStorage,
- newPropertyIndex,
+ newPropertyIndex,
&newStreamProperty);
- /*
+ /*
* Find a spot in the property chain for our newly created property.
*/
updatePropertyChain(
(StorageImpl*)This,
- newPropertyIndex,
+ newPropertyIndex,
newStreamProperty);
- /*
+ /*
* Open the stream to return it.
*/
newStream = StgStreamImpl_Construct(This, grfMode, newPropertyIndex);
* Since we are returning a pointer to the interface, we have to nail down
* the reference.
*/
- StgStreamImpl_AddRef(*ppstm);
+ IStream_AddRef(*ppstm);
}
else
{
/************************************************************************
* Storage32BaseImpl_SetClass (IStorage)
*
- * This method will write the specified CLSID in the property of this
+ * This method will write the specified CLSID in the property of this
* storage.
*
* See Windows documentation for more details on IStorage methods.
IStorage* iface,
REFCLSID clsid) /* [in] */
{
- ICOM_THIS(StorageBaseImpl,iface);
+ StorageBaseImpl *This = (StorageBaseImpl *)iface;
HRESULT hRes = E_FAIL;
StgProperty curProperty;
BOOL success;
TRACE("(%p, %p)\n", iface, clsid);
-
+
success = StorageImpl_ReadProperty(This->ancestorStorage,
This->rootPropertySetIndex,
&curProperty);
/************************************************************************
** Storage32Impl implementation
*/
-
+
/************************************************************************
* Storage32Impl_CreateStorage (IStorage)
*
*
* See Windows documentation for more details on IStorage methods.
*/
-HRESULT WINAPI StorageImpl_CreateStorage(
+HRESULT WINAPI StorageImpl_CreateStorage(
IStorage* iface,
- const OLECHAR *pwcsName, /* [string][in] */
- DWORD grfMode, /* [in] */
- DWORD reserved1, /* [in] */
- DWORD reserved2, /* [in] */
- IStorage **ppstg) /* [out] */
+ const OLECHAR *pwcsName, /* [string][in] */
+ DWORD grfMode, /* [in] */
+ DWORD reserved1, /* [in] */
+ DWORD reserved2, /* [in] */
+ IStorage **ppstg) /* [out] */
{
StorageImpl* const This=(StorageImpl*)iface;
ULONG foundPropertyIndex;
ULONG newPropertyIndex;
HRESULT hr;
+ DWORD parent_grfMode;
- TRACE("(%p, %s, %lx, %ld, %ld, %p)\n",
- iface, debugstr_w(pwcsName), grfMode,
+ TRACE("(%p, %s, %lx, %ld, %ld, %p)\n",
+ iface, debugstr_w(pwcsName), grfMode,
reserved1, reserved2, ppstg);
-
+
/*
* Validate parameters
*/
(grfMode & STGM_DELETEONRELEASE) )
return STG_E_INVALIDFLAG;
+ /*
+ * Check that we're compatible with the parent's storage mode
+ */
+ parent_grfMode = STGM_ACCESS_MODE( This->base.ancestorStorage->base.openFlags );
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )
+ return STG_E_ACCESSDENIED;
+
/*
* Initialize the out parameter
*/
/*
* Create a property enumeration and search the properties
*/
- propertyEnumeration = IEnumSTATSTGImpl_Construct( This->ancestorStorage,
- This->rootPropertySetIndex);
+ propertyEnumeration = IEnumSTATSTGImpl_Construct( This->base.ancestorStorage,
+ This->base.rootPropertySetIndex);
foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
pwcsName,
if (foundPropertyIndex != PROPERTY_NULL)
{
/*
- * An element with this name already exists
+ * An element with this name already exists
*/
- if (grfMode & STGM_CREATE)
- IStorage_DestroyElement(iface, pwcsName);
- else
+ if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
+ IStorage_DestroyElement(iface, pwcsName);
+ else
return STG_E_FILEALREADYEXISTS;
}
- /*
- * memset the empty property
+ /*
+ * memset the empty property
*/
memset(&newProperty, 0, sizeof(StgProperty));
if (newProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
return STG_E_INVALIDNAME;
- lstrcpyW(newProperty.name, pwcsName);
+ strcpyW(newProperty.name, pwcsName);
newProperty.propertyType = PROPTYPE_STORAGE;
newProperty.startingBlock = BLOCK_END_OF_CHAIN;
- newProperty.size.s.LowPart = 0;
- newProperty.size.s.HighPart = 0;
+ newProperty.size.u.LowPart = 0;
+ newProperty.size.u.HighPart = 0;
newProperty.previousProperty = PROPERTY_NULL;
newProperty.nextProperty = PROPERTY_NULL;
newProperty.dirProperty = PROPERTY_NULL;
- /* call CoFileTime to get the current time
+ /* call CoFileTime to get the current time
newProperty.timeStampS1
newProperty.timeStampD1
newProperty.timeStampS2
/* newStorageProperty.propertyUniqueID */
- /*
+ /*
* Obtain a free property in the property chain
*/
- newPropertyIndex = getFreeProperty(This->ancestorStorage);
+ newPropertyIndex = getFreeProperty(This->base.ancestorStorage);
/*
* Save the new property into the new property spot
- */
+ */
StorageImpl_WriteProperty(
- This->ancestorStorage,
- newPropertyIndex,
+ This->base.ancestorStorage,
+ newPropertyIndex,
&newProperty);
- /*
+ /*
* Find a spot in the property chain for our newly created property.
*/
updatePropertyChain(
This,
- newPropertyIndex,
+ newPropertyIndex,
newProperty);
- /*
+ /*
* Open it to get a pointer to return.
*/
hr = IStorage_OpenStorage(
iface,
- (OLECHAR*)pwcsName,
+ (const OLECHAR*)pwcsName,
0,
grfMode,
0,
return hr;
}
-
+
return S_OK;
}
/*
* Start by reading the root property
*/
- readSuccessful = StorageImpl_ReadProperty(storage->ancestorStorage,
+ readSuccessful = StorageImpl_ReadProperty(storage->base.ancestorStorage,
currentPropertyIndex,
¤tProperty);
if (readSuccessful)
{
if (currentProperty.sizeOfNameString == 0)
{
- /*
+ /*
* The property existis and is available, we found it.
*/
newPropertyIndex = currentPropertyIndex;
} while (newPropertyIndex == PROPERTY_NULL);
- /*
- * grow the property chain
+ /*
+ * grow the property chain
*/
if (! readSuccessful)
{
ULONG lastProperty = 0;
ULONG blockCount = 0;
- /*
- * obtain the new count of property blocks
+ /*
+ * obtain the new count of property blocks
*/
blockCount = BlockChainStream_GetCount(
- storage->ancestorStorage->rootBlockChain)+1;
+ storage->base.ancestorStorage->rootBlockChain)+1;
- /*
- * initialize the size used by the property stream
+ /*
+ * initialize the size used by the property stream
*/
- newSize.s.HighPart = 0;
- newSize.s.LowPart = storage->bigBlockSize * blockCount;
+ newSize.u.HighPart = 0;
+ newSize.u.LowPart = storage->bigBlockSize * blockCount;
- /*
- * add a property block to the property chain
+ /*
+ * add a property block to the property chain
*/
- BlockChainStream_SetSize(storage->ancestorStorage->rootBlockChain, newSize);
+ BlockChainStream_SetSize(storage->base.ancestorStorage->rootBlockChain, newSize);
- /*
- * memset the empty property in order to initialize the unused newly
+ /*
+ * memset the empty property in order to initialize the unused newly
* created property
*/
memset(&emptyProperty, 0, sizeof(StgProperty));
- /*
+ /*
* initialize them
*/
- lastProperty = storage->bigBlockSize / PROPSET_BLOCK_SIZE * blockCount;
-
+ lastProperty = storage->bigBlockSize / PROPSET_BLOCK_SIZE * blockCount;
+
for(
propertyIndex = newPropertyIndex;
propertyIndex < lastProperty;
propertyIndex++)
{
StorageImpl_WriteProperty(
- storage->ancestorStorage,
- propertyIndex,
+ storage->base.ancestorStorage,
+ propertyIndex,
&emptyProperty);
}
}
*
* Internal Method
*
- * Case insensitive comparaison of StgProperty.name by first considering
+ * Case insensitive comparaison of StgProperty.name by first considering
* their size.
*
* Returns <0 when newPrpoerty < currentProperty
* 0 when newPrpoerty == currentProperty
*/
static LONG propertyNameCmp(
- OLECHAR *newProperty,
- OLECHAR *currentProperty)
+ const OLECHAR *newProperty,
+ const OLECHAR *currentProperty)
{
LONG diff = lstrlenW(newProperty) - lstrlenW(currentProperty);
- if (diff == 0)
+ if (diff == 0)
{
- /*
- * We compare the string themselves only when they are of the same lenght
+ /*
+ * We compare the string themselves only when they are of the same length
*/
diff = lstrcmpiW( newProperty, currentProperty);
}
- return diff;
+ return diff;
}
/****************************************************************************
static void updatePropertyChain(
StorageImpl *storage,
ULONG newPropertyIndex,
- StgProperty newProperty)
+ StgProperty newProperty)
{
StgProperty currentProperty;
/*
* Read the root property
*/
- StorageImpl_ReadProperty(storage->ancestorStorage,
- storage->rootPropertySetIndex,
+ StorageImpl_ReadProperty(storage->base.ancestorStorage,
+ storage->base.rootPropertySetIndex,
¤tProperty);
if (currentProperty.dirProperty != PROPERTY_NULL)
{
- /*
+ /*
* The root storage contains some element, therefore, start the research
* for the appropriate location.
*/
currentPropertyId = currentProperty.dirProperty;
/*
- * Read
+ * Read
*/
- StorageImpl_ReadProperty(storage->ancestorStorage,
+ StorageImpl_ReadProperty(storage->base.ancestorStorage,
currentProperty.dirProperty,
¤tProperty);
while (found == 0)
{
LONG diff = propertyNameCmp( newProperty.name, currentProperty.name);
-
+
if (diff < 0)
{
if (previous != PROPERTY_NULL)
{
- StorageImpl_ReadProperty(storage->ancestorStorage,
+ StorageImpl_ReadProperty(storage->base.ancestorStorage,
previous,
¤tProperty);
current = previous;
else
{
currentProperty.previousProperty = newPropertyIndex;
- StorageImpl_WriteProperty(storage->ancestorStorage,
+ StorageImpl_WriteProperty(storage->base.ancestorStorage,
current,
¤tProperty);
found = 1;
{
if (next != PROPERTY_NULL)
{
- StorageImpl_ReadProperty(storage->ancestorStorage,
+ StorageImpl_ReadProperty(storage->base.ancestorStorage,
next,
¤tProperty);
current = next;
else
{
currentProperty.nextProperty = newPropertyIndex;
- StorageImpl_WriteProperty(storage->ancestorStorage,
+ StorageImpl_WriteProperty(storage->base.ancestorStorage,
current,
¤tProperty);
found = 1;
}
else
{
- /*
+ /*
* The root storage is empty, link the new property to it's dir property
*/
currentProperty.dirProperty = newPropertyIndex;
- StorageImpl_WriteProperty(storage->ancestorStorage,
- storage->rootPropertySetIndex,
+ StorageImpl_WriteProperty(storage->base.ancestorStorage,
+ storage->base.rootPropertySetIndex,
¤tProperty);
}
}
-
+
/*************************************************************************
* CopyTo (IStorage)
*/
-HRESULT WINAPI StorageImpl_CopyTo(
+HRESULT WINAPI StorageImpl_CopyTo(
IStorage* iface,
- DWORD ciidExclude, /* [in] */
- const IID* rgiidExclude, /* [size_is][unique][in] */
- SNB snbExclude, /* [unique][in] */
- IStorage* pstgDest) /* [unique][in] */
+ DWORD ciidExclude, /* [in] */
+ const IID* rgiidExclude, /* [size_is][unique][in] */
+ SNB snbExclude, /* [unique][in] */
+ IStorage* pstgDest) /* [unique][in] */
{
IEnumSTATSTG *elements = 0;
STATSTG curElement, strStat;
if ((ciidExclude != 0) || (rgiidExclude != NULL) || (snbExclude != NULL))
FIXME("Exclude option not implemented\n");
- TRACE("(%p, %ld, %p, %p, %p)\n",
- iface, ciidExclude, rgiidExclude,
+ TRACE("(%p, %ld, %p, %p, %p)\n",
+ iface, ciidExclude, rgiidExclude,
snbExclude, pstgDest);
/*
if ( pstgDest == 0 )
return STG_E_INVALIDPOINTER;
- /*
+ /*
* Enumerate the elements
*/
hr = IStorage_EnumElements( iface, 0, 0, 0, &elements );
*/
IStorage_Stat( iface, &curElement, STATFLAG_NONAME);
IStorage_SetClass( pstgDest, &curElement.clsid );
-
+
do
{
/*
return STG_E_ACCESSDENIED;
}
-
+
/*
* create a new storage in destination storage
*/
STGM_WRITE|STGM_SHARE_EXCLUSIVE,
NULL, 0, &pstgTmp );
}
-
+
if (hr != S_OK)
break;
-
+
/*
* do the copy recursively
*/
hr = IStorage_CopyTo( pstgChild, ciidExclude, rgiidExclude,
snbExclude, pstgTmp );
-
+
IStorage_Release( pstgTmp );
IStorage_Release( pstgChild );
}
* Set the size of the destination stream.
*/
IStream_SetSize(pstrTmp, strStat.cbSize);
-
+
/*
* do the copy
*/
hr = IStream_CopyTo( pstrChild, pstrTmp, strStat.cbSize,
NULL, NULL );
-
+
IStream_Release( pstrTmp );
IStream_Release( pstrChild );
}
* Clean-up
*/
IEnumSTATSTG_Release(elements);
-
+
return hr;
}
-
+
/*************************************************************************
* MoveElementTo (IStorage)
*/
-HRESULT WINAPI StorageImpl_MoveElementTo(
+HRESULT WINAPI StorageImpl_MoveElementTo(
IStorage* iface,
- const OLECHAR *pwcsName, /* [string][in] */
- IStorage *pstgDest, /* [unique][in] */
- const OLECHAR *pwcsNewName,/* [string][in] */
- DWORD grfFlags) /* [in] */
+ const OLECHAR *pwcsName, /* [string][in] */
+ IStorage *pstgDest, /* [unique][in] */
+ const OLECHAR *pwcsNewName,/* [string][in] */
+ DWORD grfFlags) /* [in] */
{
FIXME("not implemented!\n");
return E_NOTIMPL;
}
-
+
/*************************************************************************
* Commit (IStorage)
+ *
+ * Ensures that any changes made to a storage object open in transacted mode
+ * are reflected in the parent storage
+ *
+ * NOTES
+ * Wine doesn't implement transacted mode, which seems to be a basic
+ * optimization, so we can ignore this stub for now.
*/
-HRESULT WINAPI StorageImpl_Commit(
+HRESULT WINAPI StorageImpl_Commit(
IStorage* iface,
- DWORD grfCommitFlags)/* [in] */
+ DWORD grfCommitFlags)/* [in] */
{
FIXME("(%ld): stub!\n", grfCommitFlags);
return S_OK;
}
-
+
/*************************************************************************
* Revert (IStorage)
+ *
+ * Discard all changes that have been made since the last commit operation
*/
-HRESULT WINAPI StorageImpl_Revert(
+HRESULT WINAPI StorageImpl_Revert(
IStorage* iface)
{
FIXME("not implemented!\n");
/*************************************************************************
* DestroyElement (IStorage)
*
- * Stategy: This implementation is build this way for simplicity not for speed.
+ * Stategy: This implementation is build this way for simplicity not for speed.
* I always delete the top most element of the enumeration and adjust
- * the deleted element pointer all the time. This takes longer to
- * do but allow to reinvoke DestroyElement whenever we encounter a
+ * the deleted element pointer all the time. This takes longer to
+ * do but allow to reinvoke DestroyElement whenever we encounter a
* storage object. The optimisation reside in the usage of another
- * enumeration stategy that would give all the leaves of a storage
+ * enumeration stategy that would give all the leaves of a storage
* first. (postfix order)
*/
-HRESULT WINAPI StorageImpl_DestroyElement(
+HRESULT WINAPI StorageImpl_DestroyElement(
IStorage* iface,
- const OLECHAR *pwcsName)/* [string][in] */
+ const OLECHAR *pwcsName)/* [string][in] */
{
StorageImpl* const This=(StorageImpl*)iface;
ULONG typeOfRelation;
ULONG parentPropertyId;
- TRACE("(%p, %s)\n",
+ TRACE("(%p, %s)\n",
iface, debugstr_w(pwcsName));
/*
* Perform a sanity check on the parameters.
*/
- if (pwcsName==NULL)
+ if (pwcsName==NULL)
return STG_E_INVALIDPOINTER;
-
+
/*
* Create a property enumeration to search the property with the given name
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct(
- This->ancestorStorage,
- This->rootPropertySetIndex);
-
+ This->base.ancestorStorage,
+ This->base.rootPropertySetIndex);
+
foundPropertyIndexToDelete = IEnumSTATSTGImpl_FindProperty(
propertyEnumeration,
pwcsName,
IEnumSTATSTGImpl_Destroy(propertyEnumeration);
- if ( foundPropertyIndexToDelete == PROPERTY_NULL )
+ if ( foundPropertyIndexToDelete == PROPERTY_NULL )
{
return STG_E_FILENOTFOUND;
}
- /*
- * Find the parent property of the property to delete (the one that
- * link to it). If This->dirProperty == foundPropertyIndexToDelete,
+ /*
+ * Find the parent property of the property to delete (the one that
+ * link to it). If This->dirProperty == foundPropertyIndexToDelete,
* the parent is This. Otherwise, the parent is one of it's sibling...
*/
- /*
+ /*
* First, read This's StgProperty..
*/
- res = StorageImpl_ReadProperty(
- This->ancestorStorage,
- This->rootPropertySetIndex,
+ res = StorageImpl_ReadProperty(
+ This->base.ancestorStorage,
+ This->base.rootPropertySetIndex,
&parentProperty);
- assert(res==TRUE);
+ assert(res);
- /*
+ /*
* Second, check to see if by any chance the actual storage (This) is not
* the parent of the property to delete... We never know...
*/
if ( parentProperty.dirProperty == foundPropertyIndexToDelete )
{
- /*
+ /*
* Set data as it would have been done in the else part...
*/
typeOfRelation = PROPERTY_RELATION_DIR;
- parentPropertyId = This->rootPropertySetIndex;
+ parentPropertyId = This->base.rootPropertySetIndex;
}
- else
- {
+ else
+ {
/*
- * Create a property enumeration to search the parent properties, and
+ * Create a property enumeration to search the parent properties, and
* delete it once done.
*/
IEnumSTATSTGImpl* propertyEnumeration2;
propertyEnumeration2 = IEnumSTATSTGImpl_Construct(
- This->ancestorStorage,
- This->rootPropertySetIndex);
-
+ This->base.ancestorStorage,
+ This->base.rootPropertySetIndex);
+
typeOfRelation = IEnumSTATSTGImpl_FindParentProperty(
propertyEnumeration2,
foundPropertyIndexToDelete,
IEnumSTATSTGImpl_Destroy(propertyEnumeration2);
}
- if ( propertyToDelete.propertyType == PROPTYPE_STORAGE )
+ if ( propertyToDelete.propertyType == PROPTYPE_STORAGE )
{
hr = deleteStorageProperty(
- This,
+ This,
foundPropertyIndexToDelete,
propertyToDelete);
- }
+ }
else if ( propertyToDelete.propertyType == PROPTYPE_STREAM )
{
hr = deleteStreamProperty(
- This,
+ This,
foundPropertyIndexToDelete,
propertyToDelete);
}
- if (hr!=S_OK)
+ if (hr!=S_OK)
return hr;
/*
*/
hr = adjustPropertyChain(
This,
- propertyToDelete,
+ propertyToDelete,
parentProperty,
parentPropertyId,
typeOfRelation);
}
+/************************************************************************
+ * StorageImpl_Stat (IStorage)
+ *
+ * This method will retrieve information about this storage object.
+ *
+ * See Windows documentation for more details on IStorage methods.
+ */
+HRESULT WINAPI StorageImpl_Stat( IStorage* iface,
+ STATSTG* pstatstg, /* [out] */
+ DWORD grfStatFlag) /* [in] */
+{
+ StorageImpl* const This = (StorageImpl*)iface;
+ HRESULT result = StorageBaseImpl_Stat( iface, pstatstg, grfStatFlag );
+
+ if ( !FAILED(result) && ((grfStatFlag & STATFLAG_NONAME) == 0) && This->pwcsName )
+ {
+ CoTaskMemFree(pstatstg->pwcsName);
+ pstatstg->pwcsName = CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR));
+ strcpyW(pstatstg->pwcsName, This->pwcsName);
+ }
+
+ return result;
+}
+
+
+
/*********************************************************************
*
* Internal Method
return hr;
}
- /*
+ /*
* Enumerate the elements
*/
IStorage_EnumElements( childStorage, 0, 0, 0, &elements);
if (hr==S_OK)
{
destroyHr = StorageImpl_DestroyElement(
- (IStorage*)childStorage,
+ (IStorage*)childStorage,
(OLECHAR*)currentElement.pwcsName);
CoTaskMemFree(currentElement.pwcsName);
*/
propertyToDelete.sizeOfNameString = 0;
- StorageImpl_WriteProperty(parentStorage->ancestorStorage,
+ StorageImpl_WriteProperty(parentStorage->base.ancestorStorage,
indexOfPropertyToDelete,
&propertyToDelete);
IStorage_Release(childStorage);
IEnumSTATSTG_Release(elements);
-
+
return destroyHr;
}
HRESULT hr;
ULARGE_INTEGER size;
- size.s.HighPart = 0;
- size.s.LowPart = 0;
+ size.u.HighPart = 0;
+ size.u.LowPart = 0;
hr = StorageBaseImpl_OpenStream(
(IStorage*)parentStorage,
STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0,
&pis);
-
+
if (hr!=S_OK)
{
return(hr);
}
- /*
- * Zap the stream
- */
- hr = IStream_SetSize(pis, size);
+ /*
+ * Zap the stream
+ */
+ hr = IStream_SetSize(pis, size);
if(hr != S_OK)
{
*/
IStream_Release(pis);
- /*
+ /*
* Invalidate the property by zeroing it's name member.
*/
propertyToDelete.sizeOfNameString = 0;
- /*
+ /*
* Here we should re-read the property so we get the updated pointer
* but since we are here to zap it, I don't do it...
*/
StorageImpl_WriteProperty(
- parentStorage->ancestorStorage,
+ parentStorage->base.ancestorStorage,
indexOfPropertyToDelete,
&propertyToDelete);
* Read the storage property
*/
res = StorageImpl_ReadProperty(
- storage->ancestorStorage,
- storePropertyIndex,
+ storage->base.ancestorStorage,
+ storePropertyIndex,
&storeProperty);
if(! res)
{
return findPlaceholder(
storage,
- propertyIndexToStore,
+ propertyIndexToStore,
storeProperty.previousProperty,
typeOfRelation);
}
{
return findPlaceholder(
storage,
- propertyIndexToStore,
+ propertyIndexToStore,
storeProperty.nextProperty,
typeOfRelation);
}
{
storeProperty.nextProperty = propertyIndexToStore;
}
- }
+ }
else if (typeOfRelation == PROPERTY_RELATION_DIR)
{
if (storeProperty.dirProperty != PROPERTY_NULL)
{
return findPlaceholder(
storage,
- propertyIndexToStore,
+ propertyIndexToStore,
storeProperty.dirProperty,
typeOfRelation);
}
}
hr = StorageImpl_WriteProperty(
- storage->ancestorStorage,
- storePropertyIndex,
+ storage->base.ancestorStorage,
+ storePropertyIndex,
&storeProperty);
if(! hr)
*
* Internal Method
*
- * This method takes the previous and the next property link of a property
+ * This method takes the previous and the next property link of a property
* to be deleted and find them a place in the Storage.
*/
-static HRESULT adjustPropertyChain(
+static HRESULT adjustPropertyChain(
StorageImpl *This,
StgProperty propertyToDelete,
StgProperty parentProperty,
INT relationType = 0;
HRESULT hr = S_OK;
BOOL res = TRUE;
-
- if (typeOfRelation == PROPERTY_RELATION_PREVIOUS)
+
+ if (typeOfRelation == PROPERTY_RELATION_PREVIOUS)
{
- if (propertyToDelete.previousProperty != PROPERTY_NULL)
+ if (propertyToDelete.previousProperty != PROPERTY_NULL)
{
- /*
+ /*
* Set the parent previous to the property to delete previous
*/
newLinkProperty = propertyToDelete.previousProperty;
- if (propertyToDelete.nextProperty != PROPERTY_NULL)
+ if (propertyToDelete.nextProperty != PROPERTY_NULL)
{
/*
- * We also need to find a storage for the other link, setup variables
+ * We also need to find a storage for the other link, setup variables
* to do this at the end...
- */
+ */
needToFindAPlaceholder = TRUE;
storeNode = propertyToDelete.previousProperty;
toStoreNode = propertyToDelete.nextProperty;
relationType = PROPERTY_RELATION_NEXT;
}
- }
- else if (propertyToDelete.nextProperty != PROPERTY_NULL)
+ }
+ else if (propertyToDelete.nextProperty != PROPERTY_NULL)
{
- /*
+ /*
* Set the parent previous to the property to delete next
*/
newLinkProperty = propertyToDelete.nextProperty;
}
-
- /*
+
+ /*
* Link it for real...
- */
+ */
parentProperty.previousProperty = newLinkProperty;
-
- }
- else if (typeOfRelation == PROPERTY_RELATION_NEXT)
+
+ }
+ else if (typeOfRelation == PROPERTY_RELATION_NEXT)
{
- if (propertyToDelete.previousProperty != PROPERTY_NULL)
+ if (propertyToDelete.previousProperty != PROPERTY_NULL)
{
- /*
+ /*
* Set the parent next to the property to delete next previous
*/
newLinkProperty = propertyToDelete.previousProperty;
-
- if (propertyToDelete.nextProperty != PROPERTY_NULL)
+
+ if (propertyToDelete.nextProperty != PROPERTY_NULL)
{
/*
- * We also need to find a storage for the other link, setup variables
+ * We also need to find a storage for the other link, setup variables
* to do this at the end...
- */
+ */
needToFindAPlaceholder = TRUE;
storeNode = propertyToDelete.previousProperty;
toStoreNode = propertyToDelete.nextProperty;
relationType = PROPERTY_RELATION_NEXT;
}
- }
- else if (propertyToDelete.nextProperty != PROPERTY_NULL)
+ }
+ else if (propertyToDelete.nextProperty != PROPERTY_NULL)
{
- /*
+ /*
* Set the parent next to the property to delete next
*/
newLinkProperty = propertyToDelete.nextProperty;
}
- /*
+ /*
* Link it for real...
- */
+ */
parentProperty.nextProperty = newLinkProperty;
- }
+ }
else /* (typeOfRelation == PROPERTY_RELATION_DIR) */
{
- if (propertyToDelete.previousProperty != PROPERTY_NULL)
+ if (propertyToDelete.previousProperty != PROPERTY_NULL)
{
- /*
+ /*
* Set the parent dir to the property to delete previous
*/
newLinkProperty = propertyToDelete.previousProperty;
- if (propertyToDelete.nextProperty != PROPERTY_NULL)
+ if (propertyToDelete.nextProperty != PROPERTY_NULL)
{
/*
- * We also need to find a storage for the other link, setup variables
+ * We also need to find a storage for the other link, setup variables
* to do this at the end...
- */
+ */
needToFindAPlaceholder = TRUE;
storeNode = propertyToDelete.previousProperty;
toStoreNode = propertyToDelete.nextProperty;
relationType = PROPERTY_RELATION_NEXT;
}
- }
- else if (propertyToDelete.nextProperty != PROPERTY_NULL)
+ }
+ else if (propertyToDelete.nextProperty != PROPERTY_NULL)
{
- /*
+ /*
* Set the parent dir to the property to delete next
*/
newLinkProperty = propertyToDelete.nextProperty;
}
- /*
+ /*
* Link it for real...
- */
+ */
parentProperty.dirProperty = newLinkProperty;
}
- /*
- * Write back the parent property
+ /*
+ * Write back the parent property
*/
res = StorageImpl_WriteProperty(
- This->ancestorStorage,
+ This->base.ancestorStorage,
parentPropertyId,
&parentProperty);
if(! res)
}
/*
- * If a placeholder is required for the other link, then, find one and
+ * If a placeholder is required for the other link, then, find one and
* get out of here...
*/
- if (needToFindAPlaceholder)
+ if (needToFindAPlaceholder)
{
hr = findPlaceholder(
- This,
- toStoreNode,
+ This,
+ toStoreNode,
storeNode,
relationType);
}
/******************************************************************************
* SetElementTimes (IStorage)
*/
-HRESULT WINAPI StorageImpl_SetElementTimes(
+HRESULT WINAPI StorageImpl_SetElementTimes(
IStorage* iface,
- const OLECHAR *pwcsName,/* [string][in] */
- const FILETIME *pctime, /* [in] */
- const FILETIME *patime, /* [in] */
- const FILETIME *pmtime) /* [in] */
+ const OLECHAR *pwcsName,/* [string][in] */
+ const FILETIME *pctime, /* [in] */
+ const FILETIME *patime, /* [in] */
+ const FILETIME *pmtime) /* [in] */
{
- FIXME("not implemented!\n");
- return E_NOTIMPL;
+ FIXME("(%s,...), stub!\n",debugstr_w(pwcsName));
+ return S_OK;
}
/******************************************************************************
* SetStateBits (IStorage)
*/
-HRESULT WINAPI StorageImpl_SetStateBits(
+HRESULT WINAPI StorageImpl_SetStateBits(
IStorage* iface,
- DWORD grfStateBits,/* [in] */
- DWORD grfMask) /* [in] */
+ DWORD grfStateBits,/* [in] */
+ DWORD grfMask) /* [in] */
{
FIXME("not implemented!\n");
return E_NOTIMPL;
}
+/*
+ * Virtual function table for the IStorage32Impl class.
+ */
+static const IStorageVtbl Storage32Impl_Vtbl =
+{
+ StorageBaseImpl_QueryInterface,
+ StorageBaseImpl_AddRef,
+ StorageBaseImpl_Release,
+ StorageBaseImpl_CreateStream,
+ StorageBaseImpl_OpenStream,
+ StorageImpl_CreateStorage,
+ StorageBaseImpl_OpenStorage,
+ StorageImpl_CopyTo,
+ StorageImpl_MoveElementTo,
+ StorageImpl_Commit,
+ StorageImpl_Revert,
+ StorageBaseImpl_EnumElements,
+ StorageImpl_DestroyElement,
+ StorageBaseImpl_RenameElement,
+ StorageImpl_SetElementTimes,
+ StorageBaseImpl_SetClass,
+ StorageImpl_SetStateBits,
+ StorageImpl_Stat
+};
+
HRESULT StorageImpl_Construct(
StorageImpl* This,
HANDLE hFile,
+ LPCOLESTR pwcsName,
ILockBytes* pLkbyt,
DWORD openFlags,
BOOL fileBased,
StgProperty currentProperty;
BOOL readSuccessful;
ULONG currentPropertyIndex;
-
+
if ( FAILED( validateSTGM(openFlags) ))
return STG_E_INVALIDFLAG;
memset(This, 0, sizeof(StorageImpl));
-
+
/*
- * Initialize the virtual fgunction table.
+ * Initialize the virtual function table.
*/
- ICOM_VTBL(This) = &Storage32Impl_Vtbl;
- This->v_destructor = &StorageImpl_Destroy;
-
+ This->base.lpVtbl = &Storage32Impl_Vtbl;
+ This->base.pssVtbl = &IPropertySetStorage_Vtbl;
+ This->base.v_destructor = &StorageImpl_Destroy;
+ This->base.openFlags = openFlags;
+
/*
- * This is the top-level storage so initialize the ancester pointer
+ * This is the top-level storage so initialize the ancestor pointer
* to this.
*/
- This->ancestorStorage = This;
-
+ This->base.ancestorStorage = This;
+
/*
* Initialize the physical support of the storage.
*/
This->hFile = hFile;
-
+
+ /*
+ * Store copy of file path.
+ */
+ if(pwcsName) {
+ This->pwcsName = HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(pwcsName)+1)*sizeof(WCHAR));
+ if (!This->pwcsName)
+ return STG_E_INSUFFICIENTMEMORY;
+ strcpyW(This->pwcsName, pwcsName);
+ }
+
/*
* Initialize the big block cache.
*/
if (This->bigBlockFile == 0)
return E_FAIL;
-
+
if (fileCreate)
{
ULARGE_INTEGER size;
* - The properties start at block 1
* - There is no small block depot
*/
- memset( This->bigBlockDepotStart,
- BLOCK_UNUSED,
+ memset( This->bigBlockDepotStart,
+ BLOCK_UNUSED,
sizeof(This->bigBlockDepotStart));
This->bigBlockDepotCount = 1;
/*
* Add one block for the big block depot and one block for the properties
*/
- size.s.HighPart = 0;
- size.s.LowPart = This->bigBlockSize * 3;
+ size.u.HighPart = 0;
+ size.u.LowPart = This->bigBlockSize * 3;
BIGBLOCKFILE_SetSize(This->bigBlockFile, size);
/*
* Start searching for free blocks with block 0.
*/
This->prevFreeBlock = 0;
-
+
/*
* Create the block chain abstractions.
*/
- This->rootBlockChain =
- BlockChainStream_Construct(This, &This->rootStartBlock, PROPERTY_NULL);
+ if(!(This->rootBlockChain =
+ BlockChainStream_Construct(This, &This->rootStartBlock, PROPERTY_NULL)))
+ return STG_E_READFAULT;
- This->smallBlockDepotChain = BlockChainStream_Construct(
- This,
- &This->smallBlockDepotStart,
- PROPERTY_NULL);
+ if(!(This->smallBlockDepotChain =
+ BlockChainStream_Construct(This, &This->smallBlockDepotStart,
+ PROPERTY_NULL)))
+ return STG_E_READFAULT;
/*
- * Write the root property
+ * Write the root property
*/
if (fileCreate)
{
* Initialize the property chain
*/
memset(&rootProp, 0, sizeof(rootProp));
- lstrcpyAtoW(rootProp.name, rootPropertyName);
-
- rootProp.sizeOfNameString = (lstrlenW(rootProp.name)+1) * sizeof(WCHAR);
+ MultiByteToWideChar( CP_ACP, 0, rootPropertyName, -1, rootProp.name,
+ sizeof(rootProp.name)/sizeof(WCHAR) );
+ rootProp.sizeOfNameString = (strlenW(rootProp.name)+1) * sizeof(WCHAR);
rootProp.propertyType = PROPTYPE_ROOT;
rootProp.previousProperty = PROPERTY_NULL;
rootProp.nextProperty = PROPERTY_NULL;
rootProp.dirProperty = PROPERTY_NULL;
rootProp.startingBlock = BLOCK_END_OF_CHAIN;
- rootProp.size.s.HighPart = 0;
- rootProp.size.s.LowPart = 0;
+ rootProp.size.u.HighPart = 0;
+ rootProp.size.u.LowPart = 0;
StorageImpl_WriteProperty(This, 0, &rootProp);
}
/*
- * Find the ID of the root int he property sets.
+ * Find the ID of the root in the property sets.
*/
currentPropertyIndex = 0;
-
+
do
{
readSuccessful = StorageImpl_ReadProperty(
- This,
- currentPropertyIndex,
+ This,
+ currentPropertyIndex,
¤tProperty);
-
+
if (readSuccessful)
{
if ( (currentProperty.sizeOfNameString != 0 ) &&
(currentProperty.propertyType == PROPTYPE_ROOT) )
{
- This->rootPropertySetIndex = currentPropertyIndex;
+ This->base.rootPropertySetIndex = currentPropertyIndex;
}
}
currentPropertyIndex++;
-
- } while (readSuccessful && (This->rootPropertySetIndex == PROPERTY_NULL) );
-
+
+ } while (readSuccessful && (This->base.rootPropertySetIndex == PROPERTY_NULL) );
+
if (!readSuccessful)
{
/* TODO CLEANUP */
- return E_FAIL;
+ return STG_E_READFAULT;
}
/*
* Create the block chain abstraction for the small block root chain.
*/
- This->smallBlockRootChain = BlockChainStream_Construct(
- This,
- NULL,
- This->rootPropertySetIndex);
-
+ if(!(This->smallBlockRootChain =
+ BlockChainStream_Construct(This, NULL, This->base.rootPropertySetIndex)))
+ return STG_E_READFAULT;
+
return hr;
}
-void StorageImpl_Destroy(
- StorageImpl* This)
+void StorageImpl_Destroy(StorageBaseImpl* iface)
{
+ StorageImpl *This = (StorageImpl*) iface;
TRACE("(%p)\n", This);
+ HeapFree(GetProcessHeap(), 0, This->pwcsName);
+
BlockChainStream_Destroy(This->smallBlockRootChain);
BlockChainStream_Destroy(This->rootBlockChain);
BlockChainStream_Destroy(This->smallBlockDepotChain);
BIGBLOCKFILE_Destructor(This->bigBlockFile);
- return;
+ HeapFree(GetProcessHeap(), 0, This);
}
/******************************************************************************
}
else
{
- int i;
+ unsigned int i;
/*
* Follow the chain to the last one.
*/
* Params: This - Pointer to the Storage object.
* blockIndex - Index of the block to retrieve the chain
* for.
+ * nextBlockIndex - receives the return value.
*
* Returns: This method returns the index of the next block in the chain.
* It will return the constants:
*
* See Windows documentation for more details on IStorage methods.
*/
-ULONG StorageImpl_GetNextBlockInChain(
+HRESULT StorageImpl_GetNextBlockInChain(
StorageImpl* This,
- ULONG blockIndex)
+ ULONG blockIndex,
+ ULONG* nextBlockIndex)
{
ULONG offsetInDepot = blockIndex * sizeof (ULONG);
ULONG depotBlockCount = offsetInDepot / This->bigBlockSize;
ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize;
- ULONG nextBlockIndex = BLOCK_SPECIAL;
void* depotBuffer;
ULONG depotBlockIndexPos;
+ int index;
- assert(depotBlockCount < This->bigBlockDepotCount);
+ *nextBlockIndex = BLOCK_SPECIAL;
+
+ if(depotBlockCount >= This->bigBlockDepotCount)
+ {
+ WARN("depotBlockCount %ld, bigBlockDepotCount %ld\n", depotBlockCount,
+ This->bigBlockDepotCount);
+ return STG_E_READFAULT;
+ }
/*
* Cache the currently accessed depot block.
depotBuffer = StorageImpl_GetROBigBlock(This, depotBlockIndexPos);
- if (depotBuffer!=0)
- {
- int index;
-
- for (index = 0; index < NUM_BLOCKS_PER_DEPOT_BLOCK; index++)
- {
- StorageUtl_ReadDWord(depotBuffer, index*sizeof(ULONG), &nextBlockIndex);
- This->blockDepotCached[index] = nextBlockIndex;
- }
+ if (!depotBuffer)
+ return STG_E_READFAULT;
- StorageImpl_ReleaseBigBlock(This, depotBuffer);
+ for (index = 0; index < NUM_BLOCKS_PER_DEPOT_BLOCK; index++)
+ {
+ StorageUtl_ReadDWord(depotBuffer, index*sizeof(ULONG), nextBlockIndex);
+ This->blockDepotCached[index] = *nextBlockIndex;
}
+ StorageImpl_ReleaseBigBlock(This, depotBuffer);
}
- nextBlockIndex = This->blockDepotCached[depotBlockOffset/sizeof(ULONG)];
+ *nextBlockIndex = This->blockDepotCached[depotBlockOffset/sizeof(ULONG)];
- return nextBlockIndex;
+ return S_OK;
}
/******************************************************************************
}
StorageUtl_ReadWord(
- headerBigBlock,
- OFFSET_BIGBLOCKSIZEBITS,
+ headerBigBlock,
+ OFFSET_BIGBLOCKSIZEBITS,
&This->bigBlockSizeBits);
StorageUtl_ReadWord(
- headerBigBlock,
- OFFSET_SMALLBLOCKSIZEBITS,
+ headerBigBlock,
+ OFFSET_SMALLBLOCKSIZEBITS,
&This->smallBlockSizeBits);
StorageUtl_ReadDWord(
- headerBigBlock,
- OFFSET_BBDEPOTCOUNT,
+ headerBigBlock,
+ OFFSET_BBDEPOTCOUNT,
&This->bigBlockDepotCount);
StorageUtl_ReadDWord(
- headerBigBlock,
- OFFSET_ROOTSTARTBLOCK,
+ headerBigBlock,
+ OFFSET_ROOTSTARTBLOCK,
&This->rootStartBlock);
StorageUtl_ReadDWord(
- headerBigBlock,
- OFFSET_SBDEPOTSTART,
+ headerBigBlock,
+ OFFSET_SBDEPOTSTART,
&This->smallBlockDepotStart);
- StorageUtl_ReadDWord(
- headerBigBlock,
- OFFSET_EXTBBDEPOTSTART,
+ StorageUtl_ReadDWord(
+ headerBigBlock,
+ OFFSET_EXTBBDEPOTSTART,
&This->extBigBlockDepotStart);
StorageUtl_ReadDWord(
- headerBigBlock,
- OFFSET_EXTBBDEPOTCOUNT,
+ headerBigBlock,
+ OFFSET_EXTBBDEPOTCOUNT,
&This->extBigBlockDepotCount);
-
+
for (index = 0; index < COUNT_BBDEPOTINHEADER; index ++)
{
StorageUtl_ReadDWord(
- headerBigBlock,
+ headerBigBlock,
OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index),
&(This->bigBlockDepotStart[index]));
}
-
+
/*
* Make the bitwise arithmetic to get the size of the blocks in bytes.
*/
This->bigBlockSize = 0x000000001 >> (DWORD)This->bigBlockSizeBits;
This->smallBlockSize = 0x000000001 >> (DWORD)This->smallBlockSizeBits;
}
-
+
/*
- * Right now, the code is making some assumptions about the size of the
+ * Right now, the code is making some assumptions about the size of the
* blocks, just make sure they are what we're expecting.
*/
- assert( (This->bigBlockSize==DEF_BIG_BLOCK_SIZE) &&
- (This->smallBlockSize==DEF_SMALL_BLOCK_SIZE));
-
+ if (This->bigBlockSize != DEF_BIG_BLOCK_SIZE ||
+ This->smallBlockSize != DEF_SMALL_BLOCK_SIZE)
+ {
+ WARN("Broken OLE storage file\n");
+ hr = STG_E_INVALIDHEADER;
+ }
+ else
+ hr = S_OK;
+
/*
* Release the block.
*/
StorageImpl_ReleaseBigBlock(This, headerBigBlock);
-
- hr = S_OK;
}
-
+
return hr;
}
* Get a pointer to the big block of data containing the header.
*/
success = StorageImpl_ReadBigBlock(This, -1, headerBigBlock);
-
+
/*
* If the block read failed, the file is probably new.
*/
* Initialize for all unknown fields.
*/
memset(headerBigBlock, 0, BIG_BLOCK_SIZE);
-
+
/*
* Initialize the magic number.
*/
memcpy(headerBigBlock, STORAGE_magic, sizeof(STORAGE_magic));
-
+
/*
* And a bunch of things we don't know what they mean
*/
StorageUtl_WriteWord(headerBigBlock, 0x1a, 0x3);
StorageUtl_WriteWord(headerBigBlock, 0x1c, (WORD)-2);
StorageUtl_WriteDWord(headerBigBlock, 0x38, (DWORD)0x1000);
- StorageUtl_WriteDWord(headerBigBlock, 0x40, (DWORD)0x0001);
}
-
+
/*
* Write the information to the header.
*/
- if (headerBigBlock!=0)
- {
- StorageUtl_WriteWord(
- headerBigBlock,
- OFFSET_BIGBLOCKSIZEBITS,
- This->bigBlockSizeBits);
+ StorageUtl_WriteWord(
+ headerBigBlock,
+ OFFSET_BIGBLOCKSIZEBITS,
+ This->bigBlockSizeBits);
- StorageUtl_WriteWord(
- headerBigBlock,
- OFFSET_SMALLBLOCKSIZEBITS,
- This->smallBlockSizeBits);
+ StorageUtl_WriteWord(
+ headerBigBlock,
+ OFFSET_SMALLBLOCKSIZEBITS,
+ This->smallBlockSizeBits);
- StorageUtl_WriteDWord(
- headerBigBlock,
- OFFSET_BBDEPOTCOUNT,
- This->bigBlockDepotCount);
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_BBDEPOTCOUNT,
+ This->bigBlockDepotCount);
- StorageUtl_WriteDWord(
- headerBigBlock,
- OFFSET_ROOTSTARTBLOCK,
- This->rootStartBlock);
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_ROOTSTARTBLOCK,
+ This->rootStartBlock);
- StorageUtl_WriteDWord(
- headerBigBlock,
- OFFSET_SBDEPOTSTART,
- This->smallBlockDepotStart);
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_SBDEPOTSTART,
+ This->smallBlockDepotStart);
- StorageUtl_WriteDWord(
- headerBigBlock,
- OFFSET_EXTBBDEPOTSTART,
- This->extBigBlockDepotStart);
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_SBDEPOTCOUNT,
+ This->smallBlockDepotChain ?
+ BlockChainStream_GetCount(This->smallBlockDepotChain) : 0);
- StorageUtl_WriteDWord(
- headerBigBlock,
- OFFSET_EXTBBDEPOTCOUNT,
- This->extBigBlockDepotCount);
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_EXTBBDEPOTSTART,
+ This->extBigBlockDepotStart);
- for (index = 0; index < COUNT_BBDEPOTINHEADER; index ++)
- {
- StorageUtl_WriteDWord(
- headerBigBlock,
- OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index),
- (This->bigBlockDepotStart[index]));
- }
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_EXTBBDEPOTCOUNT,
+ This->extBigBlockDepotCount);
+
+ for (index = 0; index < COUNT_BBDEPOTINHEADER; index ++)
+ {
+ StorageUtl_WriteDWord(
+ headerBigBlock,
+ OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index),
+ (This->bigBlockDepotStart[index]));
}
-
+
/*
* Write the big block back to the file.
*/
BOOL readSuccessful;
ULONG bytesRead;
- offsetInPropSet.s.HighPart = 0;
- offsetInPropSet.s.LowPart = index * PROPSET_BLOCK_SIZE;
-
+ offsetInPropSet.u.HighPart = 0;
+ offsetInPropSet.u.LowPart = index * PROPSET_BLOCK_SIZE;
+
readSuccessful = BlockChainStream_ReadAt(
This->rootBlockChain,
offsetInPropSet,
PROPSET_BLOCK_SIZE,
currentProperty,
&bytesRead);
-
+
if (readSuccessful)
{
+ /* replace the name of root entry (often "Root Entry") by the file name */
+ WCHAR *propName = (index == This->base.rootPropertySetIndex) ?
+ This->filename : (WCHAR *)currentProperty+OFFSET_PS_NAME;
+
memset(buffer->name, 0, sizeof(buffer->name));
memcpy(
- buffer->name,
- currentProperty+OFFSET_PS_NAME,
+ buffer->name,
+ propName,
PROPERTY_NAME_BUFFER_LEN );
+ TRACE("storage name: %s\n", debugstr_w(buffer->name));
memcpy(&buffer->propertyType, currentProperty + OFFSET_PS_PROPERTYTYPE, 1);
-
+
StorageUtl_ReadWord(
- currentProperty,
- OFFSET_PS_NAMELENGTH,
+ currentProperty,
+ OFFSET_PS_NAMELENGTH,
&buffer->sizeOfNameString);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_PREVIOUSPROP,
+ currentProperty,
+ OFFSET_PS_PREVIOUSPROP,
&buffer->previousProperty);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_NEXTPROP,
+ currentProperty,
+ OFFSET_PS_NEXTPROP,
&buffer->nextProperty);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_DIRPROP,
+ currentProperty,
+ OFFSET_PS_DIRPROP,
&buffer->dirProperty);
StorageUtl_ReadGUID(
- currentProperty,
- OFFSET_PS_GUID,
+ currentProperty,
+ OFFSET_PS_GUID,
&buffer->propertyUniqueID);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_TSS1,
+ currentProperty,
+ OFFSET_PS_TSS1,
&buffer->timeStampS1);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_TSD1,
+ currentProperty,
+ OFFSET_PS_TSD1,
&buffer->timeStampD1);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_TSS2,
+ currentProperty,
+ OFFSET_PS_TSS2,
&buffer->timeStampS2);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_TSD2,
+ currentProperty,
+ OFFSET_PS_TSD2,
&buffer->timeStampD2);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_STARTBLOCK,
+ currentProperty,
+ OFFSET_PS_STARTBLOCK,
&buffer->startingBlock);
StorageUtl_ReadDWord(
- currentProperty,
- OFFSET_PS_SIZE,
- &buffer->size.s.LowPart);
+ currentProperty,
+ OFFSET_PS_SIZE,
+ &buffer->size.u.LowPart);
- buffer->size.s.HighPart = 0;
+ buffer->size.u.HighPart = 0;
}
return readSuccessful;
BOOL writeSuccessful;
ULONG bytesWritten;
- offsetInPropSet.s.HighPart = 0;
- offsetInPropSet.s.LowPart = index * PROPSET_BLOCK_SIZE;
+ offsetInPropSet.u.HighPart = 0;
+ offsetInPropSet.u.LowPart = index * PROPSET_BLOCK_SIZE;
memset(currentProperty, 0, PROPSET_BLOCK_SIZE);
memcpy(
- currentProperty + OFFSET_PS_NAME,
- buffer->name,
+ currentProperty + OFFSET_PS_NAME,
+ buffer->name,
PROPERTY_NAME_BUFFER_LEN );
memcpy(currentProperty + OFFSET_PS_PROPERTYTYPE, &buffer->propertyType, 1);
StorageUtl_WriteWord(
- currentProperty,
- OFFSET_PS_NAMELENGTH,
+ currentProperty,
+ OFFSET_PS_NAMELENGTH,
buffer->sizeOfNameString);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_PREVIOUSPROP,
+ currentProperty,
+ OFFSET_PS_PREVIOUSPROP,
buffer->previousProperty);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_NEXTPROP,
+ currentProperty,
+ OFFSET_PS_NEXTPROP,
buffer->nextProperty);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_DIRPROP,
+ currentProperty,
+ OFFSET_PS_DIRPROP,
buffer->dirProperty);
StorageUtl_WriteGUID(
- currentProperty,
- OFFSET_PS_GUID,
+ currentProperty,
+ OFFSET_PS_GUID,
&buffer->propertyUniqueID);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_TSS1,
+ currentProperty,
+ OFFSET_PS_TSS1,
buffer->timeStampS1);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_TSD1,
+ currentProperty,
+ OFFSET_PS_TSD1,
buffer->timeStampD1);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_TSS2,
+ currentProperty,
+ OFFSET_PS_TSS2,
buffer->timeStampS2);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_TSD2,
+ currentProperty,
+ OFFSET_PS_TSD2,
buffer->timeStampD2);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_STARTBLOCK,
+ currentProperty,
+ OFFSET_PS_STARTBLOCK,
buffer->startingBlock);
StorageUtl_WriteDWord(
- currentProperty,
- OFFSET_PS_SIZE,
- buffer->size.s.LowPart);
+ currentProperty,
+ OFFSET_PS_SIZE,
+ buffer->size.u.LowPart);
writeSuccessful = BlockChainStream_WriteAt(This->rootBlockChain,
offsetInPropSet,
memcpy(bigBlockBuffer, buffer, This->bigBlockSize);
StorageImpl_ReleaseBigBlock(This, bigBlockBuffer);
-
+
return TRUE;
}
-
+
return FALSE;
}
bbTempChain = BlockChainStream_Construct(This,
&bbHeadOfChain,
PROPERTY_NULL);
-
+ if(!bbTempChain) return NULL;
/*
* Grow the big block chain.
*/
* Copy the contents of the small block chain to the big block chain
* by small block size increments.
*/
- offset.s.LowPart = 0;
- offset.s.HighPart = 0;
+ offset.u.LowPart = 0;
+ offset.u.HighPart = 0;
cbTotalRead = 0;
cbTotalWritten = 0;
- buffer = (BYTE *) HeapAlloc(GetProcessHeap(),0,DEF_SMALL_BLOCK_SIZE);
+ buffer = HeapAlloc(GetProcessHeap(),0,DEF_SMALL_BLOCK_SIZE);
do
{
successRead = SmallBlockChainStream_ReadAt(*ppsbChain,
&cbWritten);
cbTotalWritten += cbWritten;
- offset.s.LowPart += This->smallBlockSize;
+ offset.u.LowPart += This->smallBlockSize;
} while (successRead && successWrite);
HeapFree(GetProcessHeap(),0,buffer);
* Destroy the small block chain.
*/
propertyIndex = (*ppsbChain)->ownerPropertyIndex;
- size.s.HighPart = 0;
- size.s.LowPart = 0;
+ size.u.HighPart = 0;
+ size.u.LowPart = 0;
SmallBlockChainStream_SetSize(*ppsbChain, size);
SmallBlockChainStream_Destroy(*ppsbChain);
*ppsbChain = 0;
return bigBlockChain;
}
-/******************************************************************************
-** Storage32InternalImpl implementation
-*/
-
-StorageInternalImpl* StorageInternalImpl_Construct(
- StorageImpl* ancestorStorage,
- ULONG rootPropertyIndex)
+void StorageInternalImpl_Destroy( StorageBaseImpl *iface)
{
- StorageInternalImpl* newStorage;
-
- /*
- * Allocate space for the new storage object
- */
- newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageInternalImpl));
-
- if (newStorage!=0)
- {
- memset(newStorage, 0, sizeof(StorageInternalImpl));
-
- /*
- * Initialize the virtual function table.
- */
- ICOM_VTBL(newStorage) = &Storage32InternalImpl_Vtbl;
- newStorage->v_destructor = &StorageInternalImpl_Destroy;
-
- /*
- * Keep the ancestor storage pointer and nail a reference to it.
- */
- newStorage->ancestorStorage = ancestorStorage;
- StorageBaseImpl_AddRef((IStorage*)(newStorage->ancestorStorage));
-
- /*
- * Keep the index of the root property set for this storage,
- */
- newStorage->rootPropertySetIndex = rootPropertyIndex;
-
- return newStorage;
- }
+ StorageInternalImpl* This = (StorageInternalImpl*) iface;
- return 0;
-}
-
-void StorageInternalImpl_Destroy(
- StorageInternalImpl* This)
-{
- StorageBaseImpl_Release((IStorage*)This->ancestorStorage);
+ StorageBaseImpl_Release((IStorage*)This->base.ancestorStorage);
HeapFree(GetProcessHeap(), 0, This);
}
** The non-root storages cannot be opened in transacted mode thus this function
** does nothing.
*/
-HRESULT WINAPI StorageInternalImpl_Commit(
+HRESULT WINAPI StorageInternalImpl_Commit(
IStorage* iface,
- DWORD grfCommitFlags) /* [in] */
+ DWORD grfCommitFlags) /* [in] */
{
return S_OK;
}
-
+
/******************************************************************************
**
** Storage32InternalImpl_Revert
** The non-root storages cannot be opened in transacted mode thus this function
** does nothing.
*/
-HRESULT WINAPI StorageInternalImpl_Revert(
+HRESULT WINAPI StorageInternalImpl_Revert(
IStorage* iface)
{
return S_OK;
}
-/******************************************************************************
-** IEnumSTATSTGImpl implementation
-*/
-
-IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
- StorageImpl* parentStorage,
- ULONG firstPropertyNode)
-{
- IEnumSTATSTGImpl* newEnumeration;
-
- newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl));
-
- if (newEnumeration!=0)
- {
- /*
- * Set-up the virtual function table and reference count.
- */
- ICOM_VTBL(newEnumeration) = &IEnumSTATSTGImpl_Vtbl;
- newEnumeration->ref = 0;
-
- /*
- * We want to nail-down the reference to the storage in case the
- * enumeration out-lives the storage in the client application.
- */
- newEnumeration->parentStorage = parentStorage;
- IStorage_AddRef((IStorage*)newEnumeration->parentStorage);
-
- newEnumeration->firstPropertyNode = firstPropertyNode;
-
- /*
- * Initialize the search stack
- */
- newEnumeration->stackSize = 0;
- newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT;
- newEnumeration->stackToVisit =
- HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG)*ENUMSTATSGT_SIZE_INCREMENT);
-
- /*
- * Make sure the current node of the iterator is the first one.
- */
- IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration);
- }
-
- return newEnumeration;
-}
-
void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This)
{
IStorage_Release((IStorage*)This->parentStorage);
/*
* Compare the riid with the interface IDs implemented by this object.
*/
- if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
- {
- *ppvObject = (IEnumSTATSTG*)This;
- }
- else if (memcmp(&IID_IStorage, riid, sizeof(IID_IEnumSTATSTG)) == 0)
+ if (IsEqualGUID(&IID_IUnknown, riid) ||
+ IsEqualGUID(&IID_IStorage, riid))
{
*ppvObject = (IEnumSTATSTG*)This;
+ IEnumSTATSTG_AddRef((IEnumSTATSTG*)This);
+ return S_OK;
}
- /*
- * Check that we obtained an interface.
- */
- if ((*ppvObject)==0)
- return E_NOINTERFACE;
-
- /*
- * Query Interface always increases the reference count by one when it is
- * successful
- */
- IEnumSTATSTGImpl_AddRef((IEnumSTATSTG*)This);
-
- return S_OK;
+ return E_NOINTERFACE;
}
-
+
ULONG WINAPI IEnumSTATSTGImpl_AddRef(
IEnumSTATSTG* iface)
{
IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface;
-
- This->ref++;
- return This->ref;
+ return InterlockedIncrement(&This->ref);
}
-
+
ULONG WINAPI IEnumSTATSTGImpl_Release(
IEnumSTATSTG* iface)
{
ULONG newRef;
- This->ref--;
- newRef = This->ref;
+ newRef = InterlockedDecrement(&This->ref);
/*
* If the reference count goes down to 0, perform suicide.
IEnumSTATSTGImpl_Destroy(This);
}
- return newRef;;
+ return newRef;
}
HRESULT WINAPI IEnumSTATSTGImpl_Next(
* Perform a sanity check on the parameters.
*/
if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) )
- return E_INVALIDARG;
-
+ return E_INVALIDARG;
+
/*
* To avoid the special case, get another pointer to a ULONG value if
* the caller didn't supply one.
*/
if (pceltFetched==0)
pceltFetched = &objectFetched;
-
+
/*
* Start the iteration, we will iterate until we hit the end of the
* linked list or until we hit the number of items to iterate through
*/
currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE);
- while ( ( *pceltFetched < celt) &&
+ while ( ( *pceltFetched < celt) &&
( currentSearchNode!=PROPERTY_NULL) )
{
- /*
+ /*
* Remove the top node from the stack
*/
IEnumSTATSTGImpl_PopSearchNode(This, TRUE);
* Read the property from the storage.
*/
StorageImpl_ReadProperty(This->parentStorage,
- currentSearchNode,
+ currentSearchNode,
¤tProperty);
/*
StorageUtl_CopyPropertyToSTATSTG(currentReturnStruct,
¤tProperty,
STATFLAG_DEFAULT);
-
+
/*
* Step to the next item in the iteration
*/
return S_FALSE;
}
-
+
HRESULT WINAPI IEnumSTATSTGImpl_Skip(
IEnumSTATSTG* iface,
ULONG celt)
*/
currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE);
- while ( (objectFetched < celt) &&
+ while ( (objectFetched < celt) &&
(currentSearchNode!=PROPERTY_NULL) )
{
- /*
+ /*
* Remove the top node from the stack
*/
IEnumSTATSTGImpl_PopSearchNode(This, TRUE);
* Read the property from the storage.
*/
StorageImpl_ReadProperty(This->parentStorage,
- currentSearchNode,
+ currentSearchNode,
¤tProperty);
-
+
/*
* Step to the next item in the iteration
*/
return S_FALSE;
}
-
+
HRESULT WINAPI IEnumSTATSTGImpl_Reset(
IEnumSTATSTG* iface)
{
*/
readSuccessful = StorageImpl_ReadProperty(
This->parentStorage,
- This->firstPropertyNode,
+ This->firstPropertyNode,
&rootProperty);
if (readSuccessful)
return S_OK;
}
-
+
HRESULT WINAPI IEnumSTATSTGImpl_Clone(
IEnumSTATSTG* iface,
IEnumSTATSTG** ppenum)
*/
if (ppenum==0)
return E_INVALIDARG;
-
+
newClone = IEnumSTATSTGImpl_Construct(This->parentStorage,
This->firstPropertyNode);
-
+
/*
* The new clone enumeration must point to the same current node as
* the ole one.
*/
newClone->stackSize = This->stackSize ;
newClone->stackMaxSize = This->stackMaxSize ;
- newClone->stackToVisit =
+ newClone->stackToVisit =
HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG) * newClone->stackMaxSize);
memcpy(
- newClone->stackToVisit,
- This->stackToVisit,
+ newClone->stackToVisit,
+ This->stackToVisit,
sizeof(ULONG) * newClone->stackSize);
*ppenum = (IEnumSTATSTG*)newClone;
INT IEnumSTATSTGImpl_FindParentProperty(
IEnumSTATSTGImpl *This,
- ULONG childProperty,
+ ULONG childProperty,
StgProperty *currentProperty,
ULONG *thisNodeId)
{
* Start with the node at the top of the stack.
*/
currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE);
-
+
while (currentSearchNode!=PROPERTY_NULL)
{
*/
*thisNodeId = currentSearchNode;
- /*
+ /*
* Remove the top node from the stack
*/
IEnumSTATSTGImpl_PopSearchNode(This, TRUE);
*/
StorageImpl_ReadProperty(
This->parentStorage,
- currentSearchNode,
+ currentSearchNode,
currentProperty);
-
+
if (currentProperty->previousProperty == childProperty)
return PROPERTY_RELATION_PREVIOUS;
- else if (currentProperty->nextProperty == childProperty)
+ else if (currentProperty->nextProperty == childProperty)
return PROPERTY_RELATION_NEXT;
-
+
else if (currentProperty->dirProperty == childProperty)
return PROPERTY_RELATION_DIR;
-
+
/*
* Push the next search node in the search stack.
*/
while (currentSearchNode!=PROPERTY_NULL)
{
- /*
+ /*
* Remove the top node from the stack
*/
IEnumSTATSTGImpl_PopSearchNode(This, TRUE);
* Read the property from the storage.
*/
StorageImpl_ReadProperty(This->parentStorage,
- currentSearchNode,
+ currentSearchNode,
currentProperty);
if ( propertyNameCmp(
- (OLECHAR*)currentProperty->name,
- (OLECHAR*)lpszPropName) == 0)
+ (const OLECHAR*)currentProperty->name,
+ (const OLECHAR*)lpszPropName) == 0)
return currentSearchNode;
/*
This->stackMaxSize += ENUMSTATSGT_SIZE_INCREMENT;
This->stackToVisit = HeapReAlloc(
- GetProcessHeap(),
+ GetProcessHeap(),
0,
This->stackToVisit,
sizeof(ULONG) * This->stackMaxSize);
*/
readSuccessful = StorageImpl_ReadProperty(
This->parentStorage,
- nodeToPush,
+ nodeToPush,
&rootProperty);
if (readSuccessful)
return topNode;
}
+/*
+ * Virtual function table for the IEnumSTATSTGImpl class.
+ */
+static const IEnumSTATSTGVtbl IEnumSTATSTGImpl_Vtbl =
+{
+ IEnumSTATSTGImpl_QueryInterface,
+ IEnumSTATSTGImpl_AddRef,
+ IEnumSTATSTGImpl_Release,
+ IEnumSTATSTGImpl_Next,
+ IEnumSTATSTGImpl_Skip,
+ IEnumSTATSTGImpl_Reset,
+ IEnumSTATSTGImpl_Clone
+};
+
+/******************************************************************************
+** IEnumSTATSTGImpl implementation
+*/
+
+IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
+ StorageImpl* parentStorage,
+ ULONG firstPropertyNode)
+{
+ IEnumSTATSTGImpl* newEnumeration;
+
+ newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl));
+
+ if (newEnumeration!=0)
+ {
+ /*
+ * Set-up the virtual function table and reference count.
+ */
+ newEnumeration->lpVtbl = &IEnumSTATSTGImpl_Vtbl;
+ newEnumeration->ref = 0;
+
+ /*
+ * We want to nail-down the reference to the storage in case the
+ * enumeration out-lives the storage in the client application.
+ */
+ newEnumeration->parentStorage = parentStorage;
+ IStorage_AddRef((IStorage*)newEnumeration->parentStorage);
+
+ newEnumeration->firstPropertyNode = firstPropertyNode;
+
+ /*
+ * Initialize the search stack
+ */
+ newEnumeration->stackSize = 0;
+ newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT;
+ newEnumeration->stackToVisit =
+ HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG)*ENUMSTATSGT_SIZE_INCREMENT);
+
+ /*
+ * Make sure the current node of the iterator is the first one.
+ */
+ IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration);
+ }
+
+ return newEnumeration;
+}
+
+/*
+ * Virtual function table for the Storage32InternalImpl class.
+ */
+static const IStorageVtbl Storage32InternalImpl_Vtbl =
+{
+ StorageBaseImpl_QueryInterface,
+ StorageBaseImpl_AddRef,
+ StorageBaseImpl_Release,
+ StorageBaseImpl_CreateStream,
+ StorageBaseImpl_OpenStream,
+ StorageImpl_CreateStorage,
+ StorageBaseImpl_OpenStorage,
+ StorageImpl_CopyTo,
+ StorageImpl_MoveElementTo,
+ StorageInternalImpl_Commit,
+ StorageInternalImpl_Revert,
+ StorageBaseImpl_EnumElements,
+ StorageImpl_DestroyElement,
+ StorageBaseImpl_RenameElement,
+ StorageImpl_SetElementTimes,
+ StorageBaseImpl_SetClass,
+ StorageImpl_SetStateBits,
+ StorageBaseImpl_Stat
+};
+
+/******************************************************************************
+** Storage32InternalImpl implementation
+*/
+
+StorageInternalImpl* StorageInternalImpl_Construct(
+ StorageImpl* ancestorStorage,
+ DWORD openFlags,
+ ULONG rootPropertyIndex)
+{
+ StorageInternalImpl* newStorage;
+
+ /*
+ * Allocate space for the new storage object
+ */
+ newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageInternalImpl));
+
+ if (newStorage!=0)
+ {
+ memset(newStorage, 0, sizeof(StorageInternalImpl));
+
+ /*
+ * Initialize the virtual function table.
+ */
+ newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;
+ newStorage->base.v_destructor = &StorageInternalImpl_Destroy;
+ newStorage->base.openFlags = openFlags;
+
+ /*
+ * Keep the ancestor storage pointer and nail a reference to it.
+ */
+ newStorage->base.ancestorStorage = ancestorStorage;
+ StorageBaseImpl_AddRef((IStorage*)(newStorage->base.ancestorStorage));
+
+ /*
+ * Keep the index of the root property set for this storage,
+ */
+ newStorage->base.rootPropertySetIndex = rootPropertyIndex;
+
+ return newStorage;
+ }
+
+ return 0;
+}
+
/******************************************************************************
** StorageUtl implementation
*/
-void StorageUtl_ReadWord(void* buffer, ULONG offset, WORD* value)
+void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value)
+{
+ WORD tmp;
+
+ memcpy(&tmp, buffer+offset, sizeof(WORD));
+ *value = le16toh(tmp);
+}
+
+void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value)
+{
+ value = htole16(value);
+ memcpy(buffer+offset, &value, sizeof(WORD));
+}
+
+void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value)
{
- memcpy(value, (BYTE*)buffer+offset, sizeof(WORD));
+ DWORD tmp;
+
+ memcpy(&tmp, buffer+offset, sizeof(DWORD));
+ *value = le32toh(tmp);
}
-void StorageUtl_WriteWord(void* buffer, ULONG offset, WORD value)
+void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value)
{
- memcpy((BYTE*)buffer+offset, &value, sizeof(WORD));
+ value = htole32(value);
+ memcpy(buffer+offset, &value, sizeof(DWORD));
}
-void StorageUtl_ReadDWord(void* buffer, ULONG offset, DWORD* value)
+void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,
+ ULARGE_INTEGER* value)
{
- memcpy(value, (BYTE*)buffer+offset, sizeof(DWORD));
+#ifdef WORDS_BIGENDIAN
+ ULARGE_INTEGER tmp;
+
+ memcpy(&tmp, buffer + offset, sizeof(ULARGE_INTEGER));
+ value->u.LowPart = htole32(tmp.u.HighPart);
+ value->u.HighPart = htole32(tmp.u.LowPart);
+#else
+ memcpy(value, buffer + offset, sizeof(ULARGE_INTEGER));
+#endif
}
-void StorageUtl_WriteDWord(void* buffer, ULONG offset, DWORD value)
+void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,
+ const ULARGE_INTEGER *value)
{
- memcpy((BYTE*)buffer+offset, &value, sizeof(DWORD));
+#ifdef WORDS_BIGENDIAN
+ ULARGE_INTEGER tmp;
+
+ tmp.u.LowPart = htole32(value->u.HighPart);
+ tmp.u.HighPart = htole32(value->u.LowPart);
+ memcpy(buffer + offset, &tmp, sizeof(ULARGE_INTEGER));
+#else
+ memcpy(buffer + offset, value, sizeof(ULARGE_INTEGER));
+#endif
}
-void StorageUtl_ReadGUID(void* buffer, ULONG offset, GUID* value)
+void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value)
{
StorageUtl_ReadDWord(buffer, offset, &(value->Data1));
StorageUtl_ReadWord(buffer, offset+4, &(value->Data2));
StorageUtl_ReadWord(buffer, offset+6, &(value->Data3));
- memcpy(value->Data4, (BYTE*)buffer+offset+8, sizeof(value->Data4));
+ memcpy(value->Data4, buffer+offset+8, sizeof(value->Data4));
}
-void StorageUtl_WriteGUID(void* buffer, ULONG offset, GUID* value)
+void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value)
{
StorageUtl_WriteDWord(buffer, offset, value->Data1);
StorageUtl_WriteWord(buffer, offset+4, value->Data2);
StorageUtl_WriteWord(buffer, offset+6, value->Data3);
- memcpy((BYTE*)buffer+offset+8, value->Data4, sizeof(value->Data4));
+ memcpy(buffer+offset+8, value->Data4, sizeof(value->Data4));
}
void StorageUtl_CopyPropertyToSTATSTG(
/*
* The copy of the string occurs only when the flag is not set
*/
- if ((statFlags & STATFLAG_NONAME) != 0)
+ if( ((statFlags & STATFLAG_NONAME) != 0) ||
+ (source->name == NULL) ||
+ (source->name[0] == 0) )
{
destination->pwcsName = 0;
}
else
{
- destination->pwcsName =
+ destination->pwcsName =
CoTaskMemAlloc((lstrlenW(source->name)+1)*sizeof(WCHAR));
- lstrcpyW((LPWSTR)destination->pwcsName, source->name);
+ strcpyW((LPWSTR)destination->pwcsName, source->name);
}
-
+
switch (source->propertyType)
{
case PROPTYPE_STORAGE:
break;
default:
destination->type = STGTY_STREAM;
- break;
+ break;
}
destination->cbSize = source->size;
-/*
+/*
currentReturnStruct->mtime = {0}; TODO
currentReturnStruct->ctime = {0};
- currentReturnStruct->atime = {0};
+ currentReturnStruct->atime = {0};
*/
destination->grfMode = 0;
- destination->grfLocksSupported = 0;
+ destination->grfLocksSupported = 0;
destination->clsid = source->propertyUniqueID;
- destination->grfStateBits = 0;
- destination->reserved = 0;
+ destination->grfStateBits = 0;
+ destination->reserved = 0;
}
/******************************************************************************
*/
BlockChainStream* BlockChainStream_Construct(
- StorageImpl* parentStorage,
+ StorageImpl* parentStorage,
ULONG* headOfStreamPlaceHolder,
ULONG propertyIndex)
{
newStream->numBlocks++;
newStream->tailIndex = blockIndex;
- blockIndex = StorageImpl_GetNextBlockInChain(
- parentStorage,
- blockIndex);
+ if(FAILED(StorageImpl_GetNextBlockInChain(
+ parentStorage,
+ blockIndex,
+ &blockIndex)))
+ {
+ HeapFree(GetProcessHeap(), 0, newStream);
+ return NULL;
+ }
}
return newStream;
*
* Returns the number of blocks that comprises this chain.
* This is not the size of the stream as the last block may not be full!
- *
+ *
*/
ULONG BlockChainStream_GetCount(BlockChainStream* This)
{
{
count++;
- blockIndex = StorageImpl_GetNextBlockInChain(
- This->parentStorage,
- blockIndex);
+ if(FAILED(StorageImpl_GetNextBlockInChain(
+ This->parentStorage,
+ blockIndex,
+ &blockIndex)))
+ return 0;
}
return count;
}
/******************************************************************************
- * BlockChainStream_ReadAt
+ * BlockChainStream_ReadAt
*
* Reads a specified number of bytes from this chain at the specified offset.
* bytesRead may be NULL.
void* buffer,
ULONG* bytesRead)
{
- ULONG blockNoInSequence = offset.s.LowPart / This->parentStorage->bigBlockSize;
- ULONG offsetInBlock = offset.s.LowPart % This->parentStorage->bigBlockSize;
+ ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->bigBlockSize;
+ ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->bigBlockSize;
ULONG bytesToReadInBuffer;
ULONG blockIndex;
BYTE* bufferWalker;
while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN))
{
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex);
-
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex, &blockIndex)))
+ return FALSE;
blockNoInSequence--;
}
*/
*bytesRead = 0;
bufferWalker = buffer;
-
+
while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
{
/*
* Calculate how many bytes we can copy from this big block.
*/
- bytesToReadInBuffer =
- MIN(This->parentStorage->bigBlockSize - offsetInBlock, size);
-
+ bytesToReadInBuffer =
+ min(This->parentStorage->bigBlockSize - offsetInBlock, size);
+
/*
* Copy those bytes to the buffer
*/
- bigBlockBuffer =
+ bigBlockBuffer =
StorageImpl_GetROBigBlock(This->parentStorage, blockIndex);
-
+
memcpy(bufferWalker, bigBlockBuffer + offsetInBlock, bytesToReadInBuffer);
-
+
StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer);
-
+
/*
* Step to the next big block.
*/
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex);
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex, &blockIndex)))
+ return FALSE;
bufferWalker += bytesToReadInBuffer;
size -= bytesToReadInBuffer;
offsetInBlock = 0; /* There is no offset on the next block */
}
-
+
return (size == 0);
}
const void* buffer,
ULONG* bytesWritten)
{
- ULONG blockNoInSequence = offset.s.LowPart / This->parentStorage->bigBlockSize;
- ULONG offsetInBlock = offset.s.LowPart % This->parentStorage->bigBlockSize;
+ ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->bigBlockSize;
+ ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->bigBlockSize;
ULONG bytesToWrite;
ULONG blockIndex;
- BYTE* bufferWalker;
+ const BYTE* bufferWalker;
BYTE* bigBlockBuffer;
/*
while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN))
{
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex);
-
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex,
+ &blockIndex)))
+ return FALSE;
blockNoInSequence--;
}
* This is OK since we don't intend to modify that buffer.
*/
*bytesWritten = 0;
- bufferWalker = (BYTE*)buffer;
+ bufferWalker = (const BYTE*)buffer;
while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
{
/*
* Calculate how many bytes we can copy from this big block.
*/
- bytesToWrite =
- MIN(This->parentStorage->bigBlockSize - offsetInBlock, size);
-
+ bytesToWrite =
+ min(This->parentStorage->bigBlockSize - offsetInBlock, size);
+
/*
* Copy those bytes to the buffer
*/
bigBlockBuffer = StorageImpl_GetBigBlock(This->parentStorage, blockIndex);
-
+
memcpy(bigBlockBuffer + offsetInBlock, bufferWalker, bytesToWrite);
-
+
StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer);
-
+
/*
* Step to the next big block.
*/
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex);
-
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex,
+ &blockIndex)))
+ return FALSE;
bufferWalker += bytesToWrite;
size -= bytesToWrite;
*bytesWritten += bytesToWrite;
offsetInBlock = 0; /* There is no offset on the next block */
}
-
+
return (size == 0);
}
/*
* Figure out how many blocks are needed to contain the new size
*/
- numBlocks = newSize.s.LowPart / This->parentStorage->bigBlockSize;
+ numBlocks = newSize.u.LowPart / This->parentStorage->bigBlockSize;
- if ((newSize.s.LowPart % This->parentStorage->bigBlockSize) != 0)
+ if ((newSize.u.LowPart % This->parentStorage->bigBlockSize) != 0)
numBlocks++;
blockIndex = BlockChainStream_GetHeadOfChain(This);
*/
while (count < numBlocks)
{
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex);
-
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex,
+ &blockIndex)))
+ return FALSE;
count++;
}
/* Get the next block before marking the new end */
- extraBlock =
- StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex);
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex,
+ &extraBlock)))
+ return FALSE;
/* Mark the new end of chain */
StorageImpl_SetNextBlockInChain(
- This->parentStorage,
- blockIndex,
+ This->parentStorage,
+ blockIndex,
BLOCK_END_OF_CHAIN);
This->tailIndex = blockIndex;
*/
while (extraBlock != BLOCK_END_OF_CHAIN)
{
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, extraBlock);
-
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, extraBlock,
+ &blockIndex)))
+ return FALSE;
StorageImpl_FreeBigBlock(This->parentStorage, extraBlock);
extraBlock = blockIndex;
}
assert(This->ownerPropertyIndex != PROPERTY_NULL);
StorageImpl_ReadProperty(
- This->parentStorage,
+ This->parentStorage,
This->ownerPropertyIndex,
&chainProp);
- chainProp.startingBlock = blockIndex;
+ chainProp.startingBlock = blockIndex;
StorageImpl_WriteProperty(
- This->parentStorage,
+ This->parentStorage,
This->ownerPropertyIndex,
&chainProp);
}
/*
* Figure out how many blocks are needed to contain this stream
*/
- newNumBlocks = newSize.s.LowPart / This->parentStorage->bigBlockSize;
+ newNumBlocks = newSize.u.LowPart / This->parentStorage->bigBlockSize;
- if ((newSize.s.LowPart % This->parentStorage->bigBlockSize) != 0)
+ if ((newSize.u.LowPart % This->parentStorage->bigBlockSize) != 0)
newNumBlocks++;
/*
This->numBlocks++;
currentBlock = blockIndex;
- blockIndex =
- StorageImpl_GetNextBlockInChain(This->parentStorage, currentBlock);
+ if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, currentBlock,
+ &blockIndex)))
+ return FALSE;
}
This->tailIndex = currentBlock;
blockIndex = StorageImpl_GetNextFreeBigBlock(This->parentStorage);
StorageImpl_SetNextBlockInChain(
- This->parentStorage,
- currentBlock,
+ This->parentStorage,
+ currentBlock,
blockIndex);
StorageImpl_SetNextBlockInChain(
- This->parentStorage,
- blockIndex,
+ This->parentStorage,
+ blockIndex,
BLOCK_END_OF_CHAIN);
currentBlock = blockIndex;
*
* TODO: Free the actual blocks in the file when we shrink the chain.
* Currently, the blocks are still in the file. So the file size
- * doesn't shrink even if we shrink streams.
+ * doesn't shrink even if we shrink streams.
*/
BOOL BlockChainStream_SetSize(
BlockChainStream* This,
{
ULARGE_INTEGER size = BlockChainStream_GetSize(This);
- if (newSize.s.LowPart == size.s.LowPart)
+ if (newSize.u.LowPart == size.u.LowPart)
return TRUE;
- if (newSize.s.LowPart < size.s.LowPart)
+ if (newSize.u.LowPart < size.u.LowPart)
{
BlockChainStream_Shrink(This, newSize);
}
else
{
- ULARGE_INTEGER fileSize =
+ ULARGE_INTEGER fileSize =
BIGBLOCKFILE_GetSize(This->parentStorage->bigBlockFile);
- ULONG diff = newSize.s.LowPart - size.s.LowPart;
+ ULONG diff = newSize.u.LowPart - size.u.LowPart;
/*
* Make sure the file stays a multiple of blocksize
*/
if ((diff % This->parentStorage->bigBlockSize) != 0)
- diff += (This->parentStorage->bigBlockSize -
+ diff += (This->parentStorage->bigBlockSize -
(diff % This->parentStorage->bigBlockSize) );
- fileSize.s.LowPart += diff;
+ fileSize.u.LowPart += diff;
BIGBLOCKFILE_SetSize(This->parentStorage->bigBlockFile, fileSize);
BlockChainStream_Enlarge(This, newSize);
if(This->headOfStreamPlaceHolder == NULL)
{
- /*
- * This chain is a data stream read the property and return
+ /*
+ * This chain is a data stream read the property and return
* the appropriate size
*/
StorageImpl_ReadProperty(
else
{
/*
- * this chain is a chain that does not have a property, figure out the
- * size by making the product number of used blocks times the
+ * this chain is a chain that does not have a property, figure out the
+ * size by making the product number of used blocks times the
* size of them
*/
ULARGE_INTEGER result;
- result.s.HighPart = 0;
+ result.u.HighPart = 0;
- result.s.LowPart =
- BlockChainStream_GetCount(This) *
+ result.u.LowPart =
+ BlockChainStream_GetCount(This) *
This->parentStorage->bigBlockSize;
return result;
*/
SmallBlockChainStream* SmallBlockChainStream_Construct(
- StorageImpl* parentStorage,
+ StorageImpl* parentStorage,
ULONG propertyIndex)
{
SmallBlockChainStream* newStream;
* SmallBlockChainStream_GetNextBlockInChain
*
* Returns the index of the next small block in this chain.
- *
+ *
* Return Values:
* - BLOCK_END_OF_CHAIN: end of this chain
* - BLOCK_UNUSED: small block 'blockIndex' is free
*/
-ULONG SmallBlockChainStream_GetNextBlockInChain(
+HRESULT SmallBlockChainStream_GetNextBlockInChain(
SmallBlockChainStream* This,
- ULONG blockIndex)
+ ULONG blockIndex,
+ ULONG* nextBlockInChain)
{
ULARGE_INTEGER offsetOfBlockInDepot;
DWORD buffer;
- ULONG nextBlockInChain = BLOCK_END_OF_CHAIN;
ULONG bytesRead;
BOOL success;
- offsetOfBlockInDepot.s.HighPart = 0;
- offsetOfBlockInDepot.s.LowPart = blockIndex * sizeof(ULONG);
+ *nextBlockInChain = BLOCK_END_OF_CHAIN;
+
+ offsetOfBlockInDepot.u.HighPart = 0;
+ offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG);
/*
* Read those bytes in the buffer from the small block file.
if (success)
{
- StorageUtl_ReadDWord(&buffer, 0, &nextBlockInChain);
+ StorageUtl_ReadDWord((BYTE *)&buffer, 0, nextBlockInChain);
+ return S_OK;
}
- return nextBlockInChain;
+ return STG_E_READFAULT;
}
/******************************************************************************
DWORD buffer;
ULONG bytesWritten;
- offsetOfBlockInDepot.s.HighPart = 0;
- offsetOfBlockInDepot.s.LowPart = blockIndex * sizeof(ULONG);
+ offsetOfBlockInDepot.u.HighPart = 0;
+ offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG);
- StorageUtl_WriteDWord(&buffer, 0, nextBlock);
+ StorageUtl_WriteDWord((BYTE *)&buffer, 0, nextBlock);
/*
* Read those bytes in the buffer from the small block file.
BOOL success = TRUE;
ULONG smallBlocksPerBigBlock;
- offsetOfBlockInDepot.s.HighPart = 0;
+ offsetOfBlockInDepot.u.HighPart = 0;
/*
* Scan the small block depot for a free block
*/
while (nextBlockIndex != BLOCK_UNUSED)
{
- offsetOfBlockInDepot.s.LowPart = blockIndex * sizeof(ULONG);
+ offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG);
success = BlockChainStream_ReadAt(
This->parentStorage->smallBlockDepotChain,
*/
if (success)
{
- StorageUtl_ReadDWord(&buffer, 0, &nextBlockIndex);
+ StorageUtl_ReadDWord((BYTE *)&buffer, 0, &nextBlockIndex);
if (nextBlockIndex != BLOCK_UNUSED)
blockIndex++;
}
else
{
- ULONG count =
+ ULONG count =
BlockChainStream_GetCount(This->parentStorage->smallBlockDepotChain);
ULONG sbdIndex = This->parentStorage->smallBlockDepotStart;
while (nextBlock != BLOCK_END_OF_CHAIN)
{
sbdIndex = nextBlock;
- nextBlock =
- StorageImpl_GetNextBlockInChain(This->parentStorage, sbdIndex);
+ StorageImpl_GetNextBlockInChain(This->parentStorage, sbdIndex, &nextBlock);
}
newsbdIndex = StorageImpl_GetNextFreeBigBlock(This->parentStorage);
if (sbdIndex != BLOCK_END_OF_CHAIN)
StorageImpl_SetNextBlockInChain(
- This->parentStorage,
- sbdIndex,
+ This->parentStorage,
+ sbdIndex,
newsbdIndex);
StorageImpl_SetNextBlockInChain(
- This->parentStorage,
- newsbdIndex,
+ This->parentStorage,
+ newsbdIndex,
BLOCK_END_OF_CHAIN);
/*
* Initialize all the small blocks to free
*/
- smallBlockDepot =
+ smallBlockDepot =
StorageImpl_GetBigBlock(This->parentStorage, newsbdIndex);
memset(smallBlockDepot, BLOCK_UNUSED, This->parentStorage->bigBlockSize);
* We have just created the small block depot.
*/
StgProperty rootProp;
- ULONG sbStartIndex;
+ ULONG sbStartIndex;
/*
* Save it in the header
StorageImpl_SaveFileHeader(This->parentStorage);
/*
- * And allocate the first big block that will contain small blocks
+ * And allocate the first big block that will contain small blocks
*/
- sbStartIndex =
+ sbStartIndex =
StorageImpl_GetNextFreeBigBlock(This->parentStorage);
StorageImpl_SetNextBlockInChain(
- This->parentStorage,
- sbStartIndex,
+ This->parentStorage,
+ sbStartIndex,
BLOCK_END_OF_CHAIN);
StorageImpl_ReadProperty(
- This->parentStorage,
- This->parentStorage->rootPropertySetIndex,
+ This->parentStorage,
+ This->parentStorage->base.rootPropertySetIndex,
&rootProp);
rootProp.startingBlock = sbStartIndex;
- rootProp.size.s.HighPart = 0;
- rootProp.size.s.LowPart = This->parentStorage->bigBlockSize;
+ rootProp.size.u.HighPart = 0;
+ rootProp.size.u.LowPart = This->parentStorage->bigBlockSize;
StorageImpl_WriteProperty(
- This->parentStorage,
- This->parentStorage->rootPropertySetIndex,
+ This->parentStorage,
+ This->parentStorage->base.rootPropertySetIndex,
&rootProp);
}
}
}
- smallBlocksPerBigBlock =
+ smallBlocksPerBigBlock =
This->parentStorage->bigBlockSize / This->parentStorage->smallBlockSize;
/*
ULONG blocksRequired = (blockIndex / smallBlocksPerBigBlock) + 1;
StorageImpl_ReadProperty(
- This->parentStorage,
- This->parentStorage->rootPropertySetIndex,
+ This->parentStorage,
+ This->parentStorage->base.rootPropertySetIndex,
&rootProp);
- if (rootProp.size.s.LowPart <
+ if (rootProp.size.u.LowPart <
(blocksRequired * This->parentStorage->bigBlockSize))
{
- rootProp.size.s.LowPart += This->parentStorage->bigBlockSize;
+ rootProp.size.u.LowPart += This->parentStorage->bigBlockSize;
BlockChainStream_SetSize(
- This->parentStorage->smallBlockRootChain,
+ This->parentStorage->smallBlockRootChain,
rootProp.size);
StorageImpl_WriteProperty(
- This->parentStorage,
- This->parentStorage->rootPropertySetIndex,
+ This->parentStorage,
+ This->parentStorage->base.rootPropertySetIndex,
&rootProp);
}
}
*
* Reads a specified number of bytes from this chain at the specified offset.
* bytesRead may be NULL.
- * Failure will be returned if the specified number of bytes has not been read.
+ * Failure will be returned if the specified number of bytes has not been read.
*/
BOOL SmallBlockChainStream_ReadAt(
SmallBlockChainStream* This,
ULONG* bytesRead)
{
ULARGE_INTEGER offsetInBigBlockFile;
- ULONG blockNoInSequence =
- offset.s.LowPart / This->parentStorage->smallBlockSize;
+ ULONG blockNoInSequence =
+ offset.u.LowPart / This->parentStorage->smallBlockSize;
- ULONG offsetInBlock = offset.s.LowPart % This->parentStorage->smallBlockSize;
+ ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->smallBlockSize;
ULONG bytesToReadInBuffer;
ULONG blockIndex;
ULONG bytesReadFromBigBlockFile;
/*
* This should never happen on a small block file.
*/
- assert(offset.s.HighPart==0);
+ assert(offset.u.HighPart==0);
/*
* Find the first block in the stream that contains part of the buffer.
while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN))
{
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
-
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex,
+ &blockIndex)))
+ return FALSE;
blockNoInSequence--;
}
/*
* Calculate how many bytes we can copy from this small block.
*/
- bytesToReadInBuffer =
- MIN(This->parentStorage->smallBlockSize - offsetInBlock, size);
+ bytesToReadInBuffer =
+ min(This->parentStorage->smallBlockSize - offsetInBlock, size);
/*
* Calculate the offset of the small block in the small block file.
*/
- offsetInBigBlockFile.s.HighPart = 0;
- offsetInBigBlockFile.s.LowPart =
+ offsetInBigBlockFile.u.HighPart = 0;
+ offsetInBigBlockFile.u.LowPart =
blockIndex * This->parentStorage->smallBlockSize;
- offsetInBigBlockFile.s.LowPart += offsetInBlock;
+ offsetInBigBlockFile.u.LowPart += offsetInBlock;
/*
* Read those bytes in the buffer from the small block file.
/*
* Step to the next big block.
*/
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, &blockIndex)))
+ return FALSE;
bufferWalker += bytesToReadInBuffer;
size -= bytesToReadInBuffer;
*bytesRead += bytesToReadInBuffer;
ULONG* bytesWritten)
{
ULARGE_INTEGER offsetInBigBlockFile;
- ULONG blockNoInSequence =
- offset.s.LowPart / This->parentStorage->smallBlockSize;
+ ULONG blockNoInSequence =
+ offset.u.LowPart / This->parentStorage->smallBlockSize;
- ULONG offsetInBlock = offset.s.LowPart % This->parentStorage->smallBlockSize;
+ ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->smallBlockSize;
ULONG bytesToWriteInBuffer;
ULONG blockIndex;
ULONG bytesWrittenFromBigBlockFile;
- BYTE* bufferWalker;
-
+ const BYTE* bufferWalker;
+
/*
* This should never happen on a small block file.
*/
- assert(offset.s.HighPart==0);
-
+ assert(offset.u.HighPart==0);
+
/*
* Find the first block in the stream that contains part of the buffer.
*/
blockIndex = SmallBlockChainStream_GetHeadOfChain(This);
-
+
while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN))
{
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
-
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, &blockIndex)))
+ return FALSE;
blockNoInSequence--;
}
-
+
/*
* Start writing the buffer.
*
* This is OK since we don't intend to modify that buffer.
*/
*bytesWritten = 0;
- bufferWalker = (BYTE*)buffer;
+ bufferWalker = (const BYTE*)buffer;
while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
{
/*
* Calculate how many bytes we can copy to this small block.
*/
- bytesToWriteInBuffer =
- MIN(This->parentStorage->smallBlockSize - offsetInBlock, size);
-
+ bytesToWriteInBuffer =
+ min(This->parentStorage->smallBlockSize - offsetInBlock, size);
+
/*
* Calculate the offset of the small block in the small block file.
*/
- offsetInBigBlockFile.s.HighPart = 0;
- offsetInBigBlockFile.s.LowPart =
+ offsetInBigBlockFile.u.HighPart = 0;
+ offsetInBigBlockFile.u.LowPart =
blockIndex * This->parentStorage->smallBlockSize;
- offsetInBigBlockFile.s.LowPart += offsetInBlock;
-
+ offsetInBigBlockFile.u.LowPart += offsetInBlock;
+
/*
* Write those bytes in the buffer to the small block file.
*/
bytesToWriteInBuffer,
bufferWalker,
&bytesWrittenFromBigBlockFile);
-
+
assert(bytesWrittenFromBigBlockFile == bytesToWriteInBuffer);
-
+
/*
* Step to the next big block.
*/
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex,
+ &blockIndex)))
+ return FALSE;
bufferWalker += bytesToWriteInBuffer;
size -= bytesToWriteInBuffer;
*bytesWritten += bytesToWriteInBuffer;
offsetInBlock = 0; /* There is no offset on the next block */
}
-
+
return (size == 0);
}
/******************************************************************************
* SmallBlockChainStream_Shrink
*
- * Shrinks this chain in the small block depot.
+ * Shrinks this chain in the small block depot.
*/
BOOL SmallBlockChainStream_Shrink(
SmallBlockChainStream* This,
ULONG numBlocks;
ULONG count = 0;
- numBlocks = newSize.s.LowPart / This->parentStorage->smallBlockSize;
+ numBlocks = newSize.u.LowPart / This->parentStorage->smallBlockSize;
- if ((newSize.s.LowPart % This->parentStorage->smallBlockSize) != 0)
+ if ((newSize.u.LowPart % This->parentStorage->smallBlockSize) != 0)
numBlocks++;
blockIndex = SmallBlockChainStream_GetHeadOfChain(This);
*/
while (count < numBlocks)
{
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex,
+ &blockIndex)))
+ return FALSE;
count++;
}
/*
* If the count is 0, we have a special case, the head of the chain was
- * just freed.
+ * just freed.
*/
if (count == 0)
{
StgProperty chainProp;
- StorageImpl_ReadProperty(This->parentStorage,
+ StorageImpl_ReadProperty(This->parentStorage,
This->ownerPropertyIndex,
&chainProp);
else
{
/* Get the next block before marking the new end */
- extraBlock = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex,
+ &extraBlock)))
+ return FALSE;
/* Mark the new end of chain */
SmallBlockChainStream_SetNextBlockInChain(
- This,
- blockIndex,
+ This,
+ blockIndex,
BLOCK_END_OF_CHAIN);
}
*/
while (extraBlock != BLOCK_END_OF_CHAIN)
{
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, extraBlock);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, extraBlock,
+ &blockIndex)))
+ return FALSE;
SmallBlockChainStream_FreeBlock(This, extraBlock);
extraBlock = blockIndex;
}
- return TRUE;
+ return TRUE;
}
/******************************************************************************
blockIndex = chainProp.startingBlock;
SmallBlockChainStream_SetNextBlockInChain(
- This,
- blockIndex,
+ This,
+ blockIndex,
BLOCK_END_OF_CHAIN);
}
/*
* Figure out how many blocks are needed to contain this stream
*/
- newNumBlocks = newSize.s.LowPart / This->parentStorage->smallBlockSize;
+ newNumBlocks = newSize.u.LowPart / This->parentStorage->smallBlockSize;
- if ((newSize.s.LowPart % This->parentStorage->smallBlockSize) != 0)
+ if ((newSize.u.LowPart % This->parentStorage->smallBlockSize) != 0)
newNumBlocks++;
/*
{
oldNumBlocks++;
currentBlock = blockIndex;
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, currentBlock);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, currentBlock, &blockIndex)))
+ return FALSE;
}
/*
SmallBlockChainStream_SetNextBlockInChain(This, currentBlock, blockIndex);
SmallBlockChainStream_SetNextBlockInChain(
- This,
- blockIndex,
+ This,
+ blockIndex,
BLOCK_END_OF_CHAIN);
currentBlock = blockIndex;
{
count++;
- blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex);
+ if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, &blockIndex)))
+ return 0;
}
return count;
*
* TODO: Free the actual blocks in the file when we shrink the chain.
* Currently, the blocks are still in the file. So the file size
- * doesn't shrink even if we shrink streams.
+ * doesn't shrink even if we shrink streams.
*/
BOOL SmallBlockChainStream_SetSize(
SmallBlockChainStream* This,
{
ULARGE_INTEGER size = SmallBlockChainStream_GetSize(This);
- if (newSize.s.LowPart == size.s.LowPart)
+ if (newSize.u.LowPart == size.u.LowPart)
return TRUE;
- if (newSize.s.LowPart < size.s.LowPart)
+ if (newSize.u.LowPart < size.u.LowPart)
{
SmallBlockChainStream_Shrink(This, newSize);
}
}
/******************************************************************************
- * StgCreateDocfile32 [OLE32.144]
+ * StgCreateDocfile [OLE32.@]
*/
HRESULT WINAPI StgCreateDocfile(
LPCOLESTR pwcsName,
{
StorageImpl* newStorage = 0;
HANDLE hFile = INVALID_HANDLE_VALUE;
- HRESULT hr = S_OK;
+ HRESULT hr = STG_E_INVALIDFLAG;
DWORD shareMode;
DWORD accessMode;
DWORD creationMode;
DWORD fileAttributes;
WCHAR tempFileName[MAX_PATH];
- TRACE("(%s, %lx, %ld, %p)\n",
- debugstr_w(pwcsName), grfMode,
+ TRACE("(%s, %lx, %ld, %p)\n",
+ debugstr_w(pwcsName), grfMode,
reserved, ppstgOpen);
/*
*/
if (ppstgOpen == 0)
return STG_E_INVALIDPOINTER;
+ if (reserved != 0)
+ return STG_E_INVALIDPARAMETER;
/*
* Validate the STGM flags
*/
if ( FAILED( validateSTGM(grfMode) ))
- return STG_E_INVALIDFLAG;
+ goto end;
+
+ /* StgCreateDocFile always opens for write */
+ switch(STGM_ACCESS_MODE(grfMode))
+ {
+ case STGM_WRITE:
+ case STGM_READWRITE:
+ break;
+ default:
+ goto end;
+ }
+
+ /* can't share write */
+ switch(STGM_SHARE_MODE(grfMode))
+ {
+ case STGM_SHARE_EXCLUSIVE:
+ case STGM_SHARE_DENY_WRITE:
+ break;
+ default:
+ goto end;
+ }
+
+ /* shared reading requires transacted mode */
+ if( STGM_SHARE_MODE(grfMode) == STGM_SHARE_DENY_WRITE &&
+ !(grfMode&STGM_TRANSACTED) )
+ goto end;
/*
* Generate a unique name.
if (pwcsName == 0)
{
WCHAR tempPath[MAX_PATH];
- WCHAR prefix[] = { 'S', 'T', 'O', 0 };
+ static const WCHAR prefix[] = { 'S', 'T', 'O', 0 };
+
+ if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE)
+ goto end;
memset(tempPath, 0, sizeof(tempPath));
memset(tempFileName, 0, sizeof(tempFileName));
if (GetTempFileNameW(tempPath, prefix, 0, tempFileName) != 0)
pwcsName = tempFileName;
else
- return STG_E_INSUFFICIENTMEMORY;
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+
+ creationMode = TRUNCATE_EXISTING;
+ }
+ else
+ {
+ creationMode = GetCreationModeFromSTGM(grfMode);
}
/*
- * Interpret the STGM value grfMode
+ * Interpret the STGM value grfMode
*/
shareMode = GetShareModeFromSTGM(grfMode);
accessMode = GetAccessModeFromSTGM(grfMode);
- creationMode = GetCreationModeFromSTGM(grfMode);
if (grfMode & STGM_DELETEONRELEASE)
fileAttributes = FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_DELETE_ON_CLOSE;
hFile = CreateFileW(pwcsName,
accessMode,
shareMode,
- NULL,
+ NULL,
creationMode,
fileAttributes,
- 0);
-
+ 0);
+
if (hFile == INVALID_HANDLE_VALUE)
{
- return E_FAIL;
+ if(GetLastError() == ERROR_FILE_EXISTS)
+ hr = STG_E_FILEALREADYEXISTS;
+ else
+ hr = E_FAIL;
+ goto end;
}
/*
* Allocate and initialize the new IStorage32object.
*/
newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl));
-
+
if (newStorage == 0)
- return STG_E_INSUFFICIENTMEMORY;
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
hr = StorageImpl_Construct(
newStorage,
hFile,
+ pwcsName,
NULL,
grfMode,
TRUE,
TRUE);
-
+
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, newStorage);
- return hr;
+ goto end;
}
/*
(IStorage*)newStorage,
(REFIID)&IID_IStorage,
(void**)ppstgOpen);
+end:
+ TRACE("<-- %p r = %08lx\n", *ppstgOpen, hr);
return hr;
}
/******************************************************************************
- * StgOpenStorage32 [OLE32.148]
+ * StgCreateStorageEx [OLE32.@]
+ */
+HRESULT WINAPI StgCreateStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen)
+{
+ TRACE("(%s, %lx, %lx, %lx, %p, %p, %p, %p)\n", debugstr_w(pwcsName),
+ grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen);
+
+ if (stgfmt != STGFMT_FILE && grfAttrs != 0)
+ {
+ ERR("grfAttrs must be 0 if stgfmt != STGFMT_FILE\n");
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (stgfmt != STGFMT_FILE && grfAttrs != 0 && grfAttrs != FILE_FLAG_NO_BUFFERING)
+ {
+ ERR("grfAttrs must be 0 or FILE_FLAG_NO_BUFFERING if stgfmt == STGFMT_FILE\n");
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (stgfmt == STGFMT_FILE)
+ {
+ ERR("Cannot use STGFMT_FILE - this is NTFS only\n");
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE)
+ {
+ FIXME("Stub: calling StgCreateDocfile, but ignoring pStgOptions and grfAttrs\n");
+ return StgCreateDocfile(pwcsName, grfMode, 0, (IStorage **)ppObjectOpen);
+ }
+
+ ERR("Invalid stgfmt argument\n");
+ return STG_E_INVALIDPARAMETER;
+}
+
+/******************************************************************************
+ * StgCreatePropSetStg [OLE32.@]
+ */
+HRESULT WINAPI StgCreatePropSetStg(IStorage *pstg, DWORD reserved,
+ IPropertySetStorage **ppPropSetStg)
+{
+ HRESULT hr;
+
+ TRACE("(%p, 0x%lx, %p): stub\n", pstg, reserved, ppPropSetStg);
+ if (reserved)
+ hr = STG_E_INVALIDPARAMETER;
+ else
+ hr = StorageBaseImpl_QueryInterface(pstg, &IID_IPropertySetStorage,
+ (void**)ppPropSetStg);
+ return hr;
+}
+
+/******************************************************************************
+ * StgOpenStorageEx [OLE32.@]
+ */
+HRESULT WINAPI StgOpenStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen)
+{
+ TRACE("(%s, %lx, %lx, %lx, %p, %p, %p, %p)\n", debugstr_w(pwcsName),
+ grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen);
+
+ if (stgfmt != STGFMT_DOCFILE && grfAttrs != 0)
+ {
+ ERR("grfAttrs must be 0 if stgfmt != STGFMT_DOCFILE\n");
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (stgfmt != STGFMT_DOCFILE && grfAttrs != 0 && grfAttrs != FILE_FLAG_NO_BUFFERING)
+ {
+ ERR("grfAttrs must be 0 or FILE_FLAG_NO_BUFFERING if stgfmt == STGFMT_DOCFILE\n");
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (stgfmt == STGFMT_FILE)
+ {
+ ERR("Cannot use STGFMT_FILE - this is NTFS only\n");
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE || stgfmt == STGFMT_ANY)
+ {
+ if (stgfmt == STGFMT_ANY)
+ WARN("STGFMT_ANY assuming storage\n");
+ FIXME("Stub: calling StgOpenStorage, but ignoring pStgOptions and grfAttrs\n");
+ return StgOpenStorage(pwcsName, NULL, grfMode, (SNB)NULL, 0, (IStorage **)ppObjectOpen);
+ }
+
+ ERR("Invalid stgfmt argument\n");
+ return STG_E_INVALIDPARAMETER;
+}
+
+
+/******************************************************************************
+ * StgOpenStorage [OLE32.@]
*/
HRESULT WINAPI StgOpenStorage(
const OLECHAR *pwcsName,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
- DWORD reserved,
+ DWORD reserved,
IStorage **ppstgOpen)
{
StorageImpl* newStorage = 0;
HANDLE hFile = 0;
DWORD shareMode;
DWORD accessMode;
+ WCHAR fullname[MAX_PATH];
+ DWORD length;
- TRACE("(%s, %p, %lx, %p, %ld, %p)\n",
+ TRACE("(%s, %p, %lx, %p, %ld, %p)\n",
debugstr_w(pwcsName), pstgPriority, grfMode,
snbExclude, reserved, ppstgOpen);
/*
- * Perform a sanity check
+ * Perform sanity checks
*/
- if (( pwcsName == 0) || (ppstgOpen == 0) )
- return STG_E_INVALIDPOINTER;
+ if (pwcsName == 0)
+ {
+ hr = STG_E_INVALIDNAME;
+ goto end;
+ }
+
+ if (ppstgOpen == 0)
+ {
+ hr = STG_E_INVALIDPOINTER;
+ goto end;
+ }
+
+ if (reserved)
+ {
+ hr = STG_E_INVALIDPARAMETER;
+ goto end;
+ }
+
+ /*
+ * Validate the sharing mode
+ */
+ switch(STGM_SHARE_MODE(grfMode))
+ {
+ case STGM_SHARE_EXCLUSIVE:
+ case STGM_SHARE_DENY_WRITE:
+ break;
+ default:
+ hr = STG_E_INVALIDFLAG;
+ goto end;
+ }
/*
* Validate the STGM flags
*/
- if ( FAILED( validateSTGM(grfMode) ))
- return STG_E_INVALIDFLAG;
+ if ( FAILED( validateSTGM(grfMode) ) ||
+ (grfMode&STGM_CREATE))
+ {
+ hr = STG_E_INVALIDFLAG;
+ goto end;
+ }
+
+ /* shared reading requires transacted mode */
+ if( STGM_SHARE_MODE(grfMode) == STGM_SHARE_DENY_WRITE &&
+ STGM_ACCESS_MODE(grfMode) == STGM_READWRITE &&
+ !(grfMode&STGM_TRANSACTED) )
+ {
+ hr = STG_E_INVALIDFLAG;
+ goto end;
+ }
/*
* Interpret the STGM value grfMode
* Initialize the "out" parameter.
*/
*ppstgOpen = 0;
-
- hFile = CreateFileW( pwcsName,
+
+ hFile = CreateFileW( pwcsName,
accessMode,
shareMode,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
0);
-
-
+
if (hFile==INVALID_HANDLE_VALUE)
{
- HRESULT hr = E_FAIL;
DWORD last_error = GetLastError();
+ hr = E_FAIL;
+
switch (last_error)
{
case ERROR_FILE_NOT_FOUND:
hr = E_FAIL;
}
- return hr;
+ goto end;
+ }
+
+ /*
+ * Refuse to open the file if it's too small to be a structured storage file
+ * FIXME: verify the file when reading instead of here
+ */
+ length = GetFileSize(hFile, NULL);
+ if (length < 0x100)
+ {
+ CloseHandle(hFile);
+ hr = STG_E_FILEALREADYEXISTS;
+ goto end;
}
/*
* Allocate and initialize the new IStorage32object.
*/
newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl));
-
+
if (newStorage == 0)
- return STG_E_INSUFFICIENTMEMORY;
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+ /* if the file's length was zero, initialize the storage */
hr = StorageImpl_Construct(
newStorage,
hFile,
+ pwcsName,
NULL,
grfMode,
TRUE,
- FALSE);
-
+ FALSE );
+
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, newStorage);
- return hr;
+ /*
+ * According to the docs if the file is not a storage, return STG_E_FILEALREADYEXISTS
+ */
+ if(hr == STG_E_INVALIDHEADER)
+ hr = STG_E_FILEALREADYEXISTS;
+ goto end;
}
-
+
+ /* prepare the file name string given in lieu of the root property name */
+ GetFullPathNameW(pwcsName, MAX_PATH, fullname, NULL);
+ memcpy(newStorage->filename, fullname, PROPERTY_NAME_BUFFER_LEN);
+ newStorage->filename[PROPERTY_NAME_BUFFER_LEN-1] = '\0';
+
/*
* Get an "out" pointer for the caller.
*/
(IStorage*)newStorage,
(REFIID)&IID_IStorage,
(void**)ppstgOpen);
-
+
+end:
+ TRACE("<-- %08lx, IStorage %p\n", hr, ppstgOpen ? *ppstgOpen : NULL);
return hr;
}
/******************************************************************************
- * StgCreateDocfileOnILockBytes [OLE32.145]
+ * StgCreateDocfileOnILockBytes [OLE32.@]
*/
HRESULT WINAPI StgCreateDocfileOnILockBytes(
ILockBytes *plkbyt,
hr = StorageImpl_Construct(
newStorage,
0,
+ 0,
plkbyt,
grfMode,
FALSE,
(REFIID)&IID_IStorage,
(void**)ppstgOpen);
- return hr;
+ return hr;
}
/******************************************************************************
- * StgOpenStorageOnILockBytes [OLE32.149]
+ * StgOpenStorageOnILockBytes [OLE32.@]
*/
HRESULT WINAPI StgOpenStorageOnILockBytes(
ILockBytes *plkbyt,
* Allocate and initialize the new IStorage object.
*/
newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl));
-
+
if (newStorage == 0)
return STG_E_INSUFFICIENTMEMORY;
hr = StorageImpl_Construct(
newStorage,
0,
+ 0,
plkbyt,
grfMode,
FALSE,
}
/******************************************************************************
- * StgSetTimes [ole32.150]
+ * StgSetTimes [ole32.@]
+ * StgSetTimes [OLE32.@]
*
*
*/
-HRESULT WINAPI StgSetTimes(WCHAR * str, FILETIME * a, FILETIME * b, FILETIME *c )
+HRESULT WINAPI StgSetTimes(OLECHAR const *str, FILETIME const *pctime,
+ FILETIME const *patime, FILETIME const *pmtime)
{
+ IStorage *stg = NULL;
+ HRESULT r;
- FIXME("(%p, %p, %p, %p),stub!\n", str, a, b, c);
- return FALSE;
+ TRACE("%s %p %p %p\n", debugstr_w(str), pctime, patime, pmtime);
+
+ r = StgOpenStorage(str, NULL, STGM_READWRITE | STGM_SHARE_DENY_WRITE,
+ 0, 0, &stg);
+ if( SUCCEEDED(r) )
+ {
+ r = IStorage_SetElementTimes(stg, NULL, pctime, patime, pmtime);
+ IStorage_Release(stg);
+ }
+
+ return r;
}
/******************************************************************************
- * StgIsStorageILockBytes [OLE32.147]
+ * StgIsStorageILockBytes [OLE32.@]
*
* Determines if the ILockBytes contains a storage object.
*/
BYTE sig[8];
ULARGE_INTEGER offset;
- offset.s.HighPart = 0;
- offset.s.LowPart = 0;
+ offset.u.HighPart = 0;
+ offset.u.LowPart = 0;
ILockBytes_ReadAt(plkbyt, offset, sig, sizeof(sig), NULL);
}
/******************************************************************************
- * WriteClassStg32 [OLE32.158]
+ * WriteClassStg [OLE32.@]
*
* This method will store the specified CLSID in the specified storage object
*/
return hRes;
}
-/*******************************************************************************************
- * ReadClassStg
+/***********************************************************************
+ * ReadClassStg (OLE32.@)
*
* This method reads the CLSID previously written to a storage object with the WriteClassStg.
*/
STATSTG pstatstg;
HRESULT hRes;
-
+
TRACE("()\n");
if(pclsid==NULL)
return hRes;
}
-/*************************************************************************************
- * OleLoadFromStream
+/***********************************************************************
+ * OleLoadFromStream (OLE32.@)
*
* This function loads an object from stream
*/
HRESULT WINAPI OleLoadFromStream(IStream *pStm,REFIID iidInterface,void** ppvObj)
{
- CLSID clsid;
- HRESULT res;
+ CLSID clsid;
+ HRESULT res;
+ LPPERSISTSTREAM xstm;
- FIXME("(),stub!\n");
+ TRACE("(%p,%s,%p)\n",pStm,debugstr_guid(iidInterface),ppvObj);
res=ReadClassStm(pStm,&clsid);
-
- if (SUCCEEDED(res)){
-
- res=CoCreateInstance(&clsid,NULL,CLSCTX_INPROC_SERVER,iidInterface,ppvObj);
-
- if (SUCCEEDED(res))
-
- res=IPersistStream_Load((IPersistStream*)ppvObj,pStm);
+ if (!SUCCEEDED(res))
+ return res;
+ res=CoCreateInstance(&clsid,NULL,CLSCTX_INPROC_SERVER,iidInterface,ppvObj);
+ if (!SUCCEEDED(res))
+ return res;
+ res=IUnknown_QueryInterface((IUnknown*)*ppvObj,&IID_IPersistStream,(LPVOID*)&xstm);
+ if (!SUCCEEDED(res)) {
+ IUnknown_Release((IUnknown*)*ppvObj);
+ return res;
}
-
+ res=IPersistStream_Load(xstm,pStm);
+ IPersistStream_Release(xstm);
+ /* FIXME: all refcounts ok at this point? I think they should be:
+ * pStm : unchanged
+ * ppvObj : 1
+ * xstm : 0 (released)
+ */
return res;
}
-/************************************************************************************************
- * OleSaveToStream
+/***********************************************************************
+ * OleSaveToStream (OLE32.@)
*
- * This function saves an object with the IPersistStream interface on it to the specified stream
+ * This function saves an object with the IPersistStream interface on it
+ * to the specified stream.
*/
HRESULT WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm)
{
CLSID clsid;
HRESULT res;
-
+
TRACE("(%p,%p)\n",pPStm,pStm);
res=IPersistStream_GetClassID(pPStm,&clsid);
if (SUCCEEDED(res)){
-
+
res=WriteClassStm(pStm,&clsid);
if (SUCCEEDED(res))
/****************************************************************************
* This method validate a STGM parameter that can contain the values below
*
+ * The stgm modes in 0x0000ffff are not bit masks, but distinct 4 bit values.
+ * The stgm values contained in 0xffff0000 are bitmasks.
+ *
* STGM_DIRECT 0x00000000
* STGM_TRANSACTED 0x00010000
* STGM_SIMPLE 0x08000000
- *
+ *
* STGM_READ 0x00000000
* STGM_WRITE 0x00000001
* STGM_READWRITE 0x00000002
- *
+ *
* STGM_SHARE_DENY_NONE 0x00000040
* STGM_SHARE_DENY_READ 0x00000030
* STGM_SHARE_DENY_WRITE 0x00000020
* STGM_SHARE_EXCLUSIVE 0x00000010
- *
+ *
* STGM_PRIORITY 0x00040000
* STGM_DELETEONRELEASE 0x04000000
*
*/
static HRESULT validateSTGM(DWORD stgm)
{
- BOOL bSTGM_TRANSACTED = ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED);
- BOOL bSTGM_SIMPLE = ((stgm & STGM_SIMPLE) == STGM_SIMPLE);
- BOOL bSTGM_DIRECT = ! (bSTGM_TRANSACTED || bSTGM_SIMPLE);
-
- BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE);
- BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE);
- BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE);
-
- BOOL bSTGM_SHARE_DENY_NONE =
- ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE);
-
- BOOL bSTGM_SHARE_DENY_READ =
- ((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ);
-
- BOOL bSTGM_SHARE_DENY_WRITE =
- ((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE);
-
- BOOL bSTGM_SHARE_EXCLUSIVE =
- ((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE);
-
- BOOL bSTGM_CREATE = ((stgm & STGM_CREATE) == STGM_CREATE);
- BOOL bSTGM_CONVERT = ((stgm & STGM_CONVERT) == STGM_CONVERT);
-
- BOOL bSTGM_NOSCRATCH = ((stgm & STGM_NOSCRATCH) == STGM_NOSCRATCH);
- BOOL bSTGM_NOSNAPSHOT = ((stgm & STGM_NOSNAPSHOT) == STGM_NOSNAPSHOT);
-
- /*
- * STGM_DIRECT | STGM_TRANSACTED | STGM_SIMPLE
- */
- if ( ! bSTGM_DIRECT )
- if( bSTGM_TRANSACTED && bSTGM_SIMPLE )
- return E_FAIL;
+ DWORD access = STGM_ACCESS_MODE(stgm);
+ DWORD share = STGM_SHARE_MODE(stgm);
+ DWORD create = STGM_CREATE_MODE(stgm);
- /*
- * STGM_WRITE | STGM_READWRITE | STGM_READ
- */
- if ( ! bSTGM_READ )
- if( bSTGM_WRITE && bSTGM_READWRITE )
- return E_FAIL;
+ if (stgm&~STGM_KNOWN_FLAGS)
+ {
+ ERR("unknown flags %08lx\n", stgm);
+ return E_FAIL;
+ }
+
+ switch (access)
+ {
+ case STGM_READ:
+ case STGM_WRITE:
+ case STGM_READWRITE:
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ switch (share)
+ {
+ case STGM_SHARE_DENY_NONE:
+ case STGM_SHARE_DENY_READ:
+ case STGM_SHARE_DENY_WRITE:
+ case STGM_SHARE_EXCLUSIVE:
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ switch (create)
+ {
+ case STGM_CREATE:
+ case STGM_FAILIFTHERE:
+ break;
+ default:
+ return E_FAIL;
+ }
/*
- * STGM_SHARE_DENY_NONE | others
- * (I assume here that DENY_READ implies DENY_WRITE)
+ * STGM_DIRECT | STGM_TRANSACTED | STGM_SIMPLE
*/
- if ( bSTGM_SHARE_DENY_NONE )
- if ( bSTGM_SHARE_DENY_READ ||
- bSTGM_SHARE_DENY_WRITE ||
- bSTGM_SHARE_EXCLUSIVE)
+ if ( (stgm & STGM_TRANSACTED) && (stgm & STGM_SIMPLE) )
return E_FAIL;
/*
* STGM_CREATE | STGM_CONVERT
* if both are false, STGM_FAILIFTHERE is set to TRUE
*/
- if ( bSTGM_CREATE && bSTGM_CONVERT )
+ if ( create == STGM_CREATE && (stgm & STGM_CONVERT) )
return E_FAIL;
/*
* STGM_NOSCRATCH requires STGM_TRANSACTED
*/
- if ( bSTGM_NOSCRATCH && ! bSTGM_TRANSACTED )
+ if ( (stgm & STGM_NOSCRATCH) && !(stgm & STGM_TRANSACTED) )
return E_FAIL;
-
+
/*
- * STGM_NOSNAPSHOT requires STGM_TRANSACTED and
+ * STGM_NOSNAPSHOT requires STGM_TRANSACTED and
* not STGM_SHARE_EXCLUSIVE or STGM_SHARE_DENY_WRITE`
*/
- if (bSTGM_NOSNAPSHOT)
- {
- if ( ! ( bSTGM_TRANSACTED &&
- !(bSTGM_SHARE_EXCLUSIVE || bSTGM_SHARE_DENY_WRITE)) )
+ if ( (stgm & STGM_NOSNAPSHOT) &&
+ (!(stgm & STGM_TRANSACTED) ||
+ share == STGM_SHARE_EXCLUSIVE ||
+ share == STGM_SHARE_DENY_WRITE) )
return E_FAIL;
- }
return S_OK;
}
* GetShareModeFromSTGM
*
* This method will return a share mode flag from a STGM value.
- * The STGM value is assumed valid.
+ * The STGM value is assumed valid.
*/
static DWORD GetShareModeFromSTGM(DWORD stgm)
{
- DWORD dwShareMode = 0;
- BOOL bSTGM_SHARE_DENY_NONE =
- ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE);
-
- BOOL bSTGM_SHARE_DENY_READ =
- ((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ);
-
- BOOL bSTGM_SHARE_DENY_WRITE =
- ((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE);
-
- BOOL bSTGM_SHARE_EXCLUSIVE =
- ((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE);
-
- if ((bSTGM_SHARE_EXCLUSIVE) || (bSTGM_SHARE_DENY_READ))
- dwShareMode = 0;
-
- if (bSTGM_SHARE_DENY_NONE)
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
-
- if (bSTGM_SHARE_DENY_WRITE)
- dwShareMode = FILE_SHARE_READ;
-
- return dwShareMode;
+ switch (STGM_SHARE_MODE(stgm))
+ {
+ case STGM_SHARE_DENY_NONE:
+ return FILE_SHARE_READ | FILE_SHARE_WRITE;
+ case STGM_SHARE_DENY_READ:
+ return FILE_SHARE_WRITE;
+ case STGM_SHARE_DENY_WRITE:
+ return FILE_SHARE_READ;
+ case STGM_SHARE_EXCLUSIVE:
+ return 0;
+ }
+ ERR("Invalid share mode!\n");
+ assert(0);
+ return 0;
}
/****************************************************************************
*/
static DWORD GetAccessModeFromSTGM(DWORD stgm)
{
- DWORD dwDesiredAccess = GENERIC_READ;
- BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE);
- BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE);
- BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE);
-
- if (bSTGM_READ)
- dwDesiredAccess = GENERIC_READ;
-
- if (bSTGM_WRITE)
- dwDesiredAccess |= GENERIC_WRITE;
-
- if (bSTGM_READWRITE)
- dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
-
- return dwDesiredAccess;
+ switch (STGM_ACCESS_MODE(stgm))
+ {
+ case STGM_READ:
+ return GENERIC_READ;
+ case STGM_WRITE:
+ case STGM_READWRITE:
+ return GENERIC_READ | GENERIC_WRITE;
+ }
+ ERR("Invalid access mode!\n");
+ assert(0);
+ return 0;
}
/****************************************************************************
*/
static DWORD GetCreationModeFromSTGM(DWORD stgm)
{
- if ( stgm & STGM_CREATE)
+ switch(STGM_CREATE_MODE(stgm))
+ {
+ case STGM_CREATE:
return CREATE_ALWAYS;
- if (stgm & STGM_CONVERT) {
+ case STGM_CONVERT:
FIXME("STGM_CONVERT not implemented!\n");
return CREATE_NEW;
+ case STGM_FAILIFTHERE:
+ return CREATE_NEW;
}
- /* All other cases */
- if (stgm & ~ (STGM_CREATE|STGM_CONVERT))
- FIXME("unhandled storage mode : 0x%08lx\n",stgm & ~ (STGM_CREATE|STGM_CONVERT));
- return CREATE_NEW;
+ ERR("Invalid create mode!\n");
+ assert(0);
+ return 0;
}
/*************************************************************************
- * OLECONVERT_LoadOLE10 [Internal]
+ * OLECONVERT_LoadOLE10 [Internal]
*
- * Loads the OLE10 STREAM to memory
+ * Loads the OLE10 STREAM to memory
*
* PARAMS
* pOleStream [I] The OLESTREAM
*
* NOTES
* This function is used by OleConvertOLESTREAMToIStorage only.
- *
+ *
* Memory allocated for pData must be freed by the caller
*/
HRESULT OLECONVERT_LoadOLE10(LPOLESTREAM pOleStream, OLECONVERT_OLESTREAM_DATA *pData, BOOL bStrem1)
{
if(pData->dwTypeID != 0)
{
- /* Get the lenght of the OleTypeName */
+ /* Get the length of the OleTypeName */
dwSize = pOleStream->lpstbl->Get(pOleStream, (void *) &(pData->dwOleTypeNameLength), sizeof(pData->dwOleTypeNameLength));
if(dwSize != sizeof(pData->dwOleTypeNameLength))
{
}
if(hRes == S_OK)
{
- if(pData->dwOleObjFileNameLength < 1) //there is no file name exist
+ if(pData->dwOleObjFileNameLength < 1) /* there is no file name exist */
pData->dwOleObjFileNameLength = sizeof(pData->dwOleObjFileNameLength);
- pData->pstrOleObjFileName = (CHAR *)malloc(pData->dwOleObjFileNameLength);
+ pData->pstrOleObjFileName = HeapAlloc(GetProcessHeap(), 0, pData->dwOleObjFileNameLength);
if(pData->pstrOleObjFileName)
{
dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)(pData->pstrOleObjFileName),pData->dwOleObjFileNameLength);
}
if(hRes == S_OK)
{
- /* Get the Lenght of the Data */
+ /* Get the Length of the Data */
dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwDataLength), sizeof(pData->dwDataLength));
if(dwSize != sizeof(pData->dwDataLength))
{
}
}
- if(hRes == S_OK) // I don't know what is this 8 byts information is we have to figure out
+ if(hRes == S_OK) /* I don't know what is this 8 byts information is we have to figure out */
{
- if(!bStrem1) //if it is a second OLE stream data
+ if(!bStrem1) /* if it is a second OLE stream data */
{
pData->dwDataLength -= 8;
dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)(pData->strUnknown), sizeof(pData->strUnknown));
{
if(pData->dwDataLength > 0)
{
- pData->pData = (BYTE *)HeapAlloc(GetProcessHeap(),0,pData->dwDataLength);
+ pData->pData = HeapAlloc(GetProcessHeap(),0,pData->dwDataLength);
/* Get Data (ex. IStorage, Metafile, or BMP) */
if(pData->pData)
}
/*************************************************************************
- * OLECONVERT_SaveOLE10 [Internal]
+ * OLECONVERT_SaveOLE10 [Internal]
*
- * Saves the OLE10 STREAM From memory
+ * Saves the OLE10 STREAM From memory
*
* PARAMS
* pData [I] Data Structure for the OLESTREAM Data
*
* NOTES
* This function is used by OleConvertIStorageToOLESTREAM only.
- *
+ *
*/
HRESULT OLECONVERT_SaveOLE10(OLECONVERT_OLESTREAM_DATA *pData, LPOLESTREAM pOleStream)
{
if(pData->dwOleID == OLESTREAM_ID && pData->dwTypeID != 0 && hRes == S_OK)
{
- /* Set the Lenght of the OleTypeName */
+ /* Set the Length of the OleTypeName */
dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwOleTypeNameLength), sizeof(pData->dwOleTypeNameLength));
if(dwSize != sizeof(pData->dwOleTypeNameLength))
{
if(hRes == S_OK)
{
- /* Set the lenght of the Data */
+ /* Set the length of the Data */
dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwDataLength), sizeof(pData->dwDataLength));
if(dwSize != sizeof(pData->dwDataLength))
{
}
/*************************************************************************
- * OLECONVERT_GetOLE20FromOLE10[Internal]
+ * OLECONVERT_GetOLE20FromOLE10[Internal]
*
* This function copies OLE10 Data (the IStorage in the OLESTREAM) to disk,
- * opens it, and copies the content to the dest IStorage for
+ * opens it, and copies the content to the dest IStorage for
* OleConvertOLESTREAMToIStorage
- *
+ *
*
* PARAMS
* pDestStorage [I] The IStorage to copy the data to
* Nothing
*
* NOTES
- *
- *
+ *
+ *
*/
void OLECONVERT_GetOLE20FromOLE10(LPSTORAGE pDestStorage, BYTE *pBuffer, DWORD nBufferLength)
{
IStorage *pTempStorage;
DWORD dwNumOfBytesWritten;
WCHAR wstrTempDir[MAX_PATH], wstrTempFile[MAX_PATH];
- WCHAR wstrPrefix[] = {'s', 'i', 's', 0};
+ static const WCHAR wstrPrefix[] = {'s', 'i', 's', 0};
/* Create a temp File */
GetTempPathW(MAX_PATH, wstrTempDir);
/*************************************************************************
- * OLECONVERT_WriteOLE20ToBuffer [Internal]
+ * OLECONVERT_WriteOLE20ToBuffer [Internal]
*
- * Saves the OLE10 STREAM From memory
+ * Saves the OLE10 STREAM From memory
*
* PARAMS
* pStorage [I] The Src IStorage to copy
* Memory allocated for pData must be freed by the caller
*
* Used by OleConvertIStorageToOLESTREAM only.
- *
+ *
*/
DWORD OLECONVERT_WriteOLE20ToBuffer(LPSTORAGE pStorage, BYTE **pData)
{
DWORD nDataLength = 0;
IStorage *pTempStorage;
WCHAR wstrTempDir[MAX_PATH], wstrTempFile[MAX_PATH];
- WCHAR wstrPrefix[] = {'s', 'i', 's', 0};
+ static const WCHAR wstrPrefix[] = {'s', 'i', 's', 0};
*pData = NULL;
-
+
/* Create temp Storage */
GetTempPathW(MAX_PATH, wstrTempDir);
GetTempFileNameW(wstrTempDir, wstrPrefix, 0, wstrTempFile);
if(hFile != INVALID_HANDLE_VALUE)
{
nDataLength = GetFileSize(hFile, NULL);
- *pData = (BYTE *) HeapAlloc(GetProcessHeap(),0,nDataLength);
+ *pData = HeapAlloc(GetProcessHeap(),0,nDataLength);
ReadFile(hFile, *pData, nDataLength, &nDataLength, 0);
CloseHandle(hFile);
}
}
/*************************************************************************
- * OLECONVERT_CreateOleStream [Internal]
+ * OLECONVERT_CreateOleStream [Internal]
*
- * Creates the "\001OLE" stream in the IStorage if neccessary.
+ * Creates the "\001OLE" stream in the IStorage if necessary.
*
* PARAMS
* pStorage [I] Dest storage to create the stream in
*
* This stream is still unknown, MS Word seems to have extra data
* but since the data is stored in the OLESTREAM there should be
- * no need to recreate the stream. If the stream is manually
+ * no need to recreate the stream. If the stream is manually
* deleted it will create it with this default data.
- *
+ *
*/
void OLECONVERT_CreateOleStream(LPSTORAGE pStorage)
{
HRESULT hRes;
IStream *pStream;
- WCHAR wstrStreamName[] = {1,'O', 'l', 'e', 0};
- BYTE pOleStreamHeader [] =
+ static const WCHAR wstrStreamName[] = {1,'O', 'l', 'e', 0};
+ BYTE pOleStreamHeader [] =
{
- 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
+ 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
};
-
+
/* Create stream if not present */
- hRes = IStorage_CreateStream(pStorage, wstrStreamName,
+ hRes = IStorage_CreateStream(pStorage, wstrStreamName,
STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream );
if(hRes == S_OK)
}
}
+/* write a string to a stream, preceded by its length */
+static HRESULT STREAM_WriteString( IStream *stm, LPCWSTR string )
+{
+ HRESULT r;
+ LPSTR str;
+ DWORD len = 0;
+
+ if( string )
+ len = WideCharToMultiByte( CP_ACP, 0, string, -1, NULL, 0, NULL, NULL);
+ r = IStream_Write( stm, &len, sizeof(len), NULL);
+ if( FAILED( r ) )
+ return r;
+ if(len == 0)
+ return r;
+ str = CoTaskMemAlloc( len );
+ WideCharToMultiByte( CP_ACP, 0, string, -1, str, len, NULL, NULL);
+ r = IStream_Write( stm, str, len, NULL);
+ CoTaskMemFree( str );
+ return r;
+}
+
+/* read a string preceded by its length from a stream */
+static HRESULT STREAM_ReadString( IStream *stm, LPWSTR *string )
+{
+ HRESULT r;
+ DWORD len, count = 0;
+ LPSTR str;
+ LPWSTR wstr;
+
+ r = IStream_Read( stm, &len, sizeof(len), &count );
+ if( FAILED( r ) )
+ return r;
+ if( count != sizeof(len) )
+ return E_OUTOFMEMORY;
+
+ TRACE("%ld bytes\n",len);
+
+ str = CoTaskMemAlloc( len );
+ if( !str )
+ return E_OUTOFMEMORY;
+ count = 0;
+ r = IStream_Read( stm, str, len, &count );
+ if( FAILED( r ) )
+ return r;
+ if( count != len )
+ {
+ CoTaskMemFree( str );
+ return E_OUTOFMEMORY;
+ }
+
+ TRACE("Read string %s\n",debugstr_an(str,len));
+
+ len = MultiByteToWideChar( CP_ACP, 0, str, count, NULL, 0 );
+ wstr = CoTaskMemAlloc( (len + 1)*sizeof (WCHAR) );
+ if( wstr )
+ MultiByteToWideChar( CP_ACP, 0, str, count, wstr, len );
+ CoTaskMemFree( str );
+
+ *string = wstr;
+
+ return r;
+}
+
+
+static HRESULT STORAGE_WriteCompObj( LPSTORAGE pstg, CLSID *clsid,
+ LPCWSTR lpszUserType, LPCWSTR szClipName, LPCWSTR szProgIDName )
+{
+ IStream *pstm;
+ HRESULT r = S_OK;
+ static const WCHAR szwStreamName[] = {1, 'C', 'o', 'm', 'p', 'O', 'b', 'j', 0};
+
+ static const BYTE unknown1[12] =
+ { 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF};
+ static const BYTE unknown2[16] =
+ { 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ TRACE("%p %s %s %s %s\n", pstg, debugstr_guid(clsid),
+ debugstr_w(lpszUserType), debugstr_w(szClipName),
+ debugstr_w(szProgIDName));
+
+ /* Create a CompObj stream if it doesn't exist */
+ r = IStorage_CreateStream(pstg, szwStreamName,
+ STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pstm );
+ if( FAILED (r) )
+ return r;
+
+ /* Write CompObj Structure to stream */
+ r = IStream_Write(pstm, unknown1, sizeof(unknown1), NULL);
+
+ if( SUCCEEDED( r ) )
+ r = WriteClassStm( pstm, clsid );
+
+ if( SUCCEEDED( r ) )
+ r = STREAM_WriteString( pstm, lpszUserType );
+ if( SUCCEEDED( r ) )
+ r = STREAM_WriteString( pstm, szClipName );
+ if( SUCCEEDED( r ) )
+ r = STREAM_WriteString( pstm, szProgIDName );
+ if( SUCCEEDED( r ) )
+ r = IStream_Write(pstm, unknown2, sizeof(unknown2), NULL);
+
+ IStream_Release( pstm );
+
+ return r;
+}
+
+/***********************************************************************
+ * WriteFmtUserTypeStg (OLE32.@)
+ */
+HRESULT WINAPI WriteFmtUserTypeStg(
+ LPSTORAGE pstg, CLIPFORMAT cf, LPOLESTR lpszUserType)
+{
+ HRESULT r;
+ WCHAR szwClipName[0x40];
+ CLSID clsid = CLSID_NULL;
+ LPWSTR wstrProgID = NULL;
+ DWORD n;
+
+ TRACE("(%p,%x,%s)\n",pstg,cf,debugstr_w(lpszUserType));
+
+ /* get the clipboard format name */
+ n = GetClipboardFormatNameW( cf, szwClipName, sizeof(szwClipName) );
+ szwClipName[n]=0;
+
+ TRACE("Clipboard name is %s\n", debugstr_w(szwClipName));
+
+ /* FIXME: There's room to save a CLSID and its ProgID, but
+ the CLSID is not looked up in the registry and in all the
+ tests I wrote it was CLSID_NULL. Where does it come from?
+ */
+
+ /* get the real program ID. This may fail, but that's fine */
+ ProgIDFromCLSID(&clsid, &wstrProgID);
+
+ TRACE("progid is %s\n",debugstr_w(wstrProgID));
+
+ r = STORAGE_WriteCompObj( pstg, &clsid,
+ lpszUserType, szwClipName, wstrProgID );
+
+ CoTaskMemFree(wstrProgID);
+
+ return r;
+}
+
+
+/******************************************************************************
+ * ReadFmtUserTypeStg [OLE32.@]
+ */
+HRESULT WINAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT* pcf, LPOLESTR* lplpszUserType)
+{
+ HRESULT r;
+ IStream *stm = 0;
+ static const WCHAR szCompObj[] = { 1, 'C','o','m','p','O','b','j', 0 };
+ unsigned char unknown1[12];
+ unsigned char unknown2[16];
+ DWORD count;
+ LPWSTR szProgIDName = NULL, szCLSIDName = NULL, szOleTypeName = NULL;
+ CLSID clsid;
+
+ TRACE("(%p,%p,%p)\n", pstg, pcf, lplpszUserType);
+
+ r = IStorage_OpenStream( pstg, szCompObj, NULL,
+ STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
+ if( FAILED ( r ) )
+ {
+ WARN("Failed to open stream r = %08lx\n", r);
+ return r;
+ }
+
+ /* read the various parts of the structure */
+ r = IStream_Read( stm, unknown1, sizeof(unknown1), &count );
+ if( FAILED( r ) || ( count != sizeof(unknown1) ) )
+ goto end;
+ r = ReadClassStm( stm, &clsid );
+ if( FAILED( r ) )
+ goto end;
+
+ r = STREAM_ReadString( stm, &szCLSIDName );
+ if( FAILED( r ) )
+ goto end;
+
+ r = STREAM_ReadString( stm, &szOleTypeName );
+ if( FAILED( r ) )
+ goto end;
+
+ r = STREAM_ReadString( stm, &szProgIDName );
+ if( FAILED( r ) )
+ goto end;
+
+ r = IStream_Read( stm, unknown2, sizeof(unknown2), &count );
+ if( FAILED( r ) || ( count != sizeof(unknown2) ) )
+ goto end;
+
+ /* ok, success... now we just need to store what we found */
+ if( pcf )
+ *pcf = RegisterClipboardFormatW( szOleTypeName );
+ CoTaskMemFree( szOleTypeName );
+
+ if( lplpszUserType )
+ *lplpszUserType = szCLSIDName;
+ CoTaskMemFree( szProgIDName );
+
+end:
+ IStream_Release( stm );
+
+ return r;
+}
+
/*************************************************************************
- * OLECONVERT_CreateCompObjStream [Internal]
+ * OLECONVERT_CreateCompObjStream [Internal]
*
* Creates a "\001CompObj" is the destination IStorage if necessary.
*
* PARAMS
- * pStorage [I] The dest IStorage to create the CompObj Stream
+ * pStorage [I] The dest IStorage to create the CompObj Stream
* if necessary.
* strOleTypeName [I] The ProgID
*
* This function is used by OleConvertOLESTREAMToIStorage only.
*
* The stream data is stored in the OLESTREAM and there should be
- * no need to recreate the stream. If the stream is manually
+ * no need to recreate the stream. If the stream is manually
* deleted it will attempt to create it by querying the registry.
*
- *
+ *
*/
HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName)
{
IStream *pStream;
HRESULT hStorageRes, hRes = S_OK;
OLECONVERT_ISTORAGE_COMPOBJ IStorageCompObj;
- WCHAR wstrStreamName[] = {1,'C', 'o', 'm', 'p', 'O', 'b', 'j', 0};
+ static const WCHAR wstrStreamName[] = {1,'C', 'o', 'm', 'p', 'O', 'b', 'j', 0};
+ WCHAR bufferW[OLESTREAM_MAX_STR_LEN];
BYTE pCompObjUnknown1[] = {0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
BYTE pCompObjUnknown2[] = {0xF4, 0x39, 0xB2, 0x71};
/* Create a CompObj stream if it doesn't exist */
- hStorageRes = IStorage_CreateStream(pStorage, wstrStreamName,
+ hStorageRes = IStorage_CreateStream(pStorage, wstrStreamName,
STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream );
if(hStorageRes == S_OK)
{
strcpy(IStorageCompObj.strOleTypeName, strOleTypeName);
/* copy the OleTypeName to the compobj struct */
- /* Note: in the test made, these where Identical */
+ /* Note: in the test made, these were Identical */
IStorageCompObj.dwProgIDNameLength = strlen(strOleTypeName)+1;
strcpy(IStorageCompObj.strProgIDName, strOleTypeName);
/* Get the CLSID */
- hRes = CLSIDFromProgID16(IStorageCompObj.strProgIDName, &(IStorageCompObj.clsid));
+ MultiByteToWideChar( CP_ACP, 0, IStorageCompObj.strProgIDName, -1,
+ bufferW, OLESTREAM_MAX_STR_LEN );
+ hRes = CLSIDFromProgID(bufferW, &(IStorageCompObj.clsid));
- if(hRes != S_OK)
- {
- hRes = REGDB_E_CLASSNOTREG;
- }
- else
+ if(hRes == S_OK)
{
HKEY hKey;
LONG hErr;
/* Get the CLSID Default Name from the Registry */
- hErr = RegOpenKeyA(HKEY_CLASSES_ROOT, IStorageCompObj.strProgIDName, &hKey);
+ hErr = RegOpenKeyA(HKEY_CLASSES_ROOT, IStorageCompObj.strProgIDName, &hKey);
if(hErr == ERROR_SUCCESS)
{
char strTemp[OLESTREAM_MAX_STR_LEN];
}
RegCloseKey(hKey);
}
- if(hErr != ERROR_SUCCESS)
- {
- hRes = REGDB_E_CLASSNOTREG;
- }
}
- if(hRes == S_OK )
+ /* Write CompObj Structure to stream */
+ hRes = IStream_Write(pStream, IStorageCompObj.byUnknown1, sizeof(IStorageCompObj.byUnknown1), NULL);
+
+ WriteClassStm(pStream,&(IStorageCompObj.clsid));
+
+ hRes = IStream_Write(pStream, &(IStorageCompObj.dwCLSIDNameLength), sizeof(IStorageCompObj.dwCLSIDNameLength), NULL);
+ if(IStorageCompObj.dwCLSIDNameLength > 0)
{
- /* Write CompObj Structure to stream */
- hRes = IStream_Write(pStream, IStorageCompObj.byUnknown1, sizeof(IStorageCompObj.byUnknown1), NULL);
- hRes = IStream_Write(pStream, &(IStorageCompObj.clsid) , sizeof(IStorageCompObj.clsid ), NULL);
- hRes = IStream_Write(pStream, &(IStorageCompObj.dwCLSIDNameLength), sizeof(IStorageCompObj.dwCLSIDNameLength), NULL);
- if(IStorageCompObj.dwCLSIDNameLength > 0)
- {
- hRes = IStream_Write(pStream, IStorageCompObj.strCLSIDName, IStorageCompObj.dwCLSIDNameLength, NULL);
- }
- hRes = IStream_Write(pStream, &(IStorageCompObj.dwOleTypeNameLength) , sizeof(IStorageCompObj.dwOleTypeNameLength), NULL);
- if(IStorageCompObj.dwOleTypeNameLength > 0)
- {
- hRes = IStream_Write(pStream, IStorageCompObj.strOleTypeName , IStorageCompObj.dwOleTypeNameLength, NULL);
- }
- hRes = IStream_Write(pStream, &(IStorageCompObj.dwProgIDNameLength) , sizeof(IStorageCompObj.dwProgIDNameLength), NULL);
- if(IStorageCompObj.dwProgIDNameLength > 0)
- {
- hRes = IStream_Write(pStream, IStorageCompObj.strProgIDName , IStorageCompObj.dwProgIDNameLength, NULL);
- }
- hRes = IStream_Write(pStream, IStorageCompObj.byUnknown2 , sizeof(IStorageCompObj.byUnknown2), NULL);
+ hRes = IStream_Write(pStream, IStorageCompObj.strCLSIDName, IStorageCompObj.dwCLSIDNameLength, NULL);
+ }
+ hRes = IStream_Write(pStream, &(IStorageCompObj.dwOleTypeNameLength) , sizeof(IStorageCompObj.dwOleTypeNameLength), NULL);
+ if(IStorageCompObj.dwOleTypeNameLength > 0)
+ {
+ hRes = IStream_Write(pStream, IStorageCompObj.strOleTypeName , IStorageCompObj.dwOleTypeNameLength, NULL);
+ }
+ hRes = IStream_Write(pStream, &(IStorageCompObj.dwProgIDNameLength) , sizeof(IStorageCompObj.dwProgIDNameLength), NULL);
+ if(IStorageCompObj.dwProgIDNameLength > 0)
+ {
+ hRes = IStream_Write(pStream, IStorageCompObj.strProgIDName , IStorageCompObj.dwProgIDNameLength, NULL);
}
+ hRes = IStream_Write(pStream, IStorageCompObj.byUnknown2 , sizeof(IStorageCompObj.byUnknown2), NULL);
IStream_Release(pStream);
}
return hRes;
/*************************************************************************
- * OLECONVERT_CreateOlePresStream[Internal]
+ * OLECONVERT_CreateOlePresStream[Internal]
*
* Creates the "\002OlePres000" Stream with the Metafile data
*
* PARAMS
* pStorage [I] The dest IStorage to create \002OLEPres000 stream in.
* dwExtentX [I] Width of the Metafile
- * dwExtentY [I] Height of the Metafile
+ * dwExtentY [I] Height of the Metafile
* pData [I] Metafile data
* dwDataLength [I] Size of the Metafile data
*
*
* NOTES
* This function is used by OleConvertOLESTREAMToIStorage only.
- *
+ *
*/
void OLECONVERT_CreateOlePresStream(LPSTORAGE pStorage, DWORD dwExtentX, DWORD dwExtentY , BYTE *pData, DWORD dwDataLength)
{
HRESULT hRes;
IStream *pStream;
- WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
- BYTE pOlePresStreamHeader [] =
+ static const WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
+ BYTE pOlePresStreamHeader [] =
{
- 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
- BYTE pOlePresStreamHeaderEmpty [] =
+ BYTE pOlePresStreamHeaderEmpty [] =
{
- 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
-
+
/* Create the OlePres000 Stream */
- hRes = IStorage_CreateStream(pStorage, wstrStreamName,
+ hRes = IStorage_CreateStream(pStorage, wstrStreamName,
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream );
if(hRes == S_OK)
OlePres.dwExtentX = dwExtentX;
OlePres.dwExtentY = -dwExtentY;
- /* Set Data and Lenght */
+ /* Set Data and Length */
if(dwDataLength > sizeof(METAFILEPICT16))
{
OlePres.dwSize = dwDataLength - sizeof(METAFILEPICT16);
}
/*************************************************************************
- * OLECONVERT_CreateOle10NativeStream [Internal]
+ * OLECONVERT_CreateOle10NativeStream [Internal]
*
* Creates the "\001Ole10Native" Stream (should contain a BMP)
*
* This function is used by OleConvertOLESTREAMToIStorage only.
*
* Might need to verify the data and return appropriate error message
- *
+ *
*/
void OLECONVERT_CreateOle10NativeStream(LPSTORAGE pStorage, BYTE *pData, DWORD dwDataLength)
{
HRESULT hRes;
IStream *pStream;
- WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0};
-
+ static const WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0};
+
/* Create the Ole10Native Stream */
- hRes = IStorage_CreateStream(pStorage, wstrStreamName,
+ hRes = IStorage_CreateStream(pStorage, wstrStreamName,
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream );
if(hRes == S_OK)
}
/*************************************************************************
- * OLECONVERT_GetOLE10ProgID [Internal]
+ * OLECONVERT_GetOLE10ProgID [Internal]
*
* Finds the ProgID (or OleTypeID) from the IStorage
*
* NOTES
* This function is used by OleConvertIStorageToOLESTREAM only.
*
- *
+ *
*/
HRESULT OLECONVERT_GetOLE10ProgID(LPSTORAGE pStorage, char *strProgID, DWORD *dwSize)
{
IStream *pStream;
LARGE_INTEGER iSeekPos;
OLECONVERT_ISTORAGE_COMPOBJ CompObj;
- WCHAR wstrStreamName[] = {1,'C', 'o', 'm', 'p', 'O', 'b', 'j', 0};
+ static const WCHAR wstrStreamName[] = {1,'C', 'o', 'm', 'p', 'O', 'b', 'j', 0};
/* Open the CompObj Stream */
- hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL,
+ hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream );
if(hRes == S_OK)
{
/*Get the OleType from the CompObj Stream */
- iSeekPos.s.LowPart = sizeof(CompObj.byUnknown1) + sizeof(CompObj.clsid);
- iSeekPos.s.HighPart = 0;
+ iSeekPos.u.LowPart = sizeof(CompObj.byUnknown1) + sizeof(CompObj.clsid);
+ iSeekPos.u.HighPart = 0;
IStream_Seek(pStream, iSeekPos, STREAM_SEEK_SET, NULL);
IStream_Read(pStream, &CompObj.dwCLSIDNameLength, sizeof(CompObj.dwCLSIDNameLength), NULL);
- iSeekPos.s.LowPart = CompObj.dwCLSIDNameLength;
+ iSeekPos.u.LowPart = CompObj.dwCLSIDNameLength;
IStream_Seek(pStream, iSeekPos, STREAM_SEEK_CUR , NULL);
IStream_Read(pStream, &CompObj.dwOleTypeNameLength, sizeof(CompObj.dwOleTypeNameLength), NULL);
- iSeekPos.s.LowPart = CompObj.dwOleTypeNameLength;
+ iSeekPos.u.LowPart = CompObj.dwOleTypeNameLength;
IStream_Seek(pStream, iSeekPos, STREAM_SEEK_CUR , NULL);
IStream_Read(pStream, dwSize, sizeof(*dwSize), NULL);
{
*dwSize = WideCharToMultiByte(CP_ACP, 0, wstrProgID, -1, strProgID, *dwSize, NULL, FALSE);
}
-
+
}
return hRes;
}
/*************************************************************************
- * OLECONVERT_GetOle10PresData [Internal]
+ * OLECONVERT_GetOle10PresData [Internal]
*
* Converts IStorage "/001Ole10Native" stream to a OLE10 Stream
*
* This function is used by OleConvertIStorageToOLESTREAM only.
*
* Memory allocated for pData must be freed by the caller
- *
- *
+ *
+ *
*/
void OLECONVERT_GetOle10PresData(LPSTORAGE pStorage, OLECONVERT_OLESTREAM_DATA *pOleStreamData)
{
HRESULT hRes;
IStream *pStream;
- WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0};
+ static const WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0};
/* Initialize Default data for OLESTREAM */
pOleStreamData[0].dwOleID = OLESTREAM_ID;
pOleStreamData[1].pData = NULL;
/* Open Ole10Native Stream */
- hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL,
+ hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream );
if(hRes == S_OK)
{
IStream_Read(pStream, &(pOleStreamData->dwDataLength), sizeof(pOleStreamData->dwDataLength), NULL);
if(pOleStreamData->dwDataLength > 0)
{
- pOleStreamData->pData = (LPSTR) HeapAlloc(GetProcessHeap(),0,pOleStreamData->dwDataLength);
+ pOleStreamData->pData = HeapAlloc(GetProcessHeap(),0,pOleStreamData->dwDataLength);
IStream_Read(pStream, pOleStreamData->pData, pOleStreamData->dwDataLength, NULL);
}
IStream_Release(pStream);
/*************************************************************************
- * OLECONVERT_GetOle20PresData[Internal]
+ * OLECONVERT_GetOle20PresData[Internal]
*
* Converts IStorage "/002OlePres000" stream to a OLE10 Stream
*
*
* NOTES
* This function is used by OleConvertIStorageToOLESTREAM only.
- *
+ *
* Memory allocated for pData must be freed by the caller
*/
void OLECONVERT_GetOle20PresData(LPSTORAGE pStorage, OLECONVERT_OLESTREAM_DATA *pOleStreamData)
HRESULT hRes;
IStream *pStream;
OLECONVERT_ISTORAGE_OLEPRES olePress;
- WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
+ static const WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
/* Initialize Default data for OLESTREAM */
pOleStreamData[0].dwOleID = OLESTREAM_ID;
/* Open OlePress000 stream */
- hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL,
+ hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream );
if(hRes == S_OK)
{
LARGE_INTEGER iSeekPos;
METAFILEPICT16 MetaFilePict;
- char strMetafilePictName[] = "METAFILEPICT";
+ static const char strMetafilePictName[] = "METAFILEPICT";
/* Set the TypeID for a Metafile */
pOleStreamData[1].dwTypeID = 5;
pOleStreamData[1].dwOleTypeNameLength = strlen(strMetafilePictName) +1;
strcpy(pOleStreamData[1].strOleTypeName, strMetafilePictName);
- iSeekPos.s.HighPart = 0;
- iSeekPos.s.LowPart = sizeof(olePress.byUnknown1);
+ iSeekPos.u.HighPart = 0;
+ iSeekPos.u.LowPart = sizeof(olePress.byUnknown1);
/* Get Presentation Data */
IStream_Seek(pStream, iSeekPos, STREAM_SEEK_SET, NULL);
MetaFilePict.hMF = 0;
/* Get Metafile Data */
- pOleStreamData[1].pData = (BYTE *) HeapAlloc(GetProcessHeap(),0,pOleStreamData[1].dwDataLength);
+ pOleStreamData[1].pData = HeapAlloc(GetProcessHeap(),0,pOleStreamData[1].dwDataLength);
memcpy(pOleStreamData[1].pData, &MetaFilePict, sizeof(MetaFilePict));
IStream_Read(pStream, &(pOleStreamData[1].pData[sizeof(MetaFilePict)]), pOleStreamData[1].dwDataLength-sizeof(METAFILEPICT16), NULL);
}
}
/*************************************************************************
- * OleConvertOLESTREAMToIStorage [OLE32.87]
+ * OleConvertOLESTREAMToIStorage [OLE32.@]
*
* Read info on MSDN
*
* Still unsure of some mem fields for OLE 10 Stream
* Still some unknowns for the IStorage: "\002OlePres000", "\001CompObj",
* and "\001OLE" streams
- *
+ *
*/
HRESULT WINAPI OleConvertOLESTREAMToIStorage (
- LPOLESTREAM pOleStream,
- LPSTORAGE pstg,
+ LPOLESTREAM pOleStream,
+ LPSTORAGE pstg,
const DVTARGETDEVICE* ptd)
{
int i;
/* Free allocated memory */
for(i=0; i < 2; i++)
{
- if(pOleStreamData[i].pData != NULL)
- {
- HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
- }
- if(pOleStreamData[i].pstrOleObjFileName != NULL)
- {
- HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName);
- pOleStreamData[i].pstrOleObjFileName = NULL;
- }
+ HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
+ HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName);
+ pOleStreamData[i].pstrOleObjFileName = NULL;
}
return hRes;
}
/*************************************************************************
- * OleConvertIStorageToOLESTREAM [OLE32.85]
+ * OleConvertIStorageToOLESTREAM [OLE32.@]
*
* Read info on MSDN
*
* Still unsure of some mem fields for OLE 10 Stream
* Still some unknowns for the IStorage: "\002OlePres000", "\001CompObj",
* and "\001OLE" streams.
- *
+ *
*/
HRESULT WINAPI OleConvertIStorageToOLESTREAM (
- LPSTORAGE pstg,
+ LPSTORAGE pstg,
LPOLESTREAM pOleStream)
{
int i;
HRESULT hRes = S_OK;
IStream *pStream;
OLECONVERT_OLESTREAM_DATA pOleStreamData[2];
- WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0};
+ static const WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0};
memset(pOleStreamData, 0, sizeof(pOleStreamData));
}
if(hRes == S_OK)
{
- /*Was it originaly Ole10 */
- hRes = IStorage_OpenStream(pstg, wstrStreamName, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
+ /* Was it originally Ole10 */
+ hRes = IStorage_OpenStream(pstg, wstrStreamName, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
if(hRes == S_OK)
{
IStream_Release(pStream);
- /*Get Presentation Data for Ole10Native */
+ /* Get Presentation Data for Ole10Native */
OLECONVERT_GetOle10PresData(pstg, pOleStreamData);
}
else
{
- /*Get Presentation Data (OLE20)*/
+ /* Get Presentation Data (OLE20) */
OLECONVERT_GetOle20PresData(pstg, pOleStreamData);
}
/* Free allocated memory */
for(i=0; i < 2; i++)
{
- if(pOleStreamData[i].pData != NULL)
- {
- HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
- }
+ HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
}
return hRes;
}
+
+/***********************************************************************
+ * GetConvertStg (OLE32.@)
+ */
+HRESULT WINAPI GetConvertStg(IStorage *stg) {
+ FIXME("unimplemented stub!\n");
+ return E_FAIL;
+}
+
+/******************************************************************************
+ * StgIsStorageFile [OLE32.@]
+ */
+HRESULT WINAPI
+StgIsStorageFile(LPCOLESTR fn)
+{
+ HANDLE hf;
+ BYTE magic[8];
+ DWORD bytes_read;
+
+ TRACE("(\'%s\')\n", debugstr_w(fn));
+ hf = CreateFileW(fn, GENERIC_READ,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (hf == INVALID_HANDLE_VALUE)
+ return STG_E_FILENOTFOUND;
+
+ if (!ReadFile(hf, magic, 8, &bytes_read, NULL))
+ {
+ WARN(" unable to read file\n");
+ CloseHandle(hf);
+ return S_FALSE;
+ }
+
+ CloseHandle(hf);
+
+ if (bytes_read != 8) {
+ WARN(" too short\n");
+ return S_FALSE;
+ }
+
+ if (!memcmp(magic,STORAGE_magic,8)) {
+ WARN(" -> YES\n");
+ return S_OK;
+ }
+
+ WARN(" -> Invalid header.\n");
+ return S_FALSE;
+}