📄 storage32.c
字号:
goto end;
}
/*
* Initialize the out parameter
*/
*ppstg = NULL;
/*
* Create a property enumeration to search the properties
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct(
This->ancestorStorage,
This->rootPropertySetIndex);
/*
* Search the enumeration for the property with the given name
*/
foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(
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) &&
(currentProperty.propertyType==PROPTYPE_STORAGE) )
{
/*
* Construct a new Storage object
*/
newStorage = StorageInternalImpl_Construct(
This->ancestorStorage,
grfMode,
foundPropertyIndex);
if (newStorage != 0)
{
*ppstg = (IStorage*)newStorage;
/*
* Since we are returning a pointer to the interface,
* we have to nail down the reference.
*/
StorageBaseImpl_AddRef(*ppstg);
res = S_OK;
goto end;
}
res = STG_E_INSUFFICIENTMEMORY;
goto end;
}
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
* retrieve informatino about all the properties in the storage object.
*
* See Windows documentation for more details on IStorage methods.
*/
HRESULT WINAPI StorageBaseImpl_EnumElements(
IStorage* iface,
DWORD reserved1, /* [in] */
void* reserved2, /* [size_is][unique][in] */
DWORD reserved3, /* [in] */
IEnumSTATSTG** ppenum) /* [out] */
{
StorageBaseImpl *This = (StorageBaseImpl *)iface;
IEnumSTATSTGImpl* newEnum;
TRACE("(%p, %ld, %p, %ld, %p)\n",
iface, reserved1, reserved2, reserved3, ppenum);
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (ppenum==0))
return E_INVALIDARG;
/*
* Construct the enumerator.
*/
newEnum = IEnumSTATSTGImpl_Construct(
This->ancestorStorage,
This->rootPropertySetIndex);
if (newEnum!=0)
{
*ppenum = (IEnumSTATSTG*)newEnum;
/*
* Don't forget to nail down a reference to the new object before
* returning it.
*/
IEnumSTATSTG_AddRef(*ppenum);
return S_OK;
}
return E_OUTOFMEMORY;
}
/************************************************************************
* 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(
IStorage* iface,
STATSTG* pstatstg, /* [out] */
DWORD grfStatFlag) /* [in] */
{
StorageBaseImpl *This = (StorageBaseImpl *)iface;
StgProperty curProperty;
BOOL readSuccessful;
HRESULT res = STG_E_UNKNOWN;
TRACE("(%p, %p, %lx)\n",
iface, pstatstg, grfStatFlag);
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (pstatstg==0))
{
res = E_INVALIDARG;
goto end;
}
/*
* Read the information from the property.
*/
readSuccessful = StorageImpl_ReadProperty(
This->ancestorStorage,
This->rootPropertySetIndex,
&curProperty);
if (readSuccessful)
{
StorageUtl_CopyPropertyToSTATSTG(
pstatstg,
&curProperty,
grfStatFlag);
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);
}
TRACE("<-- %08lx\n", res);
return res;
}
/************************************************************************
* Storage32BaseImpl_RenameElement (IStorage)
*
* 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
* perform a DestroyElement of the old StgProperty.
*/
HRESULT WINAPI StorageBaseImpl_RenameElement(
IStorage* iface,
const OLECHAR* pwcsOldName, /* [in] */
const OLECHAR* pwcsNewName) /* [in] */
{
StorageBaseImpl *This = (StorageBaseImpl *)iface;
IEnumSTATSTGImpl* propertyEnumeration;
StgProperty currentProperty;
ULONG foundPropertyIndex;
TRACE("(%p, %s, %s)\n",
iface, debugstr_w(pwcsOldName), debugstr_w(pwcsNewName));
/*
* Create a property enumeration to search the properties
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct(This->ancestorStorage,
This->rootPropertySetIndex);
/*
* Search the enumeration for the new property name
*/
foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
pwcsNewName,
¤tProperty);
if (foundPropertyIndex != PROPERTY_NULL)
{
/*
* There is already a property with the new name
*/
IEnumSTATSTGImpl_Destroy(propertyEnumeration);
return STG_E_FILEALREADYEXISTS;
}
IEnumSTATSTG_Reset((IEnumSTATSTG*)propertyEnumeration);
/*
* Search the enumeration for the old property name
*/
foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
pwcsOldName,
¤tProperty);
/*
* Delete the property enumeration since we don't need it anymore
*/
IEnumSTATSTGImpl_Destroy(propertyEnumeration);
if (foundPropertyIndex != PROPERTY_NULL)
{
StgProperty renamedProperty;
ULONG renamedPropertyIndex;
/*
* Setup a new property for the renamed property
*/
renamedProperty.sizeOfNameString =
( lstrlenW(pwcsNewName)+1 ) * sizeof(WCHAR);
if (renamedProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
return STG_E_INVALIDNAME;
strcpyW(renamedProperty.name, pwcsNewName);
renamedProperty.propertyType = currentProperty.propertyType;
renamedProperty.startingBlock = currentProperty.startingBlock;
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
renamedProperty.timeStampS1
renamedProperty.timeStampD1
renamedProperty.timeStampS2
renamedProperty.timeStampD2
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,
&renamedProperty);
/*
* Find a spot in the property chain for our newly created property.
*/
updatePropertyChain(
(StorageImpl*)This,
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
* 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.
*/
StorageImpl_ReadProperty(This->ancestorStorage,
foundPropertyIndex,
¤tProperty);
currentProperty.dirProperty = PROPERTY_NULL;
currentProperty.propertyType = PROPTYPE_STORAGE;
StorageImpl_WriteProperty(
This->ancestorStorage,
foundPropertyIndex,
¤tProperty);
/*
* 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
{
/*
* There is no property with the old name
*/
return STG_E_FILENOTFOUND;
}
return S_OK;
}
/************************************************************************
* Storage32BaseImpl_CreateStream (IStorage)
*
* This method will create a stream object within this storage
*
* See Windows documentation for more details on IStorage methods.
*/
HRESULT WINAPI StorageBaseImpl_CreateStream(
IStorage* iface,
const OLECHAR* pwcsName, /* [string][in] */
DWORD grfMode, /* [in] */
DWORD reserved1, /* [in] */
DWORD reserved2, /* [in] */
IStream** ppstm) /* [out] */
{
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,
reserved1, reserved2, ppstm);
/*
* Validate parameters
*/
if (ppstm == 0)
return STG_E_INVALIDPOINTER;
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_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
*/
*ppstm = 0;
/*
* Create a property enumeration to search the properties
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct(This->ancestorStorage,
This->rootPropertySetIndex);
foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
pwcsName,
¤tProperty);
IEnumSTATSTGImpl_Destroy(propertyEnumeration);
if (foundPropertyIndex != PROPERTY_NULL)
{
/*
* An element with this name already exists
*/
if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
{
IStorage_DestroyElement(iface, pwcsName);
}
else
return STG_E_FILEALREADYEXISTS;
}
/*
* memset the empty property
*/
memset(&newStreamProperty, 0, sizeof(StgProperty));
newStreamProperty.sizeOfNameString =
( lstrlenW(pwcsName)+1 ) * sizeof(WCHAR);
if (newStreamProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
return STG_E_INVALIDNAME;
strcpyW(newStreamProperty.name, pwcsName);
newStreamProperty.propertyType = PROPTYPE_STREAM;
newStreamProperty.startingBlock = BLOCK_END_OF_CHAIN;
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
newStreamProperty.timeStampS1
newStreamProperty.timeStampD1
newStreamProperty.timeStampS2
newStreamProperty.timeStampD2
*/
/* newStreamProperty.propertyUniqueID */
/*
* 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,
&newStreamProperty);
/*
* Find a spot in the property chain for our newly created property.
*/
updatePropertyChain(
(StorageImpl*)This,
newPropertyIndex,
newStreamProperty);
/*
* Open the stream to return it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -