[1/4] wmiutils: Add support for for parsing and serializing a key list.
Hans Leidekker
hans at codeweavers.com
Thu Feb 21 03:45:17 CST 2013
---
dlls/wmiutils/path.c | 180 +++++++++++++++++++++++++++++++++-----
dlls/wmiutils/tests/path.c | 48 +++++++++-
dlls/wmiutils/wmiutils_private.h | 6 ++
3 files changed, 210 insertions(+), 24 deletions(-)
diff --git a/dlls/wmiutils/path.c b/dlls/wmiutils/path.c
index 28536b6..7b7e46f 100644
--- a/dlls/wmiutils/path.c
+++ b/dlls/wmiutils/path.c
@@ -32,6 +32,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(wmiutils);
+struct key
+{
+ WCHAR *name;
+ int len_name;
+ WCHAR *value;
+ int len_value;
+};
+
struct path
{
IWbemPath IWbemPath_iface;
@@ -46,6 +54,8 @@ struct path
int num_namespaces;
WCHAR *class;
int len_class;
+ struct key *keys;
+ unsigned int num_keys;
ULONGLONG flags;
};
@@ -60,16 +70,26 @@ static void init_path( struct path *path )
path->num_namespaces = 0;
path->class = NULL;
path->len_class = 0;
+ path->keys = NULL;
+ path->num_keys = 0;
path->flags = 0;
}
static void clear_path( struct path *path )
{
+ unsigned int i;
+
heap_free( path->text );
heap_free( path->server );
heap_free( path->namespaces );
heap_free( path->len_namespaces );
heap_free( path->class );
+ for (i = 0; i < path->num_keys; i++)
+ {
+ heap_free( path->keys[i].name );
+ heap_free( path->keys[i].value );
+ }
+ heap_free( path->keys );
init_path( path );
}
@@ -124,6 +144,38 @@ static HRESULT WINAPI path_QueryInterface(
return S_OK;
}
+static HRESULT parse_key( struct key *key, const WCHAR *str, unsigned int *ret_len )
+{
+ const WCHAR *p, *q;
+ unsigned int len;
+
+ p = q = str;
+ while (*q && *q != '=')
+ {
+ if (*q == ',' || isspaceW( *q )) return WBEM_E_INVALID_PARAMETER;
+ q++;
+ }
+ len = q - p;
+ if (!(key->name = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
+ memcpy( key->name, p, len * sizeof(WCHAR) );
+ key->name[len] = 0;
+ key->len_name = len;
+
+ p = ++q;
+ if (!*p || *p == ',' || isspaceW( *p )) return WBEM_E_INVALID_PARAMETER;
+
+ while (*q && *q != ',') q++;
+ len = q - p;
+ if (!(key->value = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
+ memcpy( key->value, p, len * sizeof(WCHAR) );
+ key->value[len] = 0;
+ key->len_value = len;
+
+ *ret_len = q - str;
+ if (*q == ',') (*ret_len)++;
+ return S_OK;
+}
+
static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
{
HRESULT hr = E_OUTOFMEMORY;
@@ -181,7 +233,27 @@ static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
path->class[len] = 0;
path->len_class = len;
- if (*q == '.') FIXME("handle key list\n");
+ if (*q == '.')
+ {
+ p = ++q;
+ path->num_keys++;
+ while (*q)
+ {
+ if (*q == ',') path->num_keys++;
+ q++;
+ }
+ if (!(path->keys = heap_alloc_zero( path->num_keys * sizeof(struct key) ))) goto done;
+ i = 0;
+ q = p;
+ while (*q)
+ {
+ if (i >= path->num_keys) break;
+ hr = parse_key( &path->keys[i], q, &len );
+ if (hr != S_OK) goto done;
+ q += len;
+ i++;
+ }
+ }
hr = S_OK;
done:
@@ -267,22 +339,58 @@ static WCHAR *build_server( struct path *path, int *len )
return ret;
}
+static WCHAR *build_keylist( struct path *path, int *len )
+{
+ WCHAR *ret, *p;
+ unsigned int i;
+
+ *len = 0;
+ for (i = 0; i < path->num_keys; i++)
+ {
+ if (i > 0) *len += 1;
+ *len += path->keys[i].len_name + path->keys[i].len_value + 1;
+ }
+ if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
+ for (i = 0; i < path->num_keys; i++)
+ {
+ if (i > 0) *p++ = ',';
+ memcpy( p, path->keys[i].name, path->keys[i].len_name * sizeof(WCHAR) );
+ p += path->keys[i].len_name;
+ *p++ = '=';
+ memcpy( p, path->keys[i].value, path->keys[i].len_value * sizeof(WCHAR) );
+ p += path->keys[i].len_value;
+ }
+ *p = 0;
+ return ret;
+}
+
static WCHAR *build_path( struct path *path, LONG flags, int *len )
{
+ *len = 0;
switch (flags)
{
case 0:
{
- int len_namespace;
+ int len_namespace, len_keylist;
WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE );
+ WCHAR *keylist = build_keylist( path, &len_keylist );
- if (!namespace) return NULL;
-
+ if (!namespace || !keylist)
+ {
+ heap_free( namespace );
+ heap_free( keylist );
+ return NULL;
+ }
*len = len_namespace;
- if (path->len_class) *len += 1 + path->len_class;
+ if (path->len_class)
+ {
+ *len += path->len_class + 1;
+ if (path->num_keys) *len += len_keylist + 1;
+ }
if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
{
heap_free( namespace );
+ heap_free( keylist );
return NULL;
}
strcpyW( ret, namespace );
@@ -290,38 +398,66 @@ static WCHAR *build_path( struct path *path, LONG flags, int *len )
{
ret[len_namespace] = ':';
strcpyW( ret + len_namespace + 1, path->class );
+ if (path->num_keys)
+ {
+ ret[len_namespace + path->len_class + 1] = '.';
+ strcpyW( ret + len_namespace + path->len_class + 2, keylist );
+ }
}
heap_free( namespace );
+ heap_free( keylist );
return ret;
}
case WBEMPATH_GET_RELATIVE_ONLY:
- if (!path->len_class)
+ {
+ int len_keylist;
+ WCHAR *ret, *keylist;
+
+ if (!path->len_class) return NULL;
+ if (!(keylist = build_keylist( path, &len_keylist ))) return NULL;
+
+ *len = path->len_class;
+ if (path->num_keys) *len += len_keylist + 1;
+ if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
{
- *len = 0;
+ heap_free( keylist );
return NULL;
}
- *len = path->len_class;
- return strdupW( path->class );
-
+ strcpyW( ret, path->class );
+ if (path->num_keys)
+ {
+ ret[path->len_class] = '.';
+ strcpyW( ret + path->len_class + 1, keylist );
+ }
+ heap_free( keylist );
+ return ret;
+ }
case WBEMPATH_GET_SERVER_TOO:
{
- int len_namespace, len_server;
+ int len_namespace, len_server, len_keylist;
WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
WCHAR *server = build_server( path, &len_server );
+ WCHAR *keylist = build_keylist( path, &len_keylist );
- if (!namespace || !server)
+ if (!namespace || !server || !keylist)
{
heap_free( namespace );
heap_free( server );
+ heap_free( keylist );
return NULL;
}
*len = len_namespace + len_server;
- if (path->len_class) *len += 1 + path->len_class;
+ if (path->len_class)
+ {
+ *len += path->len_class + 1;
+ if (path->num_keys) *len += len_keylist + 1;
+ }
if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
{
heap_free( namespace );
heap_free( server );
+ heap_free( keylist );
return NULL;
}
strcpyW( p, server );
@@ -330,11 +466,17 @@ static WCHAR *build_path( struct path *path, LONG flags, int *len )
p += len_namespace;
if (path->len_class)
{
- *p = ':';
- strcpyW( p + 1, path->class );
+ *p++ = ':';
+ strcpyW( p, path->class );
+ if (path->num_keys)
+ {
+ p[path->len_class] = '.';
+ strcpyW( p + path->len_class + 1, keylist );
+ }
}
heap_free( namespace );
heap_free( server );
+ heap_free( keylist );
return ret;
}
case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY:
@@ -367,11 +509,7 @@ static WCHAR *build_path( struct path *path, LONG flags, int *len )
return build_namespace( path, len, FALSE );
case WBEMPATH_GET_ORIGINAL:
- if (!path->len_text)
- {
- *len = 0;
- return NULL;
- }
+ if (!path->len_text) return NULL;
*len = path->len_text;
return strdupW( path->text );
@@ -447,7 +585,7 @@ static HRESULT WINAPI path_GetInfo(
else
{
*response |= WBEMPATH_INFO_HAS_SUBSCOPES;
- if (path->text && strchrW( path->text, '=' )) /* FIXME */
+ if (path->num_keys)
*response |= WBEMPATH_INFO_IS_INST_REF;
else
*response |= WBEMPATH_INFO_IS_CLASS_REF;
diff --git a/dlls/wmiutils/tests/path.c b/dlls/wmiutils/tests/path.c
index 31246e9..935ee52 100644
--- a/dlls/wmiutils/tests/path.c
+++ b/dlls/wmiutils/tests/path.c
@@ -59,7 +59,19 @@ static const WCHAR path16[] =
{'\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',0};
static const WCHAR path17[] =
{'\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',':','W','i','n','3','2','_',
- 'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','d','=','"','C',':','"',0};
+ 'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','d','=',
+ '"','C',':','"',0};
+static const WCHAR path18[] =
+ {'\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',':','W','i','n','3','2','_',
+ 'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','d','=',
+ '"','C',':','"',',','D','r','i','v','e','T','y','p','e','=','3',0};
+static const WCHAR path19[] =
+ {'\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',':','W','i','n','3','2','_',
+ 'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','d','=',0};
+static const WCHAR path20[] =
+ {'\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',':','W','i','n','3','2','_',
+ 'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','d',' ','=',' ',
+ '"','C',':','"',0};
static IWbemPath *create_path(void)
{
@@ -148,6 +160,13 @@ static void test_IWbemPath_SetText(void)
static void test_IWbemPath_GetText(void)
{
+ static const WCHAR expected1W[] =
+ {'r','o','o','t','\\','c','i','m','v','2',':','W','i','n','3','2','_',
+ 'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','d','=',
+ '"','C',':','"',0};
+ static const WCHAR expected2W[] =
+ {'W','i','n','3','2','_','L','o','g','i','c','a','l','D','i','s','k','.',
+ 'D','e','v','i','c','e','I','d','=','"','C',':','"',0};
WCHAR buf[128];
ULONG len, count;
IWbemPath *path;
@@ -270,8 +289,31 @@ static void test_IWbemPath_GetText(void)
memset( buf, 0x55, sizeof(buf) );
hr = IWbemPath_GetText( path, WBEMPATH_GET_SERVER_TOO, &len, buf );
ok( hr == S_OK, "got %08x\n", hr );
- todo_wine ok( !lstrcmpW( buf, path17 ), "unexpected buffer contents %s\n", wine_dbgstr_w(buf) );
- todo_wine ok( len == lstrlenW( path17 ) + 1, "unexpected length %u\n", len );
+ ok( !lstrcmpW( buf, path17 ), "unexpected buffer contents %s\n", wine_dbgstr_w(buf) );
+ ok( len == lstrlenW( path17 ) + 1, "unexpected length %u\n", len );
+
+ len = sizeof(buf)/sizeof(buf[0]);
+ memset( buf, 0x55, sizeof(buf) );
+ hr = IWbemPath_GetText( path, 0, &len, buf );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( !lstrcmpW( buf, expected1W ), "unexpected buffer contents %s\n", wine_dbgstr_w(buf) );
+ ok( len == lstrlenW( expected1W ) + 1, "unexpected length %u\n", len );
+
+ len = sizeof(buf)/sizeof(buf[0]);
+ memset( buf, 0x55, sizeof(buf) );
+ hr = IWbemPath_GetText( path, WBEMPATH_GET_RELATIVE_ONLY, &len, buf );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( !lstrcmpW( buf, expected2W ), "unexpected buffer contents %s\n", wine_dbgstr_w(buf) );
+ ok( len == lstrlenW( expected2W ) + 1, "unexpected length %u\n", len );
+
+ hr = IWbemPath_SetText( path, WBEMPATH_CREATE_ACCEPT_ALL, path18 );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = IWbemPath_SetText( path, WBEMPATH_CREATE_ACCEPT_ALL, path19 );
+ ok( hr == WBEM_E_INVALID_PARAMETER, "got %08x\n", hr );
+
+ hr = IWbemPath_SetText( path, WBEMPATH_CREATE_ACCEPT_ALL, path20 );
+ ok( hr == WBEM_E_INVALID_PARAMETER, "got %08x\n", hr );
IWbemPath_Release( path );
}
diff --git a/dlls/wmiutils/wmiutils_private.h b/dlls/wmiutils/wmiutils_private.h
index 98180c9..fbd6ab5 100644
--- a/dlls/wmiutils/wmiutils_private.h
+++ b/dlls/wmiutils/wmiutils_private.h
@@ -27,6 +27,12 @@ static inline void *heap_alloc( size_t len )
return HeapAlloc( GetProcessHeap(), 0, len );
}
+static void *heap_alloc_zero( size_t len ) __WINE_ALLOC_SIZE(1);
+static inline void *heap_alloc_zero( size_t len )
+{
+ return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
+}
+
static void *heap_realloc( void *mem, size_t len ) __WINE_ALLOC_SIZE(2);
static inline void *heap_realloc( void *mem, size_t len )
{
--
1.7.10.4
More information about the wine-patches
mailing list