- Merge from trunk
[reactos.git] / dll / win32 / msi / appsearch.c
index 95daabb..dfab396 100644 (file)
@@ -50,7 +50,7 @@ typedef struct tagMSISIGNATURE
     LPWSTR   Languages;
 }MSISIGNATURE;
 
-static void ACTION_VerStrToInteger(LPCWSTR verStr, PDWORD ms, PDWORD ls)
+void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
 {
     const WCHAR *ptr;
     int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
@@ -89,7 +89,7 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
         'S','i','g','n','a','t','u','r','e',' ',
         'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e',' ','=',' ',
         '\'','%','s','\'',0};
-    LPWSTR minVersion, maxVersion;
+    LPWSTR minVersion, maxVersion, p;
     MSIRECORD *row;
     DWORD time;
 
@@ -106,16 +106,22 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
 
     /* get properties */
     sig->File = msi_dup_record_field(row,2);
+    if ((p = strchrW(sig->File, '|')))
+    {
+        p++;
+        memmove(sig->File, p, (strlenW(p) + 1) * sizeof(WCHAR));
+    }
+
     minVersion = msi_dup_record_field(row,3);
     if (minVersion)
     {
-        ACTION_VerStrToInteger(minVersion, &sig->MinVersionMS, &sig->MinVersionLS);
+        msi_parse_version_string( minVersion, &sig->MinVersionMS, &sig->MinVersionLS );
         msi_free( minVersion );
     }
     maxVersion = msi_dup_record_field(row,4);
     if (maxVersion)
     {
-        ACTION_VerStrToInteger(maxVersion, &sig->MaxVersionMS, &sig->MaxVersionLS);
+        msi_parse_version_string( maxVersion, &sig->MaxVersionMS, &sig->MaxVersionLS );
         msi_free( maxVersion );
     }
     sig->MinSize = MSI_RecordGetInteger(row,5);
@@ -463,7 +469,7 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNAT
         ACTION_ConvertRegValue(regType, value, sz, appValue);
         break;
     default:
-        FIXME("AppSearch unimplemented for type %d (key path %s, value %s)\n",
+        FIXME("unimplemented for type %d (key path %s, value %s)\n",
               type, debugstr_w(keyPath), debugstr_w(valueName));
     }
 end:
@@ -739,6 +745,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
     size_t dirLen = lstrlenW(dir), fileLen = lstrlenW(sig->File);
     WCHAR subpath[MAX_PATH];
     WCHAR *buf;
+    DWORD len;
 
     static const WCHAR starDotStarW[] = { '*','.','*',0 };
 
@@ -753,7 +760,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
      * here.  Add two because we might need to add a backslash if the dir name
      * isn't backslash-terminated.
      */
-    buf = msi_alloc( (dirLen + max(fileLen, strlenW(starDotStarW)) + 2) * sizeof(WCHAR));
+    len = dirLen + max(fileLen, strlenW(starDotStarW)) + 2;
+    buf = msi_alloc(len * sizeof(WCHAR));
     if (!buf)
         return ERROR_OUTOFMEMORY;
 
@@ -815,7 +823,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
         }
     }
 
-    if (!*appValue)
+    if (*appValue != buf)
         msi_free(buf);
 
     return rc;
@@ -927,7 +935,8 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
         'D','r','L','o','c','a','t','o','r',' ',
         'w','h','e','r','e',' ',
         'S','i','g','n','a','t','u','r','e','_',' ','=',' ', '\'','%','s','\'',0};
-    LPWSTR parentName = NULL, parent = NULL;
+    LPWSTR parent = NULL;
+    LPCWSTR parentName;
     WCHAR path[MAX_PATH];
     WCHAR expanded[MAX_PATH];
     MSIRECORD *row;
@@ -947,14 +956,18 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
     }
 
     /* check whether parent is set */
-    parentName = msi_dup_record_field(row,2);
+    parentName = MSI_RecordGetString(row, 2);
     if (parentName)
     {
         MSISIGNATURE parentSig;
 
         rc = ACTION_AppSearchSigName(package, parentName, &parentSig, &parent);
         ACTION_FreeSignature(&parentSig);
-        msi_free(parentName);
+        if (!parent)
+        {
+            msiobj_release(&row->hdr);
+            return ERROR_SUCCESS;
+        }
     }
 
     sz = MAX_PATH;
@@ -1024,25 +1037,34 @@ static UINT ACTION_AppSearchSigName(MSIPACKAGE *package, LPCWSTR sigName,
 static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
-    LPWSTR propName, sigName, value = NULL;
+    LPCWSTR propName, sigName;
+    LPWSTR value = NULL;
     MSISIGNATURE sig;
+    MSIRECORD *uirow;
     UINT r;
 
     /* get property and signature */
-    propName = msi_dup_record_field(row,1);
-    sigName = msi_dup_record_field(row,2);
+    propName = MSI_RecordGetString(row, 1);
+    sigName = MSI_RecordGetString(row, 2);
 
     TRACE("%s %s\n", debugstr_w(propName), debugstr_w(sigName));
 
     r = ACTION_AppSearchSigName(package, sigName, &sig, &value);
     if (value)
     {
-        MSI_SetPropertyW(package, propName, value);
+        r = msi_set_property( package->db, propName, value );
+        if (r == ERROR_SUCCESS && !strcmpW( propName, cszSourceDir ))
+            msi_reset_folders( package, TRUE );
+
         msi_free(value);
     }
     ACTION_FreeSignature(&sig);
-    msi_free(propName);
-    msi_free(sigName);
+
+    uirow = MSI_CreateRecord( 2 );
+    MSI_RecordSetStringW( uirow, 1, propName );
+    MSI_RecordSetStringW( uirow, 2, sigName );
+    ui_actiondata( package, szAppSearch, uirow );
+    msiobj_release( &uirow->hdr );
 
     return r;
 }
@@ -1056,6 +1078,14 @@ UINT ACTION_AppSearch(MSIPACKAGE *package)
     MSIQUERY *view = NULL;
     UINT r;
 
+    if (check_unique_action(package, szAppSearch))
+    {
+        TRACE("Skipping AppSearch action: already done in UI sequence\n");
+        return ERROR_SUCCESS;
+    }
+    else
+        register_unique_action(package, szAppSearch);
+
     r = MSI_OpenQuery( package->db, &view, query );
     if (r != ERROR_SUCCESS)
         return ERROR_SUCCESS;
@@ -1084,7 +1114,7 @@ static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
     if (value)
     {
         TRACE("Found signature %s\n", debugstr_w(signature));
-        MSI_SetPropertyW(package, success, szOne);
+        msi_set_property(package->db, success, szOne);
         msi_free(value);
         r = ERROR_NO_MORE_ITEMS;
     }
@@ -1103,6 +1133,14 @@ UINT ACTION_CCPSearch(MSIPACKAGE *package)
     MSIQUERY *view = NULL;
     UINT r;
 
+    if (check_unique_action(package, szCCPSearch))
+    {
+        TRACE("Skipping AppSearch action: already done in UI sequence\n");
+        return ERROR_SUCCESS;
+    }
+    else
+        register_unique_action(package, szCCPSearch);
+
     r = MSI_OpenQuery(package->db, &view, query);
     if (r != ERROR_SUCCESS)
         return ERROR_SUCCESS;