📄 storage32.c
字号:
* This method will create a stream object within this storage
*
* See Windows documentation for more details on IStorage methods.
*/
static 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;
TRACE("(%p, %s, %x, %d, %d, %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
* if not in transacted mode
*/
if(!(This->ancestorStorage->base.openFlags & STGM_TRANSACTED)) {
if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( This->openFlags ) )
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;
}
else if (STGM_ACCESS_MODE(This->openFlags) == STGM_READ)
{
WARN("read-only storage\n");
return STG_E_ACCESSDENIED;
}
/*
* 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.
*/
newStream = StgStreamImpl_Construct(This, grfMode, newPropertyIndex);
if (newStream != 0)
{
*ppstm = (IStream*)newStream;
/*
* Since we are returning a pointer to the interface, we have to nail down
* the reference.
*/
IStream_AddRef(*ppstm);
}
else
{
return STG_E_INSUFFICIENTMEMORY;
}
return S_OK;
}
/************************************************************************
* Storage32BaseImpl_SetClass (IStorage)
*
* This method will write the specified CLSID in the property of this
* storage.
*
* See Windows documentation for more details on IStorage methods.
*/
static HRESULT WINAPI StorageBaseImpl_SetClass(
IStorage* iface,
REFCLSID clsid) /* [in] */
{
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);
if (success)
{
curProperty.propertyUniqueID = *clsid;
success = StorageImpl_WriteProperty(This->ancestorStorage,
This->rootPropertySetIndex,
&curProperty);
if (success)
hRes = S_OK;
}
return hRes;
}
/************************************************************************
** Storage32Impl implementation
*/
/************************************************************************
* Storage32Impl_CreateStorage (IStorage)
*
* This method will create the storage object within the provided storage.
*
* See Windows documentation for more details on IStorage methods.
*/
static HRESULT WINAPI StorageImpl_CreateStorage(
IStorage* iface,
const OLECHAR *pwcsName, /* [string][in] */
DWORD grfMode, /* [in] */
DWORD reserved1, /* [in] */
DWORD reserved2, /* [in] */
IStorage **ppstg) /* [out] */
{
StorageImpl* const This=(StorageImpl*)iface;
IEnumSTATSTGImpl *propertyEnumeration;
StgProperty currentProperty;
StgProperty newProperty;
ULONG foundPropertyIndex;
ULONG newPropertyIndex;
HRESULT hr;
TRACE("(%p, %s, %x, %d, %d, %p)\n",
iface, debugstr_w(pwcsName), grfMode,
reserved1, reserved2, ppstg);
/*
* Validate parameters
*/
if (ppstg == 0)
return STG_E_INVALIDPOINTER;
if (pwcsName == 0)
return STG_E_INVALIDNAME;
/*
* Initialize the out parameter
*/
*ppstg = NULL;
/*
* Validate the STGM flags
*/
if ( FAILED( validateSTGM(grfMode) ) ||
(grfMode & STGM_DELETEONRELEASE) )
{
WARN("bad grfMode: 0x%x\n", grfMode);
return STG_E_INVALIDFLAG;
}
/*
* Check that we're compatible with the parent's storage mode
*/
if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( This->base.openFlags ) )
{
WARN("access denied\n");
return STG_E_ACCESSDENIED;
}
/*
* Create a property enumeration and search the properties
*/
propertyEnumeration = IEnumSTATSTGImpl_Construct( This->base.ancestorStorage,
This->base.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
{
WARN("file already exists\n");
return STG_E_FILEALREADYEXISTS;
}
}
else if (STGM_ACCESS_MODE(This->base.openFlags) == STGM_READ)
{
WARN("read-only storage\n");
return STG_E_ACCESSDENIED;
}
/*
* memset the empty property
*/
memset(&newProperty, 0, sizeof(StgProperty));
newProperty.sizeOfNameString = (lstrlenW(pwcsName)+1)*sizeof(WCHAR);
if (newProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
{
FIXME("name too long\n");
return STG_E_INVALIDNAME;
}
strcpyW(newProperty.name, pwcsName);
newProperty.propertyType = PROPTYPE_STORAGE;
newProperty.startingBlock = BLOCK_END_OF_CHAIN;
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
newProperty.timeStampS1
newProperty.timeStampD1
newProperty.timeStampS2
newProperty.timeStampD2
*/
/* newStorageProperty.propertyUniqueID */
/*
* Obtain a free property in the property chain
*/
newPropertyIndex = getFreeProperty(This->base.ancestorStorage);
/*
* Save the new property into the new property spot
*/
StorageImpl_WriteProperty(
This->base.ancestorStorage,
newPropertyIndex,
&newProperty);
/*
* Find a spot in the property chain for our newly created property.
*/
updatePropertyChain(
This,
newPropertyIndex,
newProperty);
/*
* Open it to get a pointer to return.
*/
hr = IStorage_OpenStorage(
iface,
(const OLECHAR*)pwcsName,
0,
grfMode,
0,
0,
ppstg);
if( (hr != S_OK) || (*ppstg == NULL))
{
return hr;
}
return S_OK;
}
/***************************************************************************
*
* Internal Method
*
* Get a free property or create a new one.
*/
static ULONG getFreeProperty(
StorageImpl *storage)
{
ULONG currentPropertyIndex = 0;
ULONG newPropertyIndex = PROPERTY_NULL;
BOOL readSuccessful = TRUE;
StgProperty currentProperty;
do
{
/*
* Start by reading the root property
*/
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;
}
}
else
{
/*
* We exhausted the property list, we will create more space below
*/
newPropertyIndex = currentPropertyIndex;
}
currentPropertyIndex++;
} while (newPropertyIndex == PROPERTY_NULL);
/*
* grow the property chain
*/
if (! readSuccessful)
{
StgProperty emptyProperty;
ULARGE_INTEGER newSize;
ULONG propertyIndex;
ULONG lastProperty = 0;
ULONG blockCount = 0;
/*
* obtain the new count of property blocks
*/
blockCount = BlockChainStream_GetCount(
storage->base.ancestorStorage->rootBlockChain)+1;
/*
* initialize the size used by the property stream
*/
newSize.u.HighPart = 0;
newSize.u.LowPart = storage->bigBlockSize * blockCount;
/*
* add a property block to the property chain
*/
BlockChainStream_SetSize(storage->base.ancestorStorage->rootBlockChain, newSize);
/*
* 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;
for(
propertyIndex = newPropertyIndex;
propertyIndex < lastProperty;
propertyIndex++)
{
StorageImpl_WriteProperty(
storage->base.ancestorStorage,
propertyIndex,
&emptyProperty);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -