parent
bb2eab5f79
commit
925d602766
|
@ -246,7 +246,7 @@ void StgStreamImpl_OpenBlockChain(
|
|||
BOOL readSucessful;
|
||||
|
||||
/*
|
||||
* Make sure no old object is staying behind.
|
||||
* Make sure no old object is left over.
|
||||
*/
|
||||
if (This->smallBlockChain != 0)
|
||||
{
|
||||
|
@ -303,7 +303,7 @@ void StgStreamImpl_OpenBlockChain(
|
|||
/***
|
||||
* This method is part of the ISequentialStream interface.
|
||||
*
|
||||
* If reads a block of information from the stream at the current
|
||||
* It reads a block of information from the stream at the current
|
||||
* position. It then moves the current position at the end of the
|
||||
* read block
|
||||
*
|
||||
|
@ -319,12 +319,13 @@ HRESULT WINAPI StgStreamImpl_Read(
|
|||
|
||||
ULONG bytesReadBuffer;
|
||||
ULONG bytesToReadFromBuffer;
|
||||
HRESULT res = S_FALSE;
|
||||
|
||||
TRACE("(%p, %p, %ld, %p)\n",
|
||||
iface, pv, cb, pcbRead);
|
||||
|
||||
/*
|
||||
* If the caller is not interested in the nubmer of bytes read,
|
||||
* If the caller is not interested in the number of bytes read,
|
||||
* we use another buffer to avoid "if" statements in the code.
|
||||
*/
|
||||
if (pcbRead==0)
|
||||
|
@ -338,7 +339,7 @@ HRESULT WINAPI StgStreamImpl_Read(
|
|||
|
||||
/*
|
||||
* Depending on the type of chain that was opened when the stream was constructed,
|
||||
* we delegate the work to the method that read the block chains.
|
||||
* we delegate the work to the method that reads the block chains.
|
||||
*/
|
||||
if (This->smallBlockChain!=0)
|
||||
{
|
||||
|
@ -365,7 +366,8 @@ HRESULT WINAPI StgStreamImpl_Read(
|
|||
*/
|
||||
|
||||
*pcbRead = 0;
|
||||
return S_OK;
|
||||
res = S_OK;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -379,14 +381,23 @@ HRESULT WINAPI StgStreamImpl_Read(
|
|||
*/
|
||||
This->currentPosition.s.LowPart += *pcbRead;
|
||||
|
||||
/*
|
||||
* The function returns S_OK if at least one byte could be read.
|
||||
* FIXME: What should be returned if pcbRead argument is NULL?
|
||||
*/
|
||||
if (*pcbRead > 0)
|
||||
return S_OK;
|
||||
if(*pcbRead != cb)
|
||||
{
|
||||
WARN("read %ld instead of the required %ld bytes !\n", *pcbRead, cb);
|
||||
/*
|
||||
* this used to return S_FALSE, however MSDN docu says that an app should
|
||||
* be prepared to handle error in case of stream end reached, as *some*
|
||||
* implementations *might* return an error (IOW: most do *not*).
|
||||
* As some program fails on returning S_FALSE, I better use S_OK here.
|
||||
*/
|
||||
res = S_OK;
|
||||
}
|
||||
else
|
||||
res = S_OK;
|
||||
|
||||
return S_FALSE;
|
||||
end:
|
||||
TRACE("<-- %08lx\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -632,7 +643,7 @@ HRESULT WINAPI StgStreamImpl_SetSize(
|
|||
}
|
||||
|
||||
/*
|
||||
* Write to the property the new information about this stream
|
||||
* Write the new information about this stream to the property
|
||||
*/
|
||||
Success = StorageImpl_ReadProperty(This->parentStorage->ancestorStorage,
|
||||
This->ownerProperty,
|
||||
|
@ -686,8 +697,8 @@ HRESULT WINAPI StgStreamImpl_CopyTo(
|
|||
totalBytesWritten.s.LowPart = totalBytesWritten.s.HighPart = 0;
|
||||
|
||||
/*
|
||||
* use stack to store data temporarly
|
||||
* there is surely more performant way of doing it, for now this basic
|
||||
* use stack to store data temporarily
|
||||
* there is surely a more performant way of doing it, for now this basic
|
||||
* implementation will do the job
|
||||
*/
|
||||
while ( cb.s.LowPart > 0 )
|
||||
|
@ -706,7 +717,7 @@ HRESULT WINAPI StgStreamImpl_CopyTo(
|
|||
totalBytesWritten.s.LowPart += bytesWritten;
|
||||
|
||||
/*
|
||||
* Check that read & write operations were succesfull
|
||||
* Check that read & write operations were successful
|
||||
*/
|
||||
if (bytesRead != bytesWritten)
|
||||
{
|
||||
|
|
|
@ -335,6 +335,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
|
|||
StgStreamImpl* newStream;
|
||||
StgProperty currentProperty;
|
||||
ULONG foundPropertyIndex;
|
||||
HRESULT res = STG_E_UNKNOWN;
|
||||
|
||||
TRACE("(%p, %s, %p, %lx, %ld, %p)\n",
|
||||
iface, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm);
|
||||
|
@ -343,18 +344,24 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
|
|||
* 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.
|
||||
|
@ -362,7 +369,10 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
|
|||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
|
||||
(grfMode & STGM_DELETEONRELEASE) ||
|
||||
(grfMode & STGM_TRANSACTED) )
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
{
|
||||
res = STG_E_INVALIDFUNCTION;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a property enumeration to search the properties
|
||||
|
@ -403,13 +413,21 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
|
|||
*/
|
||||
StgStreamImpl_AddRef(*ppstm);
|
||||
|
||||
return S_OK;
|
||||
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;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -433,6 +451,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
|
|||
IEnumSTATSTGImpl* propertyEnumeration;
|
||||
StgProperty currentProperty;
|
||||
ULONG foundPropertyIndex;
|
||||
HRESULT res = STG_E_UNKNOWN;
|
||||
|
||||
TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n",
|
||||
iface, debugstr_w(pwcsName), pstgPriority,
|
||||
|
@ -442,13 +461,26 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
|
|||
* 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.
|
||||
|
@ -456,12 +488,15 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
|
|||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
|
||||
(grfMode & STGM_DELETEONRELEASE) ||
|
||||
(grfMode & STGM_PRIORITY) )
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
{
|
||||
res = STG_E_INVALIDFUNCTION;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the out parameter
|
||||
*/
|
||||
*ppstg = 0;
|
||||
*ppstg = NULL;
|
||||
|
||||
/*
|
||||
* Create a property enumeration to search the properties
|
||||
|
@ -506,13 +541,19 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -579,7 +620,8 @@ HRESULT WINAPI StorageBaseImpl_Stat(
|
|||
{
|
||||
ICOM_THIS(StorageBaseImpl,iface);
|
||||
StgProperty curProperty;
|
||||
BOOL readSuccessful;
|
||||
BOOL readSuccessful;
|
||||
HRESULT res = STG_E_UNKNOWN;
|
||||
|
||||
TRACE("(%p, %p, %lx)\n",
|
||||
iface, pstatstg, grfStatFlag);
|
||||
|
@ -588,7 +630,10 @@ HRESULT WINAPI StorageBaseImpl_Stat(
|
|||
* 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.
|
||||
|
@ -605,10 +650,19 @@ HRESULT WINAPI StorageBaseImpl_Stat(
|
|||
&curProperty,
|
||||
grfStatFlag);
|
||||
|
||||
return S_OK;
|
||||
res = S_OK;
|
||||
goto end;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
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.s.LowPart, pstatstg->cbSize.s.HighPart, pstatstg->grfMode, pstatstg->grfLocksSupported, pstatstg->grfStateBits);
|
||||
}
|
||||
TRACE("<-- %08lx\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -2137,13 +2191,13 @@ HRESULT StorageImpl_Construct(
|
|||
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 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;
|
||||
|
@ -2281,7 +2335,7 @@ HRESULT StorageImpl_Construct(
|
|||
}
|
||||
|
||||
/*
|
||||
* Find the ID of the root int he property sets.
|
||||
* Find the ID of the root in the property sets.
|
||||
*/
|
||||
currentPropertyIndex = 0;
|
||||
|
||||
|
@ -2914,15 +2968,19 @@ HRESULT StorageImpl_LoadFileHeader(
|
|||
* 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;
|
||||
|
@ -3049,14 +3107,19 @@ BOOL StorageImpl_ReadProperty(
|
|||
PROPSET_BLOCK_SIZE,
|
||||
currentProperty,
|
||||
&bytesRead);
|
||||
|
||||
|
||||
if (readSuccessful)
|
||||
{
|
||||
/* replace the name of root entry (often "Root Entry") by the file name */
|
||||
WCHAR *propName = (index == This->rootPropertySetIndex) ?
|
||||
This->filename : (WCHAR *)currentProperty+OFFSET_PS_NAME;
|
||||
|
||||
memset(buffer->name, 0, sizeof(buffer->name));
|
||||
memcpy(
|
||||
buffer->name,
|
||||
currentProperty+OFFSET_PS_NAME,
|
||||
propName,
|
||||
PROPERTY_NAME_BUFFER_LEN );
|
||||
TRACE("storage name: %s\n", debugstr_w(buffer->name));
|
||||
|
||||
memcpy(&buffer->propertyType, currentProperty + OFFSET_PS_PROPERTYTYPE, 1);
|
||||
|
||||
|
@ -5440,6 +5503,8 @@ HRESULT WINAPI StgOpenStorage(
|
|||
HANDLE hFile = 0;
|
||||
DWORD shareMode;
|
||||
DWORD accessMode;
|
||||
WCHAR fullname[MAX_PATH];
|
||||
WIN32_FILE_ATTRIBUTE_DATA Fad;
|
||||
|
||||
TRACE("(%s, %p, %lx, %p, %ld, %p)\n",
|
||||
debugstr_w(pwcsName), pstgPriority, grfMode,
|
||||
|
@ -5449,13 +5514,19 @@ HRESULT WINAPI StgOpenStorage(
|
|||
* Perform a sanity check
|
||||
*/
|
||||
if (( pwcsName == 0) || (ppstgOpen == 0) )
|
||||
return STG_E_INVALIDPOINTER;
|
||||
{
|
||||
hr = STG_E_INVALIDPOINTER;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the STGM flags
|
||||
*/
|
||||
if ( FAILED( validateSTGM(grfMode) ))
|
||||
return STG_E_INVALIDFLAG;
|
||||
{
|
||||
hr = STG_E_INVALIDFLAG;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret the STGM value grfMode
|
||||
|
@ -5479,9 +5550,10 @@ HRESULT WINAPI StgOpenStorage(
|
|||
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
DWORD last_error = GetLastError();
|
||||
|
||||
hr = E_FAIL;
|
||||
|
||||
switch (last_error)
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
|
@ -5505,7 +5577,7 @@ HRESULT WINAPI StgOpenStorage(
|
|||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5514,8 +5586,12 @@ HRESULT WINAPI StgOpenStorage(
|
|||
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,
|
||||
|
@ -5523,7 +5599,7 @@ HRESULT WINAPI StgOpenStorage(
|
|||
NULL,
|
||||
grfMode,
|
||||
TRUE,
|
||||
FALSE);
|
||||
!(Fad.nFileSizeHigh || Fad.nFileSizeLow) /* FALSE */ );
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -5532,10 +5608,15 @@ HRESULT WINAPI StgOpenStorage(
|
|||
* According to the docs if the file is not a storage, return STG_E_FILEALREADYEXISTS
|
||||
*/
|
||||
if(hr == STG_E_INVALIDHEADER)
|
||||
return STG_E_FILEALREADYEXISTS;
|
||||
return hr;
|
||||
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] = '\0';
|
||||
|
||||
/*
|
||||
* Get an "out" pointer for the caller.
|
||||
*/
|
||||
|
@ -5544,6 +5625,8 @@ HRESULT WINAPI StgOpenStorage(
|
|||
(REFIID)&IID_IStorage,
|
||||
(void**)ppstgOpen);
|
||||
|
||||
end:
|
||||
TRACE("<-- %08lx, IStorage %p\n", hr, ppstgOpen ? *ppstgOpen : NULL);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -6985,17 +7068,17 @@ HRESULT WINAPI OleConvertIStorageToOLESTREAM (
|
|||
}
|
||||
if(hRes == S_OK)
|
||||
{
|
||||
/*Was it originaly Ole10 */
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -179,15 +179,15 @@ HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName
|
|||
/****************************************************************************
|
||||
* Storage32BaseImpl definitions.
|
||||
*
|
||||
* This stucture defines the base information contained in all implementations
|
||||
* of IStorage32 contained in this filee storage implementation.
|
||||
* This structure defines the base information contained in all implementations
|
||||
* of IStorage32 contained in this file storage implementation.
|
||||
*
|
||||
* In OOP terms, this is the base class for all the IStorage32 implementations
|
||||
* contained in this file.
|
||||
*/
|
||||
struct StorageBaseImpl
|
||||
{
|
||||
ICOM_VFIELD(IStorage); /* Needs to be the first item in the stuct
|
||||
ICOM_VFIELD(IStorage); /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
|
||||
/*
|
||||
|
@ -281,8 +281,8 @@ HRESULT WINAPI StorageBaseImpl_SetClass(
|
|||
*/
|
||||
struct StorageImpl
|
||||
{
|
||||
ICOM_VFIELD(IStorage); /* Needs to be the first item in the stuct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
ICOM_VFIELD(IStorage); /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
|
||||
/*
|
||||
* Declare the member of the Storage32BaseImpl class to allow
|
||||
|
@ -300,6 +300,9 @@ struct StorageImpl
|
|||
HANDLE hFile; /* Physical support for the Docfile */
|
||||
LPOLESTR pwcsName; /* Full path of the document file */
|
||||
|
||||
/* FIXME: should this be in Storage32BaseImpl ? */
|
||||
WCHAR filename[PROPERTY_NAME_BUFFER_LEN];
|
||||
|
||||
/*
|
||||
* File header
|
||||
*/
|
||||
|
@ -477,7 +480,7 @@ void Storage32Impl_SetExtDepotBlock(StorageImpl* This,
|
|||
*/
|
||||
struct StorageInternalImpl
|
||||
{
|
||||
ICOM_VFIELD(IStorage); /* Needs to be the first item in the stuct
|
||||
ICOM_VFIELD(IStorage); /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
|
||||
/*
|
||||
|
@ -521,7 +524,7 @@ HRESULT WINAPI StorageInternalImpl_Revert(
|
|||
*/
|
||||
struct IEnumSTATSTGImpl
|
||||
{
|
||||
ICOM_VFIELD(IEnumSTATSTG); /* Needs to be the first item in the stuct
|
||||
ICOM_VFIELD(IEnumSTATSTG); /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a IEnumSTATSTG pointer */
|
||||
|
||||
ULONG ref; /* Reference count */
|
||||
|
@ -606,7 +609,7 @@ INT IEnumSTATSTGImpl_FindParentProperty(
|
|||
*/
|
||||
struct StgStreamImpl
|
||||
{
|
||||
ICOM_VFIELD(IStream); /* Needs to be the first item in the stuct
|
||||
ICOM_VFIELD(IStream); /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a IStream pointer */
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue