msi: Compare strings without depending on thread locale.

Hans Leidekker hans at codeweavers.com
Tue Oct 19 04:27:44 CDT 2010


This version includes tests to show that native compares code points.
The tests fail if we use the invariant locale (after fixing up
CompareString to correctly collate the test strings) and succeed
if we use strcmpW.

This is a fix for the Office 2010 installer.
---
 dlls/msi/action.c        |   54 ++++++++-----
 dlls/msi/appsearch.c     |    8 +-
 dlls/msi/classes.c       |   12 ++--
 dlls/msi/cond.y          |   54 ++++++++------
 dlls/msi/create.c        |    3 +-
 dlls/msi/custom.c        |    2 +-
 dlls/msi/database.c      |   14 ++--
 dlls/msi/dialog.c        |   38 +++++-----
 dlls/msi/events.c        |   37 ++++-----
 dlls/msi/files.c         |    2 +-
 dlls/msi/helpers.c       |   20 +++---
 dlls/msi/insert.c        |    5 +-
 dlls/msi/install.c       |    4 +-
 dlls/msi/media.c         |    6 +-
 dlls/msi/msi.c           |  138 +++++++++++++++++-----------------
 dlls/msi/msipriv.h       |    2 +
 dlls/msi/msiquery.c      |    4 +-
 dlls/msi/package.c       |    2 +-
 dlls/msi/record.c        |    3 +-
 dlls/msi/registry.c      |    2 +-
 dlls/msi/source.c        |   26 +++---
 dlls/msi/sql.y           |    2 +-
 dlls/msi/string.c        |    4 +-
 dlls/msi/table.c         |   72 +++++++++---------
 dlls/msi/tests/db.c      |  185 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/msi/tests/package.c |   20 +++++
 dlls/msi/where.c         |    3 +-
 27 files changed, 474 insertions(+), 248 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 34c0ce4..c47e68a 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -445,7 +445,7 @@ UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si )
     guids = msi_split_string( guid_list, ';' );
     for ( i = 0; guids[i] && ret != ERROR_SUCCESS; i++ )
     {
-        if (!lstrcmpW( guids[i], product_code ))
+        if (!strcmpW( guids[i], product_code ))
             ret = ERROR_SUCCESS;
     }
     msi_free( guids );
@@ -964,6 +964,9 @@ static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
     MSICOMPONENT *comp;
 
     component = MSI_RecordGetString(row, 2);
+    if (!component)
+        return ERROR_SUCCESS;
+
     comp = get_loaded_component(package, component);
     if (!comp)
         return ERROR_SUCCESS;
@@ -1043,6 +1046,9 @@ static UINT ITERATE_RemoveFolders( MSIRECORD *row, LPVOID param )
     MSICOMPONENT *comp;
 
     component = MSI_RecordGetString(row, 2);
+    if (!component)
+        return ERROR_SUCCESS;
+
     comp = get_loaded_component(package, component);
     if (!comp)
         return ERROR_SUCCESS;
@@ -1218,7 +1224,7 @@ static MSIFEATURE *find_feature_by_name( MSIPACKAGE *package, LPCWSTR name )
 
     LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        if ( !lstrcmpW( feature->Feature, name ) )
+        if ( !strcmpW( feature->Feature, name ) )
             return feature;
     }
 
@@ -1515,9 +1521,9 @@ static UINT load_folder( MSIRECORD *row, LPVOID param )
     src_long = folder_split_path( src_short, '|' );
 
     /* check for no-op dirs */
-    if (!lstrcmpW(szDot, tgt_short))
+    if (tgt_short && !strcmpW( szDot, tgt_short ))
         tgt_short = szEmpty;
-    if (!lstrcmpW(szDot, src_short))
+    if (src_short && !strcmpW( szDot, src_short ))
         src_short = szEmpty;
 
     if (!tgt_long)
@@ -1690,13 +1696,13 @@ static BOOL process_state_property(MSIPACKAGE* package, int level,
 
     LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        if (lstrcmpW(property, szRemove) &&
+        if (strcmpW( property, szRemove ) &&
             (feature->Level <= 0 || feature->Level > level))
             continue;
 
         if (!strcmpW(property, szReinstall)) state = feature->Installed;
 
-        if (strcmpiW(override, szAll)==0)
+        if (!strcmpiW( override, szAll ))
             msi_feature_set_state(package, feature, state);
         else
         {
@@ -2310,7 +2316,7 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
          else
             ptr=value;
 
-        if (strstrW(value,szMulti))
+        if (strstrW(value, szMulti))
             *type = REG_MULTI_SZ;
 
         /* remove initial delimiter */
@@ -3749,7 +3755,7 @@ static UINT msi_publish_sourcelist(MSIPACKAGE *package, HKEY hkey)
 
     LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry)
     {
-        if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW))
+        if (!strcmpW( info->property, INSTALLPROPERTY_LASTUSEDSOURCEW ))
             msi_set_last_used_source(package->ProductCode, NULL, info->context,
                                      info->options, info->value);
         else
@@ -4852,7 +4858,7 @@ static UINT msi_unpublish_product(MSIPACKAGE *package, WCHAR *remove)
         return ERROR_FUNCTION_FAILED;
     }
 
-    if (!lstrcmpW(features[0], szAll))
+    if (!strcmpW( features[0], szAll ))
         full_uninstall = TRUE;
     else
     {
@@ -5783,7 +5789,7 @@ static MSIFILE *msi_find_file( MSIPACKAGE *package, LPCWSTR filename )
 
     LIST_FOR_EACH_ENTRY(file, &package->files, MSIFILE, entry)
     {
-        if (!lstrcmpW(file->File, filename))
+        if (!strcmpW( file->File, filename ))
             return file;
     }
 
@@ -5795,9 +5801,9 @@ static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
     MSIPACKAGE *package = param;
     LPWSTR driver, driver_path, ptr;
     WCHAR outpath[MAX_PATH];
-    MSIFILE *driver_file, *setup_file;
+    MSIFILE *driver_file = NULL, *setup_file = NULL;
     MSIRECORD *uirow;
-    LPCWSTR desc;
+    LPCWSTR desc, file_key;
     DWORD len, usage;
     UINT r = ERROR_SUCCESS;
 
@@ -5810,8 +5816,11 @@ static UINT ITERATE_InstallODBCDriver( MSIRECORD *rec, LPVOID param )
 
     desc = MSI_RecordGetString(rec, 3);
 
-    driver_file = msi_find_file(package, MSI_RecordGetString(rec, 4));
-    setup_file = msi_find_file(package, MSI_RecordGetString(rec, 5));
+    file_key = MSI_RecordGetString( rec, 4 );
+    if (file_key) driver_file = msi_find_file( package, file_key );
+
+    file_key = MSI_RecordGetString( rec, 5 );
+    if (file_key) setup_file = msi_find_file( package, file_key );
 
     if (!driver_file)
     {
@@ -5874,9 +5883,9 @@ static UINT ITERATE_InstallODBCTranslator( MSIRECORD *rec, LPVOID param )
     MSIPACKAGE *package = param;
     LPWSTR translator, translator_path, ptr;
     WCHAR outpath[MAX_PATH];
-    MSIFILE *translator_file, *setup_file;
+    MSIFILE *translator_file = NULL, *setup_file = NULL;
     MSIRECORD *uirow;
-    LPCWSTR desc;
+    LPCWSTR desc, file_key;
     DWORD len, usage;
     UINT r = ERROR_SUCCESS;
 
@@ -5887,8 +5896,11 @@ static UINT ITERATE_InstallODBCTranslator( MSIRECORD *rec, LPVOID param )
 
     desc = MSI_RecordGetString(rec, 3);
 
-    translator_file = msi_find_file(package, MSI_RecordGetString(rec, 4));
-    setup_file = msi_find_file(package, MSI_RecordGetString(rec, 5));
+    file_key = MSI_RecordGetString( rec, 4 );
+    if (file_key) translator_file = msi_find_file( package, file_key );
+
+    file_key = MSI_RecordGetString( rec, 5 );
+    if (file_key) setup_file = msi_find_file( package, file_key );
 
     if (!translator_file)
     {
@@ -6232,7 +6244,7 @@ static UINT env_parse_flags( LPCWSTR *name, LPCWSTR *value, DWORD *flags )
         else if (lstrlenW(*value) >= prefix_len)
         {
             ptr += lstrlenW(ptr) - prefix_len;
-            if (!lstrcmpW(ptr, prefix))
+            if (!strcmpW( ptr, prefix ))
             {
                 if ((ptr-1) > *value && *(ptr-1) == szSemiColon[0])
                 {
@@ -6403,7 +6415,7 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param )
         if (res != ERROR_SUCCESS)
             goto done;
 
-        if (flags & ENV_ACT_REMOVEMATCH && (!value || !lstrcmpW(data, value)))
+        if (flags & ENV_ACT_REMOVEMATCH && (!value || !strcmpW( data, value )))
         {
             action = 0x4;
             res = RegDeleteValueW(env, name);
@@ -6943,7 +6955,7 @@ static BOOL find_assembly(struct list *assemblies, LPCWSTR file, MSIASSEMBLY **o
 
     LIST_FOR_EACH_ENTRY(assembly, assemblies, MSIASSEMBLY, entry)
     {
-        if (!lstrcmpW(assembly->file->File, file))
+        if (!strcmpW( assembly->file->File, file ))
         {
             *out = assembly;
             return TRUE;
diff --git a/dlls/msi/appsearch.c b/dlls/msi/appsearch.c
index dfab396..28aac23 100644
--- a/dlls/msi/appsearch.c
+++ b/dlls/msi/appsearch.c
@@ -796,8 +796,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
         if (hFind != INVALID_HANDLE_VALUE)
         {
             if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
-                lstrcmpW(findData.cFileName, szDot) &&
-                lstrcmpW(findData.cFileName, szDotDot))
+                strcmpW( findData.cFileName, szDot ) &&
+                strcmpW( findData.cFileName, szDotDot ))
             {
                 lstrcpyW(subpath, dir);
                 PathAppendW(subpath, findData.cFileName);
@@ -808,8 +808,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
             while (rc == ERROR_SUCCESS && !*appValue &&
                    FindNextFileW(hFind, &findData) != 0)
             {
-                if (!lstrcmpW(findData.cFileName, szDot) ||
-                    !lstrcmpW(findData.cFileName, szDotDot))
+                if (!strcmpW( findData.cFileName, szDot ) ||
+                    !strcmpW( findData.cFileName, szDotDot ))
                     continue;
 
                 lstrcpyW(subpath, dir);
diff --git a/dlls/msi/classes.c b/dlls/msi/classes.c
index beaf1f0..9305e04 100644
--- a/dlls/msi/classes.c
+++ b/dlls/msi/classes.c
@@ -87,7 +87,7 @@ static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
     /* check for appids already loaded */
     LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
     {
-        if (lstrcmpiW( appid->AppID, name )==0)
+        if (!strcmpiW( appid->AppID, name ))
         {
             TRACE("found appid %s %p\n", debugstr_w(name), appid);
             return appid;
@@ -192,7 +192,7 @@ static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
     /* check for progids already loaded */
     LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
     {
-        if (strcmpiW( progid->ProgID,name )==0)
+        if (!strcmpiW( progid->ProgID, name ))
         {
             TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
             return progid;
@@ -323,7 +323,7 @@ static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
     /* check for classes already loaded */
     LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
     {
-        if (lstrcmpiW( cls->clsid, classid )==0)
+        if (!strcmpiW( cls->clsid, classid ))
         {
             TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
             return cls;
@@ -384,7 +384,7 @@ static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime )
     /* check for mime already loaded */
     LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
     {
-        if (strcmpiW(mt->ContentType,mime)==0)
+        if (!strcmpiW( mt->ContentType, mime ))
         {
             TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
             return mt;
@@ -458,7 +458,7 @@ static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name )
     /* check for extensions already loaded */
     LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
     {
-        if (strcmpiW( ext->Extension, name )==0)
+        if (!strcmpiW( ext->Extension, name ))
         {
             TRACE("extension %s already loaded %p\n", debugstr_w(name), ext);
             return ext;
@@ -578,7 +578,7 @@ static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
 
     LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
     {
-        if (strcmpiW(extension,ext->Extension))
+        if (strcmpiW(extension, ext->Extension))
             continue;
         if (comp == ext->Component)
         {
diff --git a/dlls/msi/cond.y b/dlls/msi/cond.y
index 03ea493..5bde044 100644
--- a/dlls/msi/cond.y
+++ b/dlls/msi/cond.y
@@ -456,26 +456,36 @@ static INT compare_substring( LPCWSTR a, INT operator, LPCWSTR b )
     switch (operator)
     {
     case COND_SS:
-        return strstrW( a, b ) ? 1 : 0;
+        return strstrW( a, b ) != 0;
     case COND_ISS:
-        return strstriW( a, b ) ? 1 : 0;
+        return strstriW( a, b ) != 0;
     case COND_LHS:
-    	return 0 == strncmpW( a, b, lstrlenW( b ) );
+    {
+        int l = strlenW( a );
+        int r = strlenW( b );
+        if (r > l) return 0;
+        return !strncmpW( a, b, r );
+    }
     case COND_RHS:
     {
-        int l = lstrlenW( a );
-        int r = lstrlenW( b );
+        int l = strlenW( a );
+        int r = strlenW( b );
         if (r > l) return 0;
-        return 0 == lstrcmpW( a + (l - r), b );
+        return !strncmpW( a + (l - r), b, r );
     }
     case COND_ILHS:
-    	return 0 == strncmpiW( a, b, lstrlenW( b ) );
+    {
+        int l = strlenW( a );
+        int r = strlenW( b );
+        if (r > l) return 0;
+        return !strncmpiW( a, b, r );
+    }
     case COND_IRHS:
     {
-        int l = lstrlenW( a );
-        int r = lstrlenW( b );
+        int l = strlenW( a );
+        int r = strlenW( b );
         if (r > l) return 0;
-        return 0 == lstrcmpiW( a + (l - r), b );
+        return !strncmpiW( a + (l - r), b, r );
     }
     default:
     	ERR("invalid substring operator\n");
@@ -500,29 +510,29 @@ static INT compare_string( LPCWSTR a, INT operator, LPCWSTR b, BOOL convert )
     switch (operator)
     {
     case COND_LT:
-        return -1 == lstrcmpW( a, b );
+        return strcmpW( a, b ) < 0;
     case COND_GT:
-        return  1 == lstrcmpW( a, b );
+        return strcmpW( a, b ) > 0;
     case COND_EQ:
-        return  0 == lstrcmpW( a, b );
+        return strcmpW( a, b ) == 0;
     case COND_NE:
-        return  0 != lstrcmpW( a, b );
+        return strcmpW( a, b ) != 0;
     case COND_GE:
-        return -1 != lstrcmpW( a, b );
+        return strcmpW( a, b ) >= 0;
     case COND_LE:
-        return  1 != lstrcmpW( a, b );
+        return strcmpW( a, b ) <= 0;
     case COND_ILT:
-        return -1 == lstrcmpiW( a, b );
+        return strcmpiW( a, b ) < 0;
     case COND_IGT:
-        return  1 == lstrcmpiW( a, b );
+        return strcmpiW( a, b ) > 0;
     case COND_IEQ:
-        return  0 == lstrcmpiW( a, b );
+        return strcmpiW( a, b ) == 0;
     case COND_INE:
-        return  0 != lstrcmpiW( a, b );
+        return strcmpiW( a, b ) != 0;
     case COND_IGE:
-        return -1 != lstrcmpiW( a, b );
+        return strcmpiW( a, b ) >= 0;
     case COND_ILE:
-        return  1 != lstrcmpiW( a, b );
+        return strcmpiW( a, b ) <= 0;
     default:
         ERR("invalid string operator\n");
         return 0;
diff --git a/dlls/msi/create.c b/dlls/msi/create.c
index 2e13d59..c55390c 100644
--- a/dlls/msi/create.c
+++ b/dlls/msi/create.c
@@ -24,6 +24,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 #include "msi.h"
 #include "msiquery.h"
 #include "objbase.h"
@@ -153,7 +154,7 @@ static UINT check_columns( const column_info *col_info )
     /* check for two columns with the same name */
     for( c1 = col_info; c1; c1 = c1->next )
         for( c2 = c1->next; c2; c2 = c2->next )
-            if (!lstrcmpW(c1->column, c2->column))
+            if (!strcmpW( c1->column, c2->column ))
                 return ERROR_BAD_QUERY_SYNTAX;
 
     return ERROR_SUCCESS;
diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c
index b56139f..8c080c9 100644
--- a/dlls/msi/custom.c
+++ b/dlls/msi/custom.c
@@ -594,7 +594,7 @@ static void handle_msi_break( LPCWSTR target )
     if( !GetEnvironmentVariableW( MsiBreak, val, MAX_PATH ))
         return;
 
-    if( lstrcmpiW( val, target ))
+    if( strcmpiW( val, target ))
         return;
 
     msg = msi_alloc( (lstrlenW(format) + 10) * sizeof(WCHAR) );
diff --git a/dlls/msi/database.c b/dlls/msi/database.c
index 3007d48..2bf70c0 100644
--- a/dlls/msi/database.c
+++ b/dlls/msi/database.c
@@ -79,7 +79,7 @@ static UINT find_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm )
             continue;
         }
 
-        if( !lstrcmpW( name, stat.pwcsName ) )
+        if( !strcmpW( name, stat.pwcsName ) )
         {
             TRACE("found %s\n", debugstr_w(name));
             *stm = stream->stm;
@@ -1136,7 +1136,7 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
     if (handle == INVALID_HANDLE_VALUE)
         return ERROR_FUNCTION_FAILED;
 
-    if (!lstrcmpW( table, forcecodepage ))
+    if (!strcmpW( table, forcecodepage ))
     {
         r = msi_export_forcecodepage( handle );
         goto done;
@@ -1319,7 +1319,7 @@ static BOOL merge_type_match(LPCWSTR type1, LPCWSTR type2)
         ((type2[0] == 'L') || (type2[0] == 'S')))
         return TRUE;
 
-    return !lstrcmpW(type1, type2);
+    return !strcmpW( type1, type2 );
 }
 
 static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
@@ -1341,8 +1341,7 @@ static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
         if (!MSI_RecordGetString(mergerec, i))
             break;
 
-        if (lstrcmpW(MSI_RecordGetString(dbrec, i),
-                     MSI_RecordGetString(mergerec, i)))
+        if (strcmpW( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
         {
             r = ERROR_DATATYPE_MISMATCH;
             goto done;
@@ -1405,8 +1404,7 @@ static UINT merge_verify_primary_keys(MSIDATABASE *db, MSIDATABASE *mergedb,
 
     for (i = 1; i <= count; i++)
     {
-        if (lstrcmpW(MSI_RecordGetString(dbrec, i),
-                     MSI_RecordGetString(mergerec, i)))
+        if (strcmpW( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
         {
             r = ERROR_DATATYPE_MISMATCH;
             goto done;
@@ -1434,7 +1432,7 @@ static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
     do
     {
         str = msi_dup_record_field(colnames, ++i);
-        cmp = lstrcmpW(key, str);
+        cmp = strcmpW( key, str );
         msi_free(str);
     } while (cmp);
 
diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c
index e0e27d1..32ca97b 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -578,7 +578,7 @@ static void msi_dialog_update_controls( msi_dialog *dialog, LPCWSTR property )
 
     LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
     {
-        if ( !lstrcmpW( control->property, property ) && control->update )
+        if ( control->property && !strcmpW( control->property, property ) && control->update )
             control->update( dialog, control );
     }
 }
@@ -601,7 +601,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
     ctrl = msi_dialog_find_control( dialog, control );
     if (!ctrl)
         return;
-    if( !lstrcmpW(attribute, szText) )
+    if( !strcmpW( attribute, szText ) )
     {
         font_text = MSI_RecordGetString( rec , 1 );
         font = msi_dialog_get_style( font_text, &text );
@@ -610,7 +610,7 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
         msi_free( font );
         msi_dialog_check_messages( NULL );
     }
-    else if( !lstrcmpW(attribute, szProgress) )
+    else if( !strcmpW( attribute, szProgress ) )
     {
         DWORD func, val;
 
@@ -640,12 +640,12 @@ void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
             break;
         }
     }
-    else if ( !lstrcmpW(attribute, szProperty) )
+    else if ( !strcmpW( attribute, szProperty ) )
     {
         MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
         msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory );
     }
-    else if ( !lstrcmpW(attribute, szSelectionPath) )
+    else if ( !strcmpW( attribute, szSelectionPath ) )
     {
         LPWSTR prop = msi_dialog_dup_property( dialog, ctrl->property, TRUE );
         LPWSTR path;
@@ -1368,7 +1368,7 @@ static void msi_dialog_combobox_update( msi_dialog *dialog,
     for (j = 0; j < info->num_items; j++)
     {
         tmp = (LPWSTR) SendMessageW( control->hwnd, CB_GETITEMDATA, j, 0 );
-        if (!lstrcmpW( value, tmp ))
+        if (!strcmpW( value, tmp ))
             break;
     }
 
@@ -1988,7 +1988,7 @@ static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param )
         return ERROR_FUNCTION_FAILED;
     control->handler = msi_dialog_radiogroup_handler;
 
-    if (!lstrcmpW(control->name, group->propval))
+    if (!strcmpW( control->name, group->propval ))
         SendMessageW(control->hwnd, BM_SETCHECK, BST_CHECKED, 0);
 
     prop = MSI_RecordGetString( rec, 1 );
@@ -2258,7 +2258,7 @@ msi_seltree_add_child_features( MSIPACKAGE *package, HWND hwnd,
 
     LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        if ( lstrcmpW( parent, feature->Feature_Parent ) )
+        if ( strcmpW( parent, feature->Feature_Parent ) )
             continue;
 
         if ( !feature->Title )
@@ -2682,7 +2682,7 @@ static void msi_dialog_update_directory_list( msi_dialog *dialog, msi_control *c
         if ( wfd.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY )
             continue;
 
-        if ( !lstrcmpW( wfd.cFileName, szDot ) || !lstrcmpW( wfd.cFileName, szDotDot ) )
+        if ( !strcmpW( wfd.cFileName, szDot ) || !strcmpW( wfd.cFileName, szDotDot ) )
             continue;
 
         item.mask = LVIF_TEXT;
@@ -2846,7 +2846,7 @@ static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control
         begin += end - begin + 1;
 
         /* empty braces or '0' hides the column */ 
-        if ( !num[0] || !lstrcmpW( num, szZero ) )
+        if ( !num[0] || !strcmpW( num, szZero ) )
         {
             count++;
             msi_free( num );
@@ -3151,15 +3151,15 @@ static UINT msi_dialog_set_control_condition( MSIRECORD *rec, LPVOID param )
         TRACE("%s control %s\n", debugstr_w(action), debugstr_w(name));
 
         /* FIXME: case sensitive? */
-        if(!lstrcmpW(action, szHide))
+        if (!strcmpW( action, szHide ))
             ShowWindow(control->hwnd, SW_HIDE);
-        else if(!strcmpW(action, szShow))
+        else if (!strcmpW( action, szShow ))
             ShowWindow(control->hwnd, SW_SHOW);
-        else if(!strcmpW(action, szDisable))
+        else if (!strcmpW( action, szDisable ))
             EnableWindow(control->hwnd, FALSE);
-        else if(!strcmpW(action, szEnable))
+        else if (!strcmpW( action, szEnable ))
             EnableWindow(control->hwnd, TRUE);
-        else if(!strcmpW(action, szDefault))
+        else if (!strcmpW( action, szDefault ))
             SetFocus(control->hwnd);
         else
             FIXME("Unhandled action %s\n", debugstr_w(action));
@@ -4022,11 +4022,11 @@ static UINT error_dialog_handler(MSIPACKAGE *package, LPCWSTR event,
         'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
     };
 
-    if ( lstrcmpW( event, end_dialog ) )
+    if ( strcmpW( event, end_dialog ) )
         return ERROR_SUCCESS;
 
-    if ( !lstrcmpW( argument, error_abort ) || !lstrcmpW( argument, error_cancel ) ||
-         !lstrcmpW( argument, error_no ) )
+    if ( !strcmpW( argument, error_abort ) || !strcmpW( argument, error_cancel ) ||
+         !strcmpW( argument, error_no ) )
     {
          msi_set_property( package->db, result_prop, error_abort );
     }
@@ -4108,7 +4108,7 @@ UINT msi_spawn_error_dialog( MSIPACKAGE *package, LPWSTR error_dialog, LPWSTR er
     if ( r != ERROR_SUCCESS)
         r = ERROR_SUCCESS;
 
-    if ( !lstrcmpW( result, error_abort ) )
+    if ( !strcmpW( result, error_abort ) )
         r = ERROR_FUNCTION_FAILED;
 
 done:
diff --git a/dlls/msi/events.c b/dlls/msi/events.c
index 157d185..96fc677 100644
--- a/dlls/msi/events.c
+++ b/dlls/msi/events.c
@@ -90,22 +90,18 @@ static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, msi_dialog *pare
 static UINT ControlEvent_EndDialog(MSIPACKAGE* package, LPCWSTR argument, 
                                    msi_dialog* dialog)
 {
-    static const WCHAR szExit[] = {
-    'E','x','i','t',0};
-    static const WCHAR szRetry[] = {
-    'R','e','t','r','y',0};
-    static const WCHAR szIgnore[] = {
-    'I','g','n','o','r','e',0};
-    static const WCHAR szReturn[] = {
-    'R','e','t','u','r','n',0};
-
-    if (lstrcmpW(argument,szExit)==0)
+    static const WCHAR szExit[] = {'E','x','i','t',0};
+    static const WCHAR szRetry[] = {'R','e','t','r','y',0};
+    static const WCHAR szIgnore[] = {'I','g','n','o','r','e',0};
+    static const WCHAR szReturn[] = {'R','e','t','u','r','n',0};
+
+    if (!strcmpW( argument, szExit ))
         package->CurrentInstallState = ERROR_INSTALL_USEREXIT;
-    else if (lstrcmpW(argument, szRetry) == 0)
+    else if (!strcmpW( argument, szRetry ))
         package->CurrentInstallState = ERROR_INSTALL_SUSPEND;
-    else if (lstrcmpW(argument, szIgnore) == 0)
+    else if (!strcmpW( argument, szIgnore ))
         package->CurrentInstallState = ERROR_SUCCESS;
-    else if (lstrcmpW(argument, szReturn) == 0)
+    else if (!strcmpW( argument, szReturn ))
     {
         msi_dialog *parent = msi_dialog_get_parent(dialog);
         msi_free(package->next_dialog);
@@ -172,7 +168,7 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
 {
     MSIFEATURE *feature = NULL;
 
-    if (lstrcmpW(szAll,argument))
+    if (strcmpW( szAll, argument ))
     {
         MSI_SetFeatureStateW(package,argument,INSTALLSTATE_LOCAL);
     }
@@ -191,7 +187,7 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
 {
     MSIFEATURE *feature = NULL;
 
-    if (lstrcmpW(szAll,argument))
+    if (strcmpW( szAll, argument ))
     {
         MSI_SetFeatureStateW(package,argument,INSTALLSTATE_ABSENT);
     }
@@ -210,7 +206,7 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
 {
     MSIFEATURE *feature = NULL;
 
-    if (lstrcmpW(szAll,argument))
+    if (strcmpW( szAll, argument ))
     {
         MSI_SetFeatureStateW(package,argument,INSTALLSTATE_SOURCE);
     }
@@ -284,10 +280,9 @@ VOID ControlEvent_FireSubscribedEvent( MSIPACKAGE *package, LPCWSTR event,
 
     LIST_FOR_EACH_ENTRY( sub, &package->subscriptions, struct subscriber, entry )
     {
-        if (lstrcmpiW(sub->event, event))
+        if (strcmpiW( sub->event, event ))
             continue;
-        msi_dialog_handle_event( sub->dialog, sub->control,
-                                 sub->attribute, rec );
+        msi_dialog_handle_event( sub->dialog, sub->control, sub->attribute, rec );
     }
 }
 
@@ -300,7 +295,7 @@ VOID ControlEvent_CleanupDialogSubscriptions(MSIPACKAGE *package, LPWSTR dialog)
     {
         sub = LIST_ENTRY( i, struct subscriber, entry );
 
-        if ( lstrcmpW( msi_dialog_get_name( sub->dialog ), dialog ))
+        if (strcmpW( msi_dialog_get_name( sub->dialog ), dialog ))
             continue;
 
         list_remove( &sub->entry );
@@ -441,7 +436,7 @@ UINT ControlEvent_HandleControlEvent(MSIPACKAGE *package, LPCWSTR event,
     while( Events[i].event != NULL)
     {
         LPWSTR wevent = strdupAtoW(Events[i].event);
-        if (lstrcmpW(wevent,event)==0)
+        if (!strcmpW( wevent, event ))
         {
             msi_free(wevent);
             rc = Events[i].handler(package,argument,dialog);
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index 0ed9582..68714f9 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -406,7 +406,7 @@ static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
 
     LIST_FOR_EACH_ENTRY(file, &files->entry, FILE_LIST, entry)
     {
-        if (lstrcmpW(source, file->source) < 0)
+        if (strcmpW( source, file->source ) < 0)
         {
             list_add_before(&file->entry, &new->entry);
             return TRUE;
diff --git a/dlls/msi/helpers.c b/dlls/msi/helpers.c
index d3f2d90..f6f458f 100644
--- a/dlls/msi/helpers.c
+++ b/dlls/msi/helpers.c
@@ -104,7 +104,7 @@ MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
 
     LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
     {
-        if (lstrcmpW(Component,comp->Component)==0)
+        if (!strcmpW( Component, comp->Component ))
             return comp;
     }
     return NULL;
@@ -116,7 +116,7 @@ MSIFEATURE* get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
 
     LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
-        if (lstrcmpW( Feature, feature->Feature )==0)
+        if (!strcmpW( Feature, feature->Feature ))
             return feature;
     }
     return NULL;
@@ -128,7 +128,7 @@ MSIFILE* get_loaded_file( MSIPACKAGE* package, LPCWSTR key )
 
     LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
     {
-        if (lstrcmpW( key, file->File )==0)
+        if (!strcmpW( key, file->File ))
             return file;
     }
     return NULL;
@@ -141,7 +141,7 @@ int track_tempfile( MSIPACKAGE *package, LPCWSTR path )
     TRACE("%s\n", debugstr_w(path));
 
     LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
-        if (!lstrcmpW( path, temp->Path ))
+        if (!strcmpW( path, temp->Path ))
             return 0;
 
     temp = msi_alloc_zero( sizeof (MSITEMPFILE) );
@@ -160,7 +160,7 @@ MSIFOLDER *get_loaded_folder( MSIPACKAGE *package, LPCWSTR dir )
 
     LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
     {
-        if (lstrcmpW( dir, folder->Directory )==0)
+        if (!strcmpW( dir, folder->Directory ))
             return folder;
     }
     return NULL;
@@ -262,7 +262,7 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
     if (!name)
         return NULL;
 
-    if (!lstrcmpW(name,cszSourceDir))
+    if (!strcmpW( name, cszSourceDir ))
         name = cszTargetDir;
 
     f = get_loaded_folder( package, name );
@@ -270,7 +270,7 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
         return NULL;
 
     /* special resolving for Target and Source root dir */
-    if (!strcmpW(name,cszTargetDir))
+    if (!strcmpW( name, cszTargetDir ))
     {
         if (!f->ResolvedTarget && !f->Property)
         {
@@ -286,7 +286,7 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
             /* correct misbuilt target dir */
             path = build_directory_name(2, check_path, NULL);
             clean_spaces_from_path( path );
-            if (strcmpiW(path,check_path)!=0)
+            if (strcmpiW( path, check_path ))
                 msi_set_property( package->db, cszTargetDir, path );
             msi_free(check_path);
 
@@ -561,7 +561,7 @@ void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
     MSIRECORD * row = 0;
     DWORD size;
 
-    if (!package->LastAction || strcmpW(package->LastAction,action))
+    if (!package->LastAction || strcmpW(package->LastAction, action))
     {
         row = MSI_QueryGetRecord(package->db, Query_t, action);
         if (!row)
@@ -747,7 +747,7 @@ BOOL check_unique_action(const MSIPACKAGE *package, LPCWSTR action)
         return FALSE;
 
     for (i = 0; i < package->script->UniqueActionsCount; i++)
-        if (!strcmpW(package->script->UniqueActions[i],action))
+        if (!strcmpW(package->script->UniqueActions[i], action))
             return TRUE;
 
     return FALSE;
diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c
index 61807e9..03e1bd9 100644
--- a/dlls/msi/insert.c
+++ b/dlls/msi/insert.c
@@ -24,6 +24,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 #include "msi.h"
 #include "msiquery.h"
 #include "objbase.h"
@@ -117,7 +118,7 @@ static BOOL msi_columns_in_order(MSIINSERTVIEW *iv, UINT col_count)
         iv->sv->ops->get_column_info(iv->sv, i, &a, NULL, NULL, NULL);
         iv->table->ops->get_column_info(iv->table, i, &b, NULL, NULL, NULL);
 
-        res = lstrcmpW(a, b);
+        res = strcmpW( a, b );
         msi_free(a);
         msi_free(b);
 
@@ -168,7 +169,7 @@ static UINT msi_arrange_record(MSIINSERTVIEW *iv, MSIRECORD **values)
             if (r != ERROR_SUCCESS)
                 goto err;
 
-            res = lstrcmpW(a, b);
+            res = strcmpW( a, b );
             msi_free(b);
 
             if (res == 0)
diff --git a/dlls/msi/install.c b/dlls/msi/install.c
index fa3e4f9..730e27e 100644
--- a/dlls/msi/install.c
+++ b/dlls/msi/install.c
@@ -519,7 +519,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
     msi_free(folder->Property);
     folder->Property = build_directory_name(2, szFolderPath, NULL);
 
-    if (lstrcmpiW(path, folder->Property) == 0)
+    if (!strcmpiW( path, folder->Property ))
     {
         /*
          *  Resolved Target has not really changed, so just 
@@ -828,7 +828,7 @@ UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
     /* update all the features that are children of this feature */
     LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
     {
-        if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
+        if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
             MSI_SetFeatureStateW(package, child->Feature, iState);
     }
     
diff --git a/dlls/msi/media.c b/dlls/msi/media.c
index 788528e..8b5a8c6 100644
--- a/dlls/msi/media.c
+++ b/dlls/msi/media.c
@@ -68,7 +68,7 @@ static BOOL source_matches_volume(MSIMEDIAINFO *mi, LPCWSTR source_root)
         return FALSE;
     }
 
-    return !lstrcmpW(mi->volume_label, volume_name);
+    return !strcmpW( mi->volume_label, volume_name );
 }
 
 static UINT msi_change_media(MSIPACKAGE *package, MSIMEDIAINFO *mi)
@@ -331,7 +331,7 @@ static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint,
         goto done;
     }
 
-    if (lstrcmpiW(mi->cabinet, cab))
+    if (strcmpiW( mi->cabinet, cab ))
     {
         ERR("Continuous cabinet does not match the next cabinet in the Media table\n");
         goto done;
@@ -841,7 +841,7 @@ UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
 
     /* check volume matches, change media if not */
     if (mi->volume_label && mi->disk_id > 1 &&
-        lstrcmpW(mi->first_volume, mi->volume_label))
+        strcmpW( mi->first_volume, mi->volume_label ))
     {
         LPWSTR source = msi_dup_property(package->db, cszSourceDir);
         BOOL matches;
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index 7d1b9a5..29c639c 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -983,22 +983,22 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
 
     MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
 
-    if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
-        !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
+    if (!strcmpW( szAttribute, INSTALLPROPERTY_HELPLINKW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_PUBLISHERW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) ||
+        !strcmpW( szAttribute, INSTALLPROPERTY_REGOWNERW ))
     {
         if (!prodkey)
         {
@@ -1009,25 +1009,25 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
         if (!userdata)
             return ERROR_UNKNOWN_PROPERTY;
 
-        if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
+        if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
             szAttribute = display_name;
-        else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
+        else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
             szAttribute = display_version;
 
         val = msi_reg_get_value(userdata, szAttribute, &type);
         if (!val)
             val = empty;
     }
-    else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
-             !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
+    else if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_LANGUAGEW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) ||
+             !strcmpW( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
     {
         if (!prodkey)
         {
@@ -1035,10 +1035,10 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
             goto done;
         }
 
-        if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
+        if (!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
             szAttribute = assignment;
 
-        if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
+        if (!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ))
         {
             res = RegOpenKeyW(prodkey, sourcelist, &source);
             if (res != ERROR_SUCCESS)
@@ -1061,7 +1061,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
         }
 
         if (val != empty && type != REG_DWORD &&
-            !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
+            !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ))
         {
             if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
                 badconfig = TRUE;
@@ -1324,23 +1324,23 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
             goto done;
     }
 
-    if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
+    if (!strcmpW( szProperty, INSTALLPROPERTY_HELPLINKW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_PUBLISHERW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_VERSIONMINORW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTIDW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_REGCOMPANYW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
     {
         val = msi_reg_get_value(props, package, &type);
         if (!val)
@@ -1353,9 +1353,9 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
 
         msi_free(val);
 
-        if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
+        if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
             szProperty = displayname;
-        else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
+        else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
             szProperty = displayversion;
 
         val = msi_reg_get_value(props, szProperty, &type);
@@ -1364,14 +1364,14 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
 
         r = msi_copy_outval(val, szValue, pcchValue);
     }
-    else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_LANGUAGEW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_PACKAGECODEW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_VERSIONW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTICONW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
     {
         if (!prod && !classes)
             goto done;
@@ -1389,7 +1389,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
 
         r = msi_copy_outval(val, szValue, pcchValue);
     }
-    else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTSTATEW ))
     {
         if (dwContext == MSIINSTALLCONTEXT_MACHINE)
         {
@@ -1423,7 +1423,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
 
         r = msi_copy_outval(val, szValue, pcchValue);
     }
-    else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
     {
         if (!prod && !classes)
             goto done;
@@ -1554,7 +1554,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
     if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
         return ERROR_INVALID_PARAMETER;
 
-    if (!lstrcmpW(szUserSid, szLocalSid))
+    if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
         return ERROR_INVALID_PARAMETER;
 
     if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
@@ -1575,7 +1575,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
     if (res != ERROR_SUCCESS)
         goto done;
 
-    if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
+    if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ))
     {
         if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
                                   &prod, FALSE) != ERROR_SUCCESS)
@@ -1594,25 +1594,25 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
                                         &udpatch, FALSE) != ERROR_SUCCESS)
             goto done;
 
-        if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
+        if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
         {
             if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
                 szProperty = szManagedPackage;
             datakey = udpatch;
         }
-        else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
+        else if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ))
         {
             datakey = patch;
             szProperty = szInstalled;
         }
-        else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
+        else if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
         {
             datakey = udpatch;
         }
-        else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
-                 !lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
-                 !lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
-                 !lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
+        else if (!strcmpW( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
+                 !strcmpW( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
+                 !strcmpW( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) ||
+                 !strcmpW( szProperty, INSTALLPROPERTY_MOREINFOURLW ))
         {
             datakey = patch;
         }
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 0361ff4..6f0b551 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -1151,6 +1151,8 @@ static const WCHAR szIntel64[] = {'I','n','t','e','l','6','4',0};
 static const WCHAR szX64[] = {'x','6','4',0};
 static const WCHAR szWow6432NodeCLSID[] = {'W','o','w','6','4','3','2','N','o','d','e','\\','C','L','S','I','D',0};
 static const WCHAR szWow6432Node[] = {'W','o','w','6','4','3','2','N','o','d','e',0};
+static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
+static const WCHAR szStorages[] = {'_','S','t','o','r','a','g','e','s',0};
 
 /* memory allocation macro functions */
 static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c
index cf69593..4ccf5f6 100644
--- a/dlls/msi/msiquery.c
+++ b/dlls/msi/msiquery.c
@@ -75,9 +75,9 @@ UINT VIEW_find_column( MSIVIEW *table, LPCWSTR name, LPCWSTR table_name, UINT *n
                                          NULL, &haystack_table_name );
         if( r != ERROR_SUCCESS )
             return r;
-        x = lstrcmpW( name, col_name );
+        x = strcmpW( name, col_name );
         if( table_name )
-            x |= lstrcmpW( table_name, haystack_table_name );
+            x |= strcmpW( table_name, haystack_table_name );
         msi_free( col_name );
         msi_free( haystack_table_name );
         if( !x )
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 32576a0..ac11e69 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -511,7 +511,7 @@ static LPWSTR get_fusion_filename(MSIPACKAGE *package)
         index++;
 
         /* verify existence of fusion.dll .Net 3.0 does not install a new one */
-        if (lstrcmpW(ver, name) < 0)
+        if (strcmpW( ver, name ) < 0)
         {
             LPWSTR check;
             size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
diff --git a/dlls/msi/record.c b/dlls/msi/record.c
index 7bc8281..fc30f79 100644
--- a/dlls/msi/record.c
+++ b/dlls/msi/record.c
@@ -27,6 +27,7 @@
 #include "winuser.h"
 #include "winerror.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 #include "msi.h"
 #include "msiquery.h"
 #include "msipriv.h"
@@ -1016,7 +1017,7 @@ BOOL MSI_RecordsAreEqual(MSIRECORD *a, MSIRECORD *b)
                 break;
 
             case MSIFIELD_WSTR:
-                if (lstrcmpW(a->fields[i].u.szwVal, b->fields[i].u.szwVal))
+                if (strcmpW(a->fields[i].u.szwVal, b->fields[i].u.szwVal))
                     return FALSE;
                 break;
 
diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c
index e83490f..0a063e4 100644
--- a/dlls/msi/registry.c
+++ b/dlls/msi/registry.c
@@ -2140,7 +2140,7 @@ UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
     if (!szProductCode || !squash_guid(szProductCode, squished_pc))
         return ERROR_INVALID_PARAMETER;
 
-    if (!lstrcmpW(szUserSid, szLocalSid))
+    if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
         return ERROR_INVALID_PARAMETER;
 
     if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
diff --git a/dlls/msi/source.c b/dlls/msi/source.c
index 8e4323a..602f03f 100644
--- a/dlls/msi/source.c
+++ b/dlls/msi/source.c
@@ -592,8 +592,8 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
     if (rc != ERROR_SUCCESS)
         return rc;
 
-    if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
+    if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
     {
         rc = OpenMediaSubkey(sourcekey, &media, FALSE);
         if (rc != ERROR_SUCCESS)
@@ -602,14 +602,14 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
             return ERROR_SUCCESS;
         }
 
-        if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
+        if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
             szProperty = mediapack;
 
         RegQueryValueExW(media, szProperty, 0, 0, (LPBYTE)szValue, pcchValue);
         RegCloseKey(media);
     }
-    else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) ||
-             !lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDTYPEW))
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) ||
+             !strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
     {
         rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
                               0, 0, NULL, &size);
@@ -630,7 +630,7 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
             return ERROR_SUCCESS;
         }
 
-        if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDTYPEW))
+        if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
         {
             if (*source != 'n' && *source != 'u' && *source != 'm')
             {
@@ -662,7 +662,7 @@ UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
         *pcchValue = lstrlenW(ptr);
         msi_free(source);
     }
-    else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
     {
         *pcchValue = *pcchValue * sizeof(WCHAR);
         rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
@@ -815,22 +815,22 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
     }
 
     property = szProperty;
-    if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
+    if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
         property = media_package;
 
     rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
     if (rc != ERROR_SUCCESS)
         return rc;
 
-    if (lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) &&
+    if (strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) &&
         dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL))
     {
         RegCloseKey(sourcekey);
         return ERROR_INVALID_PARAMETER;
     }
 
-    if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
-        !lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
+    if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
+        !strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
     {
         rc = OpenMediaSubkey(sourcekey, &media, TRUE);
         if (rc == ERROR_SUCCESS)
@@ -839,7 +839,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
             RegCloseKey(media);
         }
     }
-    else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
     {
         DWORD size = (lstrlenW(szValue) + 1) * sizeof(WCHAR);
         rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
@@ -847,7 +847,7 @@ UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
         if (rc != ERROR_SUCCESS)
             rc = ERROR_UNKNOWN_PROPERTY;
     }
-    else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW))
+    else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ))
     {
         if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
             rc = ERROR_INVALID_PARAMETER;
diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y
index 548a878..0121737 100644
--- a/dlls/msi/sql.y
+++ b/dlls/msi/sql.y
@@ -950,7 +950,7 @@ static BOOL SQL_MarkPrimaryKeys( column_info **cols,
         found = FALSE;
         for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
         {
-            if( lstrcmpW( k->column, c->column ) )
+            if( strcmpW( k->column, c->column ) )
                 continue;
             c->type |= MSITYPE_KEY;
             found = TRUE;
diff --git a/dlls/msi/string.c b/dlls/msi/string.c
index 5644749..0c35fa4 100644
--- a/dlls/msi/string.c
+++ b/dlls/msi/string.c
@@ -162,7 +162,7 @@ static int find_insert_index( const string_table *st, UINT string_id )
     while (low <= high)
     {
         i = (low + high) / 2;
-        c = lstrcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str );
+        c = strcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str );
 
         if (c < 0)
             high = i - 1;
@@ -402,7 +402,7 @@ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
     while (low <= high)
     {
         i = (low + high) / 2;
-        c = lstrcmpW( str, st->strings[st->sorted[i]].str );
+        c = strcmpW( str, st->strings[st->sorted[i]].str );
 
         if (c < 0)
             high = i - 1;
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 3e456ed..90bcb1f 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -512,7 +512,7 @@ static MSITABLE *find_cached_table( MSIDATABASE *db, LPCWSTR name )
     MSITABLE *t;
 
     LIST_FOR_EACH_ENTRY( t, &db->tables, MSITABLE, entry )
-        if( !lstrcmpW( name, t->name ) )
+        if( !strcmpW( name, t->name ) )
             return t;
 
     return NULL;
@@ -731,7 +731,7 @@ static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
     table->persistent = MSICONDITION_TRUE;
     lstrcpyW( table->name, name );
 
-    if ( !lstrcmpW(name, szTables) || !lstrcmpW(name, szColumns) )
+    if ( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) )
         table->persistent = MSICONDITION_NONE;
 
     r = table_get_column_info( db, name, &table->colinfo, &table->col_count);
@@ -864,12 +864,12 @@ static UINT get_defaulttablecolumns( MSIDATABASE *db, LPCWSTR name,
 
     TRACE("%s\n", debugstr_w(name));
 
-    if (!lstrcmpW( name, szTables ))
+    if (!strcmpW( name, szTables ))
     {
         p = _Tables_cols;
         n = 1;
     }
-    else if (!lstrcmpW( name, szColumns ))
+    else if (!strcmpW( name, szColumns ))
     {
         p = _Columns_cols;
         n = 4;
@@ -1037,11 +1037,8 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
     UINT r, table_id, i;
     MSITABLE *table;
 
-    static const WCHAR szStreams[] = {'_','S','t','r','e','a','m','s',0};
-    static const WCHAR szStorages[] = {'_','S','t','o','r','a','g','e','s',0};
-
-    if( !lstrcmpW( name, szTables ) || !lstrcmpW( name, szColumns ) ||
-        !lstrcmpW( name, szStreams ) || !lstrcmpW( name, szStorages ) )
+    if( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) ||
+        !strcmpW( name, szStreams ) || !strcmpW( name, szStorages ) )
         return TRUE;
 
     r = msi_string2idW( db->strings, name, &table_id );
@@ -1346,10 +1343,13 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
     else if ( columninfo.type & MSITYPE_STRING )
     {
         LPCWSTR sval = MSI_RecordGetString( rec, iField );
-
-        r = msi_string2idW(tv->db->strings, sval, pvalue);
-        if (r != ERROR_SUCCESS)
-           return ERROR_NOT_FOUND;
+        if (sval)
+        {
+            r = msi_string2idW(tv->db->strings, sval, pvalue);
+            if (r != ERROR_SUCCESS)
+                return ERROR_NOT_FOUND;
+        }
+        else *pvalue = 0;
     }
     else if ( bytes_per_column( tv->db, &columninfo, LONG_STR_BYTES ) == 2 )
     {
@@ -1432,7 +1432,6 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
                     LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
                     val = msi_addstringW( tv->db->strings, sval, -1, 1,
                       persistent ? StringPersistent : StringNonPersistent );
-
                 }
                 else
                 {
@@ -2099,7 +2098,7 @@ static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number
     msitable = find_cached_table(tv->db, table);
     for (i = 0; i < msitable->col_count; i++)
     {
-        if (!lstrcmpW(msitable->colinfo[i].colname, column))
+        if (!strcmpW( msitable->colinfo[i].colname, column ))
         {
             InterlockedIncrement(&msitable->colinfo[i].ref_count);
             break;
@@ -2340,14 +2339,11 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
     MSITABLEVIEW *tv ;
     UINT r, sz;
 
-    static const WCHAR Streams[] = {'_','S','t','r','e','a','m','s',0};
-    static const WCHAR Storages[] = {'_','S','t','o','r','a','g','e','s',0};
-
     TRACE("%p %s %p\n", db, debugstr_w(name), view );
 
-    if ( !lstrcmpW( name, Streams ) )
+    if ( !strcmpW( name, szStreams ) )
         return STREAMS_CreateView( db, view );
-    else if ( !lstrcmpW( name, Storages ) )
+    else if ( !strcmpW( name, szStorages ) )
         return STORAGES_CreateView( db, view );
 
     sz = sizeof *tv + lstrlenW(name)*sizeof name[0] ;
@@ -2634,15 +2630,19 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
              ! MSITYPE_IS_BINARY(tv->columns[i].type) )
         {
             str = MSI_RecordGetString( rec, i+1 );
-            r = msi_string2idW( tv->db->strings, str, &data[i] );
-
-            /* if there's no matching string in the string table,
-               these keys can't match any record, so fail now. */
-            if( ERROR_SUCCESS != r )
+            if (str)
             {
-                msi_free( data );
-                return NULL;
+                r = msi_string2idW( tv->db->strings, str, &data[i] );
+
+                /* if there's no matching string in the string table,
+                   these keys can't match any record, so fail now. */
+                if (r != ERROR_SUCCESS)
+                {
+                    msi_free( data );
+                    return NULL;
+                }
             }
+            else data[i] = 0;
         }
         else
         {
@@ -2818,7 +2818,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
             UINT number = MSI_NULL_INTEGER;
             UINT row = 0;
 
-            if (!lstrcmpW( name, szColumns ))
+            if (!strcmpW( name, szColumns ))
             {
                 MSI_RecordGetStringW( rec, 1, table, &sz );
                 number = MSI_RecordGetInteger( rec, 2 );
@@ -2830,7 +2830,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
                 if ( number == MSI_NULL_INTEGER )
                 {
                     /* reset the column number on a new table */
-                    if (lstrcmpW( coltable, table ))
+                    if (strcmpW( coltable, table ))
                     {
                         colcol = 0;
                         lstrcpyW( coltable, table );
@@ -2876,7 +2876,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
                     WARN("failed to insert row %u\n", r);
             }
 
-            if (number != MSI_NULL_INTEGER && !lstrcmpW( name, szColumns ))
+            if (number != MSI_NULL_INTEGER && !strcmpW( name, szColumns ))
                 msi_update_table_columns( db, table );
 
             msiobj_release( &rec->hdr );
@@ -2938,8 +2938,8 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
         if ( name[0] != 0x4840 )
             continue;
 
-        if ( !lstrcmpW( name+1, szStringPool ) ||
-             !lstrcmpW( name+1, szStringData ) )
+        if ( !strcmpW( name+1, szStringPool ) ||
+             !strcmpW( name+1, szStringData ) )
             continue;
 
         transform = msi_alloc_zero( sizeof(TRANSFORMDATA) );
@@ -2950,9 +2950,9 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
 
         transform->name = strdupW( name + 1 );
 
-        if ( !lstrcmpW( transform->name, szTables ) )
+        if ( !strcmpW( transform->name, szTables ) )
             tables = transform;
-        else if (!lstrcmpW( transform->name, szColumns ) )
+        else if (!strcmpW( transform->name, szColumns ) )
             columns = transform;
 
         TRACE("transform contains stream %s\n", debugstr_w(name));
@@ -2990,8 +2990,8 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
     {
         transform = LIST_ENTRY( list_head( &transforms ), TRANSFORMDATA, entry );
 
-        if ( lstrcmpW( transform->name, szColumns ) &&
-             lstrcmpW( transform->name, szTables ) &&
+        if ( strcmpW( transform->name, szColumns ) &&
+             strcmpW( transform->name, szTables ) &&
              ret == ERROR_SUCCESS )
         {
             ret = msi_table_load_transform( db, stg, strings, transform, bytes_per_strref );
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c
index 66c6312..4cd63c4 100644
--- a/dlls/msi/tests/db.c
+++ b/dlls/msi/tests/db.c
@@ -182,6 +182,22 @@ static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
     return r;
 }
 
+static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
+{
+    MSIHANDLE hview = 0;
+    UINT r;
+
+    r = MsiDatabaseOpenViewW(hdb, query, &hview);
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    r = MsiViewExecute(hview, hrec);
+    if( r == ERROR_SUCCESS )
+        r = MsiViewClose(hview);
+    MsiCloseHandle(hview);
+    return r;
+}
+
 static UINT create_component_table( MSIHANDLE hdb )
 {
     return run_query( hdb, 0,
@@ -4929,6 +4945,174 @@ static void test_rows_order(void)
     DeleteFile(msifile);
 }
 
+static void test_collation(void)
+{
+    static const WCHAR query1[] =
+        {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
+         '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
+         '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
+    static const WCHAR query2[] =
+        {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
+         '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
+         '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
+    static const WCHAR query3[] =
+        {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
+         '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
+           ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
+           'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
+    static const WCHAR query4[] =
+        {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
+         '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
+         'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
+    static const WCHAR query5[] =
+        {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
+         '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
+         'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
+    static const WCHAR query6[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
+         ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
+    static const WCHAR letter_C[] = {'C',0};
+    static const WCHAR letter_D[] = {'D',0};
+    static const WCHAR letter_a_ring[] = {'a',0x30a,0};
+    static const WCHAR letter_a_with_ring[] = {0xe5,0};
+    static const WCHAR letter_a_broken[] = {'a',0xb0,0};
+    const char *query;
+    MSIHANDLE hdb = 0, hview = 0, hrec = 0;
+    UINT r;
+    char buffer[100];
+    WCHAR bufferW[100];
+    DWORD sz;
+
+    r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
+    ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
+
+    query = "CREATE TABLE `bar` ( "
+        "`foo` LONGCHAR NOT NULL, "
+        "`baz` LONGCHAR NOT NULL "
+        "PRIMARY KEY `foo` )";
+    r = run_query(hdb, 0, query);
+    ok(r == ERROR_SUCCESS, "failed to create table\n");
+
+    r = run_query(hdb, 0, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
+
+    r = run_query(hdb, 0, "INSERT INTO `bar` "
+            "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
+    ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
+
+    r = run_query(hdb, 0, "INSERT INTO `bar` "
+            "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
+    ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
+
+    r = run_queryW(hdb, 0, query1);
+    ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
+
+    r = run_queryW(hdb, 0, query2);
+    ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
+
+    r = run_queryW(hdb, 0, query3);
+    ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
+
+    r = run_queryW(hdb, 0, query4);
+    ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
+
+    r = run_queryW(hdb, 0, query5);
+    ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
+
+    query = "SELECT * FROM `bar`";
+    r = MsiDatabaseOpenView(hdb, query, &hview);
+    ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
+    r = MsiViewExecute(hview, 0);
+    ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
+
+    r = MsiViewFetch(hview, &hrec);
+    ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
+    sz = sizeof(buffer);
+    r = MsiRecordGetString(hrec, 1, buffer, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmp(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
+    sz = sizeof(buffer);
+    r = MsiRecordGetString(hrec, 2, buffer, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmp(buffer, "A"), "Expected A, got '%s'\n", buffer);
+    MsiCloseHandle(hrec);
+
+    r = MsiViewFetch(hview, &hrec);
+    ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
+    sz = sizeof(buffer);
+    r = MsiRecordGetString(hrec, 1, buffer, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmp(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
+    sz = sizeof(buffer);
+    r = MsiRecordGetString(hrec, 2, buffer, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmp(buffer, "B"), "Expected B, got '%s'\n", buffer);
+    MsiCloseHandle(hrec);
+
+    r = MsiViewFetch(hview, &hrec);
+    ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
+    sz = sizeof(bufferW) / sizeof(bufferW[0]);
+    r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)) ||
+       broken(!memcmp(bufferW, letter_a_broken, sizeof(letter_a_broken))) /* win9x */,
+       "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
+    sz = sizeof(bufferW) / sizeof(bufferW[0]);
+    r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
+    MsiCloseHandle(hrec);
+
+    r = MsiViewFetch(hview, &hrec);
+    ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
+    sz = sizeof(bufferW) / sizeof(bufferW[0]);
+    r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
+       "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
+    sz = sizeof(bufferW) / sizeof(bufferW[0]);
+    r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
+    MsiCloseHandle(hrec);
+
+    r = MsiViewClose(hview);
+    ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
+    r = MsiCloseHandle(hview);
+    ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
+
+    r = MsiDatabaseOpenViewW(hdb, query6, &hview);
+    ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
+    r = MsiViewExecute(hview, 0);
+    ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
+
+    r = MsiViewFetch(hview, &hrec);
+    ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
+    sz = sizeof(bufferW) / sizeof(bufferW[0]);
+    r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
+       "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
+    sz = sizeof(bufferW) / sizeof(bufferW[0]);
+    r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
+    MsiCloseHandle(hrec);
+
+    r = MsiViewFetch(hview, &hrec);
+    ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
+
+    r = MsiViewClose(hview);
+    ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
+    r = MsiCloseHandle(hview);
+    ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
+
+    r = MsiCloseHandle(hdb);
+    ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
+
+    DeleteFile(msifile);
+}
+
 static void test_select_markers(void)
 {
     MSIHANDLE hdb = 0, rec, view, res;
@@ -9017,4 +9201,5 @@ START_TEST(db)
     test_columnorder();
     test_suminfo_import();
     test_createtable();
+    test_collation();
 }
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index 07ab4eb..765cd24 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -1166,6 +1166,10 @@ static void test_settargetpath(void)
 
 static void test_condition(void)
 {
+    static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
+    static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
+    static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
+    static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
     MSICONDITION r;
     MSIHANDLE hpkg;
 
@@ -1885,6 +1889,22 @@ static void test_condition(void)
     r = MsiEvaluateCondition(hpkg, "A <= X");
     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
 
+    r = MsiEvaluateConditionW(hpkg, cond1);
+    ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
+        "wrong return val (%d)\n", r);
+
+    r = MsiEvaluateConditionW(hpkg, cond2);
+    ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
+        "wrong return val (%d)\n", r);
+
+    r = MsiEvaluateConditionW(hpkg, cond3);
+    ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
+        "wrong return val (%d)\n", r);
+
+    r = MsiEvaluateConditionW(hpkg, cond4);
+    ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
+        "wrong return val (%d)\n", r);
+
     MsiCloseHandle( hpkg );
     DeleteFile(msifile);
 }
diff --git a/dlls/msi/where.c b/dlls/msi/where.c
index 4c4db49..7cafa2a 100644
--- a/dlls/msi/where.c
+++ b/dlls/msi/where.c
@@ -24,6 +24,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 #include "msi.h"
 #include "msiquery.h"
 #include "objbase.h"
@@ -306,7 +307,7 @@ static UINT STRCMP_Evaluate( MSIWHEREVIEW *wv, UINT row, const struct expr *cond
     else if( r_str && ! l_str )
         sr = -1;
     else
-        sr = lstrcmpW( l_str, r_str );
+        sr = strcmpW( l_str, r_str );
 
     *val = ( cond->u.expr.op == OP_EQ && ( sr == 0 ) ) ||
            ( cond->u.expr.op == OP_NE && ( sr != 0 ) );
-- 
1.7.1






More information about the wine-patches mailing list