[ros-diffs] [cwittich] 45468: [MSI] sync msi to wine 1.1.38

cwittich at svn.reactos.org cwittich at svn.reactos.org
Sat Feb 6 22:28:28 CET 2010


Author: cwittich
Date: Sat Feb  6 22:28:28 2010
New Revision: 45468

URL: http://svn.reactos.org/svn/reactos?rev=45468&view=rev
Log:
[MSI]
sync msi to wine 1.1.38

Added:
    trunk/reactos/dll/win32/msi/msi_Uk.rc   (with props)
Modified:
    trunk/reactos/dll/win32/msi/action.c
    trunk/reactos/dll/win32/msi/appsearch.c
    trunk/reactos/dll/win32/msi/automation.c
    trunk/reactos/dll/win32/msi/cond.tab.c
    trunk/reactos/dll/win32/msi/cond.tab.h
    trunk/reactos/dll/win32/msi/cond.y
    trunk/reactos/dll/win32/msi/custom.c
    trunk/reactos/dll/win32/msi/database.c
    trunk/reactos/dll/win32/msi/dialog.c
    trunk/reactos/dll/win32/msi/events.c
    trunk/reactos/dll/win32/msi/files.c
    trunk/reactos/dll/win32/msi/helpers.c
    trunk/reactos/dll/win32/msi/join.c
    trunk/reactos/dll/win32/msi/msi.rc
    trunk/reactos/dll/win32/msi/msipriv.h
    trunk/reactos/dll/win32/msi/msiquery.c
    trunk/reactos/dll/win32/msi/package.c
    trunk/reactos/dll/win32/msi/storages.c
    trunk/reactos/dll/win32/msi/streams.c
    trunk/reactos/include/psdk/msi.h

Modified: trunk/reactos/dll/win32/msi/action.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/action.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/action.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/action.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -959,10 +959,6 @@
     return ERROR_SUCCESS;
 }
 
-/*
- * Also we cannot enable/disable components either, so for now I am just going 
- * to do all the directories for all the components.
- */
 static UINT ACTION_CreateFolders(MSIPACKAGE *package)
 {
     static const WCHAR ExecSeqQuery[] =
@@ -981,7 +977,60 @@
     rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package);
     msiobj_release(&view->hdr);
 
-    msi_create_component_directories( package );
+    return rc;
+}
+
+static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    LPCWSTR dir;
+    LPWSTR full_path;
+    MSIRECORD *uirow;
+    MSIFOLDER *folder;
+
+    dir = MSI_RecordGetString( row, 1 );
+    if (!dir)
+    {
+        ERR("Unable to get folder id\n");
+        return ERROR_SUCCESS;
+    }
+
+    full_path = resolve_folder( package, dir, FALSE, FALSE, TRUE, &folder );
+    if (!full_path)
+    {
+        ERR("Unable to resolve folder id %s\n", debugstr_w(dir));
+        return ERROR_SUCCESS;
+    }
+
+    TRACE("folder is %s\n", debugstr_w(full_path));
+
+    uirow = MSI_CreateRecord( 1 );
+    MSI_RecordSetStringW( uirow, 1, full_path );
+    ui_actiondata( package, szRemoveFolders, uirow );
+    msiobj_release( &uirow->hdr );
+
+    RemoveDirectoryW( full_path );
+    folder->State = 0;
+
+    msi_free( full_path );
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_RemoveFolders( MSIPACKAGE *package )
+{
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ', '`','D','i','r','e','c','t','o','r','y','_','`',
+         ' ','F','R','O','M',' ', '`','C','r','e','a','t','e','F','o','l','d','e','r','`',0};
+
+    MSIQUERY *view;
+    UINT rc;
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_RemoveFolders, package );
+    msiobj_release( &view->hdr );
 
     return rc;
 }
@@ -1562,8 +1611,10 @@
 
             while (ptr)
             {
-                if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
-                    || (!ptr2 && strcmpW(ptr,feature->Feature)==0))
+                int len = ptr2 - ptr;
+
+                if ((ptr2 && strlenW(feature->Feature) == len && !strncmpW(ptr, feature->Feature, len))
+                    || (!ptr2 && !strcmpW(ptr, feature->Feature)))
                 {
                     msi_feature_set_state(package, feature, state);
                     break;
@@ -1583,55 +1634,57 @@
     return TRUE;
 }
 
-UINT MSI_SetFeatureStates(MSIPACKAGE *package)
-{
-    int level;
-    static const WCHAR szlevel[] =
-        {'I','N','S','T','A','L','L','L','E','V','E','L',0};
+static BOOL process_overrides( MSIPACKAGE *package, int level )
+{
     static const WCHAR szAddLocal[] =
         {'A','D','D','L','O','C','A','L',0};
     static const WCHAR szAddSource[] =
         {'A','D','D','S','O','U','R','C','E',0};
     static const WCHAR szAdvertise[] =
         {'A','D','V','E','R','T','I','S','E',0};
-    BOOL override = FALSE;
+    BOOL ret = FALSE;
+
+    /* all these activation/deactivation things happen in order and things
+     * later on the list override things earlier on the list.
+     *
+     *  0  INSTALLLEVEL processing
+     *  1  ADDLOCAL
+     *  2  REMOVE
+     *  3  ADDSOURCE
+     *  4  ADDDEFAULT
+     *  5  REINSTALL
+     *  6  ADVERTISE
+     *  7  COMPADDLOCAL
+     *  8  COMPADDSOURCE
+     *  9  FILEADDLOCAL
+     * 10  FILEADDSOURCE
+     * 11  FILEADDDEFAULT
+     */
+    ret |= process_state_property( package, level, szAddLocal, INSTALLSTATE_LOCAL );
+    ret |= process_state_property( package, level, szRemove, INSTALLSTATE_ABSENT );
+    ret |= process_state_property( package, level, szAddSource, INSTALLSTATE_SOURCE );
+    ret |= process_state_property( package, level, szReinstall, INSTALLSTATE_UNKNOWN );
+    ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED );
+
+    if (ret)
+        MSI_SetPropertyW( package, szPreselected, szOne );
+
+    return ret;
+}
+
+UINT MSI_SetFeatureStates(MSIPACKAGE *package)
+{
+    int level;
+    static const WCHAR szlevel[] =
+        {'I','N','S','T','A','L','L','L','E','V','E','L',0};
     MSICOMPONENT* component;
     MSIFEATURE *feature;
 
-
-    /* I do not know if this is where it should happen.. but */
-
     TRACE("Checking Install Level\n");
 
     level = msi_get_property_int(package, szlevel, 1);
 
-    /* ok here is the _real_ rub
-     * all these activation/deactivation things happen in order and things
-     * later on the list override things earlier on the list.
-     * 0) INSTALLLEVEL processing
-     * 1) ADDLOCAL
-     * 2) REMOVE
-     * 3) ADDSOURCE
-     * 4) ADDDEFAULT
-     * 5) REINSTALL
-     * 6) ADVERTISE
-     * 7) COMPADDLOCAL
-     * 8) COMPADDSOURCE
-     * 9) FILEADDLOCAL
-     * 10) FILEADDSOURCE
-     * 11) FILEADDDEFAULT
-     *
-     * I am still ignoring a lot of these. But that is ok for now, ADDLOCAL and
-     * REMOVE are the big ones, since we don't handle administrative installs
-     * yet anyway.
-     */
-    override |= process_state_property(package, level, szAddLocal, INSTALLSTATE_LOCAL);
-    override |= process_state_property(package, level, szRemove, INSTALLSTATE_ABSENT);
-    override |= process_state_property(package, level, szAddSource, INSTALLSTATE_SOURCE);
-    override |= process_state_property(package, level, szReinstall, INSTALLSTATE_UNKNOWN);
-    override |= process_state_property(package, level, szAdvertise, INSTALLSTATE_ADVERTISED);
-
-    if (!override)
+    if (!msi_get_property_int( package, szPreselected, 0 ))
     {
         LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
         {
@@ -1661,8 +1714,6 @@
                 msi_feature_set_state(package, fl->feature, INSTALLSTATE_UNKNOWN);
         }
     }
-    else
-        MSI_SetPropertyW(package, szPreselected, szOne);
 
     /*
      * now we want to enable or disable components base on feature
@@ -1961,7 +2012,7 @@
     static const WCHAR szOutOfDiskSpace[] =
         {'O','u','t','O','f','D','i','s','k','S','p','a','c','e',0};
     MSICOMPONENT *comp;
-    UINT rc;
+    UINT rc = ERROR_SUCCESS;
     MSIQUERY * view;
     LPWSTR level;
 
@@ -1982,26 +2033,28 @@
     TRACE("File calculations\n");
     msi_check_file_install_states( package );
 
-    TRACE("Evaluating Condition Table\n");
-
-    rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);
-    if (rc == ERROR_SUCCESS)
-    {
-        rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeConditions,
-                    package);
-        msiobj_release(&view->hdr);
-    }
-
-    TRACE("Enabling or Disabling Components\n");
-    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
-    {
-        if (MSI_EvaluateConditionW(package, comp->Condition) == MSICONDITION_FALSE)
-        {
-            TRACE("Disabling component %s\n", debugstr_w(comp->Component));
-            comp->Enabled = FALSE;
-        }
-        else
-            comp->Enabled = TRUE;
+    if (!process_overrides( package, msi_get_property_int( package, szlevel, 1 ) ))
+    {
+        TRACE("Evaluating Condition Table\n");
+
+        rc = MSI_DatabaseOpenViewW( package->db, ConditionQuery, &view );
+        if (rc == ERROR_SUCCESS)
+        {
+            rc = MSI_IterateRecords( view, NULL, ITERATE_CostFinalizeConditions, package );
+            msiobj_release( &view->hdr );
+        }
+
+        TRACE("Enabling or Disabling Components\n");
+        LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+        {
+            if (MSI_EvaluateConditionW( package, comp->Condition ) == MSICONDITION_FALSE)
+            {
+                TRACE("Disabling component %s\n", debugstr_w(comp->Component));
+                comp->Enabled = FALSE;
+            }
+            else
+                comp->Enabled = TRUE;
+        }
     }
 
     MSI_SetPropertyW(package,szCosting,szOne);
@@ -3652,6 +3705,89 @@
     return ERROR_SUCCESS;
 }
 
+static UINT ITERATE_SelfUnregModules( MSIRECORD *row, LPVOID param )
+{
+    static const WCHAR regsvr32[] =
+        {'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','u',' ','\"',0};
+    static const WCHAR close[] =  {'\"',0};
+    MSIPACKAGE *package = param;
+    LPCWSTR filename;
+    LPWSTR cmdline;
+    MSIFILE *file;
+    DWORD len;
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    BOOL ret;
+    MSIRECORD *uirow;
+    LPWSTR uipath, p;
+
+    memset( &si, 0, sizeof(STARTUPINFOW) );
+
+    filename = MSI_RecordGetString( row, 1 );
+    file = get_loaded_file( package, filename );
+
+    if (!file)
+    {
+        ERR("Unable to find file id %s\n", debugstr_w(filename));
+        return ERROR_SUCCESS;
+    }
+
+    len = strlenW( regsvr32 ) + strlenW( file->TargetPath ) + 2;
+
+    cmdline = msi_alloc( len * sizeof(WCHAR) );
+    strcpyW( cmdline, regsvr32 );
+    strcatW( cmdline, file->TargetPath );
+    strcatW( cmdline, close );
+
+    TRACE("Unregistering %s\n", debugstr_w(cmdline));
+
+    ret = CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, c_colon, &si, &pi );
+    if (ret)
+    {
+        CloseHandle( pi.hThread );
+        msi_dialog_check_messages( pi.hProcess );
+        CloseHandle( pi.hProcess );
+    }
+
+    msi_free( cmdline );
+
+    uirow = MSI_CreateRecord( 2 );
+    uipath = strdupW( file->TargetPath );
+    if ((p = strrchrW( uipath, '\\' )))
+    {
+        *p = 0;
+        MSI_RecordSetStringW( uirow, 1, ++p );
+    }
+    MSI_RecordSetStringW( uirow, 2, uipath );
+    ui_actiondata( package, szSelfUnregModules, uirow );
+    msiobj_release( &uirow->hdr );
+    msi_free( uipath );
+    /* FIXME call ui_progress? */
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','S','e','l','f','R','e','g','`',0};
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+    {
+        TRACE("no SelfReg table\n");
+        return ERROR_SUCCESS;
+    }
+
+    MSI_IterateRecords( view, NULL, ITERATE_SelfUnregModules, package );
+    msiobj_release( &view->hdr );
+
+    return ERROR_SUCCESS;
+}
+
 static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
 {
     MSIFEATURE *feature;
@@ -4462,8 +4598,8 @@
     MSIPACKAGE *package = param;
     MSICOMPONENT *comp;
     SC_HANDLE scm, service = NULL;
-    LPCWSTR name, *vector = NULL;
-    LPWSTR args;
+    LPCWSTR *vector = NULL;
+    LPWSTR name, args;
     DWORD event, numargs;
     UINT r = ERROR_FUNCTION_FAILED;
 
@@ -4471,9 +4607,9 @@
     if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
         return ERROR_SUCCESS;
 
-    name = MSI_RecordGetString(rec, 2);
+    deformat_string(package, MSI_RecordGetString(rec, 2), &name);
+    deformat_string(package, MSI_RecordGetString(rec, 4), &args);
     event = MSI_RecordGetInteger(rec, 3);
-    args = strdupW(MSI_RecordGetString(rec, 4));
 
     if (!(event & msidbServiceControlEventStart))
         return ERROR_SUCCESS;
@@ -4488,15 +4624,16 @@
     service = OpenServiceW(scm, name, SERVICE_START);
     if (!service)
     {
-        ERR("Failed to open service %s\n", debugstr_w(name));
+        ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError());
         goto done;
     }
 
     vector = msi_service_args_to_vector(args, &numargs);
 
-    if (!StartServiceW(service, numargs, vector))
-    {
-        ERR("Failed to start service %s\n", debugstr_w(name));
+    if (!StartServiceW(service, numargs, vector) &&
+        GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
+    {
+        ERR("Failed to start service %s (%u)\n", debugstr_w(name), GetLastError());
         goto done;
     }
 
@@ -4506,6 +4643,7 @@
     CloseServiceHandle(service);
     CloseServiceHandle(scm);
 
+    msi_free(name);
     msi_free(args);
     msi_free(vector);
     return r;
@@ -4570,27 +4708,12 @@
     return FALSE;
 }
 
-static UINT ITERATE_StopService(MSIRECORD *rec, LPVOID param)
-{
-    MSIPACKAGE *package = param;
-    MSICOMPONENT *comp;
+static UINT stop_service( LPCWSTR name )
+{
+    SC_HANDLE scm = NULL, service = NULL;
     SERVICE_STATUS status;
     SERVICE_STATUS_PROCESS ssp;
-    SC_HANDLE scm = NULL, service = NULL;
-    LPWSTR name, args;
-    DWORD event, needed;
-
-    event = MSI_RecordGetInteger(rec, 3);
-    if (!(event & msidbServiceControlEventStop))
-        return ERROR_SUCCESS;
-
-    comp = get_loaded_component(package, MSI_RecordGetString(rec, 6));
-    if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
-        return ERROR_SUCCESS;
-
-    deformat_string(package, MSI_RecordGetString(rec, 2), &name);
-    deformat_string(package, MSI_RecordGetString(rec, 4), &args);
-    args = strdupW(MSI_RecordGetString(rec, 4));
+    DWORD needed;
 
     scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     if (!scm)
@@ -4605,16 +4728,14 @@
                            SERVICE_ENUMERATE_DEPENDENTS);
     if (!service)
     {
-        WARN("Failed to open service (%s): %d\n",
-              debugstr_w(name), GetLastError());
+        WARN("Failed to open service (%s): %d\n", debugstr_w(name), GetLastError());
         goto done;
     }
 
     if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
                               sizeof(SERVICE_STATUS_PROCESS), &needed))
     {
-        WARN("Failed to query service status (%s): %d\n",
-             debugstr_w(name), GetLastError());
+        WARN("Failed to query service status (%s): %d\n", debugstr_w(name), GetLastError());
         goto done;
     }
 
@@ -4629,8 +4750,28 @@
 done:
     CloseServiceHandle(service);
     CloseServiceHandle(scm);
-    msi_free(name);
-    msi_free(args);
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ITERATE_StopService( MSIRECORD *rec, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    MSICOMPONENT *comp;
+    LPWSTR name;
+    DWORD event;
+
+    event = MSI_RecordGetInteger( rec, 3 );
+    if (!(event & msidbServiceControlEventStop))
+        return ERROR_SUCCESS;
+
+    comp = get_loaded_component( package, MSI_RecordGetString( rec, 6 ) );
+    if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
+        return ERROR_SUCCESS;
+
+    deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
+    stop_service( name );
+    msi_free( name );
 
     return ERROR_SUCCESS;
 }
@@ -4650,6 +4791,69 @@
 
     rc = MSI_IterateRecords(view, NULL, ITERATE_StopService, package);
     msiobj_release(&view->hdr);
+
+    return rc;
+}
+
+static UINT ITERATE_DeleteService( MSIRECORD *rec, LPVOID param )
+{
+    MSIPACKAGE *package = param;
+    MSICOMPONENT *comp;
+    LPWSTR name = NULL;
+    DWORD event;
+    SC_HANDLE scm = NULL, service = NULL;
+
+    event = MSI_RecordGetInteger( rec, 3 );
+    if (!(event & msidbServiceControlEventDelete))
+        return ERROR_SUCCESS;
+
+    comp = get_loaded_component( package, MSI_RecordGetString(rec, 6) );
+    if (!comp || comp->Action == INSTALLSTATE_UNKNOWN || comp->Action == INSTALLSTATE_ABSENT)
+        return ERROR_SUCCESS;
+
+    deformat_string( package, MSI_RecordGetString(rec, 2), &name );
+    stop_service( name );
+
+    scm = OpenSCManagerW( NULL, NULL, SC_MANAGER_ALL_ACCESS );
+    if (!scm)
+    {
+        WARN("Failed to open the SCM: %d\n", GetLastError());
+        goto done;
+    }
+
+    service = OpenServiceW( scm, name, DELETE );
+    if (!service)
+    {
+        WARN("Failed to open service (%s): %u\n", debugstr_w(name), GetLastError());
+        goto done;
+    }
+
+    if (!DeleteService( service ))
+        WARN("Failed to delete service (%s): %u\n", debugstr_w(name), GetLastError());
+
+done:
+    CloseServiceHandle( service );
+    CloseServiceHandle( scm );
+    msi_free( name );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT ACTION_DeleteServices( MSIPACKAGE *package )
+{
+    UINT rc;
+    MSIQUERY *view;
+
+    static const WCHAR query[] = {
+        'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+        'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
+
+    rc = MSI_DatabaseOpenViewW( package->db, query, &view );
+    if (rc != ERROR_SUCCESS)
+        return ERROR_SUCCESS;
+
+    rc = MSI_IterateRecords( view, NULL, ITERATE_DeleteService, package );
+    msiobj_release( &view->hdr );
 
     return rc;
 }
@@ -4922,16 +5126,30 @@
         LPCWSTR ptr = *value;
         if (!strncmpW(ptr, prefix, prefix_len))
         {
-            *flags |= ENV_MOD_APPEND;
-            *value += lstrlenW(prefix);
+            if (ptr[prefix_len] == szSemiColon[0])
+            {
+                *flags |= ENV_MOD_APPEND;
+                *value += lstrlenW(prefix);
+            }
+            else
+            {
+                *value = NULL;
+            }
         }
         else if (lstrlenW(*value) >= prefix_len)
         {
             ptr += lstrlenW(ptr) - prefix_len;
             if (!lstrcmpW(ptr, prefix))
             {
-                *flags |= ENV_MOD_PREFIX;
-                /* the "[~]" will be removed by deformat_string */;
+                if ((ptr-1) > *value && *(ptr-1) == szSemiColon[0])
+                {
+                    *flags |= ENV_MOD_PREFIX;
+                    /* the "[~]" will be removed by deformat_string */;
+                }
+                else
+                {
+                    *value = NULL;
+                }
             }
         }
     }
@@ -4977,7 +5195,7 @@
     TRACE("name %s value %s\n", debugstr_w(name), debugstr_w(value));
 
     res = env_set_flags(&name, &value, &flags);
-    if (res != ERROR_SUCCESS)
+    if (res != ERROR_SUCCESS || !value)
        goto done;
 
     if (value && !deformat_string(package, value, &deformatted))
@@ -5023,6 +5241,9 @@
             goto done;
         }
 
+        /* If we are appending but the string was empty, strip ; */
+        if ((flags & ENV_MOD_APPEND) && (value[0] == szSemiColon[0])) value++;
+
         size = (lstrlenW(value) + 1) * sizeof(WCHAR);
         newval = strdupW(value);
         if (!newval)
@@ -5033,7 +5254,8 @@
     }
     else
     {
-        if (flags & ENV_ACT_SETABSENT)
+        /* Contrary to MSDN, +-variable to [~];path works */
+        if (flags & ENV_ACT_SETABSENT && !(flags & ENV_MOD_MASK))
         {
             res = ERROR_SUCCESS;
             goto done;
@@ -5063,7 +5285,7 @@
             int multiplier = 0;
             if (flags & ENV_MOD_APPEND) multiplier++;
             if (flags & ENV_MOD_PREFIX) multiplier++;
-            mod_size = (lstrlenW(value) + 1) * multiplier;
+            mod_size = lstrlenW(value) * multiplier;
             size += mod_size * sizeof(WCHAR);
         }
 
@@ -5078,26 +5300,18 @@
         if (flags & ENV_MOD_PREFIX)
         {
             lstrcpyW(newval, value);
-            lstrcatW(newval, szSemiColon);
-            ptr = newval + lstrlenW(value) + 1;
+            ptr = newval + lstrlenW(value);
         }
 
         lstrcpyW(ptr, data);
 
         if (flags & ENV_MOD_APPEND)
         {
-            lstrcatW(newval, szSemiColon);
             lstrcatW(newval, value);
         }
     }
-
-    if (newval)
-    {
-        TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
-        res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
-    }
-    else
-        res = ERROR_SUCCESS;
+    TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
+    res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
 
 done:
     if (env) RegCloseKey(env);
@@ -5911,6 +6125,13 @@
     return r;
 }
 
+static UINT ACTION_ScheduleReboot( MSIPACKAGE *package )
+{
+    TRACE("\n");
+    package->need_reboot = 1;
+    return ERROR_SUCCESS;
+}
+
 static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
                                            LPCSTR action, LPCWSTR table )
 {
@@ -5973,18 +6194,6 @@
     return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
 }
 
-static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'S','e','l','f','R','e','g',0 };
-    return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
-}
-
-static UINT ACTION_DeleteServices( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = {
-        'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
-    return msi_unimplemented_action_stub( package, "DeleteServices", table );
-}
 static UINT ACTION_ValidateProductID( MSIPACKAGE *package )
 {
 	static const WCHAR table[] = {
@@ -6048,12 +6257,6 @@
     return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table );
 }
 
-static UINT ACTION_RemoveFolders( MSIPACKAGE *package )
-{
-    static const WCHAR table[] = { 'C','r','e','a','t','e','F','o','l','d','e','r',0 };
-    return msi_unimplemented_action_stub( package, "RemoveFolders", table );
-}
-
 static UINT ACTION_RemoveODBC( MSIPACKAGE *package )
 {
     static const WCHAR table[] = { 'O','D','B','C','D','r','i','v','e','r',0 };
@@ -6070,6 +6273,12 @@
 {
     static const WCHAR table[] = { 'S','h','o','r','t','c','u','t',0 };
     return msi_unimplemented_action_stub( package, "RemoveShortcuts", table );
+}
+
+static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
+{
+    static const WCHAR table[] = { 'D','i','r','e','c','t','o','r','y',0 };
+    return msi_unimplemented_action_stub( package, "SetODBCFolders", table );
 }
 
 static UINT ACTION_UnpublishComponents( MSIPACKAGE *package )
@@ -6173,10 +6382,10 @@
     { szRemoveShortcuts, ACTION_RemoveShortcuts },
     { szResolveSource, ACTION_ResolveSource },
     { szRMCCPSearch, ACTION_RMCCPSearch },
-    { szScheduleReboot, NULL },
+    { szScheduleReboot, ACTION_ScheduleReboot },
     { szSelfRegModules, ACTION_SelfRegModules },
     { szSelfUnregModules, ACTION_SelfUnregModules },
-    { szSetODBCFolders, NULL },
+    { szSetODBCFolders, ACTION_SetODBCFolders },
     { szStartServices, ACTION_StartServices },
     { szStopServices, ACTION_StopServices },
     { szUnpublishComponents, ACTION_UnpublishComponents },

Modified: trunk/reactos/dll/win32/msi/appsearch.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/appsearch.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/appsearch.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/appsearch.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -463,7 +463,7 @@
         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:

Modified: trunk/reactos/dll/win32/msi/automation.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/automation.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/automation.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/automation.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -1138,6 +1138,21 @@
     return S_OK;
 }
 
+static HRESULT DatabaseImpl_LastErrorRecord(WORD wFlags,
+                                            DISPPARAMS* pDispParams,
+                                            VARIANT* pVarResult,
+                                            EXCEPINFO* pExcepInfo,
+                                            UINT* puArgErr)
+{
+    if (!(wFlags & DISPATCH_METHOD))
+        return DISP_E_MEMBERNOTFOUND;
+
+    FIXME("\n");
+
+    VariantInit(pVarResult);
+    return S_OK;
+}
+
 static HRESULT WINAPI DatabaseImpl_Invoke(
         AutomationObject* This,
         DISPID dispIdMember,
@@ -1207,6 +1222,11 @@
             }
             else return DISP_E_MEMBERNOTFOUND;
             break;
+
+        case DISPID_INSTALLER_LASTERRORRECORD:
+            return DatabaseImpl_LastErrorRecord(wFlags, pDispParams,
+                                                pVarResult, pExcepInfo,
+                                                puArgErr);
 
          default:
             return DISP_E_MEMBERNOTFOUND;

Modified: trunk/reactos/dll/win32/msi/cond.tab.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/cond.tab.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/cond.tab.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/cond.tab.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -119,6 +119,7 @@
 #include "msiserver.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
+#include "wine/list.h"
 
 #define YYLEX_PARAM info
 #define YYPARSE_PARAM info
@@ -133,6 +134,7 @@
     LPCWSTR str;
     INT    n;
     MSICONDITION result;
+    struct list mem;
 } COND_input;
 
 struct cond_str {
@@ -140,9 +142,13 @@
     INT len;
 };
 
-static LPWSTR COND_GetString( const struct cond_str *str );
-static LPWSTR COND_GetLiteral( const struct cond_str *str );
+static LPWSTR COND_GetString( COND_input *info, const struct cond_str *str );
+static LPWSTR COND_GetLiteral( COND_input *info, const struct cond_str *str );
 static int cond_lex( void *COND_lval, COND_input *info);
+
+static void *cond_alloc( COND_input *cond, unsigned int sz );
+static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz );
+static void cond_free( void *ptr );
 
 static INT compare_int( INT a, INT operator, INT b );
 static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert );
@@ -152,8 +158,8 @@
     INT r;
 
     r = compare_string( a, op, b, convert );
-    msi_free( a );
-    msi_free( b );
+    cond_free( a );
+    cond_free( b );
     return r;
 }
 
@@ -184,7 +190,7 @@
 
 
 /* Line 189 of yacc.c  */
-#line 188 "cond.tab.c"
+#line 194 "cond.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -259,7 +265,7 @@
 {
 
 /* Line 214 of yacc.c  */
-#line 110 "cond.y"
+#line 116 "cond.y"
 
     struct cond_str str;
     LPWSTR    string;
@@ -268,7 +274,7 @@
 
 
 /* Line 214 of yacc.c  */
-#line 272 "cond.tab.c"
+#line 278 "cond.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -280,7 +286,7 @@
 
 
 /* Line 264 of yacc.c  */
-#line 284 "cond.tab.c"
+#line 290 "cond.tab.c"
 
 #ifdef short
 # undef short
@@ -584,12 +590,12 @@
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   134,   134,   140,   147,   151,   155,   159,   163,   170,
-     174,   181,   185,   189,   194,   198,   207,   216,   220,   224,
-     228,   232,   237,   242,   250,   251,   252,   253,   254,   255,
-     256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
-     266,   267,   271,   275,   282,   291,   295,   304,   313,   326,
-     338,   345,   359,   368
+       0,   140,   140,   146,   153,   157,   161,   165,   169,   176,
+     180,   187,   191,   195,   200,   204,   213,   222,   226,   230,
+     234,   238,   243,   248,   256,   257,   258,   259,   260,   261,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     272,   273,   277,   281,   288,   298,   302,   311,   320,   333,
+     345,   358,   375,   385
 };
 #endif
 
@@ -1540,7 +1546,7 @@
         case 2:
 
 /* Line 1455 of yacc.c  */
-#line 135 "cond.y"
+#line 141 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
             cond->result = (yyvsp[(1) - (1)].value);
@@ -1550,7 +1556,7 @@
   case 3:
 
 /* Line 1455 of yacc.c  */
-#line 140 "cond.y"
+#line 146 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
             cond->result = MSICONDITION_NONE;
@@ -1560,7 +1566,7 @@
   case 4:
 
 /* Line 1455 of yacc.c  */
-#line 148 "cond.y"
+#line 154 "cond.y"
     {
             (yyval.value) = (yyvsp[(1) - (1)].value);
         ;}
@@ -1569,7 +1575,7 @@
   case 5:
 
 /* Line 1455 of yacc.c  */
-#line 152 "cond.y"
+#line 158 "cond.y"
     {
             (yyval.value) = (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value);
         ;}
@@ -1578,7 +1584,7 @@
   case 6:
 
 /* Line 1455 of yacc.c  */
-#line 156 "cond.y"
+#line 162 "cond.y"
     {
             (yyval.value) = !(yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value);
         ;}
@@ -1587,7 +1593,7 @@
   case 7:
 
 /* Line 1455 of yacc.c  */
-#line 160 "cond.y"
+#line 166 "cond.y"
     {
             (yyval.value) = ( (yyvsp[(1) - (3)].value) || (yyvsp[(3) - (3)].value) ) && !( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) );
         ;}
@@ -1596,7 +1602,7 @@
   case 8:
 
 /* Line 1455 of yacc.c  */
-#line 164 "cond.y"
+#line 170 "cond.y"
     {
             (yyval.value) = ( (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value) ) || ( !(yyvsp[(1) - (3)].value) && !(yyvsp[(3) - (3)].value) );
         ;}
@@ -1605,7 +1611,7 @@
   case 9:
 
 /* Line 1455 of yacc.c  */
-#line 171 "cond.y"
+#line 177 "cond.y"
     {
             (yyval.value) = (yyvsp[(1) - (1)].value);
         ;}
@@ -1614,7 +1620,7 @@
   case 10:
 
 /* Line 1455 of yacc.c  */
-#line 175 "cond.y"
+#line 181 "cond.y"
     {
             (yyval.value) = (yyvsp[(1) - (3)].value) && (yyvsp[(3) - (3)].value);
         ;}
@@ -1623,7 +1629,7 @@
   case 11:
 
 /* Line 1455 of yacc.c  */
-#line 182 "cond.y"
+#line 188 "cond.y"
     {
             (yyval.value) = (yyvsp[(2) - (2)].value) ? 0 : 1;
         ;}
@@ -1632,7 +1638,7 @@
   case 12:
 
 /* Line 1455 of yacc.c  */
-#line 186 "cond.y"
+#line 192 "cond.y"
     {
             (yyval.value) = (yyvsp[(1) - (1)].value) ? 1 : 0;
         ;}
@@ -1641,17 +1647,17 @@
   case 13:
 
 /* Line 1455 of yacc.c  */
-#line 190 "cond.y"
+#line 196 "cond.y"
     {
             (yyval.value) = ((yyvsp[(1) - (1)].string) && (yyvsp[(1) - (1)].string)[0]) ? 1 : 0;
-            msi_free((yyvsp[(1) - (1)].string));
+            cond_free( (yyvsp[(1) - (1)].string) );
         ;}
     break;
 
   case 14:
 
 /* Line 1455 of yacc.c  */
-#line 195 "cond.y"
+#line 201 "cond.y"
     {
             (yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) );
         ;}
@@ -1660,35 +1666,35 @@
   case 15:
 
 /* Line 1455 of yacc.c  */
-#line 199 "cond.y"
+#line 205 "cond.y"
     {
             int num;
             if (num_from_prop( (yyvsp[(1) - (3)].string), &num ))
                 (yyval.value) = compare_int( num, (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].value) );
             else 
                 (yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE );
-            msi_free((yyvsp[(1) - (3)].string));
+            cond_free( (yyvsp[(1) - (3)].string) );
         ;}
     break;
 
   case 16:
 
 /* Line 1455 of yacc.c  */
-#line 208 "cond.y"
+#line 214 "cond.y"
     {
             int num;
             if (num_from_prop( (yyvsp[(3) - (3)].string), &num ))
                 (yyval.value) = compare_int( (yyvsp[(1) - (3)].value), (yyvsp[(2) - (3)].value), num );
             else 
                 (yyval.value) = ((yyvsp[(2) - (3)].value) == COND_NE || (yyvsp[(2) - (3)].value) == COND_INE );
-            msi_free((yyvsp[(3) - (3)].string));
+            cond_free( (yyvsp[(3) - (3)].string) );
         ;}
     break;
 
   case 17:
 
 /* Line 1455 of yacc.c  */
-#line 217 "cond.y"
+#line 223 "cond.y"
     {
             (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE );
         ;}
@@ -1697,7 +1703,7 @@
   case 18:
 
 /* Line 1455 of yacc.c  */
-#line 221 "cond.y"
+#line 227 "cond.y"
     {
             (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE );
         ;}
@@ -1706,7 +1712,7 @@
   case 19:
 
 /* Line 1455 of yacc.c  */
-#line 225 "cond.y"
+#line 231 "cond.y"
     {
             (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), TRUE );
         ;}
@@ -1715,7 +1721,7 @@
   case 20:
 
 /* Line 1455 of yacc.c  */
-#line 229 "cond.y"
+#line 235 "cond.y"
     {
             (yyval.value) = compare_and_free_strings( (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].value), (yyvsp[(3) - (3)].string), FALSE );
         ;}
@@ -1724,27 +1730,27 @@
   case 21:
 
 /* Line 1455 of yacc.c  */
-#line 233 "cond.y"
+#line 239 "cond.y"
     {
             (yyval.value) = 0;
-            msi_free((yyvsp[(1) - (3)].string));
+            cond_free( (yyvsp[(1) - (3)].string) );
         ;}
     break;
 
   case 22:
 
 /* Line 1455 of yacc.c  */
-#line 238 "cond.y"
+#line 244 "cond.y"
     {
             (yyval.value) = 0;
-            msi_free((yyvsp[(3) - (3)].string));
+            cond_free( (yyvsp[(3) - (3)].string) );
         ;}
     break;
 
   case 23:
 
 /* Line 1455 of yacc.c  */
-#line 243 "cond.y"
+#line 249 "cond.y"
     {
             (yyval.value) = (yyvsp[(2) - (3)].value);
         ;}
@@ -1753,133 +1759,133 @@
   case 24:
 
 /* Line 1455 of yacc.c  */
-#line 250 "cond.y"
+#line 256 "cond.y"
     { (yyval.value) = COND_EQ; ;}
     break;
 
   case 25:
 
 /* Line 1455 of yacc.c  */
-#line 251 "cond.y"
+#line 257 "cond.y"
     { (yyval.value) = COND_NE; ;}
     break;
 
   case 26:
 
 /* Line 1455 of yacc.c  */
-#line 252 "cond.y"
+#line 258 "cond.y"
     { (yyval.value) = COND_LT; ;}
     break;
 
   case 27:
 
 /* Line 1455 of yacc.c  */
-#line 253 "cond.y"
+#line 259 "cond.y"
     { (yyval.value) = COND_GT; ;}
     break;
 
   case 28:
 
 /* Line 1455 of yacc.c  */
-#line 254 "cond.y"
+#line 260 "cond.y"
     { (yyval.value) = COND_LE; ;}
     break;
 
   case 29:
 
 /* Line 1455 of yacc.c  */
-#line 255 "cond.y"
+#line 261 "cond.y"
     { (yyval.value) = COND_GE; ;}
     break;
 
   case 30:
 
 /* Line 1455 of yacc.c  */
-#line 256 "cond.y"
+#line 262 "cond.y"
     { (yyval.value) = COND_SS; ;}
     break;
 
   case 31:
 
 /* Line 1455 of yacc.c  */
-#line 257 "cond.y"
+#line 263 "cond.y"
     { (yyval.value) = COND_IEQ; ;}
     break;
 
   case 32:
 
 /* Line 1455 of yacc.c  */
-#line 258 "cond.y"
+#line 264 "cond.y"
     { (yyval.value) = COND_INE; ;}
     break;
 
   case 33:
 
 /* Line 1455 of yacc.c  */
-#line 259 "cond.y"
+#line 265 "cond.y"
     { (yyval.value) = COND_ILT; ;}
     break;
 
   case 34:
 
 /* Line 1455 of yacc.c  */
-#line 260 "cond.y"
+#line 266 "cond.y"
     { (yyval.value) = COND_IGT; ;}
     break;
 
   case 35:
 
 /* Line 1455 of yacc.c  */
-#line 261 "cond.y"
+#line 267 "cond.y"
     { (yyval.value) = COND_ILE; ;}
     break;
 
   case 36:
 
 /* Line 1455 of yacc.c  */
-#line 262 "cond.y"
+#line 268 "cond.y"
     { (yyval.value) = COND_IGE; ;}
     break;
 
   case 37:
 
 /* Line 1455 of yacc.c  */
-#line 263 "cond.y"
+#line 269 "cond.y"
     { (yyval.value) = COND_ISS; ;}
     break;
 
   case 38:
 
 /* Line 1455 of yacc.c  */
-#line 264 "cond.y"
+#line 270 "cond.y"
     { (yyval.value) = COND_LHS; ;}
     break;
 
   case 39:
 
 /* Line 1455 of yacc.c  */
-#line 265 "cond.y"
+#line 271 "cond.y"
     { (yyval.value) = COND_RHS; ;}
     break;
 
   case 40:
 
 /* Line 1455 of yacc.c  */
-#line 266 "cond.y"
+#line 272 "cond.y"
     { (yyval.value) = COND_ILHS; ;}
     break;
 
   case 41:
 
 /* Line 1455 of yacc.c  */
-#line 267 "cond.y"
+#line 273 "cond.y"
     { (yyval.value) = COND_IRHS; ;}
     break;
 
   case 42:
 
 /* Line 1455 of yacc.c  */
-#line 272 "cond.y"
+#line 278 "cond.y"
     {
         (yyval.string) = (yyvsp[(1) - (1)].string);
     ;}
@@ -1888,7 +1894,7 @@
   case 43:
 
 /* Line 1455 of yacc.c  */
-#line 276 "cond.y"
+#line 282 "cond.y"
     {
         (yyval.string) = (yyvsp[(1) - (1)].string);
     ;}
@@ -1897,9 +1903,10 @@
   case 44:
 
 /* Line 1455 of yacc.c  */
-#line 283 "cond.y"
-    {
-            (yyval.string) = COND_GetLiteral(&(yyvsp[(1) - (1)].str));
+#line 289 "cond.y"
+    {
+            COND_input* cond = (COND_input*) info;
+            (yyval.string) = COND_GetLiteral( cond, &(yyvsp[(1) - (1)].str) );
             if( !(yyval.string) )
                 YYABORT;
         ;}
@@ -1908,7 +1915,7 @@
   case 45:
 
 /* Line 1455 of yacc.c  */
-#line 292 "cond.y"
+#line 299 "cond.y"
     {
             (yyval.value) = (yyvsp[(1) - (1)].value);
         ;}
@@ -1917,35 +1924,35 @@
   case 46:
 
 /* Line 1455 of yacc.c  */
-#line 296 "cond.y"
+#line 303 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
             INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
       
             MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action );
             (yyval.value) = action;
-            msi_free( (yyvsp[(2) - (2)].string) );
+            cond_free( (yyvsp[(2) - (2)].string) );
         ;}
     break;
 
   case 47:
 
 /* Line 1455 of yacc.c  */
-#line 305 "cond.y"
+#line 312 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
             INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
       
             MSI_GetComponentStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action );
             (yyval.value) = install;
-            msi_free( (yyvsp[(2) - (2)].string) );
+            cond_free( (yyvsp[(2) - (2)].string) );
         ;}
     break;
 
   case 48:
 
 /* Line 1455 of yacc.c  */
-#line 314 "cond.y"
+#line 321 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
             INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
@@ -1956,58 +1963,68 @@
             else
                 (yyval.value) = action;
 
-            msi_free( (yyvsp[(2) - (2)].string) );
+            cond_free( (yyvsp[(2) - (2)].string) );
         ;}
     break;
 
   case 49:
 
 /* Line 1455 of yacc.c  */
-#line 327 "cond.y"
+#line 334 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
             INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
       
             MSI_GetFeatureStateW(cond->package, (yyvsp[(2) - (2)].string), &install, &action );
             (yyval.value) = install;
-            msi_free( (yyvsp[(2) - (2)].string) );
+            cond_free( (yyvsp[(2) - (2)].string) );
         ;}
     break;
 
   case 50:
 
 /* Line 1455 of yacc.c  */
-#line 339 "cond.y"
+#line 346 "cond.y"
     {
             COND_input* cond = (COND_input*) info;
+            UINT len;
 
             (yyval.string) = msi_dup_property( cond->package, (yyvsp[(1) - (1)].string) );
-            msi_free( (yyvsp[(1) - (1)].string) );
+            if ((yyval.string))
+            {
+                len = (lstrlenW((yyval.string)) + 1) * sizeof (WCHAR);
+                (yyval.string) = cond_track_mem( cond, (yyval.string), len );
+            }
+            cond_free( (yyvsp[(1) - (1)].string) );
         ;}
     break;
 
   case 51:
 
 /* Line 1455 of yacc.c  */
-#line 346 "cond.y"
-    {
+#line 359 "cond.y"
+    {
+            COND_input* cond = (COND_input*) info;
             UINT len = GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), NULL, 0 );
             (yyval.string) = NULL;
             if (len++)
             {
-                (yyval.string) = msi_alloc( len*sizeof (WCHAR) );
+                (yyval.string) = cond_alloc( cond, len*sizeof (WCHAR) );
+                if( !(yyval.string) )
+                    YYABORT;
                 GetEnvironmentVariableW( (yyvsp[(2) - (2)].string), (yyval.string), len );
             }
-            msi_free( (yyvsp[(2) - (2)].string) );
+            cond_free( (yyvsp[(2) - (2)].string) );
         ;}
     break;
 
   case 52:
 
 /* Line 1455 of yacc.c  */
-#line 360 "cond.y"
-    {
-            (yyval.string) = COND_GetString(&(yyvsp[(1) - (1)].str));
+#line 376 "cond.y"
+    {
+            COND_input* cond = (COND_input*) info;
+            (yyval.string) = COND_GetString( cond, &(yyvsp[(1) - (1)].str) );
             if( !(yyval.string) )
                 YYABORT;
         ;}
@@ -2016,20 +2033,21 @@
   case 53:
 
 /* Line 1455 of yacc.c  */
-#line 369 "cond.y"
-    {
-            LPWSTR szNum = COND_GetString(&(yyvsp[(1) - (1)].str));
+#line 386 "cond.y"
+    {
+            COND_input* cond = (COND_input*) info;
+            LPWSTR szNum = COND_GetString( cond, &(yyvsp[(1) - (1)].str) );
             if( !szNum )
                 YYABORT;
             (yyval.value) = atoiW( szNum );
-            msi_free( szNum );
-        ;}
-    break;
-
-
-
-/* Line 1455 of yacc.c  */
-#line 2033 "cond.tab.c"
+            cond_free( szNum );
+        ;}
+    break;
+
+
+
+/* Line 1455 of yacc.c  */
+#line 2051 "cond.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2241,7 +2259,7 @@
 
 
 /* Line 1675 of yacc.c  */
-#line 378 "cond.y"
+#line 396 "cond.y"
 
 
 
@@ -2558,11 +2576,11 @@
     return rc;
 }
 
-static LPWSTR COND_GetString( const struct cond_str *str )
+static LPWSTR COND_GetString( COND_input *cond, const struct cond_str *str )
 {
     LPWSTR ret;
 
-    ret = msi_alloc( (str->len+1) * sizeof (WCHAR) );
+    ret = cond_alloc( cond, (str->len+1) * sizeof (WCHAR) );
     if( ret )
     {
         memcpy( ret, str->data, str->len * sizeof(WCHAR));
@@ -2572,11 +2590,11 @@
     return ret;
 }
 
-static LPWSTR COND_GetLiteral( const struct cond_str *str )
+static LPWSTR COND_GetLiteral( COND_input *cond, const struct cond_str *str )
 {
     LPWSTR ret;
 
-    ret = msi_alloc( (str->len-1) * sizeof (WCHAR) );
+    ret = cond_alloc( cond, (str->len-1) * sizeof (WCHAR) );
     if( ret )
     {
         memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) );
@@ -2586,6 +2604,48 @@
     return ret;
 }
 
+static void *cond_alloc( COND_input *cond, unsigned int sz )
+{
+    struct list *mem;
+
+    mem = msi_alloc( sizeof (struct list) + sz );
+    if( !mem )
+        return NULL;
+
+    list_add_head( &(cond->mem), mem );
+    return mem + 1;
+}
+
+static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz )
+{
+    void *new_ptr;
+
+    if( !ptr )
+        return ptr;
+
+    new_ptr = cond_alloc( cond, sz );
+    if( !new_ptr )
+    {
+        msi_free( ptr );
+        return NULL;
+    }
+
+    memcpy( new_ptr, ptr, sz );
+    msi_free( ptr );
+    return new_ptr;
+}
+
+static void cond_free( void *ptr )
+{
+    struct list *mem = (struct list *)ptr - 1;
+
+    if( ptr )
+    {
+        list_remove( mem );
+        msi_free( mem );
+    }
+}
+
 static int cond_error(const char *str)
 {
     TRACE("%s\n", str );
@@ -2596,6 +2656,7 @@
 {
     COND_input cond;
     MSICONDITION r;
+    struct list *mem, *safety;
 
     TRACE("%s\n", debugstr_w( szCondition ) );
 
@@ -2606,11 +2667,22 @@
     cond.str   = szCondition;
     cond.n     = 0;
     cond.result = MSICONDITION_ERROR;
-    
+
+    list_init( &cond.mem );
+
     if ( !cond_parse( &cond ) )
         r = cond.result;
     else
         r = MSICONDITION_ERROR;
+
+    LIST_FOR_EACH_SAFE( mem, safety, &cond.mem )
+    {
+        /* The tracked memory lives directly after the list struct */
+        void *ptr = mem + 1;
+        if ( r != MSICONDITION_ERROR )
+            WARN( "condition parser failed to free up some memory: %p\n", ptr );
+        cond_free( ptr );
+    }
 
     TRACE("%i <- %s\n", r, debugstr_w(szCondition));
     return r;

Modified: trunk/reactos/dll/win32/msi/cond.tab.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/cond.tab.h?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/cond.tab.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/cond.tab.h [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -87,7 +87,7 @@
 {
 
 /* Line 1676 of yacc.c  */
-#line 110 "cond.y"
+#line 116 "cond.y"
 
     struct cond_str str;
     LPWSTR    string;

Modified: trunk/reactos/dll/win32/msi/cond.y
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/cond.y?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/cond.y [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/cond.y [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -40,6 +40,7 @@
 #include "msiserver.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
+#include "wine/list.h"
 
 #define YYLEX_PARAM info
 #define YYPARSE_PARAM info
@@ -54,6 +55,7 @@
     LPCWSTR str;
     INT    n;
     MSICONDITION result;
+    struct list mem;
 } COND_input;
 
 struct cond_str {
@@ -61,9 +63,13 @@
     INT len;
 };
 
-static LPWSTR COND_GetString( const struct cond_str *str );
-static LPWSTR COND_GetLiteral( const struct cond_str *str );
+static LPWSTR COND_GetString( COND_input *info, const struct cond_str *str );
+static LPWSTR COND_GetLiteral( COND_input *info, const struct cond_str *str );
 static int cond_lex( void *COND_lval, COND_input *info);
+
+static void *cond_alloc( COND_input *cond, unsigned int sz );
+static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz );
+static void cond_free( void *ptr );
 
 static INT compare_int( INT a, INT operator, INT b );
 static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert );
@@ -73,8 +79,8 @@
     INT r;
 
     r = compare_string( a, op, b, convert );
-    msi_free( a );
-    msi_free( b );
+    cond_free( a );
+    cond_free( b );
     return r;
 }
 
@@ -189,7 +195,7 @@
   | value_s
         {
             $$ = ($1 && $1[0]) ? 1 : 0;
-            msi_free($1);
+            cond_free( $1 );
         }
   | value_i operator value_i
         {
@@ -202,7 +208,7 @@
                 $$ = compare_int( num, $2, $3 );
             else 
                 $$ = ($2 == COND_NE || $2 == COND_INE );
-            msi_free($1);
+            cond_free( $1 );
         }
   | value_i operator symbol_s
         {
@@ -211,7 +217,7 @@
                 $$ = compare_int( $1, $2, num );
             else 
                 $$ = ($2 == COND_NE || $2 == COND_INE );
-            msi_free($3);
+            cond_free( $3 );
         }
   | symbol_s operator symbol_s
         {
@@ -232,12 +238,12 @@
   | literal operator value_i
         {
             $$ = 0;
-            msi_free($1);
+            cond_free( $1 );
         }
   | value_i operator literal
         {
             $$ = 0;
-            msi_free($3);
+            cond_free( $3 );
         }
   | COND_LPAR expression COND_RPAR
         {
@@ -281,7 +287,8 @@
 literal:
     COND_LITER
         {
-            $$ = COND_GetLiteral(&$1);
+            COND_input* cond = (COND_input*) info;
+            $$ = COND_GetLiteral( cond, &$1 );
             if( !$$ )
                 YYABORT;
         }
@@ -299,7 +306,7 @@
       
             MSI_GetComponentStateW(cond->package, $2, &install, &action );
             $$ = action;
-            msi_free( $2 );
+            cond_free( $2 );
         }
   | COND_QUESTION identifier
         {
@@ -308,7 +315,7 @@
       
             MSI_GetComponentStateW(cond->package, $2, &install, &action );
             $$ = install;
-            msi_free( $2 );
+            cond_free( $2 );
         }
   | COND_AMPER identifier
         {
@@ -321,7 +328,7 @@
             else
                 $$ = action;
 
-            msi_free( $2 );
+            cond_free( $2 );
         }
   | COND_EXCLAM identifier
         {
@@ -330,7 +337,7 @@
       
             MSI_GetFeatureStateW(cond->package, $2, &install, &action );
             $$ = install;
-            msi_free( $2 );
+            cond_free( $2 );
         }
     ;
 
@@ -338,27 +345,37 @@
     identifier
         {
             COND_input* cond = (COND_input*) info;
+            UINT len;
 
             $$ = msi_dup_property( cond->package, $1 );
-            msi_free( $1 );
+            if ($$)
+            {
+                len = (lstrlenW($$) + 1) * sizeof (WCHAR);
+                $$ = cond_track_mem( cond, $$, len );
+            }
+            cond_free( $1 );
         }
     | COND_PERCENT identifier
         {
+            COND_input* cond = (COND_input*) info;
             UINT len = GetEnvironmentVariableW( $2, NULL, 0 );
             $$ = NULL;
             if (len++)
             {
-                $$ = msi_alloc( len*sizeof (WCHAR) );
+                $$ = cond_alloc( cond, len*sizeof (WCHAR) );
+                if( !$$ )
+                    YYABORT;
                 GetEnvironmentVariableW( $2, $$, len );
             }
-            msi_free( $2 );
+            cond_free( $2 );
         }
     ;
 
 identifier:
     COND_IDENT
         {
-            $$ = COND_GetString(&$1);
+            COND_input* cond = (COND_input*) info;
+            $$ = COND_GetString( cond, &$1 );
             if( !$$ )
                 YYABORT;
         }
@@ -367,11 +384,12 @@
 integer:
     COND_NUMBER
         {
-            LPWSTR szNum = COND_GetString(&$1);
+            COND_input* cond = (COND_input*) info;
+            LPWSTR szNum = COND_GetString( cond, &$1 );
             if( !szNum )
                 YYABORT;
             $$ = atoiW( szNum );
-            msi_free( szNum );
+            cond_free( szNum );
         }
     ;
 
@@ -691,11 +709,11 @@
     return rc;
 }
 
-static LPWSTR COND_GetString( const struct cond_str *str )
+static LPWSTR COND_GetString( COND_input *cond, const struct cond_str *str )
 {
     LPWSTR ret;
 
-    ret = msi_alloc( (str->len+1) * sizeof (WCHAR) );
+    ret = cond_alloc( cond, (str->len+1) * sizeof (WCHAR) );
     if( ret )
     {
         memcpy( ret, str->data, str->len * sizeof(WCHAR));
@@ -705,11 +723,11 @@
     return ret;
 }
 
-static LPWSTR COND_GetLiteral( const struct cond_str *str )
+static LPWSTR COND_GetLiteral( COND_input *cond, const struct cond_str *str )
 {
     LPWSTR ret;
 
-    ret = msi_alloc( (str->len-1) * sizeof (WCHAR) );
+    ret = cond_alloc( cond, (str->len-1) * sizeof (WCHAR) );
     if( ret )
     {
         memcpy( ret, str->data+1, (str->len-2) * sizeof(WCHAR) );
@@ -719,6 +737,48 @@
     return ret;
 }
 
+static void *cond_alloc( COND_input *cond, unsigned int sz )
+{
+    struct list *mem;
+
+    mem = msi_alloc( sizeof (struct list) + sz );
+    if( !mem )
+        return NULL;
+
+    list_add_head( &(cond->mem), mem );
+    return mem + 1;
+}
+
+static void *cond_track_mem( COND_input *cond, void *ptr, unsigned int sz )
+{
+    void *new_ptr;
+
+    if( !ptr )
+        return ptr;
+
+    new_ptr = cond_alloc( cond, sz );
+    if( !new_ptr )
+    {
+        msi_free( ptr );
+        return NULL;
+    }
+
+    memcpy( new_ptr, ptr, sz );
+    msi_free( ptr );
+    return new_ptr;
+}
+
+static void cond_free( void *ptr )
+{
+    struct list *mem = (struct list *)ptr - 1;
+
+    if( ptr )
+    {
+        list_remove( mem );
+        msi_free( mem );
+    }
+}
+
 static int cond_error(const char *str)
 {
     TRACE("%s\n", str );
@@ -729,6 +789,7 @@
 {
     COND_input cond;
     MSICONDITION r;
+    struct list *mem, *safety;
 
     TRACE("%s\n", debugstr_w( szCondition ) );
 
@@ -739,12 +800,23 @@
     cond.str   = szCondition;
     cond.n     = 0;
     cond.result = MSICONDITION_ERROR;
-    
+
+    list_init( &cond.mem );
+
     if ( !cond_parse( &cond ) )
         r = cond.result;
     else
         r = MSICONDITION_ERROR;
 
+    LIST_FOR_EACH_SAFE( mem, safety, &cond.mem )
+    {
+        /* The tracked memory lives directly after the list struct */
+        void *ptr = mem + 1;
+        if ( r != MSICONDITION_ERROR )
+            WARN( "condition parser failed to free up some memory: %p\n", ptr );
+        cond_free( ptr );
+    }
+
     TRACE("%i <- %s\n", r, debugstr_w(szCondition));
     return r;
 }

Modified: trunk/reactos/dll/win32/msi/custom.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/custom.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/custom.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/custom.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -647,6 +647,28 @@
     return ERROR_SUCCESS;
 }
 
+#ifdef __i386__
+extern UINT CUSTOMPROC_wrapper( MsiCustomActionEntryPoint proc, MSIHANDLE handle );
+__ASM_GLOBAL_FUNC( CUSTOMPROC_wrapper,
+	"pushl %ebp\n\t"
+	__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+	__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+	"movl %esp,%ebp\n\t"
+	__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+	"pushl 12(%ebp)\n\t"
+	"movl 8(%ebp),%eax\n\t"
+	"call *%eax\n\t"
+	"leave\n\t"
+	__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+	__ASM_CFI(".cfi_same_value %ebp\n\t")
+	"ret" )
+#else
+static inline UINT CUSTOMPROC_wrapper( MsiCustomActionEntryPoint proc, MSIHANDLE handle )
+{
+	return proc(handle);
+}
+#endif
+
 static DWORD ACTION_CallDllFunction( const GUID *guid )
 {
     MsiCustomActionEntryPoint fn;
@@ -685,7 +707,7 @@
 
             __TRY
             {
-                r = fn( hPackage );
+                r = CUSTOMPROC_wrapper( fn, hPackage );
             }
             __EXCEPT_PAGE_FAULT
             {

Modified: trunk/reactos/dll/win32/msi/database.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/database.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/database.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/database.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -51,6 +51,8 @@
  *  Any binary data in a table is a reference to a stream.
  */
 
+#define IS_INTMSIDBOPEN(x)      (((ULONG_PTR)(x) >> 16) == 0)
+
 typedef struct tagMSITRANSFORM {
     struct list entry;
     IStorage *stg;
@@ -306,7 +308,7 @@
 
     save_path = szDBPath;
     szMode = szPersist;
-    if( HIWORD( szPersist ) )
+    if( !IS_INTMSIDBOPEN(szPersist) )
     {
         if (!CopyFileW( szDBPath, szPersist, FALSE ))
             return ERROR_OPEN_FAILED;
@@ -459,7 +461,7 @@
             goto end;
     }
 
-    if( HIWORD(szPersist) )
+    if( !IS_INTMSIDBOPEN(szPersist) )
     {
         szwPersist = strdupAtoW( szPersist );
         if( !szwPersist )
@@ -471,7 +473,7 @@
     r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
 
 end:
-    if( HIWORD(szPersist) )
+    if( !IS_INTMSIDBOPEN(szPersist) )
         msi_free( szwPersist );
     msi_free( szwDBPath );
 

Modified: trunk/reactos/dll/win32/msi/dialog.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/dialog.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/dialog.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/dialog.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -166,6 +166,8 @@
 #define WM_MSI_DIALOG_CREATE  (WM_USER+0x100)
 #define WM_MSI_DIALOG_DESTROY (WM_USER+0x101)
 
+#define USER_INSTALLSTATE_ALL 0x1000
+
 static DWORD uiThreadId;
 static HWND hMsiHiddenWindow;
 
@@ -1876,7 +1878,7 @@
 
     /* FIXME: load strings from resources */
     AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_LOCAL, "Install feature locally");
-    AppendMenuA( hMenu, MF_GRAYED, 0x1000, "Install entire feature");
+    AppendMenuA( hMenu, MF_ENABLED, USER_INSTALLSTATE_ALL, "Install entire feature");
     AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ADVERTISED, "Install on demand");
     AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ABSENT, "Don't install");
     r = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
@@ -1897,6 +1899,37 @@
     SendMessageW( hwnd, TVM_GETITEMW, 0, (LPARAM) &tvi );
 
     return (MSIFEATURE*) tvi.lParam;
+}
+
+static void
+msi_seltree_update_feature_installstate( HWND hwnd, HTREEITEM hItem,
+        MSIPACKAGE *package, MSIFEATURE *feature, INSTALLSTATE state )
+{
+    msi_feature_set_state( package, feature, state );
+    msi_seltree_sync_item_state( hwnd, feature, hItem );
+    ACTION_UpdateComponentStates( package, feature->Feature );
+}
+
+static void
+msi_seltree_update_siblings_and_children_installstate( HWND hwnd, HTREEITEM curr,
+        MSIPACKAGE *package, INSTALLSTATE state)
+{
+    /* update all siblings */
+    do
+    {
+        MSIFEATURE *feature;
+        HTREEITEM child;
+
+        feature = msi_seltree_feature_from_item( hwnd, curr );
+        msi_seltree_update_feature_installstate( hwnd, curr, package, feature, state );
+
+        /* update this sibling's children */
+        child = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)curr );
+        if (child)
+            msi_seltree_update_siblings_and_children_installstate( hwnd, child,
+                    package, state );
+    }
+    while ((curr = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)curr )));
 }
 
 static LRESULT
@@ -1931,18 +1964,22 @@
 
     switch (r)
     {
-    case INSTALLSTATE_LOCAL:
+    case USER_INSTALLSTATE_ALL:
+        r = INSTALLSTATE_LOCAL;
+        /* fall-through */
     case INSTALLSTATE_ADVERTISED:
     case INSTALLSTATE_ABSENT:
-        msi_feature_set_state(package, feature, r);
+        {
+            HTREEITEM child;
+            child = (HTREEITEM)SendMessageW( hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem );
+            if (child)
+                msi_seltree_update_siblings_and_children_installstate( hwnd, child, package, r );
+        }
+        /* fall-through */
+    case INSTALLSTATE_LOCAL:
+        msi_seltree_update_feature_installstate( hwnd, hItem, package, feature, r );
         break;
-    default:
-        FIXME("select feature and all children\n");
-    }
-
-    /* update */
-    msi_seltree_sync_item_state( hwnd, feature, hItem );
-    ACTION_UpdateComponentStates( package, feature->Feature );
+    }
 
     return 0;
 }

Modified: trunk/reactos/dll/win32/msi/events.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/events.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/events.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/events.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -383,6 +383,28 @@
     return MSI_SetPropertyW( package, szReinstallMode, argument );
 }
 
+static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,
+                                           msi_dialog *dialog)
+{
+    static const WCHAR szProductID[] = {'P','r','o','d','u','c','t','I','D',0};
+    static const WCHAR szPIDTemplate[] = {'P','I','D','T','e','m','p','l','a','t','e',0};
+    static const WCHAR szPIDKEY[] = {'P','I','D','K','E','Y',0};
+    LPWSTR key, template;
+    UINT ret = ERROR_SUCCESS;
+
+    template = msi_dup_property( package, szPIDTemplate );
+    key = msi_dup_property( package, szPIDKEY );
+
+    if (key && template)
+    {
+        FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) );
+        ret = MSI_SetPropertyW( package, szProductID, key );
+    }
+    msi_free( template );
+    msi_free( key );
+    return ret;
+}
+
 static const struct _events Events[] = {
     { "EndDialog",ControlEvent_EndDialog },
     { "NewDialog",ControlEvent_NewDialog },
@@ -398,6 +420,7 @@
     { "DirectoryListUp",ControlEvent_DirectoryListUp },
     { "SelectionBrowse",ControlEvent_SpawnDialog },
     { "ReinstallMode",ControlEvent_ReinstallMode },
+    { "ValidateProductID",ControlEvent_ValidateProductID },
     { NULL,NULL },
 };
 

Modified: trunk/reactos/dll/win32/msi/files.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/files.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/files.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/files.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -365,7 +365,8 @@
                         debugstr_w(component));
 
         /* the action taken was the same as the current install state */        
-        comp->Action = comp->Installed;
+        if (comp)
+            comp->Action = comp->Installed;
 
         return ERROR_SUCCESS;
     }

Modified: trunk/reactos/dll/win32/msi/helpers.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/helpers.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/helpers.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/helpers.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -438,238 +438,6 @@
     msi_free(package->script->Actions[script]);
     package->script->Actions[script] = NULL;
     package->script->ActionCount[script] = 0;
-}
-
-static void remove_tracked_tempfiles(MSIPACKAGE* package)
-{
-    struct list *item, *cursor;
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
-    {
-        MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
-
-        list_remove( &temp->entry );
-        TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
-        if (!DeleteFileW( temp->Path ))
-            ERR("failed to delete %s\n", debugstr_w( temp->Path ));
-        msi_free( temp->Path );
-        msi_free( temp );
-    }
-}
-
-static void free_feature( MSIFEATURE *feature )
-{
-    struct list *item, *cursor;
-
-    LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
-    {
-        FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
-        list_remove( &fl->entry );
-        msi_free( fl );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
-    {
-        ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
-        list_remove( &cl->entry );
-        msi_free( cl );
-    }
-    msi_free( feature->Feature );
-    msi_free( feature->Feature_Parent );
-    msi_free( feature->Directory );
-    msi_free( feature->Description );
-    msi_free( feature->Title );
-    msi_free( feature );
-}
-
-static void free_extension( MSIEXTENSION *ext )
-{
-    struct list *item, *cursor;
-
-    LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
-    {
-        MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
-
-        list_remove( &verb->entry );
-        msi_free( verb->Verb );
-        msi_free( verb->Command );
-        msi_free( verb->Argument );
-        msi_free( verb );
-    }
-
-    msi_free( ext->Extension );
-    msi_free( ext->ProgIDText );
-    msi_free( ext );
-}
-
-/* Called when the package is being closed */
-void ACTION_free_package_structures( MSIPACKAGE* package)
-{
-    INT i;
-    struct list *item, *cursor;
-
-    TRACE("Freeing package action data\n");
-
-    remove_tracked_tempfiles(package);
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->features )
-    {
-        MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
-        list_remove( &feature->entry );
-        free_feature( feature );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
-    {
-        MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
-
-        list_remove( &folder->entry );
-        msi_free( folder->Parent );
-        msi_free( folder->Directory );
-        msi_free( folder->TargetDefault );
-        msi_free( folder->SourceLongPath );
-        msi_free( folder->SourceShortPath );
-        msi_free( folder->ResolvedTarget );
-        msi_free( folder->ResolvedSource );
-        msi_free( folder->Property );
-        msi_free( folder );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->components )
-    {
-        MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
-
-        list_remove( &comp->entry );
-        msi_free( comp->Component );
-        msi_free( comp->ComponentId );
-        msi_free( comp->Directory );
-        msi_free( comp->Condition );
-        msi_free( comp->KeyPath );
-        msi_free( comp->FullKeypath );
-        msi_free( comp );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->files )
-    {
-        MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
-
-        list_remove( &file->entry );
-        msi_free( file->File );
-        msi_free( file->FileName );
-        msi_free( file->ShortName );
-        msi_free( file->LongName );
-        msi_free( file->Version );
-        msi_free( file->Language );
-        msi_free( file->TargetPath );
-        msi_free( file );
-    }
-
-    /* clean up extension, progid, class and verb structures */
-    LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
-    {
-        MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
-
-        list_remove( &cls->entry );
-        msi_free( cls->clsid );
-        msi_free( cls->Context );
-        msi_free( cls->Description );
-        msi_free( cls->FileTypeMask );
-        msi_free( cls->IconPath );
-        msi_free( cls->DefInprocHandler );
-        msi_free( cls->DefInprocHandler32 );
-        msi_free( cls->Argument );
-        msi_free( cls->ProgIDText );
-        msi_free( cls );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
-    {
-        MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
-
-        list_remove( &ext->entry );
-        free_extension( ext );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
-    {
-        MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
-
-        list_remove( &progid->entry );
-        msi_free( progid->ProgID );
-        msi_free( progid->Description );
-        msi_free( progid->IconPath );
-        msi_free( progid );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
-    {
-        MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
-
-        list_remove( &mt->entry );
-        msi_free( mt->clsid );
-        msi_free( mt->ContentType );
-        msi_free( mt );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
-    {
-        MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
-
-        list_remove( &appid->entry );
-        msi_free( appid->AppID );
-        msi_free( appid->RemoteServerName );
-        msi_free( appid->LocalServer );
-        msi_free( appid->ServiceParameters );
-        msi_free( appid->DllSurrogate );
-        msi_free( appid );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
-    {
-        MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
-
-        list_remove( &info->entry );
-        msi_free( info->value );
-	msi_free( info );
-    }
-
-    LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
-    {
-        MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
-
-        list_remove( &info->entry );
-        msi_free( info->volume_label );
-        msi_free( info->disk_prompt );
-	msi_free( info );
-    }
-
-    if (package->script)
-    {
-        for (i = 0; i < TOTAL_SCRIPTS; i++)
-            msi_free_action_script(package, i);
-
-        for (i = 0; i < package->script->UniqueActionsCount; i++)
-            msi_free(package->script->UniqueActions[i]);
-
-        msi_free(package->script->UniqueActions);
-        msi_free(package->script);
-    }
-
-    if (package->patch)
-    {
-        msi_free(package->patch->patchcode);
-        msi_free(package->patch->transforms);
-        msi_free(package->patch);
-    }
-
-    msi_free(package->BaseURL);
-    msi_free(package->PackagePath);
-    msi_free(package->ProductCode);
-    msi_free(package->ActionFormat);
-    msi_free(package->LastAction);
-
-    /* cleanup control event subscriptions */
-    ControlEvent_CleanupSubscriptions(package);
 }
 
 /*

Modified: trunk/reactos/dll/win32/msi/join.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/join.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/join.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/join.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -117,8 +117,11 @@
 
 static UINT JOIN_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
 {
-    FIXME("(%p, %d, %p): stub!\n", view, row, rec);
-    return ERROR_FUNCTION_FAILED;
+    MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
+
+    TRACE("%p %d %p\n", jv, row, rec);
+
+    return msi_view_get_row( jv->db, view, row, rec );
 }
 
 static UINT JOIN_execute( struct tagMSIVIEW *view, MSIRECORD *record )
@@ -219,11 +222,117 @@
     return ERROR_FUNCTION_FAILED;
 }
 
-static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                         MSIRECORD *rec, UINT row )
-{
-    TRACE("%p %d %p\n", view, eModifyMode, rec);
+static UINT join_find_row( MSIJOINVIEW *jv, MSIRECORD *rec, UINT *row )
+{
+    LPCWSTR str;
+    UINT i, id, data;
+
+    str = MSI_RecordGetString( rec, 1 );
+    msi_string2idW( jv->db->strings, str, &id );
+
+    for (i = 0; i < jv->rows; i++)
+    {
+        JOIN_fetch_int( &jv->view, i, 1, &data );
+
+        if (data == id)
+        {
+            *row = i;
+            return ERROR_SUCCESS;
+        }
+    }
+
     return ERROR_FUNCTION_FAILED;
+}
+
+static UINT JOIN_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
+{
+    MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
+    JOINTABLE *table;
+    UINT i, reduced_mask = 0, r = ERROR_SUCCESS, offset = 0, col_count;
+    MSIRECORD *reduced;
+
+    TRACE("%p %d %p %u %08x\n", jv, row, rec, rec->count, mask );
+
+    if (mask >= 1 << jv->columns)
+        return ERROR_INVALID_PARAMETER;
+
+    LIST_FOR_EACH_ENTRY(table, &jv->tables, JOINTABLE, entry)
+    {
+        r = table->view->ops->get_dimensions( table->view, NULL, &col_count );
+        if (r != ERROR_SUCCESS)
+            return r;
+
+        reduced = MSI_CreateRecord( col_count );
+        if (!reduced)
+            return ERROR_FUNCTION_FAILED;
+
+        for (i = 0; i < col_count; i++)
+        {
+            r = MSI_RecordCopyField( rec, i + offset + 1, reduced, i + 1 );
+            if (r != ERROR_SUCCESS)
+                break;
+        }
+
+        offset += col_count;
+        reduced_mask = mask >> (jv->columns - offset) & ((1 << col_count) - 1);
+
+        if (r == ERROR_SUCCESS)
+            r = table->view->ops->set_row( table->view, row, reduced, reduced_mask );
+
+        msiobj_release( &reduced->hdr );
+    }
+
+    return r;
+}
+
+static UINT join_modify_update( struct tagMSIVIEW *view, MSIRECORD *rec )
+{
+    MSIJOINVIEW *jv = (MSIJOINVIEW *)view;
+    UINT r, row;
+
+    r = join_find_row( jv, rec, &row );
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    return JOIN_set_row( view, row, rec, (1 << jv->columns) - 1 );
+}
+
+static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY mode, MSIRECORD *rec, UINT row )
+{
+    UINT r;
+
+    TRACE("%p %d %p %u\n", view, mode, rec, row);
+
+    switch (mode)
+    {
+    case MSIMODIFY_UPDATE:
+        return join_modify_update( view, rec );
+
+    case MSIMODIFY_ASSIGN:
+    case MSIMODIFY_DELETE:
+    case MSIMODIFY_INSERT:
+    case MSIMODIFY_INSERT_TEMPORARY:
+    case MSIMODIFY_MERGE:
+    case MSIMODIFY_REPLACE:
+    case MSIMODIFY_SEEK:
+    case MSIMODIFY_VALIDATE:
+    case MSIMODIFY_VALIDATE_DELETE:
+    case MSIMODIFY_VALIDATE_FIELD:
+    case MSIMODIFY_VALIDATE_NEW:
+        r = ERROR_FUNCTION_FAILED;
+        break;
+
+    case MSIMODIFY_REFRESH:
+        r = ERROR_CALL_NOT_IMPLEMENTED;
+        break;
+
+    default:
+        WARN("%p %d %p %u - unknown mode\n", view, mode, rec, row );
+        r = ERROR_INVALID_PARAMETER;
+        break;
+    }
+
+    return r;
 }
 
 static UINT JOIN_delete( struct tagMSIVIEW *view )
@@ -259,7 +368,7 @@
     if (col == 0 || col > jv->columns)
         return ERROR_INVALID_PARAMETER;
 
-    for (i = (UINT)*handle; i < jv->rows; i++)
+    for (i = PtrToUlong(*handle); i < jv->rows; i++)
     {
         if (view->ops->fetch_int( view, i, col, &row_value ) != ERROR_SUCCESS)
             continue;

Modified: trunk/reactos/dll/win32/msi/msi.rc
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi.rc?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/msi.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msi.rc [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -48,6 +48,7 @@
 #include "msi_Si.rc"
 #include "msi_Sv.rc"
 #include "msi_Tr.rc"
+#include "msi_Uk.rc"
 #include "msi_Zh.rc"
 
 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

Added: trunk/reactos/dll/win32/msi/msi_Uk.rc
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msi_Uk.rc?rev=45468&view=auto
==============================================================================
--- trunk/reactos/dll/win32/msi/msi_Uk.rc (added)
+++ trunk/reactos/dll/win32/msi/msi_Uk.rc [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -1,0 +1,41 @@
+/*
+ * Ukrainian resources for MSI
+ *
+ * Copyright 2005 Mike McCormack
+ * Copyright 2007 Artem Reznikov
+ * Copyright 2010 Igor Paliychuk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "windef.h"
+
+/* UTF-8 */
+#pragma code_page(65001)
+
+LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+	4 "Не вдалося відкрити вказаний пакет інсталяції.  Перевірте шляÑ
 до файлу та спробуйте знов."
+	5 "шляÑ
 %s не знайдено"
+	9 "вставте диск %s"
+	10 "невірні параметри"
+	11 "вкажіть папку, що містить %s"
+	12 "джерело встановлення даної можливості не вказане"
+	13 "мережевий диск для даної можливості не вказаний"
+	14 "можливість з:"
+	15 "виберіть папку, що містить %s"
+}

Propchange: trunk/reactos/dll/win32/msi/msi_Uk.rc
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/win32/msi/msipriv.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msipriv.h?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/msipriv.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msipriv.h [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -689,7 +689,6 @@
 
 /* action internals */
 extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR );
-extern void ACTION_free_package_structures( MSIPACKAGE* );
 extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR);
 extern UINT ACTION_ForceReboot(MSIPACKAGE *package);
 extern UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR szTable, INT iSequenceMode );

Modified: trunk/reactos/dll/win32/msi/msiquery.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/msiquery.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/msiquery.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/msiquery.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -831,7 +831,7 @@
             return ERROR_INVALID_HANDLE;
 
         IWineMsiRemoteDatabase_Release( remote_database );
-        WARN("MsiDatabaseCommit not allowed during a custom action!\n");
+        WARN("not allowed during a custom action!\n");
 
         return ERROR_SUCCESS;
     }

Modified: trunk/reactos/dll/win32/msi/package.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/package.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/package.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/package.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -49,6 +49,237 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
+static void remove_tracked_tempfiles( MSIPACKAGE *package )
+{
+    struct list *item, *cursor;
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
+    {
+        MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
+
+        list_remove( &temp->entry );
+        TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
+        if (!DeleteFileW( temp->Path ))
+            ERR("failed to delete %s\n", debugstr_w( temp->Path ));
+        msi_free( temp->Path );
+        msi_free( temp );
+    }
+}
+
+static void free_feature( MSIFEATURE *feature )
+{
+    struct list *item, *cursor;
+
+    LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
+    {
+        FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
+        list_remove( &fl->entry );
+        msi_free( fl );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
+    {
+        ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
+        list_remove( &cl->entry );
+        msi_free( cl );
+    }
+    msi_free( feature->Feature );
+    msi_free( feature->Feature_Parent );
+    msi_free( feature->Directory );
+    msi_free( feature->Description );
+    msi_free( feature->Title );
+    msi_free( feature );
+}
+
+static void free_extension( MSIEXTENSION *ext )
+{
+    struct list *item, *cursor;
+
+    LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
+    {
+        MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
+
+        list_remove( &verb->entry );
+        msi_free( verb->Verb );
+        msi_free( verb->Command );
+        msi_free( verb->Argument );
+        msi_free( verb );
+    }
+
+    msi_free( ext->Extension );
+    msi_free( ext->ProgIDText );
+    msi_free( ext );
+}
+
+static void free_package_structures( MSIPACKAGE *package )
+{
+    INT i;
+    struct list *item, *cursor;
+
+    TRACE("Freeing package action data\n");
+
+    remove_tracked_tempfiles(package);
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->features )
+    {
+        MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
+        list_remove( &feature->entry );
+        free_feature( feature );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
+    {
+        MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
+
+        list_remove( &folder->entry );
+        msi_free( folder->Parent );
+        msi_free( folder->Directory );
+        msi_free( folder->TargetDefault );
+        msi_free( folder->SourceLongPath );
+        msi_free( folder->SourceShortPath );
+        msi_free( folder->ResolvedTarget );
+        msi_free( folder->ResolvedSource );
+        msi_free( folder->Property );
+        msi_free( folder );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->components )
+    {
+        MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
+
+        list_remove( &comp->entry );
+        msi_free( comp->Component );
+        msi_free( comp->ComponentId );
+        msi_free( comp->Directory );
+        msi_free( comp->Condition );
+        msi_free( comp->KeyPath );
+        msi_free( comp->FullKeypath );
+        msi_free( comp );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->files )
+    {
+        MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
+
+        list_remove( &file->entry );
+        msi_free( file->File );
+        msi_free( file->FileName );
+        msi_free( file->ShortName );
+        msi_free( file->LongName );
+        msi_free( file->Version );
+        msi_free( file->Language );
+        msi_free( file->TargetPath );
+        msi_free( file );
+    }
+
+    /* clean up extension, progid, class and verb structures */
+    LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
+    {
+        MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
+
+        list_remove( &cls->entry );
+        msi_free( cls->clsid );
+        msi_free( cls->Context );
+        msi_free( cls->Description );
+        msi_free( cls->FileTypeMask );
+        msi_free( cls->IconPath );
+        msi_free( cls->DefInprocHandler );
+        msi_free( cls->DefInprocHandler32 );
+        msi_free( cls->Argument );
+        msi_free( cls->ProgIDText );
+        msi_free( cls );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
+    {
+        MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
+
+        list_remove( &ext->entry );
+        free_extension( ext );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
+    {
+        MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
+
+        list_remove( &progid->entry );
+        msi_free( progid->ProgID );
+        msi_free( progid->Description );
+        msi_free( progid->IconPath );
+        msi_free( progid );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
+    {
+        MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
+
+        list_remove( &mt->entry );
+        msi_free( mt->clsid );
+        msi_free( mt->ContentType );
+        msi_free( mt );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
+    {
+        MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
+
+        list_remove( &appid->entry );
+        msi_free( appid->AppID );
+        msi_free( appid->RemoteServerName );
+        msi_free( appid->LocalServer );
+        msi_free( appid->ServiceParameters );
+        msi_free( appid->DllSurrogate );
+        msi_free( appid );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
+    {
+        MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
+
+        list_remove( &info->entry );
+        msi_free( info->value );
+        msi_free( info );
+    }
+
+    LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
+    {
+        MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
+
+        list_remove( &info->entry );
+        msi_free( info->volume_label );
+        msi_free( info->disk_prompt );
+        msi_free( info );
+    }
+
+    if (package->script)
+    {
+        for (i = 0; i < TOTAL_SCRIPTS; i++)
+            msi_free_action_script( package, i );
+
+        for (i = 0; i < package->script->UniqueActionsCount; i++)
+            msi_free( package->script->UniqueActions[i] );
+
+        msi_free( package->script->UniqueActions );
+        msi_free( package->script );
+    }
+
+    if (package->patch)
+    {
+        msi_free( package->patch->patchcode );
+        msi_free( package->patch->transforms );
+        msi_free( package->patch );
+    }
+
+    msi_free( package->BaseURL );
+    msi_free( package->PackagePath );
+    msi_free( package->ProductCode );
+    msi_free( package->ActionFormat );
+    msi_free( package->LastAction );
+
+    /* cleanup control event subscriptions */
+    ControlEvent_CleanupSubscriptions( package );
+}
+
 static void MSI_FreePackage( MSIOBJECTHDR *arg)
 {
     MSIPACKAGE *package= (MSIPACKAGE*) arg;
@@ -57,7 +288,7 @@
         msi_dialog_destroy( package->dialog );
 
     msiobj_release( &package->db->hdr );
-    ACTION_free_package_structures(package);
+    free_package_structures(package);
 }
 
 static UINT create_temp_property_table(MSIPACKAGE *package)

Modified: trunk/reactos/dll/win32/msi/storages.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/storages.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/storages.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/storages.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -452,7 +452,7 @@
                                        UINT val, UINT *row, MSIITERHANDLE *handle)
 {
     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
-    UINT index = (UINT)*handle;
+    UINT index = PtrToUlong(*handle);
 
     TRACE("(%d, %d): %d\n", *row, col, val);
 
@@ -470,7 +470,7 @@
         index++;
     }
 
-    *handle = (MSIITERHANDLE)++index;
+    *handle = UlongToPtr(++index);
     if (index >= sv->num_rows)
         return ERROR_NO_MORE_ITEMS;
 

Modified: trunk/reactos/dll/win32/msi/streams.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msi/streams.c?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msi/streams.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msi/streams.c [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -41,7 +41,6 @@
 typedef struct tabSTREAM
 {
     UINT str_index;
-    LPWSTR name;
     IStream *stream;
 } STREAM;
 
@@ -72,7 +71,6 @@
 {
     STREAM *stream;
     WCHAR decoded[MAX_STREAM_NAME_LEN];
-    LPWSTR ptr = name;
 
     stream = msi_alloc(sizeof(STREAM));
     if (!stream)
@@ -81,18 +79,11 @@
     if (encoded)
     {
         decode_streamname(name, decoded);
-        ptr = decoded;
         TRACE("stream -> %s %s\n", debugstr_w(name), debugstr_w(decoded));
-    }
-
-    stream->name = strdupW(ptr);
-    if (!stream->name)
-    {
-        msi_free(stream);
-        return NULL;
-    }
-
-    stream->str_index = msi_addstringW(sv->db->strings, 0, stream->name, -1, 1, StringNonPersistent);
+        name = decoded;
+    }
+
+    stream->str_index = msi_addstringW(sv->db->strings, 0, name, -1, 1, StringNonPersistent);
     stream->stream = stm;
     return stream;
 }
@@ -133,9 +124,9 @@
 {
     MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
 
-    FIXME("%p %d %p\n", sv, row, rec);
-
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    TRACE("%p %d %p\n", sv, row, rec);
+
+    return msi_view_get_row( sv->db, view, row, rec );
 }
 
 static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
@@ -144,13 +135,13 @@
     STREAM *stream;
     IStream *stm;
     STATSTG stat;
-    LPWSTR name = NULL;
+    LPWSTR encname = NULL, name = NULL;
     USHORT *data = NULL;
     HRESULT hr;
     ULONG count;
     UINT r = ERROR_FUNCTION_FAILED;
 
-    TRACE("(%p, %p)\n", view, rec);
+    TRACE("(%p, %d, %p, %08x)\n", view, row, rec, mask);
 
     if (row > sv->num_rows)
         return ERROR_FUNCTION_FAILED;
@@ -167,7 +158,10 @@
     }
 
     if (stat.cbSize.QuadPart >> 32)
-        goto done;
+    {
+        WARN("stream too large\n");
+        goto done;
+    }
 
     data = msi_alloc(stat.cbSize.QuadPart);
     if (!data)
@@ -182,7 +176,13 @@
 
     name = strdupW(MSI_RecordGetString(rec, 1));
     if (!name)
-        goto done;
+    {
+        WARN("failed to retrieve stream name\n");
+        goto done;
+    }
+
+    encname = encode_streamname(FALSE, name);
+    IStorage_DestroyElement(sv->db->storage, encname);
 
     r = write_stream_data(sv->db->storage, name, data, count, FALSE);
     if (r != ERROR_SUCCESS)
@@ -195,14 +195,20 @@
     if (!stream)
         goto done;
 
-    IStorage_OpenStream(sv->db->storage, name, 0,
-                        STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
+    hr = IStorage_OpenStream(sv->db->storage, encname, 0,
+                             STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
+    if (FAILED(hr))
+    {
+        WARN("failed to open stream: %08x\n", hr);
+        goto done;
+    }
 
     sv->streams[row] = stream;
 
 done:
     msi_free(name);
     msi_free(data);
+    msi_free(encname);
 
     IStream_Release(stm);
 
@@ -212,6 +218,9 @@
 static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
 {
     MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
+    UINT i;
+
+    TRACE("(%p, %p, %d, %d)\n", view, rec, row, temporary);
 
     if (!streams_set_table_size(sv, ++sv->num_rows))
         return ERROR_FUNCTION_FAILED;
@@ -219,7 +228,11 @@
     if (row == -1)
         row = sv->num_rows - 1;
 
-    /* FIXME have to readjust rows */
+    /* shift the rows to make room for the new row */
+    for (i = sv->num_rows - 1; i > row; i--)
+    {
+        sv->streams[i] = sv->streams[i - 1];
+    }
 
     return STREAMS_set_row(view, row, rec, 0);
 }
@@ -274,7 +287,7 @@
     {
     case 1:
         name_ptr = Name;
-        if (type) *type = MSITYPE_STRING | MAX_STREAM_NAME_LEN;
+        if (type) *type = MSITYPE_STRING | MSITYPE_VALID | MAX_STREAM_NAME_LEN;
         break;
 
     case 2:
@@ -404,8 +417,6 @@
         {
             if (sv->streams[i]->stream)
                 IStream_Release(sv->streams[i]->stream);
-
-            msi_free(sv->streams[i]->name);
             msi_free(sv->streams[i]);
         }
     }
@@ -420,9 +431,9 @@
                                        UINT val, UINT *row, MSIITERHANDLE *handle)
 {
     MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
-    UINT index = (UINT)*handle;
-
-    TRACE("(%d, %d): %d\n", *row, col, val);
+    UINT index = PtrToUlong(*handle);
+
+    TRACE("(%p, %d, %d, %p, %p)\n", view, col, val, row, handle);
 
     if (col == 0 || col > NUM_STREAMS_COLS)
         return ERROR_INVALID_PARAMETER;
@@ -438,8 +449,9 @@
         index++;
     }
 
-    *handle = (MSIITERHANDLE)++index;
-    if (index >= sv->num_rows)
+    *handle = UlongToPtr(++index);
+
+    if (index > sv->num_rows)
         return ERROR_NO_MORE_ITEMS;
 
     return ERROR_SUCCESS;
@@ -510,9 +522,16 @@
             break;
         }
 
-        IStorage_OpenStream(sv->db->storage, stat.pwcsName, 0,
-                            STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
+        hr = IStorage_OpenStream(sv->db->storage, stat.pwcsName, 0,
+                                 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream);
         CoTaskMemFree(stat.pwcsName);
+
+        if (FAILED(hr))
+        {
+            WARN("failed to open stream: %08x\n", hr);
+            count = -1;
+            break;
+        }
 
         if (!streams_set_table_size(sv, ++count))
         {

Modified: trunk/reactos/include/psdk/msi.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/msi.h?rev=45468&r1=45467&r2=45468&view=diff
==============================================================================
--- trunk/reactos/include/psdk/msi.h [iso-8859-1] (original)
+++ trunk/reactos/include/psdk/msi.h [iso-8859-1] Sat Feb  6 22:28:28 2010
@@ -597,6 +597,10 @@
 UINT WINAPI MsiSourceListEnumSourcesW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPWSTR, LPDWORD);
 #define     MsiSourceListEnumSources WINELIB_NAME_AW(MsiSourceListEnumSources)
 
+UINT WINAPI MsiSourceListClearSourceA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR);
+UINT WINAPI MsiSourceListClearSourceW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR);
+#define     MsiSourceListClearSource WINELIB_NAME_AW(MsiSourceListClearSource)
+
 UINT WINAPI MsiSourceListClearAllA(LPCSTR, LPCSTR, DWORD);
 UINT WINAPI MsiSourceListClearAllW(LPCWSTR, LPCWSTR, DWORD);
 #define     MsiSourceListClearAll WINELIB_NAME_AW(MsiSourceListClearAll)




More information about the Ros-diffs mailing list