MSI: implement, test and document MsiDecomposeDescriptor

Mike McCormack mike at codeweavers.com
Tue Jan 25 09:01:49 CST 2005


This function is undocumented by MSDN.  Fixed conflict with Aric's patch.

Mike


ChangeLog:
* implement, test and document MsiDecomposeDescriptor

-------------- next part --------------
Index: dlls/msi/msi.spec
===================================================================
RCS file: /home/wine/wine/dlls/msi/msi.spec,v
retrieving revision 1.28
diff -u -p -r1.28 msi.spec
--- dlls/msi/msi.spec	21 Jan 2005 10:17:01 -0000	1.28
+++ dlls/msi/msi.spec	25 Jan 2005 15:00:37 -0000
@@ -197,8 +197,8 @@
 197 stdcall MsiLoadStringW(long long long long long)
 198 stdcall MsiMessageBoxA(long long long long long long)
 199 stdcall MsiMessageBoxW(long long long long long long)
-200 stub MsiDecomposeDescriptorA
-201 stub MsiDecomposeDescriptorW
+200 stdcall MsiDecomposeDescriptorA(str str ptr ptr ptr)
+201 stdcall MsiDecomposeDescriptorW(wstr wstr ptr ptr ptr)
 202 stub MsiProvideQualifiedComponentExA
 203 stdcall MsiProvideQualifiedComponentExW(wstr wstr long wstr long long ptr ptr)
 204 stdcall MsiEnumRelatedProductsA(str long long ptr)
Index: dlls/msi/registry.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/registry.c,v
retrieving revision 1.1
diff -u -p -r1.1 registry.c
--- dlls/msi/registry.c	25 Jan 2005 10:58:36 -0000	1.1
+++ dlls/msi/registry.c	25 Jan 2005 15:00:37 -0000
@@ -388,3 +388,99 @@ UINT MSIREG_OpenProductsKey(LPCWSTR szPr
 
     return rc;
 }
+
+/*************************************************************************
+ *  MsiDecomposeDescriptorW   [MSI.@]
+ *
+ * Decomposes an MSI descriptor into product, feature and component parts.
+ * An MSI descriptor is a string of the form:
+ *   [base 85 guid] [feature code] '>' [base 85 guid]
+ *
+ * PARAMS
+ *   szDescriptor  [I]  the descriptor to decompose
+ *   szProduct     [O]  buffer of MAX_FEATURE_CHARS for the product guid
+ *   szFeature     [O]  buffer of MAX_FEATURE_CHARS for the feature code
+ *   szComponent   [O]  buffer of MAX_FEATURE_CHARS for the component guid
+ *   pUsed         [O]  the length of the descriptor
+ *
+ * RETURNS
+ *   ERROR_SUCCESS             if everything worked correctly
+ *   ERROR_INVALID_PARAMETER   if the descriptor was invalid
+ *
+ */
+UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
+                LPWSTR szFeature, LPWSTR szComponent, DWORD *pUsed )
+{
+    UINT r, len;
+    LPWSTR p;
+    GUID product, component;
+
+    TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
+          szFeature, szComponent, pUsed);
+
+    r = decode_base85_guid( szDescriptor, &product );
+    if( !r )
+        return ERROR_INVALID_PARAMETER;
+
+    TRACE("product %s\n", debugstr_guid( &product ));
+
+    p = strchrW(&szDescriptor[20],'>');
+    if( !p )
+        return ERROR_INVALID_PARAMETER;
+
+    len = (p - &szDescriptor[20]);
+    if( len > MAX_FEATURE_CHARS )
+        return ERROR_INVALID_PARAMETER;
+    memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
+    szFeature[len] = 0;
+
+    TRACE("feature %s\n", debugstr_w( szFeature ));
+
+    r = decode_base85_guid( p+1, &component );
+    if( !r )
+        return ERROR_INVALID_PARAMETER;
+
+    TRACE("component %s\n", debugstr_guid( &component ));
+
+    StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
+    StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
+    len = ( &p[21] - szDescriptor );
+
+    TRACE("length = %d\n", len);
+    *pUsed = len;
+
+    return ERROR_SUCCESS;
+}
+
+UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
+                LPSTR szFeature, LPSTR szComponent, DWORD *pUsed )
+{
+    WCHAR product[MAX_FEATURE_CHARS+1];
+    WCHAR feature[MAX_FEATURE_CHARS+1];
+    WCHAR component[MAX_FEATURE_CHARS+1];
+    LPWSTR str = NULL;
+    UINT r, len;
+
+    TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
+          szFeature, szComponent, pUsed);
+
+    if( szDescriptor )
+    {
+        len = MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, NULL, 0 );
+        str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+        MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, str, len );
+    }
+
+    r = MsiDecomposeDescriptorW( str, product, feature, component, pUsed );
+
+    WideCharToMultiByte( CP_ACP, 0, product, MAX_FEATURE_CHARS+1,
+                         szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
+    WideCharToMultiByte( CP_ACP, 0, feature, MAX_FEATURE_CHARS+1,
+                         szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
+    WideCharToMultiByte( CP_ACP, 0, component, MAX_FEATURE_CHARS+1,
+                         szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
+
+    HeapFree( GetProcessHeap(), 0, str );
+
+    return r;
+}
Index: dlls/msi/tests/db.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/tests/db.c,v
retrieving revision 1.3
diff -u -p -r1.3 db.c
--- dlls/msi/tests/db.c	20 Jan 2005 20:39:15 -0000	1.3
+++ dlls/msi/tests/db.c	25 Jan 2005 15:00:37 -0000
@@ -120,8 +120,60 @@ void test_msiinsert(void)
     ok(r == TRUE, "file didn't exist after commit\n");
 }
 
+typedef UINT (WINAPI *fnMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
+fnMsiDecomposeDescriptorA MsiDecomposeDescriptorA;
+
+void test_msidecomposedesc(void)
+{
+    char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
+    char *desc;
+    UINT r;
+    DWORD len;
+    HMODULE hmod;
+
+    hmod = GetModuleHandle("msi.dll");
+    if (!hmod)
+        return;
+    MsiDecomposeDescriptorA = (fnMsiDecomposeDescriptorA) 
+        GetProcAddress(hmod, "MsiDecomposeDescriptorA");
+    if (!MsiDecomposeDescriptorA)
+        return;
+
+    /* test a valid feature descriptor */
+    desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
+    len = 0;
+    r = MsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
+    ok(r == ERROR_SUCCESS, "returned an error\n");
+    ok(len == strlen(desc), "length was wrong\n");
+    ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
+    ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
+    ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
+
+    /* test an invalid feature descriptor with too many characters */
+    desc = "']gAVn-}f(ZXfeAR6.ji"
+           "ThisWillFailIfTheresMoreThanAGuidsChars>"
+           "3w2x^IGfe?CxI5heAvk.";
+    len = 0;
+    r = MsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
+    ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
+
+    /*
+     * Test a valid feature descriptor with the
+     * maximum number of characters and some trailing characters.
+     */
+    desc = "']gAVn-}f(ZXfeAR6.ji"
+           "ThisWillWorkIfTheresLTEThanAGuidsChars>"
+           "3w2x^IGfe?CxI5heAvk."
+           "extra";
+    len = 0;
+    r = MsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
+    ok(r == ERROR_SUCCESS, "returned wrong error\n");
+    ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
+}
+
 START_TEST(db)
 {
     test_msidatabase();
     test_msiinsert();
+    test_msidecomposedesc();
 }


More information about the wine-patches mailing list