diff --git a/dlls/wbemdisp/locator.c b/dlls/wbemdisp/locator.c index c3103fa5b11..989c6108f90 100644 --- a/dlls/wbemdisp/locator.c +++ b/dlls/wbemdisp/locator.c @@ -93,11 +93,22 @@ static HRESULT get_typeinfo( enum type_id tid, ITypeInfo **ret ) return S_OK; } +#define DISPID_BASE 0x1800000 + +struct member +{ + BSTR name; + DISPID dispid; +}; + struct object { ISWbemObject ISWbemObject_iface; LONG refs; IWbemClassObject *object; + struct member *members; + UINT nb_members; + DISPID last_dispid; }; static inline struct object *impl_from_ISWbemObject( @@ -120,8 +131,12 @@ static ULONG WINAPI object_Release( LONG refs = InterlockedDecrement( &object->refs ); if (!refs) { + UINT i; + TRACE( "destroying %p\n", object ); IWbemClassObject_Release( object->object ); + for (i = 0; i < object->nb_members; i++) SysFreeString( object->members[i].name ); + heap_free( object->members ); heap_free( object ); } return refs; @@ -169,9 +184,63 @@ static HRESULT WINAPI object_GetTypeInfo( ITypeInfo **info ) { struct object *object = impl_from_ISWbemObject( iface ); - TRACE( "%p, %u, %u, %p\n", object, index, lcid, info ); + FIXME( "%p, %u, %u, %p\n", object, index, lcid, info ); + return E_NOTIMPL; +} - return get_typeinfo( ISWbemObject_tid, info ); +#define DISPID_BASE 0x1800000 + +static HRESULT init_members( struct object *object ) +{ + LONG bound, i; + SAFEARRAY *sa; + HRESULT hr; + + if (object->members) return S_OK; + + hr = IWbemClassObject_GetNames( object->object, NULL, 0, NULL, &sa ); + if (FAILED( hr )) return hr; + hr = SafeArrayGetUBound( sa, 1, &bound ); + if (FAILED( hr )) + { + SafeArrayDestroy( sa ); + return hr; + } + if (!(object->members = heap_alloc( sizeof(struct member) * (bound + 1) ))) + { + SafeArrayDestroy( sa ); + return E_OUTOFMEMORY; + } + for (i = 0; i <= bound; i++) + { + hr = SafeArrayGetElement( sa, &i, &object->members[i].name ); + if (FAILED( hr )) + { + for (i--; i >= 0; i--) SysFreeString( object->members[i].name ); + SafeArrayDestroy( sa ); + heap_free( object->members ); + object->members = NULL; + return E_OUTOFMEMORY; + } + object->members[i].dispid = 0; + } + object->nb_members = bound + 1; + SafeArrayDestroy( sa ); + return S_OK; +} + +static DISPID get_member_dispid( struct object *object, const WCHAR *name ) +{ + UINT i; + for (i = 0; i < object->nb_members; i++) + { + if (!strcmpiW( object->members[i].name, name )) + { + if (!object->members[i].dispid) object->members[i].dispid = ++object->last_dispid; + return object->members[i].dispid; + } + } + return DISPID_UNKNOWN; } static HRESULT WINAPI object_GetIDsOfNames( @@ -183,20 +252,22 @@ static HRESULT WINAPI object_GetIDsOfNames( DISPID *dispid ) { struct object *object = impl_from_ISWbemObject( iface ); - ITypeInfo *typeinfo; HRESULT hr; + UINT i; TRACE( "%p, %s, %p, %u, %u, %p\n", object, debugstr_guid(riid), names, count, lcid, dispid ); if (!names || !count || !dispid) return E_INVALIDARG; - hr = get_typeinfo( ISWbemObject_tid, &typeinfo ); - if (SUCCEEDED(hr)) + hr = init_members( object ); + if (FAILED( hr )) return hr; + + for (i = 0; i < count; i++) { - hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid ); - ITypeInfo_Release( typeinfo ); + if ((dispid[i] = get_member_dispid( object, names[i] )) == DISPID_UNKNOWN) break; } - return hr; + if (i != count) return DISP_E_UNKNOWNNAME; + return S_OK; } static HRESULT WINAPI object_Invoke( @@ -260,6 +331,9 @@ static HRESULT SWbemObject_create( IWbemClassObject *wbem_object, ISWbemObject * object->refs = 1; object->object = wbem_object; IWbemClassObject_AddRef( object->object ); + object->members = NULL; + object->nb_members = 0; + object->last_dispid = DISPID_BASE; *obj = &object->ISWbemObject_iface; TRACE( "returning iface %p\n", *obj ); diff --git a/dlls/wbemdisp/tests/wbemdisp.c b/dlls/wbemdisp/tests/wbemdisp.c index 863115b98d3..d91e5b88319 100644 --- a/dlls/wbemdisp/tests/wbemdisp.c +++ b/dlls/wbemdisp/tests/wbemdisp.c @@ -26,10 +26,14 @@ #include "wine/test.h" DEFINE_GUID(CLSID_WINMGMTS,0x172bddf8,0xceea,0x11d1,0x8b,0x05,0x00,0x60,0x08,0x06,0xd9,0xb6); +DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); static void test_ParseDisplayName(void) { static const WCHAR biosW[] = {'W','i','n','3','2','_','B','i','o','s',0}; + static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; + static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; + static const WCHAR nosuchW[] = {'N','o','S','u','c','h',0}; static const WCHAR name1[] = {'w','i','n','m','g','m','t','s',':',0}; static const WCHAR name2[] = @@ -54,12 +58,13 @@ static void test_ParseDisplayName(void) { name3, S_OK, &IID_ISWbemObject, sizeof(name3)/sizeof(name3[0]) - 1 }, { name4, S_OK, &IID_ISWbemObject, sizeof(name4)/sizeof(name4[0]) - 1 } }; + LCID english = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT); IParseDisplayName *displayname; IBindCtx *ctx; IMoniker *moniker; IUnknown *obj; BSTR str; - ULONG i, eaten; + ULONG i, eaten, count; HRESULT hr; hr = CoCreateInstance( &CLSID_WINMGMTS, NULL, CLSCTX_INPROC_SERVER, &IID_IParseDisplayName, (void **)&displayname ); @@ -127,6 +132,8 @@ static void test_ParseDisplayName(void) { VARIANT var; ULONG fetched; + IDispatch *dispatch = NULL; + DISPID dispid; fetched = 0xdeadbeef; hr = IEnumVARIANT_Next( enumvar, 0, &var, &fetched ); @@ -141,6 +148,41 @@ static void test_ParseDisplayName(void) ok( fetched == 1, "got %u\n", fetched ); ok( V_VT( &var ) == VT_DISPATCH, "got %u\n", V_VT( &var ) ); ok( V_DISPATCH( &var ) != (IDispatch *)0xdeadbeef, "got %u\n", V_VT( &var ) ); + + dispatch = V_DISPATCH( &var ); + count = 0; + hr = IDispatch_GetTypeInfoCount( dispatch, &count ); + ok( hr == S_OK, "got %x\n", hr ); + ok( count == 1, "got %u\n", count ); + + str = SysAllocString( manufacturerW ); + dispid = 0xdeadbeef; + hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid ); + SysFreeString( str ); + ok( hr == S_OK, "got %x\n", hr ); + ok( dispid == 0x1800001 || dispid == 0x10b /* win2k */, "got %x\n", dispid ); + + str = SysAllocString( versionW ); + dispid = 0xdeadbeef; + hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid ); + SysFreeString( str ); + ok( hr == S_OK, "got %x\n", hr ); + ok( dispid == 0x1800002 || dispid == 0x119 /* win2k */, "got %x\n", dispid ); + + str = SysAllocString( nosuchW ); + dispid = 0xdeadbeef; + hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid ); + SysFreeString( str ); + ok( hr == DISP_E_UNKNOWNNAME, "got %x\n", hr ); + ok( dispid == DISPID_UNKNOWN, "got %x\n", dispid ); + + str = SysAllocString( manufacturerW ); + dispid = 0xdeadbeef; + hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid ); + SysFreeString( str ); + ok( hr == S_OK, "got %x\n", hr ); + ok( dispid == 0x1800001 || dispid == 0x10b /* win2k */, "got %x\n", dispid ); + VariantClear( &var ); fetched = 0xdeadbeef;