2009-11-07 13:29:11 +01:00
/*
* OLE DB Marshaling Tests
*
* Copyright 2009 Robert Shearman
*
* 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 _WIN32_DCOM
# define COBJMACROS
# define CONST_VTABLE
# include <stdarg.h>
# include <stdio.h>
# include "windef.h"
# include "winbase.h"
# include "objbase.h"
# include "oledb.h"
# include "wine/test.h"
# define RELEASEMARSHALDATA WM_USER
# define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
struct host_object_data
{
IStream * stream ;
IID iid ;
IUnknown * object ;
MSHLFLAGS marshal_flags ;
HANDLE marshal_event ;
IMessageFilter * filter ;
} ;
static DWORD CALLBACK host_object_proc ( LPVOID p )
{
struct host_object_data * data = p ;
HRESULT hr ;
MSG msg ;
CoInitializeEx ( NULL , COINIT_APARTMENTTHREADED ) ;
if ( data - > filter )
{
IMessageFilter * prev_filter = NULL ;
hr = CoRegisterMessageFilter ( data - > filter , & prev_filter ) ;
if ( prev_filter ) IMessageFilter_Release ( prev_filter ) ;
ok_ole_success ( hr , CoRegisterMessageFilter ) ;
}
hr = CoMarshalInterface ( data - > stream , & data - > iid , data - > object , MSHCTX_INPROC , NULL , data - > marshal_flags ) ;
ok_ole_success ( hr , CoMarshalInterface ) ;
/* force the message queue to be created before signaling parent thread */
PeekMessage ( & msg , NULL , WM_USER , WM_USER , PM_NOREMOVE ) ;
SetEvent ( data - > marshal_event ) ;
while ( GetMessage ( & msg , NULL , 0 , 0 ) )
{
if ( msg . hwnd = = NULL & & msg . message = = RELEASEMARSHALDATA )
{
CoReleaseMarshalData ( data - > stream ) ;
SetEvent ( ( HANDLE ) msg . lParam ) ;
}
else
DispatchMessage ( & msg ) ;
}
HeapFree ( GetProcessHeap ( ) , 0 , data ) ;
CoUninitialize ( ) ;
return hr ;
}
static DWORD start_host_object2 ( IStream * stream , REFIID riid , IUnknown * object , MSHLFLAGS marshal_flags , IMessageFilter * filter , HANDLE * thread )
{
DWORD tid = 0 ;
HANDLE marshal_event = CreateEvent ( NULL , FALSE , FALSE , NULL ) ;
struct host_object_data * data = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( * data ) ) ;
data - > stream = stream ;
data - > iid = * riid ;
data - > object = object ;
data - > marshal_flags = marshal_flags ;
data - > marshal_event = marshal_event ;
data - > filter = filter ;
* thread = CreateThread ( NULL , 0 , host_object_proc , data , 0 , & tid ) ;
/* wait for marshaling to complete before returning */
ok ( ! WaitForSingleObject ( marshal_event , 10000 ) , " wait timed out \n " ) ;
CloseHandle ( marshal_event ) ;
return tid ;
}
static DWORD start_host_object ( IStream * stream , REFIID riid , IUnknown * object , MSHLFLAGS marshal_flags , HANDLE * thread )
{
return start_host_object2 ( stream , riid , object , marshal_flags , NULL , thread ) ;
}
static void end_host_object ( DWORD tid , HANDLE thread )
{
BOOL ret = PostThreadMessage ( tid , WM_QUIT , 0 , 0 ) ;
ok ( ret , " PostThreadMessage failed with error %d \n " , GetLastError ( ) ) ;
/* be careful of races - don't return until hosting thread has terminated */
ok ( ! WaitForSingleObject ( thread , 10000 ) , " wait timed out \n " ) ;
CloseHandle ( thread ) ;
}
# define TEST_PROPID 0xdead
static const WCHAR wszDBPropertyTestString [ ] = { ' D ' , ' B ' , ' P ' , ' r ' , ' o ' , ' p ' , ' e ' , ' r ' , ' t ' , ' y ' , ' T ' , ' e ' , ' s ' , ' t ' , ' S ' , ' t ' , ' r ' , ' i ' , ' n ' , ' g ' , 0 } ;
static const WCHAR wszDBPropertyColumnName [ ] = { ' C ' , ' o ' , ' l ' , ' u ' , ' m ' , ' n ' , 0 } ;
static HRESULT WINAPI Test_DBProperties_QueryInterface (
IDBProperties * iface ,
REFIID riid ,
void * * ppvObject )
{
if ( IsEqualIID ( riid , & IID_IUnknown ) | |
IsEqualIID ( riid , & IID_IDBProperties ) )
{
* ppvObject = iface ;
return S_OK ;
}
* ppvObject = NULL ;
return E_NOINTERFACE ;
}
static ULONG WINAPI Test_DBProperties_AddRef (
IDBProperties * iface )
{
return 2 ;
}
static ULONG WINAPI Test_DBProperties_Release (
IDBProperties * iface )
{
return 1 ;
}
/*** IDBProperties methods ***/
static HRESULT WINAPI Test_DBProperties_GetProperties (
IDBProperties * iface ,
ULONG cPropertyIDSets ,
const DBPROPIDSET rgPropertyIDSets [ ] ,
ULONG * pcPropertySets ,
DBPROPSET * * prgPropertySets )
{
ok ( cPropertyIDSets = = 0 , " Expected cPropertyIDSets to be 0 instead of %d \n " , cPropertyIDSets ) ;
2009-11-12 01:30:26 +01:00
ok ( * pcPropertySets = = 0 , " Expected *pcPropertySets to be 0 instead of %d \n " , * pcPropertySets ) ;
* pcPropertySets = 1 ;
2009-11-12 01:30:32 +01:00
* prgPropertySets = CoTaskMemAlloc ( sizeof ( DBPROPSET ) ) ;
( * prgPropertySets ) [ 0 ] . rgProperties = CoTaskMemAlloc ( sizeof ( DBPROP ) ) ;
( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . dwPropertyID = TEST_PROPID ;
( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . dwOptions = DBPROPOPTIONS_REQUIRED ;
( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . dwStatus = S_OK ;
( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . colid . eKind = DBKIND_GUID_NAME ;
2009-11-07 13:29:11 +01:00
/* colid contents */
2009-11-12 01:30:32 +01:00
( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . colid . uGuid . guid = IID_IDBProperties ;
( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . colid . uName . pwszName = CoTaskMemAlloc ( sizeof ( wszDBPropertyColumnName ) ) ;
memcpy ( ( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . colid . uName . pwszName , wszDBPropertyColumnName , sizeof ( wszDBPropertyColumnName ) ) ;
2009-11-07 13:29:11 +01:00
/* vValue contents */
2009-11-12 01:30:32 +01:00
V_VT ( & ( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . vValue ) = VT_BSTR ;
V_BSTR ( & ( * prgPropertySets ) [ 0 ] . rgProperties [ 0 ] . vValue ) = SysAllocString ( wszDBPropertyTestString ) ;
( * prgPropertySets ) [ 0 ] . cProperties = 1 ;
( * prgPropertySets ) [ 0 ] . guidPropertySet = IID_IDBProperties ;
2009-11-07 13:29:11 +01:00
return S_OK ;
}
static HRESULT WINAPI Test_DBProperties_GetPropertyInfo (
IDBProperties * iface ,
ULONG cPropertyIDSets ,
const DBPROPIDSET rgPropertyIDSets [ ] ,
ULONG * pcPropertyInfoSets ,
DBPROPINFOSET * * prgPropertyInfoSets ,
OLECHAR * * ppDescBuffer )
{
return E_NOTIMPL ;
}
static HRESULT WINAPI Test_DBProperties_SetProperties (
IDBProperties * iface ,
ULONG cPropertySets ,
DBPROPSET rgPropertySets [ ] )
{
return E_NOTIMPL ;
}
static const IDBPropertiesVtbl Test_DBProperties_Vtbl =
{
Test_DBProperties_QueryInterface ,
Test_DBProperties_AddRef ,
Test_DBProperties_Release ,
Test_DBProperties_GetProperties ,
Test_DBProperties_GetPropertyInfo ,
Test_DBProperties_SetProperties ,
} ;
static IDBProperties Test_DBProperties =
{
& Test_DBProperties_Vtbl
} ;
static void test_IDBProperties ( void )
{
HRESULT hr ;
IStream * pStream = NULL ;
IDBProperties * pProxy = NULL ;
DWORD tid ;
HANDLE thread ;
static const LARGE_INTEGER ullZero ;
ULONG propset_count ;
DBPROPSET * propsets = NULL ;
hr = CreateStreamOnHGlobal ( NULL , TRUE , & pStream ) ;
ok_ole_success ( hr , " CreateStreamOnHGlobal " ) ;
tid = start_host_object ( pStream , & IID_IDBProperties , ( IUnknown * ) & Test_DBProperties , MSHLFLAGS_NORMAL , & thread ) ;
IStream_Seek ( pStream , ullZero , STREAM_SEEK_SET , NULL ) ;
hr = CoUnmarshalInterface ( pStream , & IID_IDBProperties , ( void * * ) & pProxy ) ;
ok_ole_success ( hr , " CoUnmarshalInterface " ) ;
IStream_Release ( pStream ) ;
propset_count = 1 ;
hr = IDBProperties_GetProperties ( pProxy , 0 , NULL , & propset_count , & propsets ) ;
2009-11-14 15:56:02 +01:00
ok ( hr = = S_OK , " IDBProperties_GetProperties failed with error 0x%08x \n " , hr ) ;
2009-11-07 13:29:11 +01:00
ok ( propset_count = = 1 , " Expected propset_count of 1 but got %d \n " , propset_count ) ;
ok ( propsets - > rgProperties [ 0 ] . dwPropertyID = = TEST_PROPID , " Expected property ID of 0x%x, but got 0x%x \n " , TEST_PROPID , propsets - > rgProperties [ 0 ] . dwPropertyID ) ;
ok ( propsets - > rgProperties [ 0 ] . dwOptions = = DBPROPOPTIONS_REQUIRED , " Expected property options of 0x%x, but got 0x%x \n " , DBPROPOPTIONS_REQUIRED , propsets - > rgProperties [ 0 ] . dwOptions ) ;
ok ( propsets - > rgProperties [ 0 ] . dwStatus = = S_OK , " Expected property options of 0x%x, but got 0x%x \n " , S_OK , propsets - > rgProperties [ 0 ] . dwStatus ) ;
ok ( propsets - > rgProperties [ 0 ] . colid . eKind = = DBKIND_GUID_NAME , " Expected property colid kind of DBKIND_GUID_NAME, but got %d \n " , propsets - > rgProperties [ 0 ] . colid . eKind ) ;
/* colid contents */
ok ( IsEqualGUID ( & propsets - > rgProperties [ 0 ] . colid . uGuid . guid , & IID_IDBProperties ) , " Unexpected property colid guid \n " ) ;
ok ( ! lstrcmpW ( propsets - > rgProperties [ 0 ] . colid . uName . pwszName , wszDBPropertyColumnName ) , " Unexpected property colid name \n " ) ;
/* vValue contents */
ok ( V_VT ( & propsets - > rgProperties [ 0 ] . vValue ) = = VT_BSTR , " Expected property value vt of VT_BSTR, but got %d \n " , V_VT ( & propsets - > rgProperties [ 0 ] . vValue ) ) ;
ok ( ! lstrcmpW ( V_BSTR ( & propsets - > rgProperties [ 0 ] . vValue ) , wszDBPropertyTestString ) , " Unexpected property value string \n " ) ;
ok ( propsets - > cProperties = = 1 , " Expected property count of 1 but got %d \n " , propsets - > cProperties ) ;
ok ( IsEqualGUID ( & propsets - > guidPropertySet , & IID_IDBProperties ) , " Unexpected guid for property set \n " ) ;
IDBProperties_Release ( pProxy ) ;
end_host_object ( tid , thread ) ;
}
START_TEST ( marshal )
{
CoInitializeEx ( NULL , COINIT_APARTMENTTHREADED ) ;
test_IDBProperties ( ) ;
CoUninitialize ( ) ;
}