[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