combase: Move Wdtp* marshalling functions.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ed83583934
commit
7d67c412ea
|
@ -1,8 +1,10 @@
|
|||
MODULE = combase.dll
|
||||
IMPORTLIB = combase
|
||||
IMPORTS = advapi32 ole32 uuid
|
||||
|
||||
EXTRADLLFLAGS = -mno-cygwin
|
||||
|
||||
C_SRCS = \
|
||||
roapi.c \
|
||||
string.c
|
||||
string.c \
|
||||
usrmarshal.c
|
||||
|
|
|
@ -281,11 +281,13 @@
|
|||
@ stdcall StringFromGUID2(ptr ptr long) ole32.StringFromGUID2
|
||||
@ stdcall StringFromIID(ptr ptr) ole32.StringFromIID
|
||||
@ stub UpdateDCOMSettings
|
||||
@ stdcall WdtpInterfacePointer_UserMarshal(ptr long ptr ptr ptr) ole32.WdtpInterfacePointer_UserMarshal
|
||||
@ stdcall WdtpInterfacePointer_UserFree(ptr)
|
||||
@ stub WdtpInterfacePointer_UserFree64
|
||||
@ stdcall WdtpInterfacePointer_UserMarshal(ptr long ptr ptr ptr)
|
||||
@ stub WdtpInterfacePointer_UserMarshal64
|
||||
@ stdcall WdtpInterfacePointer_UserSize(ptr long long ptr ptr) ole32.WdtpInterfacePointer_UserSize
|
||||
@ stdcall WdtpInterfacePointer_UserSize(ptr long long ptr ptr)
|
||||
@ stub WdtpInterfacePointer_UserSize64
|
||||
@ stdcall WdtpInterfacePointer_UserUnmarshal(ptr ptr ptr ptr) ole32.WdtpInterfacePointer_UserUnmarshal
|
||||
@ stdcall WdtpInterfacePointer_UserUnmarshal(ptr ptr ptr ptr)
|
||||
@ stub WdtpInterfacePointer_UserUnmarshal64
|
||||
@ stdcall WindowsCompareStringOrdinal(ptr ptr ptr)
|
||||
@ stdcall WindowsConcatString(ptr ptr ptr)
|
||||
|
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Marshaling Routines
|
||||
*
|
||||
* Copyright 2005 Robert Shearman
|
||||
* Copyright 2009 Huw Davies
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
|
||||
#include "ole2.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
|
||||
#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
|
||||
#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
|
||||
#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
|
||||
|
||||
static const char* debugstr_user_flags(ULONG *pFlags)
|
||||
{
|
||||
char buf[12];
|
||||
const char* loword;
|
||||
switch (LOWORD(*pFlags))
|
||||
{
|
||||
case MSHCTX_LOCAL:
|
||||
loword = "MSHCTX_LOCAL";
|
||||
break;
|
||||
case MSHCTX_NOSHAREDMEM:
|
||||
loword = "MSHCTX_NOSHAREDMEM";
|
||||
break;
|
||||
case MSHCTX_DIFFERENTMACHINE:
|
||||
loword = "MSHCTX_DIFFERENTMACHINE";
|
||||
break;
|
||||
case MSHCTX_INPROC:
|
||||
loword = "MSHCTX_INPROC";
|
||||
break;
|
||||
default:
|
||||
sprintf(buf, "%d", LOWORD(*pFlags));
|
||||
loword=buf;
|
||||
}
|
||||
|
||||
if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION)
|
||||
return wine_dbg_sprintf("MAKELONG(%s, NDR_LOCAL_DATA_REPRESENTATION)", loword);
|
||||
else
|
||||
return wine_dbg_sprintf("MAKELONG(%s, 0x%04x)", loword, HIWORD(*pFlags));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserSize (combase.@)
|
||||
*
|
||||
* Calculates the buffer size required to marshal an interface pointer.
|
||||
*
|
||||
* PARAMS
|
||||
* pFlags [I] Flags. See notes.
|
||||
* RealFlags [I] The MSHCTX to use when marshaling the interface.
|
||||
* punk [I] Interface pointer to size.
|
||||
* StartingSize [I] Starting size of the buffer. This value is added on to
|
||||
* the buffer size required for the clip format.
|
||||
* riid [I] ID of interface to size.
|
||||
*
|
||||
* RETURNS
|
||||
* The buffer size required to marshal an interface pointer plus the starting size.
|
||||
*
|
||||
* NOTES
|
||||
* Even though the function is documented to take a pointer to a ULONG in
|
||||
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
|
||||
* the first parameter is a ULONG.
|
||||
*/
|
||||
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid)
|
||||
{
|
||||
DWORD marshal_size = 0;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%s, %#x, %u, %p, %s.\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid));
|
||||
|
||||
hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL);
|
||||
if (FAILED(hr)) return StartingSize;
|
||||
|
||||
ALIGN_LENGTH(StartingSize, 3);
|
||||
StartingSize += 2 * sizeof(DWORD);
|
||||
return StartingSize + marshal_size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserMarshal (combase.@)
|
||||
*
|
||||
* Marshals an interface pointer into a buffer.
|
||||
*
|
||||
* PARAMS
|
||||
* pFlags [I] Flags. See notes.
|
||||
* RealFlags [I] The MSHCTX to use when marshaling the interface.
|
||||
* pBuffer [I] Buffer to marshal the clip format into.
|
||||
* punk [I] Interface pointer to marshal.
|
||||
* riid [I] ID of interface to marshal.
|
||||
*
|
||||
* RETURNS
|
||||
* The end of the marshaled data in the buffer.
|
||||
*
|
||||
* NOTES
|
||||
* Even though the function is documented to take a pointer to a ULONG in
|
||||
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
|
||||
* the first parameter is a ULONG.
|
||||
*/
|
||||
unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid)
|
||||
{
|
||||
HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
|
||||
IStream *stm;
|
||||
DWORD size;
|
||||
void *ptr;
|
||||
|
||||
TRACE("%s, %#x, %p, &%p, %s.\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid));
|
||||
|
||||
if (!h) return NULL;
|
||||
if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
|
||||
{
|
||||
GlobalFree(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK)
|
||||
{
|
||||
IStream_Release(stm);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
ALIGN_POINTER(pBuffer, 3);
|
||||
size = GlobalSize(h);
|
||||
|
||||
*(DWORD *)pBuffer = size;
|
||||
pBuffer += sizeof(DWORD);
|
||||
*(DWORD *)pBuffer = size;
|
||||
pBuffer += sizeof(DWORD);
|
||||
|
||||
ptr = GlobalLock(h);
|
||||
memcpy(pBuffer, ptr, size);
|
||||
GlobalUnlock(h);
|
||||
|
||||
IStream_Release(stm);
|
||||
return pBuffer + size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserUnmarshal (combase.@)
|
||||
*
|
||||
* Unmarshals an interface pointer from a buffer.
|
||||
*
|
||||
* PARAMS
|
||||
* pFlags [I] Flags. See notes.
|
||||
* pBuffer [I] Buffer to marshal the clip format from.
|
||||
* ppunk [I/O] Address that receives the unmarshaled interface pointer.
|
||||
* riid [I] ID of interface to unmarshal.
|
||||
*
|
||||
* RETURNS
|
||||
* The end of the marshaled data in the buffer.
|
||||
*
|
||||
* NOTES
|
||||
* Even though the function is documented to take a pointer to an ULONG in
|
||||
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
|
||||
* the first parameter is an ULONG.
|
||||
*/
|
||||
unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid)
|
||||
{
|
||||
HRESULT hr;
|
||||
HGLOBAL h;
|
||||
IStream *stm;
|
||||
DWORD size;
|
||||
void *ptr;
|
||||
IUnknown *orig;
|
||||
|
||||
TRACE("%s, %p, %p, %s.\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
|
||||
|
||||
ALIGN_POINTER(pBuffer, 3);
|
||||
|
||||
size = *(DWORD *)pBuffer;
|
||||
pBuffer += sizeof(DWORD);
|
||||
if (size != *(DWORD *)pBuffer)
|
||||
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
|
||||
|
||||
pBuffer += sizeof(DWORD);
|
||||
|
||||
/* FIXME: sanity check on size */
|
||||
|
||||
h = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||
if (!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
|
||||
|
||||
if (CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
|
||||
{
|
||||
GlobalFree(h);
|
||||
RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
|
||||
}
|
||||
|
||||
ptr = GlobalLock(h);
|
||||
memcpy(ptr, pBuffer, size);
|
||||
GlobalUnlock(h);
|
||||
|
||||
orig = *ppunk;
|
||||
hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
|
||||
IStream_Release(stm);
|
||||
|
||||
if (hr != S_OK) RaiseException(hr, 0, 0, NULL);
|
||||
|
||||
if (orig) IUnknown_Release(orig);
|
||||
|
||||
return pBuffer + size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserFree (combase.@)
|
||||
*/
|
||||
void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk)
|
||||
{
|
||||
TRACE("%p.\n", punk);
|
||||
if (punk) IUnknown_Release(punk);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
MODULE = ole32.dll
|
||||
IMPORTLIB = ole32
|
||||
IMPORTS = uuid advapi32 user32 gdi32 rpcrt4
|
||||
IMPORTS = uuid advapi32 user32 gdi32 combase rpcrt4
|
||||
DELAYIMPORTS = oleaut32
|
||||
EXTRADEFS = -D_OLE32_
|
||||
|
||||
|
|
|
@ -287,10 +287,10 @@
|
|||
@ stub UtConvertDvtd32toDvtd16
|
||||
@ stub UtGetDvtd16Info
|
||||
@ stub UtGetDvtd32Info
|
||||
@ stdcall WdtpInterfacePointer_UserFree(ptr)
|
||||
@ stdcall WdtpInterfacePointer_UserMarshal(ptr long ptr ptr ptr)
|
||||
@ stdcall WdtpInterfacePointer_UserSize(ptr long long ptr ptr)
|
||||
@ stdcall WdtpInterfacePointer_UserUnmarshal(ptr ptr ptr ptr)
|
||||
@ stdcall WdtpInterfacePointer_UserFree(ptr) combase.WdtpInterfacePointer_UserFree
|
||||
@ stdcall WdtpInterfacePointer_UserMarshal(ptr long ptr ptr ptr) combase.WdtpInterfacePointer_UserMarshal
|
||||
@ stdcall WdtpInterfacePointer_UserSize(ptr long long ptr ptr) combase.WdtpInterfacePointer_UserSize
|
||||
@ stdcall WdtpInterfacePointer_UserUnmarshal(ptr ptr ptr ptr) combase.WdtpInterfacePointer_UserUnmarshal
|
||||
@ stdcall WriteClassStg(ptr ptr)
|
||||
@ stdcall WriteClassStm(ptr ptr)
|
||||
@ stdcall WriteFmtUserTypeStg(ptr long ptr)
|
||||
|
|
|
@ -48,6 +48,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|||
( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
|
||||
( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
|
||||
|
||||
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid);
|
||||
unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer,
|
||||
IUnknown *punk, REFIID riid);
|
||||
unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid);
|
||||
|
||||
static const char* debugstr_user_flags(ULONG *pFlags)
|
||||
{
|
||||
char buf[12];
|
||||
|
@ -1491,182 +1496,6 @@ void __RPC_USER HMETAFILEPICT_UserFree(ULONG *pFlags, HMETAFILEPICT *phMfp)
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserSize [OLE32.@]
|
||||
*
|
||||
* Calculates the buffer size required to marshal an interface pointer.
|
||||
*
|
||||
* PARAMS
|
||||
* pFlags [I] Flags. See notes.
|
||||
* RealFlags [I] The MSHCTX to use when marshaling the interface.
|
||||
* punk [I] Interface pointer to size.
|
||||
* StartingSize [I] Starting size of the buffer. This value is added on to
|
||||
* the buffer size required for the clip format.
|
||||
* riid [I] ID of interface to size.
|
||||
*
|
||||
* RETURNS
|
||||
* The buffer size required to marshal an interface pointer plus the starting size.
|
||||
*
|
||||
* NOTES
|
||||
* Even though the function is documented to take a pointer to a ULONG in
|
||||
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
|
||||
* the first parameter is a ULONG.
|
||||
*/
|
||||
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, ULONG StartingSize, IUnknown *punk, REFIID riid)
|
||||
{
|
||||
DWORD marshal_size = 0;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%s, 0%x, %d, %p, %s)\n", debugstr_user_flags(pFlags), RealFlags, StartingSize, punk, debugstr_guid(riid));
|
||||
|
||||
hr = CoGetMarshalSizeMax(&marshal_size, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL);
|
||||
if(FAILED(hr)) return StartingSize;
|
||||
|
||||
ALIGN_LENGTH(StartingSize, 3);
|
||||
StartingSize += 2 * sizeof(DWORD);
|
||||
return StartingSize + marshal_size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserMarshal [OLE32.@]
|
||||
*
|
||||
* Marshals an interface pointer into a buffer.
|
||||
*
|
||||
* PARAMS
|
||||
* pFlags [I] Flags. See notes.
|
||||
* RealFlags [I] The MSHCTX to use when marshaling the interface.
|
||||
* pBuffer [I] Buffer to marshal the clip format into.
|
||||
* punk [I] Interface pointer to marshal.
|
||||
* riid [I] ID of interface to marshal.
|
||||
*
|
||||
* RETURNS
|
||||
* The end of the marshaled data in the buffer.
|
||||
*
|
||||
* NOTES
|
||||
* Even though the function is documented to take a pointer to a ULONG in
|
||||
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
|
||||
* the first parameter is a ULONG.
|
||||
*/
|
||||
unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer, IUnknown *punk, REFIID riid)
|
||||
{
|
||||
HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
|
||||
IStream *stm;
|
||||
DWORD size;
|
||||
void *ptr;
|
||||
|
||||
TRACE("(%s, 0x%x, %p, &%p, %s)\n", debugstr_user_flags(pFlags), RealFlags, pBuffer, punk, debugstr_guid(riid));
|
||||
|
||||
if(!h) return NULL;
|
||||
if(CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
|
||||
{
|
||||
GlobalFree(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(CoMarshalInterface(stm, riid, punk, LOWORD(RealFlags), NULL, MSHLFLAGS_NORMAL) != S_OK)
|
||||
{
|
||||
IStream_Release(stm);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
ALIGN_POINTER(pBuffer, 3);
|
||||
size = GlobalSize(h);
|
||||
|
||||
*(DWORD *)pBuffer = size;
|
||||
pBuffer += sizeof(DWORD);
|
||||
*(DWORD *)pBuffer = size;
|
||||
pBuffer += sizeof(DWORD);
|
||||
|
||||
ptr = GlobalLock(h);
|
||||
memcpy(pBuffer, ptr, size);
|
||||
GlobalUnlock(h);
|
||||
|
||||
IStream_Release(stm);
|
||||
return pBuffer + size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserUnmarshal [OLE32.@]
|
||||
*
|
||||
* Unmarshals an interface pointer from a buffer.
|
||||
*
|
||||
* PARAMS
|
||||
* pFlags [I] Flags. See notes.
|
||||
* pBuffer [I] Buffer to marshal the clip format from.
|
||||
* ppunk [I/O] Address that receives the unmarshaled interface pointer.
|
||||
* riid [I] ID of interface to unmarshal.
|
||||
*
|
||||
* RETURNS
|
||||
* The end of the marshaled data in the buffer.
|
||||
*
|
||||
* NOTES
|
||||
* Even though the function is documented to take a pointer to an ULONG in
|
||||
* pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
|
||||
* the first parameter is an ULONG.
|
||||
*/
|
||||
unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid)
|
||||
{
|
||||
HRESULT hr;
|
||||
HGLOBAL h;
|
||||
IStream *stm;
|
||||
DWORD size;
|
||||
void *ptr;
|
||||
IUnknown *orig;
|
||||
|
||||
TRACE("(%s, %p, %p, %s)\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
|
||||
|
||||
ALIGN_POINTER(pBuffer, 3);
|
||||
|
||||
size = *(DWORD *)pBuffer;
|
||||
pBuffer += sizeof(DWORD);
|
||||
if(size != *(DWORD *)pBuffer)
|
||||
RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
|
||||
|
||||
pBuffer += sizeof(DWORD);
|
||||
|
||||
/* FIXME: sanity check on size */
|
||||
|
||||
h = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||
if(!h) RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
|
||||
|
||||
if(CreateStreamOnHGlobal(h, TRUE, &stm) != S_OK)
|
||||
{
|
||||
GlobalFree(h);
|
||||
RaiseException(RPC_X_NO_MEMORY, 0, 0, NULL);
|
||||
}
|
||||
|
||||
ptr = GlobalLock(h);
|
||||
memcpy(ptr, pBuffer, size);
|
||||
GlobalUnlock(h);
|
||||
|
||||
orig = *ppunk;
|
||||
hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
|
||||
IStream_Release(stm);
|
||||
|
||||
if(hr != S_OK) RaiseException(hr, 0, 0, NULL);
|
||||
|
||||
if(orig) IUnknown_Release(orig);
|
||||
|
||||
return pBuffer + size;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* WdtpInterfacePointer_UserFree [OLE32.@]
|
||||
*
|
||||
* Releases an unmarshaled interface pointer.
|
||||
*
|
||||
* PARAMS
|
||||
* punk [I] Interface pointer to release.
|
||||
*
|
||||
* RETURNS
|
||||
* Nothing.
|
||||
*/
|
||||
void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk)
|
||||
{
|
||||
TRACE("(%p)\n", punk);
|
||||
if(punk) IUnknown_Release(punk);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* STGMEDIUM_UserSize [OLE32.@]
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue