diff --git a/dlls/wbemprox/services.c b/dlls/wbemprox/services.c index c2aaa3aaa5..e33ff364fe 100644 --- a/dlls/wbemprox/services.c +++ b/dlls/wbemprox/services.c @@ -136,6 +136,7 @@ struct wbem_services { IWbemServices IWbemServices_iface; LONG refs; + WCHAR *namespace; }; static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface ) @@ -158,6 +159,7 @@ static ULONG WINAPI wbem_services_Release( if (!refs) { TRACE("destroying %p\n", ws); + heap_free( ws->namespace ); heap_free( ws ); } return refs; @@ -486,7 +488,7 @@ static const IWbemServicesVtbl wbem_services_vtbl = wbem_services_ExecMethodAsync }; -HRESULT WbemServices_create( IUnknown *pUnkOuter, LPVOID *ppObj ) +HRESULT WbemServices_create( IUnknown *pUnkOuter, WCHAR *namespace, LPVOID *ppObj ) { struct wbem_services *ws; @@ -497,6 +499,7 @@ HRESULT WbemServices_create( IUnknown *pUnkOuter, LPVOID *ppObj ) ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl; ws->refs = 1; + ws->namespace = namespace; *ppObj = &ws->IWbemServices_iface; diff --git a/dlls/wbemprox/tests/services.c b/dlls/wbemprox/tests/services.c index 64be978604..ff798a3c61 100644 --- a/dlls/wbemprox/tests/services.c +++ b/dlls/wbemprox/tests/services.c @@ -84,9 +84,96 @@ static void test_IClientSecurity(void) SysFreeString( path ); } +static void test_IWbemLocator(void) +{ + static const WCHAR path0W[] = {0}; + static const WCHAR path1W[] = {'\\',0}; + static const WCHAR path2W[] = {'\\','\\',0}; + static const WCHAR path3W[] = {'\\','\\','.',0}; + static const WCHAR path4W[] = {'\\','\\','.','\\',0}; + static const WCHAR path5W[] = {'\\','R','O','O','T',0}; + static const WCHAR path6W[] = {'\\','\\','R','O','O','T',0}; + static const WCHAR path7W[] = {'\\','\\','.','R','O','O','T',0}; + static const WCHAR path8W[] = {'\\','\\','.','\\','N','O','N','E',0}; + static const WCHAR path9W[] = {'\\','\\','.','\\','R','O','O','T',0}; + static const WCHAR path10W[] = {'\\','\\','\\','.','\\','R','O','O','T',0}; + static const WCHAR path11W[] = {'\\','/','.','\\','R','O','O','T',0}; + static const WCHAR path12W[] = {'/','/','.','\\','R','O','O','T',0}; + static const WCHAR path13W[] = {'\\','\\','.','/','R','O','O','T',0}; + static const WCHAR path14W[] = {'/','/','.','/','R','O','O','T',0}; + static const WCHAR path15W[] = {'N','O','N','E',0}; + static const WCHAR path16W[] = {'R','O','O','T',0}; + static const WCHAR path17W[] = {'R','O','O','T','\\','N','O','N','E',0}; + static const WCHAR path18W[] = {'R','O','O','T','\\','C','I','M','V','2',0}; + static const WCHAR path19W[] = {'R','O','O','T','\\','\\','C','I','M','V','2',0}; + static const WCHAR path20W[] = {'R','O','O','T','\\','C','I','M','V','2','\\',0}; + static const WCHAR path21W[] = {'R','O','O','T','/','C','I','M','V','2',0}; + static const struct + { + const WCHAR *path; + HRESULT result; + int todo; + HRESULT result_broken; + } + test[] = + { + { path0W, WBEM_E_INVALID_NAMESPACE }, + { path1W, WBEM_E_INVALID_NAMESPACE }, + { path2W, WBEM_E_INVALID_NAMESPACE }, + { path3W, WBEM_E_INVALID_NAMESPACE }, + { path4W, WBEM_E_INVALID_NAMESPACE, 0, WBEM_E_INVALID_PARAMETER }, + { path5W, WBEM_E_INVALID_NAMESPACE }, + { path6W, 0x800706ba, 1 }, + { path7W, 0x800706ba, 1 }, + { path8W, WBEM_E_INVALID_NAMESPACE }, + { path9W, S_OK }, + { path10W, WBEM_E_INVALID_PARAMETER }, + { path11W, S_OK }, + { path12W, S_OK }, + { path13W, S_OK }, + { path14W, S_OK }, + { path15W, WBEM_E_INVALID_NAMESPACE }, + { path16W, S_OK }, + { path17W, WBEM_E_INVALID_NAMESPACE }, + { path18W, S_OK }, + { path19W, WBEM_E_INVALID_NAMESPACE }, + { path20W, WBEM_E_INVALID_NAMESPACE }, + { path21W, S_OK } + }; + IWbemLocator *locator; + IWbemServices *services; + unsigned int i; + HRESULT hr; + BSTR resource; + + hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (void **)&locator ); + if (hr != S_OK) + { + win_skip("can't create instance of WbemLocator\n"); + return; + } + ok( hr == S_OK, "failed to create IWbemLocator interface %08x\n", hr ); + + for (i = 0; i < sizeof(test) / sizeof(test[0]); i++) + { + resource = SysAllocString( test[i].path ); + hr = IWbemLocator_ConnectServer( locator, resource, NULL, NULL, NULL, 0, NULL, NULL, &services ); + if (test[i].todo) todo_wine + ok( hr == test[i].result || broken(hr == test[i].result_broken), + "%u: expected %08x got %08x\n", i, test[i].result, hr ); + else + ok( hr == test[i].result || broken(hr == test[i].result_broken), + "%u: expected %08x got %08x\n", i, test[i].result, hr ); + SysFreeString( resource ); + if (hr == S_OK) IWbemServices_Release( services ); + } + IWbemLocator_Release( locator ); +} + START_TEST(services) { CoInitialize( NULL ); test_IClientSecurity(); + test_IWbemLocator(); CoUninitialize(); } diff --git a/dlls/wbemprox/wbemlocator.c b/dlls/wbemprox/wbemlocator.c index b80e080bca..87a4d012a3 100644 --- a/dlls/wbemprox/wbemlocator.c +++ b/dlls/wbemprox/wbemlocator.c @@ -86,6 +86,77 @@ static HRESULT WINAPI wbem_locator_QueryInterface( return S_OK; } +static BOOL is_local_machine( const WCHAR *server ) +{ + static const WCHAR dotW[] = {'.',0}; + WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD len = sizeof(buffer) / sizeof(buffer[0]); + + if (!server || !strcmpW( server, dotW )) return TRUE; + if (GetComputerNameW( buffer, &len ) && !strcmpiW( server, buffer )) return TRUE; + return FALSE; +} + +static HRESULT parse_resource( const WCHAR *resource, WCHAR **server, WCHAR **namespace ) +{ + static const WCHAR rootW[] = {'R','O','O','T'}; + static const WCHAR cimv2W[] = {'C','I','M','V','2'}; + HRESULT hr = WBEM_E_INVALID_NAMESPACE; + const WCHAR *p, *q; + unsigned int len; + + *server = NULL; + *namespace = NULL; + p = q = resource; + if (*p == '\\' || *p == '/') + { + p++; + if (*p == '\\' || *p == '/') p++; + if (!*p) return WBEM_E_INVALID_NAMESPACE; + if (*p == '\\' || *p == '/') return WBEM_E_INVALID_PARAMETER; + q = p + 1; + while (*q && *q != '\\' && *q != '/') q++; + if (!*q) return WBEM_E_INVALID_NAMESPACE; + len = q - p; + if (!(*server = heap_alloc( (len + 1) * sizeof(WCHAR) ))) + { + hr = E_OUTOFMEMORY; + goto done; + } + memcpy( *server, p, len * sizeof(WCHAR) ); + (*server)[len] = 0; + q++; + } + if (!*q) goto done; + p = q; + while (*q && *q != '\\' && *q != '/') q++; + len = q - p; + if (len >= sizeof(rootW) / sizeof(rootW[0]) && memicmpW( rootW, p, len )) goto done; + if (!*q) + { + hr = S_OK; + goto done; + } + q++; + if ((len = strlenW( q )) != sizeof(cimv2W) / sizeof(cimv2W[0]) || memicmpW( q, cimv2W, len )) + goto done; + if (!(*namespace = heap_alloc( (len + 1) * sizeof(WCHAR) ))) hr = E_OUTOFMEMORY; + else + { + memcpy( *namespace, p, len * sizeof(WCHAR) ); + (*namespace)[len] = 0; + hr = S_OK; + } + +done: + if (hr != S_OK) + { + heap_free( *server ); + heap_free( *namespace ); + } + return hr; +} + static HRESULT WINAPI wbem_locator_ConnectServer( IWbemLocator *iface, const BSTR NetworkResource, @@ -98,14 +169,19 @@ static HRESULT WINAPI wbem_locator_ConnectServer( IWbemServices **ppNamespace) { HRESULT hr; + WCHAR *server, *namespace; TRACE("%p, %s, %s, %s, %s, 0x%08x, %s, %p, %p)\n", iface, debugstr_w(NetworkResource), debugstr_w(User), debugstr_w(Password), debugstr_w(Locale), SecurityFlags, debugstr_w(Authority), pCtx, ppNamespace); - if (((NetworkResource[0] == '\\' && NetworkResource[1] == '\\') || - (NetworkResource[0] == '/' && NetworkResource[1] == '/')) && NetworkResource[2] != '.') + hr = parse_resource( NetworkResource, &server, &namespace ); + if (hr != S_OK) return hr; + + if (!is_local_machine( server )) { FIXME("remote computer not supported\n"); + heap_free( server ); + heap_free( namespace ); return WBEM_E_TRANSPORT_FAILURE; } if (User || Password || Authority) @@ -115,10 +191,11 @@ static HRESULT WINAPI wbem_locator_ConnectServer( if (SecurityFlags) FIXME("unsupported flags\n"); - hr = WbemServices_create( NULL, (void **)ppNamespace ); + hr = WbemServices_create( NULL, namespace, (void **)ppNamespace ); if (SUCCEEDED( hr )) return WBEM_NO_ERROR; + heap_free( namespace ); return WBEM_E_FAILED; } diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index 779d43db20..d0cdb76081 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -121,7 +121,7 @@ HRESULT get_propval( const struct view *, UINT, const WCHAR *, VARIANT *, HRESULT get_properties( const struct view *, SAFEARRAY ** ) DECLSPEC_HIDDEN; HRESULT WbemLocator_create(IUnknown *, LPVOID *) DECLSPEC_HIDDEN; -HRESULT WbemServices_create(IUnknown *, LPVOID *) DECLSPEC_HIDDEN; +HRESULT WbemServices_create(IUnknown *, WCHAR *, LPVOID *) DECLSPEC_HIDDEN; HRESULT WbemClassObject_create(IUnknown *, IEnumWbemClassObject *, UINT, LPVOID *) DECLSPEC_HIDDEN; HRESULT EnumWbemClassObject_create(IUnknown *, struct query *, LPVOID *) DECLSPEC_HIDDEN;