Sync to Wine-20050725:
authorGé van Geldorp <ge@gse.nl>
Fri, 12 Aug 2005 17:07:28 +0000 (17:07 +0000)
committerGé van Geldorp <ge@gse.nl>
Fri, 12 Aug 2005 17:07:28 +0000 (17:07 +0000)
Robert Shearman <rob@codeweavers.com>
- In MsiLocateComponent pcchBuf can be NULL so don't try to dereference
  it.
Alexandre Julliard <julliard@winehq.org>
- Use the official names for the Unicode string constants.
Aric Stewart <aric@codeweavers.com>
- Implement MsiGetLanguage.
- Relocate the msi file to prevent cd locking, corrected to properly not
  try to relocated #nnnn handles as files.
- Use the SourceList functions to get the source path in
  ConfigureProductExW.
- Handle installs off multiple volumes and properly pull the prompt
  string from the error table.
- If MsiGetProperty(A/W) is called with a NULL for the value buffer but
  a value in the size for the value buffer, then Msi fills in the size
  of the value into the pointer for size.  This is tested and confirmed
  with native MSI.
- Bail out if the reg key is empty. This prevents us from writing
  garbage to the property table.
- Properly resize the buffer based on ERROR_MORE_DATA.
  Also remember to free the allocated buffer.
- Further testing shows that when CustomActionData needs to be blank it
  is an empty string not ' '.
- Correct an error where I was not properly advancing a pointer.
- Add source.c to start handling the various MsiSourceList apis used in
  v3 of MSI, and now internally.
- Update files.c to use the MsiSourceList apis to make sure our
  SourceList keys in the registry are included and correct.
- Use the strings defined in msi.h.
- Use SOURCEDIR instead of PackagePath. Because the PackagePath may be
  local, while SOURCEDIR is more proper and will be a full directory.
- InstallShield does a number of actions using DoAction before the
  Install starts so the PackageCode needs to be loaded on OpenPackage
  instead of the beginning of the install process.
- When working toward install on demand support we need to reset all the
  constant values so that multiple install process do not get confused
  by leftover values from the previous install.
- Fill and use the ProductCode part of the MSIPACKAGE structure.
- Add the string constants located in msi.h and make use of them in
  files.c and source.c.
- Keep track of what sequence we are in and register unique
  actions. This allows us to make sure actions and custom actions
  flagged to run only once, actually run only once.
- Also clean up some of the numeric constants in custom.c using the
  defined values from msidefs.h.
Mike McCormack <mike@codeweavers.com>
- gcc 4.0 -Wpointer-sign fixes.
- Display icons in buttons that have them.
- Use LoadImage to load bitmaps and icons.
- Set the initial focus on the control specified by Control_First in the
  Dialog table.
- Move to the next mask edit field when the current one becomes full.
- Make the tab order in msi dialogs right.
- Don't crash when cancelling out of a modeless dialog.
- Stop the install when cancelling from a modeless dialog.

svn path=/trunk/; revision=17331

21 files changed:
reactos/lib/msi/Makefile.in
reactos/lib/msi/action.c
reactos/lib/msi/action.h
reactos/lib/msi/appsearch.c
reactos/lib/msi/custom.c
reactos/lib/msi/dialog.c
reactos/lib/msi/events.c
reactos/lib/msi/files.c
reactos/lib/msi/helpers.c
reactos/lib/msi/install.c
reactos/lib/msi/msi.c
reactos/lib/msi/msi.spec
reactos/lib/msi/msi.xml
reactos/lib/msi/msipriv.h
reactos/lib/msi/package.c
reactos/lib/msi/registry.c
reactos/lib/msi/source.c [new file with mode: 0644]
reactos/lib/msi/string.c
reactos/lib/msi/suminfo.c
reactos/lib/msi/upgrade.c
reactos/w32api/include/msi.h

index 38098fa..e1216ae 100644 (file)
@@ -33,6 +33,7 @@ C_SRCS = \
        registry.c \\r
        regsvr.c \\r
        select.c \\r
        registry.c \\r
        regsvr.c \\r
        select.c \\r
+       source.c \\r
        string.c \\r
        suminfo.c \\r
        table.c \\r
        string.c \\r
        suminfo.c \\r
        table.c \\r
index 6f6ca2e..e16f356 100644 (file)
@@ -432,7 +432,7 @@ static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
  *****************************************************/
 
 UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
  *****************************************************/
 
 UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
-                              LPCWSTR szCommandLine)
+                              LPCWSTR szCommandLine, LPCWSTR msiFilePath)
 {
     DWORD sz;
     WCHAR buffer[10];
 {
     DWORD sz;
     WCHAR buffer[10];
@@ -447,6 +447,10 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
     package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
     memset(package->script,0,sizeof(MSISCRIPT));
 
     package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
     memset(package->script,0,sizeof(MSISCRIPT));
 
+    package->script->InWhatSequence = SEQUENCE_INSTALL;
+
+    package->msiFilePath= strdupW(msiFilePath);
+
     if (szPackagePath)   
     {
         LPWSTR p, check, path;
     if (szPackagePath)   
     {
         LPWSTR p, check, path;
@@ -538,10 +542,14 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
     {
         if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED)
         {
     {
         if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED)
         {
+            package->script->InWhatSequence |= SEQUENCE_UI;
             rc = ACTION_ProcessUISequence(package);
             ui = TRUE;
             if (rc == ERROR_SUCCESS)
             rc = ACTION_ProcessUISequence(package);
             ui = TRUE;
             if (rc == ERROR_SUCCESS)
+            {
+                package->script->InWhatSequence |= SEQUENCE_EXEC;
                 rc = ACTION_ProcessExecSequence(package,TRUE);
                 rc = ACTION_ProcessExecSequence(package,TRUE);
+            }
         }
         else
             rc = ACTION_ProcessExecSequence(package,FALSE);
         }
         else
             rc = ACTION_ProcessExecSequence(package,FALSE);
@@ -666,6 +674,11 @@ static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
     else
         rc = ACTION_PerformAction(iap->package,action,FALSE);
 
     else
         rc = ACTION_PerformAction(iap->package,action,FALSE);
 
+    msi_dialog_check_messages( NULL );
+
+    if (iap->package->CurrentInstallState != ERROR_SUCCESS )
+        rc = iap->package->CurrentInstallState;
+
     if (rc == ERROR_FUNCTION_NOT_CALLED)
         rc = ERROR_SUCCESS;
 
     if (rc == ERROR_FUNCTION_NOT_CALLED)
         rc = ERROR_SUCCESS;
 
@@ -814,18 +827,6 @@ static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
     return ret;
 }
 
     return ret;
 }
 
-static BOOL ACTION_HandleDialogBox( MSIPACKAGE *package, LPCWSTR dialog, UINT* rc )
-{
-    BOOL ret = FALSE;
-
-    if (ACTION_DialogBox(package,dialog) == ERROR_SUCCESS)
-    {
-        *rc = package->CurrentInstallState;
-        ret = TRUE;
-    }
-    return ret;
-}
-
 static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
                                        UINT* rc, BOOL force )
 {
 static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
                                        UINT* rc, BOOL force )
 {
@@ -868,7 +869,6 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force)
         rc = ERROR_FUNCTION_NOT_CALLED;
     }
 
         rc = ERROR_FUNCTION_NOT_CALLED;
     }
 
-    package->CurrentInstallState = rc;
     return rc;
 }
 
     return rc;
 }
 
@@ -884,10 +884,8 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
     if (!handled)
         handled = ACTION_HandleCustomAction(package, action, &rc, FALSE);
 
     if (!handled)
         handled = ACTION_HandleCustomAction(package, action, &rc, FALSE);
 
-    if (!handled)
-        handled = ACTION_HandleDialogBox(package, action, &rc);
-
-    msi_dialog_check_messages( NULL );
+    if( !handled && ACTION_DialogBox(package,action) == ERROR_SUCCESS )
+        handled = TRUE;
 
     if (!handled)
     {
 
     if (!handled)
     {
@@ -895,7 +893,6 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
         rc = ERROR_FUNCTION_NOT_CALLED;
     }
 
         rc = ERROR_FUNCTION_NOT_CALLED;
     }
 
-    package->CurrentInstallState = rc;
     return rc;
 }
 
     return rc;
 }
 
@@ -1371,9 +1368,6 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
     if (targetdir[0] == '.' && targetdir[1] == 0)
         targetdir = NULL;
         
     if (targetdir[0] == '.' && targetdir[1] == 0)
         targetdir = NULL;
         
-    if (srcdir && srcdir[0] == '.' && srcdir[1] == 0)
-        srcdir = NULL;
-
     if (targetdir)
     {
         TRACE("   TargetDefault = %s\n",debugstr_w(targetdir));
     if (targetdir)
     {
         TRACE("   TargetDefault = %s\n",debugstr_w(targetdir));
@@ -1414,14 +1408,11 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
 static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
 {
     int i;
 static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
 {
     int i;
-    LPWSTR productcode;
-
-    productcode = load_dynamic_property(package,szProductCode,NULL);
 
     for (i = 0; i < package->loaded_components; i++)
     {
         INSTALLSTATE res;
 
     for (i = 0; i < package->loaded_components; i++)
     {
         INSTALLSTATE res;
-        res = MsiGetComponentPathW(productcode, 
+        res = MsiGetComponentPathW(package->ProductCode, 
                         package->components[i].ComponentId , NULL, NULL);
         if (res < 0)
             res = INSTALLSTATE_ABSENT;
                         package->components[i].ComponentId , NULL, NULL);
         if (res < 0)
             res = INSTALLSTATE_ABSENT;
@@ -2127,7 +2118,7 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
     {
         TRACE("Setting value %s of %s\n",debugstr_w(deformated),
                         debugstr_w(uikey));
     {
         TRACE("Setting value %s of %s\n",debugstr_w(deformated),
                         debugstr_w(uikey));
-        RegSetValueExW(hkey, deformated, 0, type, value_data, size);
+        RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value_data, size);
     }
     else
     {
     }
     else
     {
@@ -2143,7 +2134,7 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
             TRACE("Checked and setting value %s of %s\n",
                             debugstr_w(deformated), debugstr_w(uikey));
             if (deformated || size)
             TRACE("Checked and setting value %s of %s\n",
                             debugstr_w(deformated), debugstr_w(uikey));
             if (deformated || size)
-                RegSetValueExW(hkey, deformated, 0, type, value_data, size);
+                RegSetValueExW(hkey, deformated, 0, type, (LPBYTE) value_data, size);
         }
     }
     RegCloseKey(hkey);
         }
     }
     RegCloseKey(hkey);
@@ -2500,7 +2491,6 @@ static void ACTION_RefCountComponent( MSIPACKAGE* package, UINT index)
  */
 static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
 {
  */
 static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
 {
-    LPWSTR productcode;
     WCHAR squished_pc[GUID_SIZE];
     WCHAR squished_cc[GUID_SIZE];
     UINT rc;
     WCHAR squished_pc[GUID_SIZE];
     WCHAR squished_cc[GUID_SIZE];
     UINT rc;
@@ -2511,15 +2501,12 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         return ERROR_INVALID_HANDLE;
 
     /* writes the Component and Features values to the registry */
         return ERROR_INVALID_HANDLE;
 
     /* writes the Component and Features values to the registry */
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
 
     rc = MSIREG_OpenComponents(&hkey);
     if (rc != ERROR_SUCCESS)
         goto end;
       
 
     rc = MSIREG_OpenComponents(&hkey);
     if (rc != ERROR_SUCCESS)
         goto end;
       
-    squash_guid(productcode,squished_pc);
+    squash_guid(package->ProductCode,squished_pc);
     ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);
     for (i = 0; i < package->loaded_components; i++)
     {
     ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);
     for (i = 0; i < package->loaded_components; i++)
     {
@@ -2555,7 +2542,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
 
                 if (keypath)
                 {
 
                 if (keypath)
                 {
-                    RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath,
+                    RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPBYTE)keypath,
                                 (strlenW(keypath)+1)*sizeof(WCHAR));
 
                     if (package->components[i].Attributes & 
                                 (strlenW(keypath)+1)*sizeof(WCHAR));
 
                     if (package->components[i].Attributes & 
@@ -2567,7 +2554,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
                               '0','0','0','0','0','0','0','0',0};
 
                         RegSetValueExW(hkey2,szPermKey,0,REG_SZ,
                               '0','0','0','0','0','0','0','0',0};
 
                         RegSetValueExW(hkey2,szPermKey,0,REG_SZ,
-                                        (LPVOID)keypath,
+                                        (LPBYTE)keypath,
                                         (strlenW(keypath)+1)*sizeof(WCHAR));
                     }
                     
                                         (strlenW(keypath)+1)*sizeof(WCHAR));
                     }
                     
@@ -2575,7 +2562,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         
                     /* UI stuff */
                     uirow = MSI_CreateRecord(3);
         
                     /* UI stuff */
                     uirow = MSI_CreateRecord(3);
-                    MSI_RecordSetStringW(uirow,1,productcode);
+                    MSI_RecordSetStringW(uirow,1,package->ProductCode);
                     MSI_RecordSetStringW(uirow,2,package->components[i].
                                                             ComponentId);
                     MSI_RecordSetStringW(uirow,3,keypath);
                     MSI_RecordSetStringW(uirow,2,package->components[i].
                                                             ComponentId);
                     MSI_RecordSetStringW(uirow,3,keypath);
@@ -2602,7 +2589,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         
                 /* UI stuff */
                 uirow = MSI_CreateRecord(2);
         
                 /* UI stuff */
                 uirow = MSI_CreateRecord(2);
-                MSI_RecordSetStringW(uirow,1,productcode);
+                MSI_RecordSetStringW(uirow,1,package->ProductCode);
                 MSI_RecordSetStringW(uirow,2,package->components[i].
                                 ComponentId);
                 ui_actiondata(package,szProcessComponents,uirow);
                 MSI_RecordSetStringW(uirow,2,package->components[i].
                                 ComponentId);
                 ui_actiondata(package,szProcessComponents,uirow);
@@ -2611,7 +2598,6 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         }
     } 
 end:
         }
     } 
 end:
-    HeapFree(GetProcessHeap(), 0, productcode);
     RegCloseKey(hkey);
     return rc;
 }
     RegCloseKey(hkey);
     return rc;
 }
@@ -3019,25 +3005,14 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
          '`','I','c','o','n','`',0};
     /* for registry stuff */
         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
          '`','I','c','o','n','`',0};
     /* for registry stuff */
-    LPWSTR productcode;
     HKEY hkey=0;
     HKEY hukey=0;
     HKEY hkey=0;
     HKEY hukey=0;
-    static const WCHAR szProductName[] =
-        {'P','r','o','d','u','c','t','N','a','m','e',0};
-    static const WCHAR szPackageCode[] =
-        {'P','a','c','k','a','g','e','C','o','d','e',0};
-    static const WCHAR szLanguage[] =
-        {'L','a','n','g','u','a','g','e',0};
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
-    static const WCHAR szProductIcon[] =
-        {'P','r','o','d','u','c','t','I','c','o','n',0};
     static const WCHAR szARPProductIcon[] =
         {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
     static const WCHAR szProductVersion[] =
         {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
     static const WCHAR szARPProductIcon[] =
         {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
     static const WCHAR szProductVersion[] =
         {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
-    static const WCHAR szVersion[] =
-        {'V','e','r','s','i','o','n',0};
     DWORD langid;
     LPWSTR buffer;
     DWORD size;
     DWORD langid;
     LPWSTR buffer;
     DWORD size;
@@ -3057,28 +3032,26 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
 
     /* ok there is a lot more done here but i need to figure out what */
 
 
     /* ok there is a lot more done here but i need to figure out what */
 
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenProductsKey(productcode,&hkey,TRUE);
+    rc = MSIREG_OpenProductsKey(package->ProductCode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
 
     if (rc != ERROR_SUCCESS)
         goto end;
 
-    rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
+    rc = MSIREG_OpenUserProductsKey(package->ProductCode,&hukey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
 
 
     if (rc != ERROR_SUCCESS)
         goto end;
 
 
-    buffer = load_dynamic_property(package,szProductName,NULL);
+    buffer = load_dynamic_property(package,INSTALLPROPERTY_PRODUCTNAMEW,NULL);
     size = strlenW(buffer)*sizeof(WCHAR);
     size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hukey,szProductName,0,REG_SZ, (BYTE *)buffer,size);
+    RegSetValueExW(hukey,INSTALLPROPERTY_PRODUCTNAMEW,0,REG_SZ, 
+            (LPBYTE)buffer,size);
     HeapFree(GetProcessHeap(),0,buffer);
 
     buffer = load_dynamic_property(package,szProductLanguage,NULL);
     size = sizeof(DWORD);
     langid = atoiW(buffer);
     HeapFree(GetProcessHeap(),0,buffer);
 
     buffer = load_dynamic_property(package,szProductLanguage,NULL);
     size = sizeof(DWORD);
     langid = atoiW(buffer);
-    RegSetValueExW(hukey,szLanguage,0,REG_DWORD, (BYTE *)&langid,size);
+    RegSetValueExW(hukey,INSTALLPROPERTY_LANGUAGEW,0,REG_DWORD, 
+            (LPBYTE)&langid,size);
     HeapFree(GetProcessHeap(),0,buffer);
 
     buffer = load_dynamic_property(package,szARPProductIcon,NULL);
     HeapFree(GetProcessHeap(),0,buffer);
 
     buffer = load_dynamic_property(package,szARPProductIcon,NULL);
@@ -3087,7 +3060,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
         LPWSTR path;
         build_icon_path(package,buffer,&path);
         size = strlenW(path) * sizeof(WCHAR);
         LPWSTR path;
         build_icon_path(package,buffer,&path);
         size = strlenW(path) * sizeof(WCHAR);
-        RegSetValueExW(hukey,szProductIcon,0,REG_SZ, (BYTE *)path,size);
+        RegSetValueExW(hukey,INSTALLPROPERTY_PRODUCTICONW,0,REG_SZ,
+                (LPBYTE)path,size);
     }
     HeapFree(GetProcessHeap(),0,buffer);
 
     }
     HeapFree(GetProcessHeap(),0,buffer);
 
@@ -3096,7 +3070,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
     {
         DWORD verdword = build_version_dword(buffer);
         size = sizeof(DWORD);
     {
         DWORD verdword = build_version_dword(buffer);
         size = sizeof(DWORD);
-        RegSetValueExW(hukey,szVersion,0,REG_DWORD, (BYTE *)&verdword,size);
+        RegSetValueExW(hukey,INSTALLPROPERTY_VERSIONW,0,REG_DWORD, (LPBYTE
+                    )&verdword,size);
     }
     HeapFree(GetProcessHeap(),0,buffer);
     
     }
     HeapFree(GetProcessHeap(),0,buffer);
     
@@ -3119,8 +3094,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
             if (ptr) *ptr = 0;
             squash_guid(guidbuffer,squashed);
             size = strlenW(squashed)*sizeof(WCHAR);
             if (ptr) *ptr = 0;
             squash_guid(guidbuffer,squashed);
             size = strlenW(squashed)*sizeof(WCHAR);
-            RegSetValueExW(hukey,szPackageCode,0,REG_SZ, (LPSTR)squashed,
-                           size);
+            RegSetValueExW(hukey,INSTALLPROPERTY_PACKAGECODEW,0,REG_SZ,
+                    (LPBYTE)squashed, size);
         }
         else
         {
         }
         else
         {
@@ -3137,7 +3112,6 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
 
 end:
 
 
 end:
 
-    HeapFree(GetProcessHeap(),0,productcode);    
     RegCloseKey(hkey);
     RegCloseKey(hukey);
 
     RegCloseKey(hkey);
     RegCloseKey(hukey);
 
@@ -3331,7 +3305,6 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
 
 static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
 {
 
 static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
 {
-    LPWSTR productcode;
     UINT rc;
     DWORD i;
     HKEY hkey=0;
     UINT rc;
     DWORD i;
     HKEY hkey=0;
@@ -3340,15 +3313,11 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
     if (!package)
         return ERROR_INVALID_HANDLE;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenFeaturesKey(productcode,&hkey,TRUE);
+    rc = MSIREG_OpenFeaturesKey(package->ProductCode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
 
     if (rc != ERROR_SUCCESS)
         goto end;
 
-    rc = MSIREG_OpenUserFeaturesKey(productcode,&hukey,TRUE);
+    rc = MSIREG_OpenUserFeaturesKey(package->ProductCode,&hukey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
 
     if (rc != ERROR_SUCCESS)
         goto end;
 
@@ -3400,14 +3369,14 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
 
         size = (strlenW(data)+1)*sizeof(WCHAR);
         RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ,
 
         size = (strlenW(data)+1)*sizeof(WCHAR);
         RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)data,size);
+                       (LPBYTE)data,size);
         HeapFree(GetProcessHeap(),0,data);
 
         if (!absent)
         {
             size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
             RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
         HeapFree(GetProcessHeap(),0,data);
 
         if (!absent)
         {
             size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
             RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)package->features[i].Feature_Parent,size);
+                       (LPBYTE)package->features[i].Feature_Parent,size);
         }
         else
         {
         }
         else
         {
@@ -3417,7 +3386,7 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
             data[0] = 0x6;
             strcpyW(&data[1],package->features[i].Feature_Parent);
             RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
             data[0] = 0x6;
             strcpyW(&data[1],package->features[i].Feature_Parent);
             RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)data,size);
+                       (LPBYTE)data,size);
             HeapFree(GetProcessHeap(),0,data);
         }
     }
             HeapFree(GetProcessHeap(),0,data);
         }
     }
@@ -3425,7 +3394,6 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
 end:
     RegCloseKey(hkey);
     RegCloseKey(hukey);
 end:
     RegCloseKey(hkey);
     RegCloseKey(hukey);
-    HeapFree(GetProcessHeap(), 0, productcode);
     return rc;
 }
 
     return rc;
 }
 
@@ -3433,7 +3401,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
 {
     HKEY hkey=0;
     LPWSTR buffer = NULL;
 {
     HKEY hkey=0;
     LPWSTR buffer = NULL;
-    LPWSTR productcode;
     UINT rc,i;
     DWORD size;
     static WCHAR szNONE[] = {0};
     UINT rc,i;
     DWORD size;
     static WCHAR szNONE[] = {0};
@@ -3484,8 +3451,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
     '%','s','\\',
     'I','n','s','t','a','l','l','e','r','\\',
     '%','x','.','m','s','i',0};
     '%','s','\\',
     'I','n','s','t','a','l','l','e','r','\\',
     '%','x','.','m','s','i',0};
-    static const WCHAR szLocalPackage[]=
-         {'L','o','c','a','l','P','a','c','k','a','g','e',0};
     static const WCHAR szUpgradeCode[] = 
         {'U','p','g','r','a','d','e','C','o','d','e',0};
     static const WCHAR modpath_fmt[] = 
     static const WCHAR szUpgradeCode[] = 
         {'U','p','g','r','a','d','e','C','o','d','e',0};
     static const WCHAR modpath_fmt[] = 
@@ -3496,20 +3461,10 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
         {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
     static const WCHAR szEstimatedSize[] = 
         {'E','s','t','i','m','a','t','e','d','S','i','z','e',0};
         {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
     static const WCHAR szEstimatedSize[] = 
         {'E','s','t','i','m','a','t','e','d','S','i','z','e',0};
-    static const WCHAR szInstallDate[] = 
-        {'I','n','s','t','a','l','l','D','a','t','e',0};
-    static const WCHAR szLanguage[] =
-        {'L','a','n','g','u','a','g','e',0};
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
     static const WCHAR szProductVersion[] =
         {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
     static const WCHAR szProductVersion[] =
         {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
-    static const WCHAR szVersion[] =
-        {'V','e','r','s','i','o','n',0};
-    static const WCHAR szVersionMajor[] =
-        {'V','e','r','s','i','o','n','M','a','j','o','r',0};
-    static const WCHAR szVersionMinor[] =
-        {'V','e','r','s','i','o','n','M','i','n','o','r',0};
 
     SYSTEMTIME systime;
     static const WCHAR date_fmt[] = {'%','i','%','i','%','i',0};
 
     SYSTEMTIME systime;
     static const WCHAR date_fmt[] = {'%','i','%','i','%','i',0};
@@ -3520,11 +3475,7 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
     if (!package)
         return ERROR_INVALID_HANDLE;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
+    rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
 
     if (rc != ERROR_SUCCESS)
         goto end;
 
@@ -3538,14 +3489,14 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
         if (rc != ERROR_SUCCESS)
             buffer = szNONE;
         size = strlenW(buffer)*sizeof(WCHAR);
         if (rc != ERROR_SUCCESS)
             buffer = szNONE;
         size = strlenW(buffer)*sizeof(WCHAR);
-        RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
+        RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPBYTE)buffer,size);
         HeapFree(GetProcessHeap(),0,buffer);
         i++;
     }
 
     rc = 0x1;
     size = sizeof(rc);
         HeapFree(GetProcessHeap(),0,buffer);
         i++;
     }
 
     rc = 0x1;
     size = sizeof(rc);
-    RegSetValueExW(hkey,szWindowsInstaler,0,REG_DWORD,(LPSTR)&rc,size);
+    RegSetValueExW(hkey,szWindowsInstaler,0,REG_DWORD,(LPBYTE)&rc,size);
     
     /* copy the package locally */
     num = GetTickCount() & 0xffff;
     
     /* copy the package locally */
     num = GetTickCount() & 0xffff;
@@ -3574,34 +3525,37 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
     snprintfW(path,sizeof(path)/sizeof(path[0]),installerPathFmt,windir);
     create_full_pathW(path);
     TRACE("Copying to local package %s\n",debugstr_w(packagefile));
     snprintfW(path,sizeof(path)/sizeof(path[0]),installerPathFmt,windir);
     create_full_pathW(path);
     TRACE("Copying to local package %s\n",debugstr_w(packagefile));
-    if (!CopyFileW(package->PackagePath,packagefile,FALSE))
+    if (!CopyFileW(package->msiFilePath,packagefile,FALSE))
         ERR("Unable to copy package (%s -> %s) (error %ld)\n",
         ERR("Unable to copy package (%s -> %s) (error %ld)\n",
-            debugstr_w(package->PackagePath), debugstr_w(packagefile),
+            debugstr_w(package->msiFilePath), debugstr_w(packagefile),
             GetLastError());
     size = strlenW(packagefile)*sizeof(WCHAR);
             GetLastError());
     size = strlenW(packagefile)*sizeof(WCHAR);
-    RegSetValueExW(hkey,szLocalPackage,0,REG_SZ,(LPSTR)packagefile,size);
+    RegSetValueExW(hkey,INSTALLPROPERTY_LOCALPACKAGEW,0,REG_SZ,
+            (LPBYTE)packagefile,size);
 
     /* do ModifyPath and UninstallString */
     size = deformat_string(package,modpath_fmt,&buffer);
 
     /* do ModifyPath and UninstallString */
     size = deformat_string(package,modpath_fmt,&buffer);
-    RegSetValueExW(hkey,szModifyPath,0,REG_EXPAND_SZ,(LPSTR)buffer,size);
-    RegSetValueExW(hkey,szUninstallString,0,REG_EXPAND_SZ,(LPSTR)buffer,size);
+    RegSetValueExW(hkey,szModifyPath,0,REG_EXPAND_SZ,(LPBYTE)buffer,size);
+    RegSetValueExW(hkey,szUninstallString,0,REG_EXPAND_SZ,(LPBYTE)buffer,size);
     HeapFree(GetProcessHeap(),0,buffer);
 
     FIXME("Write real Estimated Size when we have it\n");
     size = 0;
     HeapFree(GetProcessHeap(),0,buffer);
 
     FIXME("Write real Estimated Size when we have it\n");
     size = 0;
-    RegSetValueExW(hkey,szEstimatedSize,0,REG_DWORD,(LPSTR)&size,sizeof(DWORD));
+    RegSetValueExW(hkey,szEstimatedSize,0,REG_DWORD,(LPBYTE)&size,sizeof(DWORD));
    
     GetLocalTime(&systime);
     size = 9*sizeof(WCHAR);
     buffer= HeapAlloc(GetProcessHeap(),0,size);
     sprintfW(buffer,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
     size = strlenW(buffer)*sizeof(WCHAR);
    
     GetLocalTime(&systime);
     size = 9*sizeof(WCHAR);
     buffer= HeapAlloc(GetProcessHeap(),0,size);
     sprintfW(buffer,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
     size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hkey,szInstallDate,0,REG_SZ,(LPSTR)buffer,size);
+    RegSetValueExW(hkey,INSTALLPROPERTY_INSTALLDATEW,0,REG_SZ,
+            (LPBYTE)buffer,size);
     HeapFree(GetProcessHeap(),0,buffer);
    
     buffer = load_dynamic_property(package,szProductLanguage,NULL);
     size = atoiW(buffer);
     HeapFree(GetProcessHeap(),0,buffer);
    
     buffer = load_dynamic_property(package,szProductLanguage,NULL);
     size = atoiW(buffer);
-    RegSetValueExW(hkey,szLanguage,0,REG_DWORD, (LPSTR)&size,sizeof(DWORD));
+    RegSetValueExW(hkey,INSTALLPROPERTY_LANGUAGEW,0,REG_DWORD,
+            (LPBYTE)&size,sizeof(DWORD));
     HeapFree(GetProcessHeap(),1,buffer);
 
     buffer = load_dynamic_property(package,szProductVersion,NULL);
     HeapFree(GetProcessHeap(),1,buffer);
 
     buffer = load_dynamic_property(package,szProductVersion,NULL);
@@ -3611,9 +3565,12 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
         DWORD vermajor = verdword>>24;
         DWORD verminor = (verdword>>16)&0x00FF;
         size = sizeof(DWORD);
         DWORD vermajor = verdword>>24;
         DWORD verminor = (verdword>>16)&0x00FF;
         size = sizeof(DWORD);
-        RegSetValueExW(hkey,szVersion,0,REG_DWORD,(LPSTR)&verdword,size);
-        RegSetValueExW(hkey,szVersionMajor,0,REG_DWORD,(LPSTR)&vermajor,size);
-        RegSetValueExW(hkey,szVersionMinor,0,REG_DWORD,(LPSTR)&verminor,size);
+        RegSetValueExW(hkey,INSTALLPROPERTY_VERSIONW,0,REG_DWORD,
+                (LPBYTE)&verdword,size);
+        RegSetValueExW(hkey,INSTALLPROPERTY_VERSIONMAJORW,0,REG_DWORD,
+                (LPBYTE)&vermajor,size);
+        RegSetValueExW(hkey,INSTALLPROPERTY_VERSIONMINORW,0,REG_DWORD,
+                (LPBYTE)&verminor,size);
     }
     HeapFree(GetProcessHeap(),0,buffer);
     
     }
     HeapFree(GetProcessHeap(),0,buffer);
     
@@ -3624,11 +3581,11 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
         HKEY hkey2;
         WCHAR squashed[33];
         MSIREG_OpenUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
         HKEY hkey2;
         WCHAR squashed[33];
         MSIREG_OpenUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
-        squash_guid(productcode,squashed);
+        squash_guid(package->ProductCode,squashed);
         RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0);
         RegCloseKey(hkey2);
         MSIREG_OpenUserUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
         RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0);
         RegCloseKey(hkey2);
         MSIREG_OpenUserUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
-        squash_guid(productcode,squashed);
+        squash_guid(package->ProductCode,squashed);
         RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0);
         RegCloseKey(hkey2);
 
         RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0);
         RegCloseKey(hkey2);
 
@@ -3636,7 +3593,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
     }
     
 end:
     }
     
 end:
-    HeapFree(GetProcessHeap(),0,productcode);
     RegCloseKey(hkey);
 
     return ERROR_SUCCESS;
     RegCloseKey(hkey);
 
     return ERROR_SUCCESS;
@@ -3700,26 +3656,14 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package)
     'A','F','T','E','R','R','E','B','O','O','T','=','1',' ',
     'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0};
     WCHAR buffer[256], sysdir[MAX_PATH];
     'A','F','T','E','R','R','E','B','O','O','T','=','1',' ',
     'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0};
     WCHAR buffer[256], sysdir[MAX_PATH];
-    HKEY hkey,hukey;
-    LPWSTR productcode;
+    HKEY hkey;
     WCHAR  squished_pc[100];
     WCHAR  squished_pc[100];
-    INT rc;
     DWORD size;
     DWORD size;
-    static const WCHAR szLUS[] = {
-         'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
-    static const WCHAR szSourceList[] = {
-         'S','o','u','r','c','e','L','i','s','t',0};
-    static const WCHAR szPackageName[] = { 
-        'P','a','c','k','a','g','e','N','a','m','e',0};
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    squash_guid(productcode,squished_pc);
+    squash_guid(package->ProductCode,squished_pc);
 
     GetSystemDirectoryW(sysdir, sizeof(sysdir)/sizeof(sysdir[0]));
     RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey);
 
     GetSystemDirectoryW(sysdir, sizeof(sysdir)/sizeof(sysdir[0]));
     RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey);
@@ -3727,41 +3671,18 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package)
      squished_pc);
 
     size = strlenW(buffer)*sizeof(WCHAR);
      squished_pc);
 
     size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
+    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPBYTE)buffer,size);
     RegCloseKey(hkey);
 
     TRACE("Reboot command %s\n",debugstr_w(buffer));
 
     RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey);
     RegCloseKey(hkey);
 
     TRACE("Reboot command %s\n",debugstr_w(buffer));
 
     RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey);
-    sprintfW(buffer,install_fmt,productcode,squished_pc);
+    sprintfW(buffer,install_fmt,package->ProductCode,squished_pc);
 
     size = strlenW(buffer)*sizeof(WCHAR);
 
     size = strlenW(buffer)*sizeof(WCHAR);
-    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
+    RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPBYTE)buffer,size);
     RegCloseKey(hkey);
 
     RegCloseKey(hkey);
 
-    rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
-    if (rc == ERROR_SUCCESS)
-    {
-        HKEY hukey2;
-        LPWSTR buf;
-        RegCreateKeyW(hukey, szSourceList, &hukey2);
-        buf = load_dynamic_property(package,cszSourceDir,NULL);
-        size = strlenW(buf)*sizeof(WCHAR);
-        RegSetValueExW(hukey2,szLUS,0,REG_SZ,(LPSTR)buf,size);
-        HeapFree(GetProcessHeap(),0,buf); 
-
-        buf = strrchrW(package->PackagePath,'\\');
-        if (buf)
-        {
-            buf++;
-            size = strlenW(buf)*sizeof(WCHAR);
-            RegSetValueExW(hukey2,szPackageName,0,REG_SZ,(LPSTR)buf,size);
-        }
-
-        RegCloseKey(hukey2);
-    }
-    HeapFree(GetProcessHeap(),0,productcode);
-
     return ERROR_INSTALL_SUSPEND;
 }
 
     return ERROR_INSTALL_SUSPEND;
 }
 
@@ -3776,11 +3697,8 @@ UINT ACTION_ResolveSource(MSIPACKAGE* package)
 
 static UINT ACTION_RegisterUser(MSIPACKAGE *package)
 {
 
 static UINT ACTION_RegisterUser(MSIPACKAGE *package)
 {
-    static const WCHAR szProductID[]=
-         {'P','r','o','d','u','c','t','I','D',0};
     HKEY hkey=0;
     LPWSTR buffer;
     HKEY hkey=0;
     LPWSTR buffer;
-    LPWSTR productcode;
     LPWSTR productid;
     UINT rc,i;
     DWORD size;
     LPWSTR productid;
     UINT rc,i;
     DWORD size;
@@ -3804,15 +3722,12 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package)
     if (!package)
         return ERROR_INVALID_HANDLE;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    productid = load_dynamic_property(package,szProductID,&rc);
+    productid = load_dynamic_property(package,INSTALLPROPERTY_PRODUCTIDW,
+            &rc);
     if (!productid)
         return ERROR_SUCCESS;
 
     if (!productid)
         return ERROR_SUCCESS;
 
-    productcode = load_dynamic_property(package,szProductCode,&rc);
-    if (!productcode)
-        return rc;
-
-    rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
+    rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
     if (rc != ERROR_SUCCESS)
         goto end;
 
     if (rc != ERROR_SUCCESS)
         goto end;
 
@@ -3823,7 +3738,7 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package)
         if (rc == ERROR_SUCCESS)
         {
             size = strlenW(buffer)*sizeof(WCHAR);
         if (rc == ERROR_SUCCESS)
         {
             size = strlenW(buffer)*sizeof(WCHAR);
-            RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
+            RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPBYTE)buffer,size);
         }
         else
             RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,NULL,0);
         }
         else
             RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,NULL,0);
@@ -3831,7 +3746,6 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package)
     }
 
 end:
     }
 
 end:
-    HeapFree(GetProcessHeap(),0,productcode);
     HeapFree(GetProcessHeap(),0,productid);
     RegCloseKey(hkey);
 
     HeapFree(GetProcessHeap(),0,productid);
     RegCloseKey(hkey);
 
@@ -3848,6 +3762,7 @@ static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
     level = load_dynamic_property(package,szUILevel,NULL);
 
     MSI_SetPropertyW(package,szUILevel,szTwo);
     level = load_dynamic_property(package,szUILevel,NULL);
 
     MSI_SetPropertyW(package,szUILevel,szTwo);
+    package->script->InWhatSequence |= SEQUENCE_EXEC;
     rc = ACTION_ProcessExecSequence(package,FALSE);
     MSI_SetPropertyW(package,szUILevel,level);
     HeapFree(GetProcessHeap(),0,level);
     rc = ACTION_ProcessExecSequence(package,FALSE);
     MSI_SetPropertyW(package,szUILevel,level);
     HeapFree(GetProcessHeap(),0,level);
index 9c472a5..b891407 100644 (file)
@@ -187,13 +187,19 @@ enum SCRIPTS {
         TOTAL_SCRIPTS = 3
 };
 
         TOTAL_SCRIPTS = 3
 };
 
+#define SEQUENCE_UI       0x1
+#define SEQUENCE_EXEC     0x2
+#define SEQUENCE_INSTALL  0x10
+
 typedef struct tagMSISCRIPT
 {
     LPWSTR  *Actions[TOTAL_SCRIPTS];
     UINT    ActionCount[TOTAL_SCRIPTS];
     BOOL    ExecuteSequenceRun;
 typedef struct tagMSISCRIPT
 {
     LPWSTR  *Actions[TOTAL_SCRIPTS];
     UINT    ActionCount[TOTAL_SCRIPTS];
     BOOL    ExecuteSequenceRun;
-    BOOL    FindRelatedProductsRun;
     BOOL    CurrentlyScripting;
     BOOL    CurrentlyScripting;
+    UINT    InWhatSequence;
+    LPWSTR  *UniqueActions;
+    UINT    UniqueActionsCount;
 }MSISCRIPT;
 
 
 }MSISCRIPT;
 
 
@@ -234,6 +240,9 @@ void reduce_to_longfilename(WCHAR*);
 void reduce_to_shortfilename(WCHAR*);
 LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
 void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
 void reduce_to_shortfilename(WCHAR*);
 LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
 void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
+UINT register_unique_action(MSIPACKAGE *, LPCWSTR);
+BOOL check_unique_action(MSIPACKAGE *, LPCWSTR);
+WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
 
 
 /* control event stuff */
 
 
 /* control event stuff */
index 42ea8a4..4f080fa 100644 (file)
@@ -334,6 +334,13 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, BOOL *appFound,
             goto end;
         }
 
             goto end;
         }
 
+        /* bail out if the registry key is empty */
+        if (sz == 0)
+        {
+            rc = ERROR_SUCCESS;
+            goto end;
+        }
+        
         switch (regType)
         {
             case REG_SZ:
         switch (regType)
         {
             case REG_SZ:
index 17645e9..5475fa5 100644 (file)
@@ -36,6 +36,7 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/summa
 #include "wine/debug.h"
 #include "fdi.h"
 #include "msi.h"
 #include "wine/debug.h"
 #include "fdi.h"
 #include "msi.h"
+#include "msidefs.h"
 #include "msiquery.h"
 #include "fcntl.h"
 #include "objbase.h"
 #include "msiquery.h"
 #include "fcntl.h"
 #include "objbase.h"
@@ -74,6 +75,45 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source,
 static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
                                 LPCWSTR target, const INT type, LPCWSTR action);
 
 static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
                                 LPCWSTR target, const INT type, LPCWSTR action);
 
+
+static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
+{
+    if (!package->script)
+        return TRUE;
+
+    if ((options & msidbCustomActionTypeClientRepeat) == 
+            msidbCustomActionTypeClientRepeat)
+    {
+        if (!(package->script->InWhatSequence & SEQUENCE_UI &&
+            package->script->InWhatSequence & SEQUENCE_EXEC))
+        {
+            TRACE("Skipping action due to dbCustomActionTypeClientRepeat option.\n");
+            return FALSE;
+        }
+    }
+    else if (options & msidbCustomActionTypeFirstSequence)
+    {
+        if (package->script->InWhatSequence & SEQUENCE_UI &&
+            package->script->InWhatSequence & SEQUENCE_EXEC )
+        {
+            TRACE("Skipping action due to msidbCustomActionTypeFirstSequence option.\n");
+            return FALSE;
+        }
+    }
+    else if (options & msidbCustomActionTypeOncePerProcess)
+    {
+        if (check_unique_action(package,action))
+        {
+            TRACE("Skipping action due to msidbCustomActionTypeOncePerProcess option.\n");
+            return FALSE;
+        }
+        else
+            register_unique_action(package,action);
+    }
+
+    return TRUE;
+}
+
 UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
 {
     UINT rc = ERROR_SUCCESS;
 UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
 {
     UINT rc = ERROR_SUCCESS;
@@ -101,9 +141,15 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
           debugstr_w(source), debugstr_w(target));
 
     /* handle some of the deferred actions */
           debugstr_w(source), debugstr_w(target));
 
     /* handle some of the deferred actions */
-    if (type & 0x400)
+    if (type & msidbCustomActionTypeTSAware)
+        FIXME("msidbCustomActionTypeTSAware not handled\n");
+
+    if (type & msidbCustomActionTypeInScript)
     {
     {
-        if (type & 0x100)
+        if (type & msidbCustomActionTypeNoImpersonate)
+            FIXME("msidbCustomActionTypeNoImpersonate not handled\n");
+
+        if (type & msidbCustomActionTypeRollback)
         {
             FIXME("Rollback only action... rollbacks not supported yet\n");
             schedule_action(package, ROLLBACK_SCRIPT, action);
         {
             FIXME("Rollback only action... rollbacks not supported yet\n");
             schedule_action(package, ROLLBACK_SCRIPT, action);
@@ -114,7 +160,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
         }
         if (!execute)
         {
         }
         if (!execute)
         {
-            if (type & 0x200)
+            if (type & msidbCustomActionTypeCommit)
             {
                 TRACE("Deferring Commit Action!\n");
                 schedule_action(package, COMMIT_SCRIPT, action);
             {
                 TRACE("Deferring Commit Action!\n");
                 schedule_action(package, COMMIT_SCRIPT, action);
@@ -136,11 +182,16 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
 
             static const WCHAR szActionData[] = {
             'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0};
 
             static const WCHAR szActionData[] = {
             'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0};
+            static const WCHAR szBlank[] = {0};
             LPWSTR actiondata = load_dynamic_property(package,action,NULL);
             if (actiondata)
                 MSI_SetPropertyW(package,szActionData,actiondata);
             LPWSTR actiondata = load_dynamic_property(package,action,NULL);
             if (actiondata)
                 MSI_SetPropertyW(package,szActionData,actiondata);
+            else
+                MSI_SetPropertyW(package,szActionData,szBlank);
         }
     }
         }
     }
+    else if (!check_execution_scheduling_options(package,action,type))
+        return ERROR_SUCCESS;
 
     switch (type & CUSTOM_ACTION_TYPE_MASK)
     {
 
     switch (type & CUSTOM_ACTION_TYPE_MASK)
     {
@@ -304,7 +355,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type,
 {
     UINT rc = ERROR_SUCCESS;
 
 {
     UINT rc = ERROR_SUCCESS;
 
-    if (!(type & 0x80))
+    if (!(type & msidbCustomActionTypeAsync))
     {
         /* synchronous */
         TRACE("Synchronous Execution of action %s\n",debugstr_w(Name));
     {
         /* synchronous */
         TRACE("Synchronous Execution of action %s\n",debugstr_w(Name));
@@ -313,7 +364,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type,
         else
             msi_dialog_check_messages(ThreadHandle);
 
         else
             msi_dialog_check_messages(ThreadHandle);
 
-        if (!(type & 0x40))
+        if (!(type & msidbCustomActionTypeContinue))
         {
             if (ProcessHandle)
                 rc = process_action_return_value(2,ProcessHandle);
         {
             if (ProcessHandle)
                 rc = process_action_return_value(2,ProcessHandle);
@@ -331,7 +382,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type,
     {
         TRACE("Asynchronous Execution of action %s\n",debugstr_w(Name));
         /* asynchronous */
     {
         TRACE("Asynchronous Execution of action %s\n",debugstr_w(Name));
         /* asynchronous */
-        if (type & 0x40)
+        if (type & msidbCustomActionTypeContinue)
         {
             if (ProcessHandle)
             {
         {
             if (ProcessHandle)
             {
index 69e2b1e..be98cbc 100644 (file)
@@ -53,8 +53,9 @@ struct msi_control_tag
     msi_handler handler;
     LPWSTR property;
     LPWSTR value;
     msi_handler handler;
     LPWSTR property;
     LPWSTR value;
-    IPicture *pic;
+    HBITMAP hBitmap;
     HICON hIcon;
     HICON hIcon;
+    LPWSTR tabnext;
     WCHAR name[1];
 };
 
     WCHAR name[1];
 };
 
@@ -76,6 +77,7 @@ struct msi_dialog_tag
     LPWSTR default_font;
     msi_font *font_list;
     msi_control *control_list;
     LPWSTR default_font;
     msi_font *font_list;
     msi_control *control_list;
+    HWND hWndFocus;
     WCHAR name[1];
 };
 
     WCHAR name[1];
 };
 
@@ -143,6 +145,8 @@ static msi_control *msi_dialog_find_control( msi_dialog *dialog, LPCWSTR name )
 {
     msi_control *control;
 
 {
     msi_control *control;
 
+    if( !name )
+        return NULL;
     for( control = dialog->control_list; control; control = control->next )
         if( !strcmpW( control->name, name ) ) /* FIXME: case sensitive? */
             break;
     for( control = dialog->control_list; control; control = control->next )
         if( !strcmpW( control->name, name ) ) /* FIXME: case sensitive? */
             break;
@@ -297,8 +301,9 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
     control->handler = NULL;
     control->property = NULL;
     control->value = NULL;
     control->handler = NULL;
     control->property = NULL;
     control->value = NULL;
-    control->pic = NULL;
+    control->hBitmap = NULL;
     control->hIcon = NULL;
     control->hIcon = NULL;
+    control->tabnext = strdupW( MSI_RecordGetString( rec, 11) );
 
     x = MSI_RecordGetInteger( rec, 4 );
     y = MSI_RecordGetInteger( rec, 5 );
 
     x = MSI_RecordGetInteger( rec, 4 );
     y = MSI_RecordGetInteger( rec, 5 );
@@ -331,6 +336,97 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog,
     return control;
 }
 
     return control;
 }
 
+static MSIRECORD *msi_get_binary_record( MSIDATABASE *db, LPCWSTR name )
+{
+    const static WCHAR query[] = {
+        's','e','l','e','c','t',' ','*',' ',
+        'f','r','o','m',' ','B','i','n','a','r','y',' ',
+        'w','h','e','r','e',' ',
+            '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0
+    };
+
+    return MSI_QueryGetRecord( db, query, name );
+}
+
+static LPWSTR msi_create_tmp_path(void)
+{
+    WCHAR tmp[MAX_PATH];
+    LPWSTR path = NULL;
+    static const WCHAR prefix[] = { 'm','s','i',0 };
+    DWORD len, r;
+
+    r = GetTempPathW( MAX_PATH, tmp );
+    if( !r )
+        return path;
+    len = lstrlenW( tmp ) + 20;
+    path = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
+    if( path )
+    {
+        r = GetTempFileNameW( tmp, prefix, 0, path );
+        if (!r)
+        {
+            HeapFree( GetProcessHeap(), 0, path );
+            path = NULL;
+        }
+    }
+    return path;
+}
+
+
+static HANDLE msi_load_image( MSIDATABASE *db, LPCWSTR name, UINT type,
+                              UINT cx, UINT cy, UINT flags )
+{
+    MSIRECORD *rec = NULL;
+    HANDLE himage = NULL;
+    LPWSTR tmp;
+    UINT r;
+
+    TRACE("%p %s %u %u %08x\n", db, debugstr_w(name), cx, cy, flags);
+
+    tmp = msi_create_tmp_path();
+    if( !tmp )
+        return himage;
+
+    rec = msi_get_binary_record( db, name );
+    if( rec )
+    {
+        r = MSI_RecordStreamToFile( rec, 2, tmp );
+        if( r == ERROR_SUCCESS )
+        {
+            himage = LoadImageW( 0, tmp, type, cx, cy, flags );
+            DeleteFileW( tmp );
+        }
+        msiobj_release( &rec->hdr );
+    }
+
+    HeapFree( GetProcessHeap(), 0, tmp );
+    return himage;
+}
+
+static HICON msi_load_icon( MSIDATABASE *db, LPCWSTR text, UINT attributes )
+{
+    DWORD cx = 0, cy = 0, flags;
+
+    flags = LR_LOADFROMFILE | LR_DEFAULTSIZE;
+    if( attributes & msidbControlAttributesFixedSize )
+    {
+        flags &= ~LR_DEFAULTSIZE;
+        if( attributes & msidbControlAttributesIconSize16 )
+        {
+            cx += 16;
+            cy += 16;
+        }
+        if( attributes & msidbControlAttributesIconSize32 )
+        {
+            cx += 32;
+            cy += 32;
+        }
+        /* msidbControlAttributesIconSize48 handled by above logic */
+    }
+    return msi_load_image( db, text, IMAGE_ICON, cx, cy, flags );
+}
+
+
 /* called from the Control Event subscription code */
 void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, 
                               LPCWSTR attribute, MSIRECORD *rec )
 /* called from the Control Event subscription code */
 void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control, 
                               LPCWSTR attribute, MSIRECORD *rec )
@@ -475,12 +571,28 @@ static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec )
 static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec )
 {
     msi_control *control;
 static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec )
 {
     msi_control *control;
+    UINT attributes, style;
+    LPCWSTR text;
 
     TRACE("%p %p\n", dialog, rec);
 
 
     TRACE("%p %p\n", dialog, rec);
 
-    control = msi_dialog_add_control( dialog, rec, szButton, WS_TABSTOP );
+    style = WS_TABSTOP;
+    attributes = MSI_RecordGetInteger( rec, 8 );
+    if( attributes & msidbControlAttributesIcon )
+        style |= BS_ICON;
+
+    control = msi_dialog_add_control( dialog, rec, szButton, style );
+    if( !control )
+        return ERROR_FUNCTION_FAILED;
+
     control->handler = msi_dialog_button_handler;
 
     control->handler = msi_dialog_button_handler;
 
+    /* set the icon */
+    text = MSI_RecordGetString( rec, 10 );
+    control->hIcon = msi_load_icon( dialog->package->db, text, attributes );
+    if( attributes & msidbControlAttributesIcon )
+        SendMessageW( control->hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM) control->hIcon );
+
     return ERROR_SUCCESS;
 }
 
     return ERROR_SUCCESS;
 }
 
@@ -611,161 +723,56 @@ static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec )
     return ERROR_SUCCESS;
 }
 
     return ERROR_SUCCESS;
 }
 
-static MSIRECORD *msi_get_binary_record( MSIDATABASE *db, LPCWSTR name )
-{
-    const static WCHAR query[] = {
-        's','e','l','e','c','t',' ','*',' ',
-        'f','r','o','m',' ','B','i','n','a','r','y',' ',
-        'w','h','e','r','e',' ',
-            '`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0
-    };
-
-    return MSI_QueryGetRecord( db, query, name );
-}
-
-static UINT msi_load_bitmap( MSIDATABASE *db, LPCWSTR name, IPicture **pic )
-{
-    MSIRECORD *rec = NULL;
-    IStream *stm = NULL;
-    UINT r;
-
-    rec = msi_get_binary_record( db, name );
-    if( !rec )
-        return ERROR_FUNCTION_FAILED;
-
-    r = MSI_RecordGetIStream( rec, 2, &stm );
-    msiobj_release( &rec->hdr );
-    if( r != ERROR_SUCCESS )
-        return r;
-
-    r = OleLoadPicture( stm, 0, TRUE, &IID_IPicture, (LPVOID*) pic );
-    IStream_Release( stm );
-    if( FAILED( r ) )
-        return ERROR_FUNCTION_FAILED;
-
-    return ERROR_SUCCESS;
-}
-
 static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec )
 {
 static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec )
 {
-    IPicture *pic = NULL;
+    UINT cx, cy, flags, style, attributes;
     msi_control *control;
     msi_control *control;
-    OLE_HANDLE hBitmap = 0;
     LPCWSTR text;
     LPCWSTR text;
-    UINT r;
 
 
-    control = msi_dialog_add_control( dialog, rec, szStatic,
-                            SS_BITMAP | SS_LEFT | SS_CENTERIMAGE );
-    text = MSI_RecordGetString( rec, 10 );
-    r = msi_load_bitmap( dialog->package->db, text, &pic );
-    if( r == ERROR_SUCCESS )
-    {
-        r = IPicture_get_Handle( pic, &hBitmap );
-        if( SUCCEEDED( r ) )
-            SendMessageW( control->hwnd, STM_SETIMAGE, IMAGE_BITMAP, hBitmap );
-        control->pic = pic;
-    }
-    
-    return ERROR_SUCCESS;
-}
-
-static LPWSTR msi_create_tmp_path(void)
-{
-    WCHAR tmp[MAX_PATH];
-    LPWSTR path = NULL;
-    static const WCHAR prefix[] = { 'm','s','i',0 };
-    DWORD len, r;
+    flags = LR_LOADFROMFILE;
+    style = SS_BITMAP | SS_LEFT | WS_GROUP;
 
 
-    r = GetTempPathW( MAX_PATH, tmp );
-    if( !r )
-        return path;
-    len = lstrlenW( tmp ) + 20;
-    path = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
-    if( path )
-    {
-        r = GetTempFileNameW( tmp, prefix, 0, path );
-        if (!r)
-        {
-            HeapFree( GetProcessHeap(), 0, path );
-            path = NULL;
-        }
-    }
-    return path;
-}
-
-static UINT
-msi_load_icon( MSIDATABASE *db, LPCWSTR name, DWORD attributes, HICON *picon )
-{
-    UINT r = ERROR_FUNCTION_FAILED;
-    LPWSTR tmp;
-    MSIRECORD *rec;
-    HICON hicon = 0;
-
-    TRACE("loading %s\n", debugstr_w( name ) );
-
-    tmp = msi_create_tmp_path();
-    if( !tmp )
-        return r;
-
-    rec = msi_get_binary_record( db, name );
-    if( rec )
+    attributes = MSI_RecordGetInteger( rec, 8 );
+    if( attributes & msidbControlAttributesFixedSize )
     {
     {
-        r = MSI_RecordStreamToFile( rec, 2, tmp );
-        if( r == ERROR_SUCCESS )
-        {
-            DWORD cx = 0, cy = 0, flags = LR_LOADFROMFILE | LR_DEFAULTSIZE;
-            
-            if( attributes & msidbControlAttributesFixedSize )
-            {
-                flags &= ~LR_DEFAULTSIZE;
-                if( attributes & msidbControlAttributesIconSize16 )
-                {
-                    cx += 16;
-                    cy += 16;
-                }
-                if( attributes & msidbControlAttributesIconSize32 )
-                {
-                    cx += 32;
-                    cy += 32;
-                }
-                /* msidbControlAttributesIconSize48 handled by above logic */
-            }
-            
-            hicon = LoadImageW( 0, tmp, IMAGE_ICON, cx, cy, flags );
-            if( hicon )
-                *picon = hicon;
-            else
-                ERR("failed to load icon from %s\n", debugstr_w( tmp ));
-            DeleteFileW( tmp );
-        }
-        msiobj_release( &rec->hdr );
+        flags |= LR_DEFAULTSIZE;
+        style |= SS_CENTERIMAGE;
     }
 
     }
 
-    HeapFree( GetProcessHeap(), 0, tmp );
-
-    return r;
+    control = msi_dialog_add_control( dialog, rec, szStatic, style );
+    text = MSI_RecordGetString( rec, 10 );
+    cx = MSI_RecordGetInteger( rec, 6 );
+    cy = MSI_RecordGetInteger( rec, 7 );
+    cx = msi_dialog_scale_unit( dialog, cx );
+    cy = msi_dialog_scale_unit( dialog, cy );
+
+    control->hBitmap = msi_load_image( dialog->package->db, text,
+                                       IMAGE_BITMAP, cx, cy, flags );
+    if( control->hBitmap )
+        SendMessageW( control->hwnd, STM_SETIMAGE,
+                      IMAGE_BITMAP, (LPARAM) control->hBitmap );
+    else
+        ERR("Failed to load bitmap %s\n", debugstr_w(text));
+    
+    return ERROR_SUCCESS;
 }
 
 static UINT msi_dialog_icon_control( msi_dialog *dialog, MSIRECORD *rec )
 {
     msi_control *control;
     DWORD attributes;
 }
 
 static UINT msi_dialog_icon_control( msi_dialog *dialog, MSIRECORD *rec )
 {
     msi_control *control;
     DWORD attributes;
-    HICON hIcon = 0;
     LPCWSTR text;
     LPCWSTR text;
-    UINT r;
 
     TRACE("\n");
 
     control = msi_dialog_add_control( dialog, rec, szStatic,
                             SS_ICON | SS_CENTERIMAGE | WS_GROUP );
 
     TRACE("\n");
 
     control = msi_dialog_add_control( dialog, rec, szStatic,
                             SS_ICON | SS_CENTERIMAGE | WS_GROUP );
-    text = MSI_RecordGetString( rec, 10 );
+            
     attributes = MSI_RecordGetInteger( rec, 8 );
     attributes = MSI_RecordGetInteger( rec, 8 );
-    r = msi_load_icon( dialog->package->db, text, attributes, &hIcon );
-    if( r == ERROR_SUCCESS )
-    {
-        r = SendMessageW( control->hwnd, STM_SETICON, (WPARAM) hIcon, 0 );
-        control->hIcon = hIcon;
-    }
+    text = MSI_RecordGetString( rec, 10 );
+    control->hIcon = msi_load_icon( dialog->package->db, text, attributes );
+    if( control->hIcon )
+        SendMessageW( control->hwnd, STM_SETICON, (WPARAM) control->hIcon, 0 );
     else
         ERR("Failed to load bitmap %s\n", debugstr_w(text));
     return ERROR_SUCCESS;
     else
         ERR("Failed to load bitmap %s\n", debugstr_w(text));
     return ERROR_SUCCESS;
@@ -853,6 +860,28 @@ static void msi_mask_control_change( struct msi_maskedit_info *info )
     HeapFree( GetProcessHeap(), 0, val );
 }
 
     HeapFree( GetProcessHeap(), 0, val );
 }
 
+/* now move to the next control if necessary */
+static VOID msi_mask_next_control( struct msi_maskedit_info *info, HWND hWnd )
+{
+    HWND hWndNext;
+    UINT len, i;
+
+    for( i=0; i<info->num_groups; i++ )
+        if( info->group[i].hwnd == hWnd )
+            break;
+
+    /* don't move from the last control */
+    if( i >= (info->num_groups-1) )
+        return;
+
+    len = SendMessageW( hWnd, WM_GETTEXTLENGTH, 0, 0 );
+    if( len < info->group[i].len )
+        return;
+
+    hWndNext = GetNextDlgTabItem( GetParent( hWnd ), hWnd, FALSE );
+    SetFocus( hWndNext );
+}
+
 static LRESULT WINAPI
 MSIMaskedEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 static LRESULT WINAPI
 MSIMaskedEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
@@ -869,7 +898,10 @@ MSIMaskedEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
     {
     case WM_COMMAND:
         if (HIWORD(wParam) == EN_CHANGE)
     {
     case WM_COMMAND:
         if (HIWORD(wParam) == EN_CHANGE)
+        {
             msi_mask_control_change( info );
             msi_mask_control_change( info );
+            msi_mask_next_control( info, (HWND) lParam );
+        }
         break;
     case WM_NCDESTROY:
         HeapFree( GetProcessHeap(), 0, info->prop );
         break;
     case WM_NCDESTROY:
         HeapFree( GetProcessHeap(), 0, info->prop );
@@ -1351,6 +1383,39 @@ static void msi_dialog_adjust_dialog_size( msi_dialog *dialog, LPSIZE sz )
     sz->cy = rect.bottom - rect.top;
 }
 
     sz->cy = rect.bottom - rect.top;
 }
 
+static BOOL msi_control_set_next( msi_control *control, msi_control *next )
+{
+    return SetWindowPos( next->hwnd, control->hwnd, 0, 0, 0, 0,
+                         SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW |
+                         SWP_NOREPOSITION | SWP_NOSENDCHANGING | SWP_NOSIZE );
+}
+
+static UINT msi_dialog_set_tab_order( msi_dialog *dialog )
+{
+    msi_control *control, *tab_next;
+
+    for( control = dialog->control_list; control; control = control->next )
+    {
+        tab_next = msi_dialog_find_control( dialog, control->tabnext );
+        if( !tab_next )
+            continue;
+        msi_control_set_next( control, tab_next );
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static void msi_dialog_set_first_control( msi_dialog* dialog, LPCWSTR name )
+{
+    msi_control *control;
+
+    control = msi_dialog_find_control( dialog, name );
+    if( control )
+        dialog->hWndFocus = control->hwnd;
+    else
+        dialog->hWndFocus = NULL;
+}
+
 static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
 {
     static const WCHAR df[] = {
 static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
 {
     static const WCHAR df[] = {
@@ -1390,11 +1455,13 @@ static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs )
                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW );
 
     HeapFree( GetProcessHeap(), 0, title );
                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW );
 
     HeapFree( GetProcessHeap(), 0, title );
-    msiobj_release( &rec->hdr );
 
     msi_dialog_build_font_list( dialog );
     msi_dialog_fill_controls( dialog );
     msi_dialog_evaluate_control_conditions( dialog );
 
     msi_dialog_build_font_list( dialog );
     msi_dialog_fill_controls( dialog );
     msi_dialog_evaluate_control_conditions( dialog );
+    msi_dialog_set_tab_order( dialog );
+    msi_dialog_set_first_control( dialog, MSI_RecordGetString( rec, 8 ) );
+    msiobj_release( &rec->hdr );
 
     return 0;
 }
 
     return 0;
 }
@@ -1617,6 +1684,16 @@ static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd
     return 0;
 }
 
     return 0;
 }
 
+static void msi_dialog_setfocus( msi_dialog *dialog )
+{
+    HWND hwnd = dialog->hWndFocus;
+
+    hwnd = GetNextDlgTabItem( dialog->hwnd, hwnd, TRUE);
+    hwnd = GetNextDlgTabItem( dialog->hwnd, hwnd, FALSE);
+    SetFocus( hwnd );
+    dialog->hWndFocus = hwnd;
+}
+
 static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
                 WPARAM wParam, LPARAM lParam )
 {
 static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
                 WPARAM wParam, LPARAM lParam )
 {
@@ -1632,6 +1709,17 @@ static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
     case WM_COMMAND:
         return msi_dialog_oncommand( dialog, wParam, (HWND)lParam );
 
     case WM_COMMAND:
         return msi_dialog_oncommand( dialog, wParam, (HWND)lParam );
 
+    case WM_ACTIVATE:
+        if( LOWORD(wParam) == WA_INACTIVE )
+            dialog->hWndFocus = GetFocus();
+        else
+            msi_dialog_setfocus( dialog );
+        return 0;
+
+    case WM_SETFOCUS:
+        msi_dialog_setfocus( dialog );
+        return 0;
+
     /* bounce back to our subclassed static control */
     case WM_CTLCOLORSTATIC:
         return SendMessageW( (HWND) lParam, WM_CTLCOLORSTATIC, wParam, lParam );
     /* bounce back to our subclassed static control */
     case WM_CTLCOLORSTATIC:
         return SendMessageW( (HWND) lParam, WM_CTLCOLORSTATIC, wParam, lParam );
@@ -1821,10 +1909,11 @@ void msi_dialog_destroy( msi_dialog *dialog )
         /* leave dialog->hwnd - destroying parent destroys child windows */
         HeapFree( GetProcessHeap(), 0, t->property );
         HeapFree( GetProcessHeap(), 0, t->value );
         /* leave dialog->hwnd - destroying parent destroys child windows */
         HeapFree( GetProcessHeap(), 0, t->property );
         HeapFree( GetProcessHeap(), 0, t->value );
-        if( t->pic )
-            IPicture_Release( t->pic );
+        if( t->hBitmap )
+            DeleteObject( t->hBitmap );
         if( t->hIcon )
             DestroyIcon( t->hIcon );
         if( t->hIcon )
             DestroyIcon( t->hIcon );
+        HeapFree( GetProcessHeap(), 0, t->tabnext );
         HeapFree( GetProcessHeap(), 0, t );
     }
 
         HeapFree( GetProcessHeap(), 0, t );
     }
 
index 6d6682b..1c44b95 100644 (file)
@@ -57,21 +57,23 @@ UINT ControlEvent_HandleControlEvent(MSIPACKAGE *, LPCWSTR, LPCWSTR, msi_dialog*
 /*
  * Create a dialog box and run it if it's modal
  */
 /*
  * Create a dialog box and run it if it's modal
  */
-static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name )
+static UINT event_do_dialog( MSIPACKAGE *package, LPCWSTR name, BOOL destroy_modeless )
 {
     msi_dialog *dialog;
     UINT r;
 
 {
     msi_dialog *dialog;
     UINT r;
 
-    /* kill the current modeless dialog */
-    if( package->dialog )
-        msi_dialog_destroy( package->dialog );
-    package->dialog = NULL;
-
     /* create a new dialog */
     dialog = msi_dialog_create( package, name,
                                 ControlEvent_HandleControlEvent );
     if( dialog )
     {
     /* create a new dialog */
     dialog = msi_dialog_create( package, name,
                                 ControlEvent_HandleControlEvent );
     if( dialog )
     {
+        /* kill the current modeless dialog */
+        if( destroy_modeless && package->dialog )
+        {
+            msi_dialog_destroy( package->dialog );
+            package->dialog = NULL;
+        }
+
         /* modeless dialogs return an error message */
         r = msi_dialog_run_message_loop( dialog );
         if( r == ERROR_SUCCESS )
         /* modeless dialogs return an error message */
         r = msi_dialog_run_message_loop( dialog );
         if( r == ERROR_SUCCESS )
@@ -139,7 +141,8 @@ static UINT ControlEvent_NewDialog(MSIPACKAGE* package, LPCWSTR argument,
 static UINT ControlEvent_SpawnDialog(MSIPACKAGE* package, LPCWSTR argument, 
                               msi_dialog *dialog)
 {
 static UINT ControlEvent_SpawnDialog(MSIPACKAGE* package, LPCWSTR argument, 
                               msi_dialog *dialog)
 {
-    event_do_dialog( package, argument );
+    /* don't destroy a modeless dialogs that might be our parent */
+    event_do_dialog( package, argument, FALSE );
     if( package->CurrentInstallState != ERROR_SUCCESS )
         msi_dialog_end_dialog( dialog );
     return ERROR_SUCCESS;
     if( package->CurrentInstallState != ERROR_SUCCESS )
         msi_dialog_end_dialog( dialog );
     return ERROR_SUCCESS;
@@ -339,13 +342,13 @@ UINT ACTION_DialogBox( MSIPACKAGE* package, LPCWSTR szDialogName )
      *  dialog, as it returns ERROR_IO_PENDING when we try to run
      *  its message loop.
      */
      *  dialog, as it returns ERROR_IO_PENDING when we try to run
      *  its message loop.
      */
-    r = event_do_dialog( package, szDialogName );
+    r = event_do_dialog( package, szDialogName, TRUE );
     while( r == ERROR_SUCCESS && package->next_dialog )
     {
         LPWSTR name = package->next_dialog;
 
         package->next_dialog = NULL;
     while( r == ERROR_SUCCESS && package->next_dialog )
     {
         LPWSTR name = package->next_dialog;
 
         package->next_dialog = NULL;
-        r = event_do_dialog( package, name );
+        r = event_do_dialog( package, name, TRUE );
         HeapFree( GetProcessHeap(), 0, name );
     }
 
         HeapFree( GetProcessHeap(), 0, name );
     }
 
index a4fd40e..c7f0862 100644 (file)
@@ -37,6 +37,7 @@
 #include "winerror.h"
 #include "wine/debug.h"
 #include "fdi.h"
 #include "winerror.h"
 #include "wine/debug.h"
 #include "fdi.h"
+#include "msi.h"
 #include "msidefs.h"
 #include "msvcrt/fcntl.h"
 #include "msipriv.h"
 #include "msidefs.h"
 #include "msvcrt/fcntl.h"
 #include "msipriv.h"
@@ -359,7 +360,81 @@ static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, MSICOMPONENT*
         file->SourcePath = build_directory_name(2, path, file->File);
 }
 
         file->SourcePath = build_directory_name(2, path, file->File);
 }
 
-static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
+static BOOL check_volume(LPCWSTR path, LPCWSTR want_volume, LPWSTR volume, 
+        UINT *intype)
+{
+    WCHAR drive[4];
+    WCHAR name[MAX_PATH];
+    UINT type;
+
+    if (!(path[0] && path[1] == ':'))
+        return TRUE;
+
+    drive[0] = path[0];
+    drive[1] = path[1];
+    drive[2] = '\\';
+    drive[3] = 0;
+    TRACE("Checking volume %s .. (%s)\n",debugstr_w(drive), debugstr_w(want_volume));
+    type = GetDriveTypeW(drive);
+    TRACE("drive is of type %x\n",type);
+
+    if (type == DRIVE_UNKNOWN || type == DRIVE_NO_ROOT_DIR || 
+            type == DRIVE_FIXED || type == DRIVE_RAMDISK)
+        return TRUE;
+
+    GetVolumeInformationW(drive, name, MAX_PATH, NULL, NULL, NULL, NULL, 0);
+    TRACE("Drive contains %s\n", debugstr_w(name));
+    volume = strdupW(name);
+    if (*intype)
+        *intype=type;
+    return (strcmpiW(want_volume,name)==0);
+}
+
+static BOOL check_for_sourcefile(LPCWSTR source)
+{
+    DWORD attrib = GetFileAttributesW(source);
+    return (!(attrib == INVALID_FILE_ATTRIBUTES));
+}
+
+static UINT ready_volume(MSIPACKAGE* package, LPCWSTR path, LPWSTR last_volume, 
+                         MSIRECORD *row,UINT *type )
+{
+    LPWSTR volume = NULL; 
+    LPCWSTR want_volume = MSI_RecordGetString(row, 5);
+    BOOL ok = check_volume(path, want_volume, volume, type);
+
+    TRACE("Readying Volume for %s (%s, %s)\n",debugstr_w(path), debugstr_w(want_volume), debugstr_w(last_volume));
+
+    if (check_for_sourcefile(path) && !ok)
+    {
+        FIXME("Found the Sourcefile but not on the correct volume.(%s,%s,%s)\n",
+                debugstr_w(path),debugstr_w(want_volume), debugstr_w(volume));
+        return ERROR_SUCCESS;
+    }
+
+    while (!ok)
+    {
+        INT rc;
+        LPCWSTR prompt;
+        LPWSTR msg;
+      
+        prompt = MSI_RecordGetString(row,3);
+        msg = generate_error_string(package, 1302, 1, prompt);
+        rc = MessageBoxW(NULL,msg,NULL,MB_OKCANCEL);
+        HeapFree(GetProcessHeap(),0,volume);
+        HeapFree(GetProcessHeap(),0,msg);
+        if (rc == IDOK)
+            ok = check_for_sourcefile(path);
+        else
+            return ERROR_INSTALL_USEREXIT;
+    }
+
+    HeapFree(GetProcessHeap(),0,last_volume);
+    last_volume = strdupW(volume);
+    return ERROR_SUCCESS;
+}
+
+static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, 
                                  MSICOMPONENT* comp)
 {
     UINT rc = ERROR_SUCCESS;
                                  MSICOMPONENT* comp)
 {
     UINT rc = ERROR_SUCCESS;
@@ -371,17 +446,27 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
          '`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ','>','=',
          ' ','%', 'i',' ','O','R','D','E','R',' ','B','Y',' ',
          '`','L','a','s','t','S','e','q','u','e','n','c','e','`',0};
          '`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ','>','=',
          ' ','%', 'i',' ','O','R','D','E','R',' ','B','Y',' ',
          '`','L','a','s','t','S','e','q','u','e','n','c','e','`',0};
-    LPCWSTR cab;
+    LPCWSTR cab, volume;
     DWORD sz;
     INT seq;
     static UINT last_sequence = 0; 
     DWORD sz;
     INT seq;
     static UINT last_sequence = 0; 
+    static LPWSTR last_volume = NULL;
     static LPWSTR last_path = NULL;
     MSIFILE* file = NULL;
     static LPWSTR last_path = NULL;
     MSIFILE* file = NULL;
+    UINT type;
+    LPCWSTR prompt;
+    static DWORD count = 0;
 
     /* cleanup signal */
     if (!package)
     {
         HeapFree(GetProcessHeap(),0,last_path);
 
     /* cleanup signal */
     if (!package)
     {
         HeapFree(GetProcessHeap(),0,last_path);
+        HeapFree(GetProcessHeap(),0,last_volume);
+        last_sequence = 0;
+        last_path = NULL;
+        last_volume = NULL;
+        count = 0;
+        memset(source,0,sizeof(source));
         return ERROR_SUCCESS;
     }
 
         return ERROR_SUCCESS;
     }
 
@@ -394,6 +479,7 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
         return ERROR_SUCCESS;
     }
 
         return ERROR_SUCCESS;
     }
 
+    count ++;
     row = MSI_QueryGetRecord(package->db, ExecSeqQuery, file->Sequence);
     if (!row)
     {
     row = MSI_QueryGetRecord(package->db, ExecSeqQuery, file->Sequence);
     if (!row)
     {
@@ -404,6 +490,9 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
     seq = MSI_RecordGetInteger(row,2);
     last_sequence = seq;
 
     seq = MSI_RecordGetInteger(row,2);
     last_sequence = seq;
 
+    volume = MSI_RecordGetString(row, 5);
+    prompt = MSI_RecordGetString(row, 3);
+
     HeapFree(GetProcessHeap(),0,last_path);
     last_path = NULL;
 
     HeapFree(GetProcessHeap(),0,last_path);
     last_path = NULL;
 
@@ -411,6 +500,23 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
     {
         last_path = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
         set_file_source(package,file,comp,last_path);
     {
         last_path = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
         set_file_source(package,file,comp,last_path);
+        rc = ready_volume(package, file->SourcePath, last_volume, row,&type);
+
+        MsiSourceListAddMediaDiskW(package->ProductCode, NULL, 
+            MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, count, volume,
+            prompt);
+
+        if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM || 
+                type == DRIVE_RAMDISK)
+            MsiSourceListSetInfoW(package->ProductCode, NULL, 
+                MSIINSTALLCONTEXT_USERMANAGED, 
+                MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
+                INSTALLPROPERTY_LASTUSEDSOURCEW, last_path);
+        else
+            MsiSourceListSetInfoW(package->ProductCode, NULL, 
+                MSIINSTALLCONTEXT_USERMANAGED, 
+                MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                INSTALLPROPERTY_LASTUSEDSOURCEW, last_path);
         msiobj_release(&row->hdr);
         return rc;
     }
         msiobj_release(&row->hdr);
         return rc;
     }
@@ -422,9 +528,24 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
         /* the stream does not contain the # character */
         if (cab[0]=='#')
         {
         /* the stream does not contain the # character */
         if (cab[0]=='#')
         {
+            LPWSTR path;
+
             writeout_cabinet_stream(package,&cab[1],source);
             last_path = strdupW(source);
             *(strrchrW(last_path,'\\')+1)=0;
             writeout_cabinet_stream(package,&cab[1],source);
             last_path = strdupW(source);
             *(strrchrW(last_path,'\\')+1)=0;
+
+            path = load_dynamic_property(package,cszSourceDir,NULL);
+
+            MsiSourceListAddMediaDiskW(package->ProductCode, NULL, 
+                MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, count,
+                volume, prompt);
+
+            MsiSourceListSetInfoW(package->ProductCode, NULL,
+                MSIINSTALLCONTEXT_USERMANAGED,
+                MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                INSTALLPROPERTY_LASTUSEDSOURCEW, path);
+
+            HeapFree(GetProcessHeap(),0,path);
         }
         else
         {
         }
         else
         {
@@ -439,6 +560,20 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
             {
                 strcpyW(last_path,source);
                 strcatW(source,cab);
             {
                 strcpyW(last_path,source);
                 strcatW(source,cab);
+
+                rc = ready_volume(package, source, last_volume, row, &type);
+                if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM || 
+                        type == DRIVE_RAMDISK)
+                    MsiSourceListSetInfoW(package->ProductCode, NULL,
+                            MSIINSTALLCONTEXT_USERMANAGED,
+                            MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
+                            INSTALLPROPERTY_LASTUSEDSOURCEW, last_path);
+                else
+                    MsiSourceListSetInfoW(package->ProductCode, NULL,
+                            MSIINSTALLCONTEXT_USERMANAGED,
+                            MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                            INSTALLPROPERTY_LASTUSEDSOURCEW, last_path);
+
                 /* extract the cab file into a folder in the temp folder */
                 sz = MAX_PATH;
                 if (MSI_GetPropertyW(package, cszTempFolder,last_path, &sz) 
                 /* extract the cab file into a folder in the temp folder */
                 sz = MAX_PATH;
                 if (MSI_GetPropertyW(package, cszTempFolder,last_path, &sz) 
@@ -456,8 +591,26 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex,
         last_path = HeapAlloc(GetProcessHeap(),0,MAX_PATH*sizeof(WCHAR));
         MSI_GetPropertyW(package,cszSourceDir,source,&sz);
         strcpyW(last_path,source);
         last_path = HeapAlloc(GetProcessHeap(),0,MAX_PATH*sizeof(WCHAR));
         MSI_GetPropertyW(package,cszSourceDir,source,&sz);
         strcpyW(last_path,source);
+        rc = ready_volume(package, last_path, last_volume, row, &type);
+
+        if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM || 
+                type == DRIVE_RAMDISK)
+            MsiSourceListSetInfoW(package->ProductCode, NULL,
+                    MSIINSTALLCONTEXT_USERMANAGED,
+                    MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
+                    INSTALLPROPERTY_LASTUSEDSOURCEW, last_path);
+        else
+            MsiSourceListSetInfoW(package->ProductCode, NULL,
+                    MSIINSTALLCONTEXT_USERMANAGED,
+                    MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                    INSTALLPROPERTY_LASTUSEDSOURCEW, last_path);
     }
     set_file_source(package, file, comp, last_path);
     }
     set_file_source(package, file, comp, last_path);
+
+    MsiSourceListAddMediaDiskW(package->ProductCode, NULL,
+            MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, count, volume,
+            prompt);
+
     msiobj_release(&row->hdr);
 
     return rc;
     msiobj_release(&row->hdr);
 
     return rc;
@@ -499,6 +652,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
 {
     UINT rc = ERROR_SUCCESS;
     DWORD index;
 {
     UINT rc = ERROR_SUCCESS;
     DWORD index;
+    LPWSTR ptr;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -506,6 +660,18 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
     /* increment progress bar each time action data is sent */
     ui_progress(package,1,1,0,0);
 
     /* increment progress bar each time action data is sent */
     ui_progress(package,1,1,0,0);
 
+    /* handle the keys for the SouceList */
+    ptr = strrchrW(package->PackagePath,'\\');
+    if (ptr)
+    {
+        ptr ++;
+        MsiSourceListSetInfoW(package->ProductCode, NULL,
+                MSIINSTALLCONTEXT_USERMANAGED,
+                MSICODE_PRODUCT,
+                INSTALLPROPERTY_PACKAGENAMEW, ptr);
+    }
+    FIXME("Write DiskPrompt\n");
+    
     /* Pass 1 */
     for (index = 0; index < package->loaded_files; index++)
     {
     /* Pass 1 */
     for (index = 0; index < package->loaded_files; index++)
     {
index e9e12f1..f44e339 100644 (file)
@@ -40,7 +40,6 @@ static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
 static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
 
 const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
 static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
 
 const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
-const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0};
 const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
 const WCHAR cszbs[]={'\\',0};
 
 const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
 const WCHAR cszbs[]={'\\',0};
 
@@ -88,10 +87,8 @@ DWORD build_version_dword(LPCWSTR version_string)
 UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, 
                             LPWSTR *FilePath)
 {
 UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, 
                             LPWSTR *FilePath)
 {
-    LPWSTR ProductCode;
     LPWSTR SystemFolder;
     LPWSTR dest;
     LPWSTR SystemFolder;
     LPWSTR dest;
-    UINT rc;
 
     static const WCHAR szInstaller[] = 
         {'M','i','c','r','o','s','o','f','t','\\',
 
     static const WCHAR szInstaller[] = 
         {'M','i','c','r','o','s','o','f','t','\\',
@@ -99,20 +96,15 @@ UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
     static const WCHAR szFolder[] =
         {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
 
     static const WCHAR szFolder[] =
         {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
 
-    ProductCode = load_dynamic_property(package,szProductCode,&rc);
-    if (!ProductCode)
-        return rc;
-
     SystemFolder = load_dynamic_property(package,szFolder,NULL);
 
     SystemFolder = load_dynamic_property(package,szFolder,NULL);
 
-    dest = build_directory_name(3, SystemFolder, szInstaller, ProductCode);
+    dest = build_directory_name(3, SystemFolder, szInstaller, package->ProductCode);
 
     create_full_pathW(dest);
 
     *FilePath = build_directory_name(2, dest, icon_name);
 
     HeapFree(GetProcessHeap(),0,SystemFolder);
 
     create_full_pathW(dest);
 
     *FilePath = build_directory_name(2, dest, icon_name);
 
     HeapFree(GetProcessHeap(),0,SystemFolder);
-    HeapFree(GetProcessHeap(),0,ProductCode);
     HeapFree(GetProcessHeap(),0,dest);
     return ERROR_SUCCESS;
 }
     HeapFree(GetProcessHeap(),0,dest);
     return ERROR_SUCCESS;
 }
@@ -576,10 +568,17 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
         
             HeapFree(GetProcessHeap(),0,package->script->Actions[i]);
         }
         
             HeapFree(GetProcessHeap(),0,package->script->Actions[i]);
         }
+
+        for (i = 0; i < package->script->UniqueActionsCount; i++)
+            HeapFree(GetProcessHeap(),0,package->script->UniqueActions[i]);
+
+        HeapFree(GetProcessHeap(),0,package->script->UniqueActions);
         HeapFree(GetProcessHeap(),0,package->script);
     }
 
     HeapFree(GetProcessHeap(),0,package->PackagePath);
         HeapFree(GetProcessHeap(),0,package->script);
     }
 
     HeapFree(GetProcessHeap(),0,package->PackagePath);
+    HeapFree(GetProcessHeap(),0,package->msiFilePath);
+    HeapFree(GetProcessHeap(),0,package->ProductCode);
 
     /* cleanup control event subscriptions */
     ControlEvent_CleanupSubscriptions(package);
 
     /* cleanup control event subscriptions */
     ControlEvent_CleanupSubscriptions(package);
@@ -795,7 +794,6 @@ void reduce_to_shortfilename(WCHAR* filename)
 LPWSTR create_component_advertise_string(MSIPACKAGE* package, 
                 MSICOMPONENT* component, LPCWSTR feature)
 {
 LPWSTR create_component_advertise_string(MSIPACKAGE* package, 
                 MSICOMPONENT* component, LPCWSTR feature)
 {
-    LPWSTR productid=NULL;
     GUID clsid;
     WCHAR productid_85[21];
     WCHAR component_85[21];
     GUID clsid;
     WCHAR productid_85[21];
     WCHAR component_85[21];
@@ -814,8 +812,7 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package,
     memset(productid_85,0,sizeof(productid_85));
     memset(component_85,0,sizeof(component_85));
 
     memset(productid_85,0,sizeof(productid_85));
     memset(component_85,0,sizeof(component_85));
 
-    productid = load_dynamic_property(package,szProductCode,NULL);
-    CLSIDFromString(productid, &clsid);
+    CLSIDFromString(package->ProductCode, &clsid);
     
     encode_base85_guid(&clsid,productid_85);
 
     
     encode_base85_guid(&clsid,productid_85);
 
@@ -840,8 +837,6 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package,
         sprintfW(output,fmt2,productid_85,feature,component_85);
     else
         sprintfW(output,fmt1,productid_85,feature);
         sprintfW(output,fmt2,productid_85,feature,component_85);
     else
         sprintfW(output,fmt1,productid_85,feature);
-
-    HeapFree(GetProcessHeap(),0,productid);
     
     return output;
 }
     
     return output;
 }
@@ -911,3 +906,91 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
             component->Action, component->ActionRequest);
     } 
 }
             component->Action, component->ActionRequest);
     } 
 }
+
+UINT register_unique_action(MSIPACKAGE *package, LPCWSTR action)
+{
+    UINT count;
+    LPWSTR *newbuf = NULL;
+
+    if (!package || !package->script)
+        return FALSE;
+
+    TRACE("Registering Action %s as having fun\n",debugstr_w(action));
+    
+    count = package->script->UniqueActionsCount;
+    package->script->UniqueActionsCount++;
+    if (count != 0)
+        newbuf = HeapReAlloc(GetProcessHeap(),0,
+                        package->script->UniqueActions,
+                        package->script->UniqueActionsCount* sizeof(LPWSTR));
+    else
+        newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR));
+
+    newbuf[count] = strdupW(action);
+    package->script->UniqueActions = newbuf;
+
+   return ERROR_SUCCESS;
+}
+
+BOOL check_unique_action(MSIPACKAGE *package, LPCWSTR action)
+{
+    INT i;
+
+    if (!package || !package->script)
+        return FALSE;
+
+    for (i = 0; i < package->script->UniqueActionsCount; i++)
+        if (!strcmpW(package->script->UniqueActions[i],action))
+            return TRUE;
+
+    return FALSE;
+}
+
+WCHAR* generate_error_string(MSIPACKAGE *package, UINT error, DWORD count, ... )
+{
+    static const WCHAR query[] = {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ','F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ','%','i',0};
+
+    MSIRECORD *rec;
+    MSIRECORD *row;
+    DWORD size = 0;
+    DWORD i;
+    va_list va;
+    LPCWSTR str;
+    LPWSTR data;
+
+    row = MSI_QueryGetRecord(package->db, query, error);
+    if (!row)
+        return 0;
+
+    rec = MSI_CreateRecord(count+2);
+
+    str = MSI_RecordGetString(row,1);
+    MSI_RecordSetStringW(rec,0,str);
+    msiobj_release( &row->hdr );
+    MSI_RecordSetInteger(rec,1,error);
+
+    va_start(va,count);
+    for (i = 0; i < count; i++)
+    {
+        str = va_arg(va,LPCWSTR);
+        MSI_RecordSetStringW(rec,(i+2),str);
+    }
+    va_end(va);
+
+    MSI_FormatRecordW(package,rec,NULL,&size);
+    if (size >= 0)
+    {
+        size++;
+        data = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
+        if (size > 1)
+            MSI_FormatRecordW(package,rec,data,&size);
+        else
+            data[0] = 0;
+        msiobj_release( &rec->hdr );
+        return data;
+    }
+
+    msiobj_release( &rec->hdr );
+    data = NULL;
+    return data;
+}
index 9b9ea41..78f02d0 100644 (file)
@@ -585,3 +585,26 @@ UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
     msiobj_release( &package->hdr );
     return ret;
 }
     msiobj_release( &package->hdr );
     return ret;
 }
+
+/***********************************************************************
+ * MsiGetLanguage (MSI.@)
+ */
+LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
+{
+    MSIPACKAGE* package;
+    LANGID langid;
+    LPWSTR buffer;
+    static const WCHAR szProductLanguage[] =
+        {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
+    
+    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    buffer = load_dynamic_property(package,szProductLanguage,NULL);
+    langid = atoiW(buffer);
+
+    HeapFree(GetProcessHeap(),0,buffer);
+    msiobj_release (&package->hdr);
+    return langid;
+}
index bec3ccb..cf3bf60 100644 (file)
@@ -83,9 +83,6 @@ UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
 
 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
 {
 
 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
 {
-    static const WCHAR szLocalPackage[] = {
-        'L','o','c','a','l','P','a','c','k','a','g','e', 0
-    };
     LPWSTR path = NULL;
     UINT r;
     HKEY hKeyProduct = NULL;
     LPWSTR path = NULL;
     UINT r;
     HKEY hKeyProduct = NULL;
@@ -102,7 +99,7 @@ UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
 
     /* find the size of the path */
     type = count = 0;
 
     /* find the size of the path */
     type = count = 0;
-    r = RegQueryValueExW( hKeyProduct, szLocalPackage,
+    r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
                           NULL, &type, NULL, &count );
     if( r != ERROR_SUCCESS )
     {
                           NULL, &type, NULL, &count );
     if( r != ERROR_SUCCESS )
     {
@@ -115,7 +112,7 @@ UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
     if( !path )
         goto end;
 
     if( !path )
         goto end;
 
-    r = RegQueryValueExW( hKeyProduct, szLocalPackage,
+    r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
                           NULL, &type, (LPBYTE) path, &count );
     if( r != ERROR_SUCCESS )
     {
                           NULL, &type, (LPBYTE) path, &count );
     if( r != ERROR_SUCCESS )
     {
@@ -202,6 +199,9 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
     MSIPACKAGE *package = NULL;
     UINT r;
     MSIHANDLE handle;
     MSIPACKAGE *package = NULL;
     UINT r;
     MSIHANDLE handle;
+    WCHAR path[MAX_PATH];
+    WCHAR filename[MAX_PATH];
+    static const WCHAR szMSI[] = {'M','S','I',0};
 
     FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
 
 
     FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
 
@@ -209,16 +209,31 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
     if (r != ERROR_SUCCESS)
         return r;
 
     if (r != ERROR_SUCCESS)
         return r;
 
-    r = MSI_OpenPackageW(szPackagePath,&package);
+    /* copy the msi file to a temp file to pervent locking a CD
+     * with a multi disc install 
+     */
+    GetTempPathW(MAX_PATH, path);
+    GetTempFileNameW(path, szMSI, 0, filename);
+
+    CopyFileW(szPackagePath, filename, FALSE);
+
+    TRACE("Opening relocated package %s\n",debugstr_w(filename));
+    r = MSI_OpenPackageW(filename, &package);
     if (r != ERROR_SUCCESS)
     if (r != ERROR_SUCCESS)
+    {
+        DeleteFileW(filename);
         return r;
         return r;
+    }
 
     handle = alloc_msihandle( &package->hdr );
 
 
     handle = alloc_msihandle( &package->hdr );
 
-    r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine);
+    r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine, 
+                                 filename);
 
     MsiCloseHandle(handle);
     msiobj_release( &package->hdr );
 
     MsiCloseHandle(handle);
     msiobj_release( &package->hdr );
+
+    DeleteFileW(filename);
     return r;
 }
 
     return r;
 }
 
@@ -256,13 +271,9 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
     MSIHANDLE handle = -1;
     MSIPACKAGE* package;
     UINT rc;
     MSIHANDLE handle = -1;
     MSIPACKAGE* package;
     UINT rc;
-    HKEY hkey=0,hkey1=0;
     DWORD sz;
     DWORD sz;
-    static const WCHAR szSouceList[] = {
-        'S','o','u','r','c','e','L','i','s','t',0};
-    static const WCHAR szLUS[] = {
-        'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
-    WCHAR sourcepath[0x200];
+    WCHAR sourcepath[MAX_PATH];
+    WCHAR filename[MAX_PATH];
     static const WCHAR szInstalled[] = {
         ' ','I','n','s','t','a','l','l','e','d','=','1',0};
     LPWSTR commandline;
     static const WCHAR szInstalled[] = {
         ' ','I','n','s','t','a','l','l','e','d','=','1',0};
     LPWSTR commandline;
@@ -277,20 +288,17 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
         return ERROR_CALL_NOT_IMPLEMENTED;
     }
 
         return ERROR_CALL_NOT_IMPLEMENTED;
     }
 
-    rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
-    if (rc != ERROR_SUCCESS)
-        goto end;
+    sz = sizeof(sourcepath);
+    MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 
+            MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
+            &sz);
 
 
-    rc = RegOpenKeyW(hkey,szSouceList,&hkey1);
-    if (rc != ERROR_SUCCESS)
-        goto end;
+    sz = sizeof(filename);
+    MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 
+            MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
 
 
-    sz = sizeof(sourcepath);
-    rc = RegQueryValueExW(hkey1, szLUS, NULL, NULL,(LPBYTE)sourcepath, &sz);
-    if (rc != ERROR_SUCCESS)
-        goto end;
+    strcatW(sourcepath,filename);
 
 
-    RegCloseKey(hkey1);
     /*
      * ok 1, we need to find the msi file for this product.
      *    2, find the source dir for the files
     /*
      * ok 1, we need to find the msi file for this product.
      *    2, find the source dir for the files
@@ -324,13 +332,12 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
     if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
         lstrcatW(commandline,szInstalled);
 
     if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
         lstrcatW(commandline,szInstalled);
 
-    rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline);
+    rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline, sourcepath);
 
     msiobj_release( &package->hdr );
 
     HeapFree(GetProcessHeap(),0,commandline);
 end:
 
     msiobj_release( &package->hdr );
 
     HeapFree(GetProcessHeap(),0,commandline);
 end:
-    RegCloseKey(hkey);
     if (handle != -1)
         MsiCloseHandle(handle);
 
     if (handle != -1)
         MsiCloseHandle(handle);
 
@@ -509,16 +516,8 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
 {
     MSIHANDLE hProduct;
     UINT r;
 {
     MSIHANDLE hProduct;
     UINT r;
-    static const WCHAR szPackageCode[] =
-        {'P','a','c','k','a','g','e','C','o','d','e',0};
-    static const WCHAR szVersionString[] =
-        {'V','e','r','s','i','o','n','S','t','r','i','n','g',0};
     static const WCHAR szProductVersion[] =
         {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
     static const WCHAR szProductVersion[] =
         {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
-    static const WCHAR szAssignmentType[] =
-        {'A','s','s','i','g','n','m','e','n','t','T','y','p','e',0};
-    static const WCHAR szLanguage[] =
-        {'L','a','n','g','u','a','g','e',0};
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
 
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
 
@@ -531,7 +530,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
         return ERROR_INVALID_PARAMETER;
     
     /* check for special properties */
         return ERROR_INVALID_PARAMETER;
     
     /* check for special properties */
-    if (strcmpW(szAttribute, szPackageCode)==0)
+    if (strcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW)==0)
     {
         HKEY hkey;
         WCHAR squished[GUID_SIZE];
     {
         HKEY hkey;
         WCHAR squished[GUID_SIZE];
@@ -542,7 +541,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
         if (r != ERROR_SUCCESS)
             return ERROR_UNKNOWN_PRODUCT;
 
         if (r != ERROR_SUCCESS)
             return ERROR_UNKNOWN_PRODUCT;
 
-        r = RegQueryValueExW(hkey, szPackageCode, NULL, NULL, 
+        r = RegQueryValueExW(hkey, INSTALLPROPERTY_PACKAGECODEW, NULL, NULL, 
                         (LPBYTE)squished, &sz);
         if (r != ERROR_SUCCESS)
         {
                         (LPBYTE)squished, &sz);
         if (r != ERROR_SUCCESS)
         {
@@ -563,7 +562,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
         RegCloseKey(hkey);
         r = ERROR_SUCCESS;
     }
         RegCloseKey(hkey);
         r = ERROR_SUCCESS;
     }
-    else if (strcmpW(szAttribute, szVersionString)==0)
+    else if (strcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW)==0)
     {
         r = MsiOpenProductW(szProduct, &hProduct);
         if (ERROR_SUCCESS != r)
     {
         r = MsiOpenProductW(szProduct, &hProduct);
         if (ERROR_SUCCESS != r)
@@ -572,7 +571,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
         r = MsiGetPropertyW(hProduct, szProductVersion, szBuffer, pcchValueBuf);
         MsiCloseHandle(hProduct);
     }
         r = MsiGetPropertyW(hProduct, szProductVersion, szBuffer, pcchValueBuf);
         MsiCloseHandle(hProduct);
     }
-    else if (strcmpW(szAttribute, szAssignmentType)==0)
+    else if (strcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW)==0)
     {
         FIXME("0 (zero) if advertised or per user , 1(one) if per machine.\n");
         if (szBuffer)
     {
         FIXME("0 (zero) if advertised or per user , 1(one) if per machine.\n");
         if (szBuffer)
@@ -584,7 +583,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
             *pcchValueBuf = 1;
         r = ERROR_SUCCESS;
     }
             *pcchValueBuf = 1;
         r = ERROR_SUCCESS;
     }
-    else if (strcmpW(szAttribute, szLanguage)==0)
+    else if (strcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW)==0)
     {
         r = MsiOpenProductW(szProduct, &hProduct);
         if (ERROR_SUCCESS != r)
     {
         r = MsiOpenProductW(szProduct, &hProduct);
         if (ERROR_SUCCESS != r)
@@ -835,14 +834,14 @@ LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
                 DWORD *pcchBuf)
 {
 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
                 DWORD *pcchBuf)
 {
-    FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf);
+    FIXME("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
     return INSTALLSTATE_UNKNOWN;
 }
 
 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
                 DWORD *pcchBuf)
 {
     return INSTALLSTATE_UNKNOWN;
 }
 
 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
                 DWORD *pcchBuf)
 {
-    FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf);
+    FIXME("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
     return INSTALLSTATE_UNKNOWN;
 }
 
     return INSTALLSTATE_UNKNOWN;
 }
 
@@ -1569,9 +1568,6 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
     HKEY hkey;
     DWORD sz;
     UINT rc = ERROR_SUCCESS,rc2 = ERROR_SUCCESS;
     HKEY hkey;
     DWORD sz;
     UINT rc = ERROR_SUCCESS,rc2 = ERROR_SUCCESS;
-    static const WCHAR szOwner[] = {'R','e','g','O','w','n','e','r',0};
-    static const WCHAR szCompany[] = {'R','e','g','C','o','m','p','a','n','y',0};
-    static const WCHAR szSerial[] = {'P','r','o','d','u','c','t','I','D',0};
 
     TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
           pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
 
     TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
           pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
@@ -1584,13 +1580,15 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
     if (lpUserNameBuf)
     {
         sz = *lpUserNameBuf * sizeof(WCHAR);
     if (lpUserNameBuf)
     {
         sz = *lpUserNameBuf * sizeof(WCHAR);
-        rc = RegQueryValueExW( hkey, szOwner, NULL, NULL, (LPBYTE)lpUserNameBuf,
+        rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL,
+                NULL, (LPBYTE)lpUserNameBuf,
                                &sz);
     }
     if (!lpUserNameBuf && pcchUserNameBuf)
     {
         sz = 0;
                                &sz);
     }
     if (!lpUserNameBuf && pcchUserNameBuf)
     {
         sz = 0;
-        rc = RegQueryValueExW( hkey, szOwner, NULL, NULL, NULL, &sz);
+        rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL,
+                NULL, NULL, &sz);
     }
 
     if (pcchUserNameBuf)
     }
 
     if (pcchUserNameBuf)
@@ -1599,13 +1597,14 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
     if (lpOrgNameBuf)
     {
         sz = *pcchOrgNameBuf * sizeof(WCHAR);
     if (lpOrgNameBuf)
     {
         sz = *pcchOrgNameBuf * sizeof(WCHAR);
-        rc2 = RegQueryValueExW( hkey, szCompany, NULL, NULL, 
-                               (LPBYTE)lpOrgNameBuf, &sz);
+        rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL,
+                NULL, (LPBYTE)lpOrgNameBuf, &sz);
     }
     if (!lpOrgNameBuf && pcchOrgNameBuf)
     {
         sz = 0;
     }
     if (!lpOrgNameBuf && pcchOrgNameBuf)
     {
         sz = 0;
-        rc2 = RegQueryValueExW( hkey, szCompany, NULL, NULL, NULL, &sz);
+        rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL,
+                NULL, NULL, &sz);
     }
 
     if (pcchOrgNameBuf)
     }
 
     if (pcchOrgNameBuf)
@@ -1621,13 +1620,14 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
     if (lpSerialBuf)
     {
         sz = *pcchSerialBuf * sizeof(WCHAR);
     if (lpSerialBuf)
     {
         sz = *pcchSerialBuf * sizeof(WCHAR);
-        RegQueryValueExW( hkey, szSerial, NULL, NULL, (LPBYTE)lpSerialBuf,
-                               &sz);
+        RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL, NULL,
+                (LPBYTE)lpSerialBuf, &sz);
     }
     if (!lpSerialBuf && pcchSerialBuf)
     {
         sz = 0;
     }
     if (!lpSerialBuf && pcchSerialBuf)
     {
         sz = 0;
-        rc = RegQueryValueExW( hkey, szSerial, NULL, NULL, NULL, &sz);
+        rc = RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL,
+                NULL, NULL, &sz);
     }
     if (pcchSerialBuf)
         *pcchSerialBuf = sz / sizeof(WCHAR);
     }
     if (pcchSerialBuf)
         *pcchSerialBuf = sz / sizeof(WCHAR);
index ecb7621..1cd5944 100644 (file)
@@ -60,7 +60,7 @@
 60 stdcall MsiGetFeatureUsageW(wstr wstr ptr ptr)\r
 61 stub MsiGetFeatureValidStatesA\r
 62 stub MsiGetFeatureValidStatesW\r
 60 stdcall MsiGetFeatureUsageW(wstr wstr ptr ptr)\r
 61 stub MsiGetFeatureValidStatesA\r
 62 stub MsiGetFeatureValidStatesW\r
-63 stub MsiGetLanguage\r
+63 stdcall MsiGetLanguage(long)\r
 64 stdcall MsiGetMode(long long)\r
 65 stdcall MsiGetProductCodeA(str str)\r
 66 stdcall MsiGetProductCodeW(wstr wstr)\r
 64 stdcall MsiGetMode(long long)\r
 65 stdcall MsiGetProductCodeA(str str)\r
 66 stdcall MsiGetProductCodeW(wstr wstr)\r
index 81bb068..ed7fdd2 100644 (file)
@@ -47,6 +47,7 @@
        <file>registry.c</file>
        <file>regsvr.c</file>
        <file>select.c</file>
        <file>registry.c</file>
        <file>regsvr.c</file>
        <file>select.c</file>
+       <file>source.c</file>
        <file>sql.tab.c</file>
        <file>string.c</file>
        <file>suminfo.c</file>
        <file>sql.tab.c</file>
        <file>string.c</file>
        <file>suminfo.c</file>
index dde6129..eaef4f5 100644 (file)
@@ -55,7 +55,7 @@ struct tagMSIOBJECTHDR
 {
     UINT magic;
     UINT type;
 {
     UINT magic;
     UINT type;
-    DWORD refcount;
+    LONG refcount;
     msihandledestructor destructor;
     struct tagMSIOBJECTHDR *next;
     struct tagMSIOBJECTHDR *prev;
     msihandledestructor destructor;
     struct tagMSIOBJECTHDR *next;
     struct tagMSIOBJECTHDR *prev;
@@ -216,6 +216,8 @@ typedef struct tagMSIPACKAGE
     UINT RunningActionCount;
 
     LPWSTR PackagePath;
     UINT RunningActionCount;
 
     LPWSTR PackagePath;
+    LPWSTR msiFilePath;
+    LPWSTR ProductCode;
 
     UINT CurrentInstallState;
     msi_dialog *dialog;
 
     UINT CurrentInstallState;
     msi_dialog *dialog;
@@ -281,8 +283,8 @@ extern HRESULT init_string_table( IStorage *stg );
 
 
 /* string table functions */
 
 
 /* string table functions */
-extern BOOL msi_addstring( string_table *st, int string_no, const CHAR *data, int len, UINT refcount );
-extern BOOL msi_addstringW( string_table *st, int string_no, const WCHAR *data, int len, UINT refcount );
+extern BOOL msi_addstring( string_table *st, UINT string_no, const CHAR *data, int len, UINT refcount );
+extern BOOL msi_addstringW( string_table *st, UINT string_no, const WCHAR *data, int len, UINT refcount );
 extern UINT msi_id2stringW( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz );
 extern UINT msi_id2stringA( string_table *st, UINT string_no, LPSTR buffer, UINT *sz );
 
 extern UINT msi_id2stringW( string_table *st, UINT string_no, LPWSTR buffer, UINT *sz );
 extern UINT msi_id2stringA( string_table *st, UINT string_no, LPSTR buffer, UINT *sz );
 
@@ -307,7 +309,7 @@ extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname,
                               USHORT **pdata, UINT *psz );
 
 /* action internals */
                               USHORT **pdata, UINT *psz );
 
 /* action internals */
-extern UINT ACTION_DoTopLevelINSTALL( MSIPACKAGE *, LPCWSTR, LPCWSTR );
+extern UINT ACTION_DoTopLevelINSTALL( MSIPACKAGE *, LPCWSTR, LPCWSTR, LPCWSTR );
 extern void ACTION_free_package_structures( MSIPACKAGE* );
 extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR);
 
 extern void ACTION_free_package_structures( MSIPACKAGE* );
 extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR);
 
index 54a6924..d3114df 100644 (file)
@@ -408,6 +408,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
     MSIDATABASE *db = NULL;
     MSIPACKAGE *package;
     MSIHANDLE handle;
     MSIDATABASE *db = NULL;
     MSIPACKAGE *package;
     MSIHANDLE handle;
+    DWORD size;
+    static const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0};
 
     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
 
 
     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
 
@@ -445,6 +447,13 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         MSI_SetPropertyW( package, Database, szPackage );
     }
 
         MSI_SetPropertyW( package, Database, szPackage );
     }
 
+    /* this property must exist */
+    size  = 0;
+    MSI_GetPropertyW(package,szProductCode,NULL,&size);
+    size ++;
+    package->ProductCode = HeapAlloc(GetProcessHeap(),0,size * sizeof(WCHAR));
+    MSI_GetPropertyW(package,szProductCode,package->ProductCode, &size);
+    
     *pPackage = package;
 
     return ERROR_SUCCESS;
     *pPackage = package;
 
     return ERROR_SUCCESS;
@@ -454,18 +463,40 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP
 {
     MSIPACKAGE *package = NULL;
     UINT ret;
 {
     MSIPACKAGE *package = NULL;
     UINT ret;
+    WCHAR path[MAX_PATH];
+    WCHAR filename[MAX_PATH];
+    static const WCHAR szMSI[] = {'M','S','I',0};
 
     TRACE("%s %08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
 
 
     TRACE("%s %08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
 
+    /* copy the msi file to a temp file to pervent locking a CD
+     * with a multi disc install 
+     */ 
+    if( szPackage[0] == '#' )
+        strcpyW(filename,szPackage);
+    else
+    {
+        GetTempPathW(MAX_PATH, path);
+        GetTempFileNameW(path, szMSI, 0, filename);
+
+        CopyFileW(szPackage, filename, FALSE);
+
+        TRACE("Opening relocated package %s\n",debugstr_w(filename));
+    }
+    
     if( dwOptions )
         FIXME("dwOptions %08lx not supported\n", dwOptions);
 
     if( dwOptions )
         FIXME("dwOptions %08lx not supported\n", dwOptions);
 
-    ret = MSI_OpenPackageW( szPackage, &package);
+    ret = MSI_OpenPackageW( filename, &package);
     if( ret == ERROR_SUCCESS )
     {
         *phPackage = alloc_msihandle( &package->hdr );
         msiobj_release( &package->hdr );
     }
     if( ret == ERROR_SUCCESS )
     {
         *phPackage = alloc_msihandle( &package->hdr );
         msiobj_release( &package->hdr );
     }
+
+    if( szPackage[0] != '#' )
+        DeleteFileW(filename);
+
     return ret;
 }
 
     return ret;
 }
 
@@ -862,6 +893,10 @@ UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf,
     if (NULL != szValueBuf && NULL == pchValueBuf)
         return ERROR_INVALID_PARAMETER;
 
     if (NULL != szValueBuf && NULL == pchValueBuf)
         return ERROR_INVALID_PARAMETER;
 
+    /* This was tested against native msi */
+    if (NULL == szValueBuf && NULL != pchValueBuf)
+        *pchValueBuf = 0;
+
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
         return ERROR_INVALID_HANDLE;
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -889,6 +924,10 @@ UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
     if (NULL != szValueBuf && NULL == pchValueBuf)
         return ERROR_INVALID_PARAMETER;
 
     if (NULL != szValueBuf && NULL == pchValueBuf)
         return ERROR_INVALID_PARAMETER;
 
+    /* This was tested against native msi */
+    if (NULL == szValueBuf && NULL != pchValueBuf)
+        *pchValueBuf = 0;
+
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
         return ERROR_INVALID_HANDLE;
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
         return ERROR_INVALID_HANDLE;
index 0129861..c96a766 100644 (file)
@@ -873,9 +873,18 @@ UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex,
     rc = RegEnumValueW(key, iIndex, lpQualifierBuf, pcchQualifierBuf, NULL, 
                     NULL, (LPBYTE)full_buffer, &full_buffer_size);
 
     rc = RegEnumValueW(key, iIndex, lpQualifierBuf, pcchQualifierBuf, NULL, 
                     NULL, (LPBYTE)full_buffer, &full_buffer_size);
 
+    if (rc == ERROR_MORE_DATA)
+    {
+        HeapFree(GetProcessHeap(),0,full_buffer);
+        full_buffer_size+=sizeof(WCHAR);
+        full_buffer = HeapAlloc(GetProcessHeap(),0,full_buffer_size);
+        rc = RegEnumValueW(key, iIndex, lpQualifierBuf, pcchQualifierBuf, NULL, 
+                    NULL, (LPBYTE)full_buffer, &full_buffer_size);
+    }
+    
     RegCloseKey(key);
 
     RegCloseKey(key);
 
-    if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
+    if (rc == ERROR_SUCCESS)
     {
         if (lpApplicationDataBuf && pcchApplicationDataBuf)
         {
     {
         if (lpApplicationDataBuf && pcchApplicationDataBuf)
         {
@@ -898,6 +907,8 @@ UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex,
                         debugstr_w(lpApplicationDataBuf));
     }
 
                         debugstr_w(lpApplicationDataBuf));
     }
 
+    HeapFree(GetProcessHeap(),0,full_buffer);
+
     return rc;
 }
 
     return rc;
 }
 
diff --git a/reactos/lib/msi/source.c b/reactos/lib/msi/source.c
new file mode 100644 (file)
index 0000000..136d492
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2005 Aric Stewart for CodeWeavers
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winnls.h"
+#include "shlwapi.h"
+#include "wine/debug.h"
+#include "msi.h"
+#include "msiquery.h"
+#include "msipriv.h"
+#include "wincrypt.h"
+#include "winver.h"
+#include "winuser.h"
+#include "wine/unicode.h"
+#include "action.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+/*
+ * These apis are defined in MSI 3.0
+ */
+
+typedef struct tagMediaInfo
+{
+    LPWSTR  path;
+    WCHAR   szIndex[10];
+    WCHAR   type;
+} media_info;
+
+static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, BOOL user, BOOL create)
+{
+    HKEY rootkey = 0; 
+    UINT rc; 
+    static const WCHAR szSourceList[] = {'S','o','u','r','c','e','L','i','s','t',0};
+
+    if (user)
+        rc = MSIREG_OpenUserProductsKey(szProduct, &rootkey, create);
+    else
+        rc = MSIREG_OpenProductsKey(szProduct, &rootkey, create);
+
+    if (rc)
+        return rc;
+
+    if (create)
+        rc = RegCreateKeyW(rootkey, szSourceList, key);
+    else
+        rc = RegOpenKeyW(rootkey,szSourceList, key); 
+
+    return rc;
+}
+
+static UINT OpenMediaSubkey(HKEY rootkey, HKEY *key, BOOL create)
+{
+    UINT rc;
+    static const WCHAR media[] = {'M','e','d','i','a',0};
+
+    if (create)
+        rc = RegCreateKeyW(rootkey, media, key);
+    else
+        rc = RegOpenKeyW(rootkey,media, key); 
+
+    return rc;
+}
+
+static UINT OpenNetworkSubkey(HKEY rootkey, HKEY *key, BOOL create)
+{
+    UINT rc;
+    static const WCHAR net[] = {'N','e','t',0};
+
+    if (create)
+        rc = RegCreateKeyW(rootkey, net, key);
+    else
+        rc = RegOpenKeyW(rootkey, net, key); 
+
+    return rc;
+}
+
+static UINT OpenURLSubkey(HKEY rootkey, HKEY *key, BOOL create)
+{
+    UINT rc;
+    static const WCHAR URL[] = {'U','R','L',0};
+
+    if (create)
+        rc = RegCreateKeyW(rootkey, URL, key);
+    else
+        rc = RegOpenKeyW(rootkey, URL, key); 
+
+    return rc;
+}
+
+
+static UINT find_given_source(HKEY key, LPCWSTR szSource, media_info *ss)
+{
+    DWORD index = 0;
+    WCHAR szIndex[10];
+    DWORD size;
+    DWORD val_size;
+    LPWSTR val;
+    UINT rc = ERROR_SUCCESS;
+
+    while (rc == ERROR_SUCCESS)
+    {
+        val = NULL;
+        val_size = 0;
+        rc = RegEnumValueW(key, index, szIndex, &size, NULL, NULL, NULL, &val_size);
+        if (rc != ERROR_NO_MORE_ITEMS)
+        {
+            val = HeapAlloc(GetProcessHeap(),0,val_size);
+            RegEnumValueW(key, index, szIndex, &size, NULL, NULL, (LPBYTE)val, 
+                &val_size);
+            if (lstrcmpiW(szSource,val)==0)
+            {
+                ss->path = val;
+                strcpyW(ss->szIndex,szIndex);
+                break;
+            }
+            else
+                strcpyW(ss->szIndex,szIndex);
+
+            HeapFree(GetProcessHeap(),0,val);
+            index ++;
+        }
+    }
+    return rc;
+}
+
+/******************************************************************
+ *  MsiSourceListGetInfoW   (MSI.@)
+ */
+UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
+                                   MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
+                                   LPCWSTR szProperty, LPWSTR szValue, 
+                                   LPDWORD pcchValue) 
+{
+    HKEY sourcekey;
+    UINT rc;
+
+    TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szProperty));
+
+    if (!szProduct || lstrlenW(szProduct) > 39)
+        return ERROR_INVALID_PARAMETER;
+
+    if (szValue && !pcchValue)
+        return ERROR_INVALID_PARAMETER;
+    
+    if (dwOptions == MSICODE_PATCH)
+    {
+        FIXME("Unhandled options MSICODE_PATCH\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+    
+    if (szUserSid)
+        FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
+
+    if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
+        FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
+
+    if (dwContext == MSIINSTALLCONTEXT_MACHINE)
+        rc = OpenSourceKey(szProduct, &sourcekey, FALSE, FALSE);
+    else
+        rc = OpenSourceKey(szProduct, &sourcekey, TRUE, FALSE);
+
+    if (rc != ERROR_SUCCESS)
+        return ERROR_UNKNOWN_PRODUCT;
+
+    if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
+    {
+        HKEY key;
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegQueryValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW,
+                    0, 0, (LPBYTE)szValue, pcchValue);
+        if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) ==0)
+    {
+        HKEY key;
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegQueryValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0, 0,
+                    (LPBYTE)szValue, pcchValue);
+        if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
+    {
+        LPWSTR buffer;
+        DWORD size = 0;
+
+        RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
+                NULL, &size);
+        if (size == 0)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        else
+        {
+            LPWSTR ptr;
+            buffer = HeapAlloc(GetProcessHeap(),0,size);
+            rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
+                    0, 0, (LPBYTE)buffer,&size); 
+            ptr = strchrW(buffer,';');
+            if (ptr) ptr = strchrW(ptr+1,';');
+            if (!ptr)
+                rc = ERROR_UNKNOWN_PROPERTY;
+            else
+            {
+                ptr ++;
+                lstrcpynW(szValue, ptr, *pcchValue);
+                if (lstrlenW(ptr) > *pcchValue)
+                {
+                    *pcchValue = lstrlenW(ptr)+1;
+                    rc = ERROR_MORE_DATA;
+                }
+                else
+                    rc = ERROR_SUCCESS;
+            }
+            HeapFree(GetProcessHeap(),0,buffer);
+        }
+    }
+    else if (strcmpW(INSTALLPROPERTY_LASTUSEDTYPEW, szProperty)==0)
+    {
+        LPWSTR buffer;
+        DWORD size = 0;
+
+        RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
+                NULL, &size);
+        if (size == 0)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        else
+        {
+            buffer = HeapAlloc(GetProcessHeap(),0,size);
+            rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
+                    0, 0, (LPBYTE)buffer,&size); 
+            if (*pcchValue < 1)
+            {
+                rc = ERROR_MORE_DATA;
+                *pcchValue = 1;
+            }
+            else
+            {
+                szValue[0] = buffer[0];
+                rc = ERROR_SUCCESS;
+            }
+            HeapFree(GetProcessHeap(),0,buffer);
+        }
+    }
+    else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
+    {
+        rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0, 
+                (LPBYTE)szValue, pcchValue);
+        if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
+            rc = ERROR_UNKNOWN_PROPERTY;
+    }
+    else
+    {
+        FIXME("Unknown property %s\n",debugstr_w(szProperty));
+        rc = ERROR_UNKNOWN_PROPERTY;
+    }
+
+    RegCloseKey(sourcekey);
+    return rc;
+}
+
+/******************************************************************
+ *  MsiSourceListSetInfoW   (MSI.@)
+ */
+UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
+                                   MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
+                                   LPCWSTR szProperty, LPCWSTR szValue)
+{
+    HKEY sourcekey;
+    UINT rc;
+
+    TRACE("%s %s %x %lx %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid), 
+            dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue));
+
+    if (!szProduct || lstrlenW(szProduct) > 39)
+        return ERROR_INVALID_PARAMETER;
+
+    if (dwOptions & MSICODE_PATCH)
+    {
+        FIXME("Unhandled options MSICODE_PATCH\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+    
+    if (szUserSid)
+        FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
+
+    if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
+        FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
+
+    if (dwContext == MSIINSTALLCONTEXT_MACHINE)
+        rc = OpenSourceKey(szProduct, &sourcekey, FALSE, TRUE);
+    else
+        rc = OpenSourceKey(szProduct, &sourcekey, TRUE, TRUE);
+
+    if (rc != ERROR_SUCCESS)
+        return ERROR_UNKNOWN_PRODUCT;
+
+
+    if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
+    {
+        HKEY key;
+        DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegSetValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW, 0,
+                    REG_SZ, (LPBYTE)szValue, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) == 0)
+    {
+        HKEY key;
+        DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegSetValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0,
+                    REG_SZ, (LPBYTE)szValue, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
+    {
+        LPWSTR buffer = NULL;
+        DWORD size;
+        WCHAR typechar = 'n';
+        static const WCHAR LastUsedSource_Fmt[] = {'%','c',';','%','i',';','%','s',0};
+
+        /* make sure the source is registered */
+        MsiSourceListAddSourceExW(szProduct, szUserSid, dwContext, 
+                dwOptions, szValue, 0); 
+
+        if (dwOptions & MSISOURCETYPE_NETWORK)
+            typechar = 'n';
+        else if (dwOptions & MSISOURCETYPE_URL)
+            typechar = 'u';
+        else if (dwOptions & MSISOURCETYPE_MEDIA)
+            typechar = 'm';
+        else 
+            ERR("Unknown source type! 0x%lx\n",dwOptions);
+        
+        size = (lstrlenW(szValue)+5)*sizeof(WCHAR);
+        buffer = HeapAlloc(GetProcessHeap(),0,size);
+        sprintfW(buffer, LastUsedSource_Fmt, typechar, 1, szValue);
+        rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 
+                REG_EXPAND_SZ, (LPBYTE)buffer, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        HeapFree( GetProcessHeap(), 0, buffer );
+    }
+    else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
+    {
+        DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
+        rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
+                REG_SZ, (LPBYTE)szValue, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+    }
+    else
+    {
+        FIXME("Unknown property %s\n",debugstr_w(szProperty));
+        rc = ERROR_UNKNOWN_PROPERTY;
+    }
+
+    RegCloseKey(sourcekey);
+    return rc;
+
+}
+
+/******************************************************************
+ *  MsiSourceListAddSourceExW (MSI.@)
+ */
+UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
+        MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szSource, 
+        DWORD dwIndex)
+{
+    HKEY sourcekey;
+    HKEY typekey;
+    UINT rc;
+    media_info source_struct;
+   
+    TRACE("%s, %s, %x, %lx, %s, %li\n", debugstr_w(szProduct), 
+            debugstr_w(szUserSid), dwContext, dwOptions, debugstr_w(szSource), 
+            dwIndex);
+    
+    if (!szProduct)
+        return ERROR_INVALID_PARAMETER;
+
+    if (!szSource)
+        return ERROR_INVALID_PARAMETER;
+
+    if (dwOptions & MSICODE_PATCH)
+    {
+        FIXME("Unhandled options MSICODE_PATCH\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    if (szUserSid)
+        FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
+
+    if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
+        FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
+
+    if (dwContext == MSIINSTALLCONTEXT_MACHINE)
+        rc = OpenSourceKey(szProduct, &sourcekey, FALSE, TRUE);
+    else
+        rc = OpenSourceKey(szProduct, &sourcekey, TRUE, TRUE);
+
+    if (rc != ERROR_SUCCESS)
+        return ERROR_UNKNOWN_PRODUCT;
+
+    if (dwOptions & MSISOURCETYPE_NETWORK)
+        rc = OpenNetworkSubkey(sourcekey, &typekey, TRUE);
+    else if (dwOptions & MSISOURCETYPE_URL)
+        rc = OpenURLSubkey(sourcekey, &typekey, TRUE);
+    else
+    {
+        ERR("Unknown media type!\n");
+        RegCloseKey(sourcekey);
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    source_struct.szIndex[0] = 0;
+    if (find_given_source(typekey, szSource, &source_struct)==ERROR_SUCCESS)
+    {
+        DWORD current_index = atoiW(source_struct.szIndex);
+        /* found the source */
+        if (dwIndex > 0 && current_index != dwIndex)
+            FIXME("Need to reorder the souces! UNHANDLED\n");
+    }
+    else
+    {
+        DWORD current_index = 0;
+        static const WCHAR fmt[] = {'%','i',0};
+        DWORD size = lstrlenW(szSource)*sizeof(WCHAR);
+
+        if (source_struct.szIndex[0])
+            current_index = atoiW(source_struct.szIndex);
+        /* new source */
+        if (dwIndex > 0 && dwIndex < current_index)
+            FIXME("Need to reorder the souces! UNHANDLED\n");
+
+        current_index ++;
+        sprintfW(source_struct.szIndex,fmt,current_index);
+        rc = RegSetValueExW(typekey, source_struct.szIndex, 0, REG_EXPAND_SZ, 
+                (LPBYTE)szSource, size);
+    }
+
+    RegCloseKey(typekey);
+    RegCloseKey(sourcekey);
+    return rc;
+}
+
+/******************************************************************
+ *  MsiSourceListAddMediaDisk(MSI.@)
+ */
+UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid, 
+        MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId, 
+        LPCWSTR szVolumeLabel, LPCWSTR szDiskPrompt)
+{
+    HKEY sourcekey;
+    HKEY mediakey;
+    UINT rc;
+    WCHAR szIndex[10];
+    static const WCHAR fmt[] = {'%','i',0};
+    static const WCHAR disk_fmt[] = {'%','s',';','%','s',0};
+    static const WCHAR empty[1] = {0};
+    LPCWSTR pt1,pt2;
+    LPWSTR buffer;
+    DWORD size;
+
+    TRACE("%s %s %x %lx %li %s %s\n", debugstr_w(szProduct), 
+            debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId, 
+            debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt)); 
+
+    if (!szProduct || lstrlenW(szProduct) > 39)
+        return ERROR_INVALID_PARAMETER;
+
+    if (dwOptions & MSICODE_PATCH)
+    {
+        FIXME("Unhandled options MSICODE_PATCH\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+    
+    if (szUserSid)
+        FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
+
+    if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
+        FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
+
+    if (dwContext == MSIINSTALLCONTEXT_MACHINE)
+        rc = OpenSourceKey(szProduct, &sourcekey, FALSE, TRUE);
+    else
+        rc = OpenSourceKey(szProduct, &sourcekey, TRUE, TRUE);
+
+    if (rc != ERROR_SUCCESS)
+        return ERROR_UNKNOWN_PRODUCT;
+
+    OpenMediaSubkey(sourcekey,&mediakey,TRUE);
+
+    sprintfW(szIndex,fmt,dwDiskId);
+
+    size = 2;
+    if (szVolumeLabel)
+    {
+        size +=lstrlenW(szVolumeLabel);
+        pt1 = szVolumeLabel;
+    }
+    else
+        pt1 = empty;
+    if (szDiskPrompt)
+    {
+        size +=lstrlenW(szDiskPrompt);
+        pt2 = szDiskPrompt;
+    }
+    else
+        pt2 = empty;
+
+    size *=sizeof(WCHAR);
+
+    buffer = HeapAlloc(GetProcessHeap(),0,size);
+    sprintfW(buffer,disk_fmt,pt1,pt2);
+
+    RegSetValueExW(mediakey, szIndex, 0, REG_SZ, (LPBYTE)buffer, size);
+    HeapFree( GetProcessHeap(), 0, buffer );
+
+    RegCloseKey(sourcekey);
+    RegCloseKey(mediakey);
+
+    return ERROR_SUCCESS;
+}
index 4222894..62a7331 100644 (file)
@@ -142,7 +142,7 @@ static void st_mark_entry_used( string_table *st, UINT n )
     st->freeslot = n + 1;
 }
 
     st->freeslot = n + 1;
 }
 
-int msi_addstring( string_table *st, int n, const CHAR *data, int len, UINT refcount )
+int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, UINT refcount )
 {
     int sz;
 
 {
     int sz;
 
@@ -190,7 +190,7 @@ int msi_addstring( string_table *st, int n, const CHAR *data, int len, UINT refc
     return n;
 }
 
     return n;
 }
 
-int msi_addstringW( string_table *st, int n, const WCHAR *data, int len, UINT refcount )
+int msi_addstringW( string_table *st, UINT n, const WCHAR *data, int len, UINT refcount )
 {
     /* TRACE("[%2d] = %s\n", string_no, debugstr_an(data,len) ); */
 
 {
     /* TRACE("[%2d] = %s\n", string_no, debugstr_an(data,len) ); */
 
index cd507f2..f7692a4 100644 (file)
@@ -333,7 +333,7 @@ static DWORD write_string( LPBYTE data, DWORD ofs, LPCSTR str )
     DWORD len = lstrlenA( str ) + 1;
     write_dword( data, ofs, len );
     if( data )
     DWORD len = lstrlenA( str ) + 1;
     write_dword( data, ofs, len );
     if( data )
-        lstrcpyA( &data[ofs + 4], str );
+        memcpy( &data[ofs + 4], str, len );
     return (7 + len) & ~3;
 }
 
     return (7 + len) & ~3;
 }
 
index 7a066ca..e96a8e4 100644 (file)
@@ -136,10 +136,6 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
             DWORD sz = 0x100;
             HKEY hukey;
             INT r;
             DWORD sz = 0x100;
             HKEY hukey;
             INT r;
-            static const WCHAR szVersion[] =
-                {'V','e','r','s','i','o','n',0};
-            static const WCHAR szLanguage[] =
-                {'L','a','n','g','u','a','g','e',0};
 
             unsquash_guid(product,productid);
             rc = MSIREG_OpenUserProductsKey(productid, &hukey, FALSE);
 
             unsquash_guid(product,productid);
             rc = MSIREG_OpenUserProductsKey(productid, &hukey, FALSE);
@@ -151,8 +147,8 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
             }
           
             sz = sizeof(DWORD);
             }
           
             sz = sizeof(DWORD);
-            RegQueryValueExW(hukey, szVersion, NULL, NULL, (LPBYTE)&check, 
-                            &sz);
+            RegQueryValueExW(hukey, INSTALLPROPERTY_VERSIONW, NULL, NULL,
+                    (LPBYTE)&check, &sz);
             /* check min */
             ver = MSI_RecordGetString(rec,2);
             comp_ver = build_version_dword(ver);
             /* check min */
             ver = MSI_RecordGetString(rec,2);
             comp_ver = build_version_dword(ver);
@@ -179,8 +175,8 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param)
 
             /* check language*/
             sz = sizeof(DWORD);
 
             /* check language*/
             sz = sizeof(DWORD);
-            RegQueryValueExW(hukey, szLanguage, NULL, NULL, (LPBYTE)&check, 
-                            &sz);
+            RegQueryValueExW(hukey, INSTALLPROPERTY_LANGUAGEW, NULL, NULL,
+                    (LPBYTE)&check, &sz);
             RegCloseKey(hukey);
             language = MSI_RecordGetString(rec,4);
             TRACE("Checking languages 0x%lx and %s\n", check, 
             RegCloseKey(hukey);
             language = MSI_RecordGetString(rec,4);
             TRACE("Checking languages 0x%lx and %s\n", check, 
@@ -211,12 +207,14 @@ UINT ACTION_FindRelatedProducts(MSIPACKAGE *package)
     UINT rc = ERROR_SUCCESS;
     MSIQUERY *view;
 
     UINT rc = ERROR_SUCCESS;
     MSIQUERY *view;
 
-    if (package->script && package->script->FindRelatedProductsRun)
+    if (check_unique_action(package,szFindRelatedProducts))
+    {
+        TRACE("Skipping FindRelatedProducts action: already done on client side\n");
         return ERROR_SUCCESS;
         return ERROR_SUCCESS;
+    }
+    else
+        register_unique_action(package,szFindRelatedProducts);
 
 
-    if (package->script)
-        package->script->FindRelatedProductsRun = TRUE;
-    
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
     if (rc != ERROR_SUCCESS)
         return ERROR_SUCCESS;
index 1c12782..38e3725 100644 (file)
@@ -148,8 +148,192 @@ typedef enum tagINSTALLTYPE
     INSTALLTYPE_NETWORK_IMAGE = 1
 } INSTALLTYPE;
 
     INSTALLTYPE_NETWORK_IMAGE = 1
 } INSTALLTYPE;
 
+typedef enum tagMSIINSTALLCONTEXT
+{
+    MSIINSTALLCONTEXT_FIRSTVISIBLE  =   0,
+    MSIINSTALLCONTEXT_NONE          =   0,
+    MSIINSTALLCONTEXT_USERMANAGED   =   1,
+    MSIINSTALLCONTEXT_USERUNMANAGED =   2,
+    MSIINSTALLCONTEXT_MACHINE       =   4,
+    MSIINSTALLCONTEXT_ALL           = (MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED | MSIINSTALLCONTEXT_MACHINE),
+    MSIINSTALLCONTEXT_ALLUSERMANAGED=   8,
+} MSIINSTALLCONTEXT;
+
+typedef enum tagMSISOURCETYPE
+{
+    MSISOURCETYPE_UNKNOWN = 0x00000000L,
+    MSISOURCETYPE_NETWORK = 0x00000001L,
+    MSISOURCETYPE_URL     = 0x00000002L,
+    MSISOURCETYPE_MEDIA   = 0x00000004
+} MSISOURCETYPE;
+
+typedef enum tagMSICODE
+{
+    MSICODE_PRODUCT = 0x00000000L,
+    MSICODE_PATCH = 0x40000000L
+} MSICODE;
+
 #define MAX_FEATURE_CHARS 38
 
 #define MAX_FEATURE_CHARS 38
 
+/* Strings defined in msi.h */
+/* Advertised Information */
+
+#define INSTALLPROPERTY_PACKAGENAMEA "PackageName"
+static const WCHAR INSTALLPROPERTY_PACKAGENAMEW[] = {'P','a','c','k','a','g','e','N','a','m','e',0};
+#define INSTALLPROPERTY_PACKAGENAME WINELIB_NAME_AW(INSTALLPROPERTY_PACKAGENAME)
+
+#define INSTALLPROPERTY_TRANSFORMSA "Transforms"
+static const WCHAR INSTALLPROPERTY_TRANSFORMSW[] = {'T','r','a','n','s','f','o','r','m','s',0};
+#define INSTALLPROPERTY_TRANSFORMS WINELIB_NAME_AW(INSTALLPROPERTY_TRANSFORMS)
+
+#define INSTALLPROPERTY_LANGUAGEA "Language"
+static const WCHAR INSTALLPROPERTY_LANGUAGEW[] = {'L','a','n','g','u','a','g','e',0};
+#define INSTALLPROPERTY_LANGUAGE WINELIB_NAME_AW(INSTALLPROPERTY_LANGUAGE)
+
+#define INSTALLPROPERTY_PRODUCTNAMEA "ProductName"
+static const WCHAR INSTALLPROPERTY_PRODUCTNAMEW[] = {'P','r','o','d','u','c','t','N','a','m','e',0};
+#define INSTALLPROPERTY_PRODUCTNAME WINELIB_NAME_AW(INSTALLPROPERTY_PRODUCTNAME)
+
+#define INSTALLPROPERTY_ASSIGNMENTTYPEA "AssignmentType"
+static const WCHAR INSTALLPROPERTY_ASSIGNMENTTYPEW[] = {'A','s','s','i','g','n','m','e','n','t','T','y','p','e',0};
+#define INSTALLPROPERTY_ASSIGNMENTTYPE WINELIB_NAME_AW(INSTALLPROPERTY_ASSIGNMENTTYPE)
+
+#define INSTALLPROPERTY_PACKAGECODEA "PackageCode"
+static const WCHAR INSTALLPROPERTY_PACKAGECODEW[] = {'P','a','c','k','a','g','e','C','o','d','e',0};
+#define INSTALLPROPERTY_PACKAGECODE WINELIB_NAME_AW(INSTALLPROPERTY_PACKAGECODE)
+
+#define INSTALLPROPERTY_VERSIONA "Version"
+static const WCHAR INSTALLPROPERTY_VERSIONW[]= {'V','e','r','s','i','o','n',0};
+#define INSTALLPROPERTY_VERSION WINELIB_NAME_AW(INSTALLPROPERTY_VERSION)
+
+/* MSI version 1.1 and above */
+
+#define INSTALLPROPERTY_PRODUCTICONA "ProductIcon"
+static const WCHAR INSTALLPROPERTY_PRODUCTICONW[]  = {'P','r','o','d','u','c','t','I','c','o','n',0};
+#define INSTALLPROPERTY_PRODUCTICON WINELIB_NAME_AW(INSTALLPROPERTY_PRODUCTICON)
+
+/* MSI version 1.5 and above */
+#define INSTALLPROPERTY_INSTANCETYPEA "InstanceType"
+static const WCHAR INSTALLPROPERTY_INSTANCETYPEW[] = {'I','n','s','t','a','n','c','e','T','y','p','e',0};
+#define INSTALLPROPERTY_INSTANCETYPE WINELIB_NAME_AW(INSTALLPROPERTY_INSTANCETYPE)
+
+/* MSI version 3 and above */
+#define INSTALLPROPERTY_AUTHORIZED_LUA_APPA "AuthorizedLUAApp"
+static const WCHAR INSTALLPROPERTY_AUTHORIZED_LUA_APPW[] = {'A','u','t','h','o','r','i','z','e','d','L','U','A','A','p','p',0};
+#define INSTALLPROPERTY_AUTHORIZED_LUA_APP WINELIB_NAME_AW(INSTALLPROPERTY_AUTHORIZED_LUA_APP)
+
+
+/* Installed Information */
+#define INSTALLPROPERTY_INSTALLEDPRODUCTNAMEA "InstalledProductName"
+static const WCHAR INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW[] = {'I','n','s','t','a','l','l','e','d','P','r','o','d','u','c','t','N','a','m','e',0};
+#define INSTALLPROPERTY_INSTALLEDPRODUCTNAME WINELIB_NAME_AW(INSTALLPROPERTY_INSTALLEDPRODUCTNAME)
+
+#define INSTALLPROPERTY_VERSIONSTRINGA "VersionString"
+static const WCHAR INSTALLPROPERTY_VERSIONSTRINGW[] = {'V','e','r','s','i','o','n','S','t','r','i','n','g',0};
+#define INSTALLPROPERTY_VERSIONSTRING WINELIB_NAME_AW(INSTALLPROPERTY_VERSIONSTRING)
+
+#define INSTALLPROPERTY_HELPLINKA "HelpLink"
+static const WCHAR INSTALLPROPERTY_HELPLINKW[] = {'H','e','l','p','L','i','n','k',0};
+#define INSTALLPROPERTY_HELPLINK WINELIB_NAME_AW(INSTALLPROPERTY_HELPLINK)
+
+#define INSTALLPROPERTY_HELPTELEPHONEA "HelpTelephone"
+static const WCHAR INSTALLPROPERTY_HELPTELEPHONEW[] = {'H','e','l','p','T','e','l','e','p','h','o','n','e',0};
+#define INSTALLPROPERTY_HELPTELEPHONE WINELIB_NAME_AW(INSTALLPROPERTY_HELPTELEPHONE)
+
+#define INSTALLPROPERTY_INSTALLLOCATIONA "InstallLocation"
+static const WCHAR INSTALLPROPERTY_INSTALLLOCATIONW[] = {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0};
+#define INSTALLPROPERTY_INSTALLLOCATION WINELIB_NAME_AW(INSTALLPROPERTY_INSTALLLOCATION)
+
+#define INSTALLPROPERTY_INSTALLSOURCEA "InstallSource"
+static const WCHAR INSTALLPROPERTY_INSTALLSOURCEW[] = {'I','n','s','t','a','l','l','S','o','u','r','c','e',0};
+#define INSTALLPROPERTY_INSTALLSOURCE WINELIB_NAME_AW(INSTALLPROPERTY_INSTALLSOURCE)
+
+#define INSTALLPROPERTY_INSTALLDATEA "InstallDate"
+static const WCHAR INSTALLPROPERTY_INSTALLDATEW[] = {'I','n','s','t','a','l','l','D','a','t','e',0};
+#define INSTALLPROPERTY_INSTALLDATE WINELIB_NAME_AW(INSTALLPROPERTY_INSTALLDATE)
+
+#define INSTALLPROPERTY_PUBLISHERA "Publisher"
+static const WCHAR INSTALLPROPERTY_PUBLISHERW[] ={'P','u','b','l','i','s','h','e','r',0};
+#define INSTALLPROPERTY_PUBLISHER WINELIB_NAME_AW(INSTALLPROPERTY_PUBLISHER)
+
+#define INSTALLPROPERTY_LOCALPACKAGEA "LocalPackage"
+static const WCHAR INSTALLPROPERTY_LOCALPACKAGEW[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
+#define INSTALLPROPERTY_LOCALPACKAGE WINELIB_NAME_AW(INSTALLPROPERTY_LOCALPACKAGE)
+
+#define INSTALLPROPERTY_URLINFOABOUTA "URLInfoAbout"
+static const WCHAR INSTALLPROPERTY_URLINFOABOUTW[] = {'U','R','L','I','n','f','o','A','b','o','u','t',0};
+#define INSTALLPROPERTY_URLINFOABOUT WINELIB_NAME_AW(INSTALLPROPERTY_URLINFOABOUT)
+
+#define INSTALLPROPERTY_URLUPDATEINFOA "URLUpdateInfo"
+static const WCHAR INSTALLPROPERTY_URLUPDATEINFOW[] = {'U','R','L','U','p','d','a','t','e','I','n','f','o',0};
+#define INSTALLPROPERTY_URLUPDATEINFO WINELIB_NAME_AW(INSTALLPROPERTY_URLUPDATEINFO)
+
+#define INSTALLPROPERTY_VERSIONMINORA "VersionMinor"
+static const WCHAR INSTALLPROPERTY_VERSIONMINORW[] = {'V','e','r','s','i','o','n','M','i','n','o','r',0};
+#define INSTALLPROPERTY_VERSIONMINOR WINELIB_NAME_AW(INSTALLPROPERTY_VERSIONMINOR)
+
+#define INSTALLPROPERTY_VERSIONMAJORA "VersionMajor"
+static const WCHAR INSTALLPROPERTY_VERSIONMAJORW[] = {'V','e','r','s','i','o','n','M','a','j','o','r',0};
+#define INSTALLPROPERTY_VERSIONMAJOR WINELIB_NAME_AW(INSTALLPROPERTY_VERSIONMAJOR)
+
+#define INSTALLPROPERTY_PRODUCTIDA "ProductID"
+static const WCHAR INSTALLPROPERTY_PRODUCTIDW[] = {'P','r','o','d','u','c','t','I','D',0};
+#define INSTALLPROPERTY_PRODUCTID WINELIB_NAME_AW(INSTALLPROPERTY_PRODUCTID)
+
+#define INSTALLPROPERTY_REGCOMPANYA "RegCompany"
+static const WCHAR INSTALLPROPERTY_REGCOMPANYW[] = {'R','e','g','C','o','m','p','a','n','y',0};
+#define INSTALLPROPERTY_REGCOMPANY WINELIB_NAME_AW(INSTALLPROPERTY_REGCOMPANY)
+
+#define INSTALLPROPERTY_REGOWNERA "RegOwner"
+static const WCHAR INSTALLPROPERTY_REGOWNERW[] = {'R','e','g','O','w','n','e','r',0};
+#define INSTALLPROPERTY_REGOWNER WINELIB_NAME_AW(INSTALLPROPERTY_REGOWNER)
+
+/* MSI Version 3.0 and greater */
+#define INSTALLPROPERTY_UNINSTALLABLEA "Uninstallable"
+static const WCHAR INSTALLPROPERTY_UNINSTALLABLEW[] = {'U','n','i','n','s','t','a','l','l','a','b','l','e',0};
+#define INSTALLPROPERTY_UNINSTALLABLE WINELIB_NAME_AW(INSTALLPROPERTY_UNINSTALLABLE)
+
+#define INSTALLPROPERTY_PRODUCTSTATEA "State"
+static const WCHAR INSTALLPROPERTY_PRODUCTSTATEW[] = {'S','t','a','t','e',0};
+#define INSTALLPROPERTY_PRODUCTSTATE WINELIB_NAME_AW(INSTALLPROPERTY_PRODUCTSTATE)
+
+#define INSTALLPROPERTY_PATCHSTATEA "State"
+static const WCHAR INSTALLPROPERTY_PATCHSTATEW[] ={'S','t','a','t','e',0};
+#define INSTALLPROPERTY_PATCHSTATE WINELIB_NAME_AW(INSTALLPROPERTY_PATCHSTATE)
+
+#define INSTALLPROPERTY_PATCHTYPEA "PatchType"
+static const WCHAR INSTALLPROPERTY_PATCHTYPEW[] = {'P','a','t','c','h','T','y','p','e',0};
+#define INSTALLPROPERTY_PATCHTYPE WINELIB_NAME_AW(INSTALLPROPERTY_PATCHTYPE)
+
+#define INSTALLPROPERTY_LUAENABLEDA "LUAEnabled"
+static const WCHAR INSTALLPROPERTY_LUAENABLEDW[] = {'L','U','A','E','n','a','b','l','e','d',0};
+#define INSTALLPROPERTY_LUAENABLED WINELIB_NAME_AW(INSTALLPROPERTY_LUAENABLED)
+
+#define INSTALLPROPERTY_DISPLAYNAMEA "DisplayName"
+static const WCHAR INSTALLPROPERTY_DISPLAYNAMEW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
+#define INSTALLPROPERTY_DISPLAYNAME WINELIB_NAME_AW(INSTALLPROPERTY_DISPLAYNAME)
+
+#define INSTALLPROPERTY_MOREINFOURLA "MoreInfoURL"
+static const WCHAR INSTALLPROPERTY_MOREINFOURLW[] = {'M','o','r','e','I','n','f','o','U','R','L',0};
+#define INSTALLPROPERTY_MOREINFOURL WINELIB_NAME_AW(INSTALLPROPERTY_MOREINFOURL)
+
+/* Source List Info */
+#define INSTALLPROPERTY_LASTUSEDSOURCEA "LastUsedSource"
+static const WCHAR INSTALLPROPERTY_LASTUSEDSOURCEW[] = {'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
+#define INSTALLPROPERTY_LASTUSEDSOURCE WINELIB_NAME_AW(INSTALLPROPERTY_LASTUSEDSOURCEW)
+
+#define INSTALLPROPERTY_LASTUSEDTYPEA "LastUsedType"
+static const WCHAR INSTALLPROPERTY_LASTUSEDTYPEW[] = {'L','a','s','t','U','s','e','d','T','y','p','e',0};
+#define INSTALLPROPERTY_LASTUSEDTYPE WINELIB_NAME_AW(INSTALLPROPERTY_LASTUSEDTYPE)
+
+#define INSTALLPROPERTY_MEDIAPACKAGEPATHA "MediaPackagePath"
+static const WCHAR INSTALLPROPERTY_MEDIAPACKAGEPATHW[] = {'M','e','d','i','a','P','a','c','k','a','g','e','P','a','t','h',0};
+#define INSTALLPROPERTY_MEDIAPACKAGEPATH WINELIB_NAME_AW(INSTALLPROPERTY_MEDIAPACKAGEPATH)
+
+#define INSTALLPROPERTY_DISKPROMPTA "DiskPrompt"
+static const WCHAR INSTALLPROPERTY_DISKPROMPTW[] = {'D','i','s','k','P','r','o','m','p','t',0};
+#define INSTALLPROPERTY_DISKPROMPT WINELIB_NAME_AW(INSTALLPROPERTY_DISKPROMPT)
+
 typedef INT (CALLBACK *INSTALLUI_HANDLERA)(LPVOID, UINT, LPCSTR);
 typedef INT (CALLBACK *INSTALLUI_HANDLERW)(LPVOID, UINT, LPCWSTR);
 
 typedef INT (CALLBACK *INSTALLUI_HANDLERA)(LPVOID, UINT, LPCSTR);
 typedef INT (CALLBACK *INSTALLUI_HANDLERW)(LPVOID, UINT, LPCWSTR);
 
@@ -189,10 +373,6 @@ UINT WINAPI MsiEnumClientsA(LPCSTR, DWORD, LPSTR);
 UINT WINAPI MsiEnumClientsW(LPCWSTR, DWORD, LPWSTR);
 #define     MsiEnumClients WINELIB_NAME_AW(MsiEnumClients)
 
 UINT WINAPI MsiEnumClientsW(LPCWSTR, DWORD, LPWSTR);
 #define     MsiEnumClients WINELIB_NAME_AW(MsiEnumClients)
 
-UINT WINAPI MsiOpenDatabaseA(LPCSTR, LPCSTR, MSIHANDLE *);
-UINT WINAPI MsiOpenDatabaseW(LPCWSTR, LPCWSTR, MSIHANDLE *);
-#define     MsiOpenDatabase WINELIB_NAME_AW(MsiOpenDatabase)
-
 UINT WINAPI MsiOpenPackageA(LPCSTR, MSIHANDLE*);
 UINT WINAPI MsiOpenPackageW(LPCWSTR, MSIHANDLE*);
 #define     MsiOpenPackage WINELIB_NAME_AW(MsiOpenPackage)
 UINT WINAPI MsiOpenPackageA(LPCSTR, MSIHANDLE*);
 UINT WINAPI MsiOpenPackageW(LPCWSTR, MSIHANDLE*);
 #define     MsiOpenPackage WINELIB_NAME_AW(MsiOpenPackage)
@@ -213,10 +393,6 @@ UINT WINAPI MsiGetProductPropertyA(MSIHANDLE,LPCSTR,LPSTR,DWORD*);
 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE,LPCWSTR,LPWSTR,DWORD*);
 #define     MsiGetProductProperty WINELIB_NAME_AW(MsiGetProductProperty)
 
 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE,LPCWSTR,LPWSTR,DWORD*);
 #define     MsiGetProductProperty WINELIB_NAME_AW(MsiGetProductProperty)
 
-UINT WINAPI MsiGetPropertyA(MSIHANDLE, LPCSTR, LPSTR, DWORD*);
-UINT WINAPI MsiGetPropertyW(MSIHANDLE, LPCWSTR, LPWSTR, DWORD*);
-#define     MsiGetProperty WINELIB_NAME_AW(MsiGetProperty)
-
 UINT WINAPI MsiVerifyPackageA(LPCSTR);
 UINT WINAPI MsiVerifyPackageW(LPCWSTR);
 #define     MsiVerifyPackage WINELIB_NAME_AW(MsiVerifyPackage)
 UINT WINAPI MsiVerifyPackageA(LPCSTR);
 UINT WINAPI MsiVerifyPackageW(LPCWSTR);
 #define     MsiVerifyPackage WINELIB_NAME_AW(MsiVerifyPackage)
@@ -321,6 +497,22 @@ INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR, LPSTR, DWORD *);
 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR, LPWSTR, DWORD *);
 #define  MsiLocateComponent WINELIB_NAME_AW(MsiLocateComponent)
 
 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR, LPWSTR, DWORD *);
 #define  MsiLocateComponent WINELIB_NAME_AW(MsiLocateComponent)
 
+UINT WINAPI MsiSourceListGetInfoA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
+UINT WINAPI MsiSourceListGetInfoW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, LPWSTR, LPDWORD);
+#define     MsiSourceListGetInfo WINELIB_NAME_AW(MsiSourceListGetInfo)
+
+UINT WINAPI MsiSourceListSetInfoA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPCSTR);
+UINT WINAPI MsiSourceListSetInfoW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, LPCWSTR);
+#define     MsiSourceListSetInfo WINELIB_NAME_AW(MsiSourceListSetInfo)
+
+UINT WINAPI MsiSourceListAddSourceExA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, DWORD);
+UINT WINAPI MsiSourceListAddSourceExW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, DWORD);
+#define     MsiSourceListAddSourceEx WINELIB_NAME_AW(MsiSourceListAddSourceEx)
+
+UINT WINAPI MsiSourceListAddMediaDiskA(LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPCSTR, LPCSTR);
+UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPCWSTR, LPCWSTR);
+#define     MsiSourceListAddMediaDisk WINELIB_NAME_AW(MsiSourceListAddMediaDisk)
+
 /* Non Unicode */
 UINT WINAPI MsiCloseHandle(MSIHANDLE);
 UINT WINAPI MsiCloseAllHandles(void);
 /* Non Unicode */
 UINT WINAPI MsiCloseHandle(MSIHANDLE);
 UINT WINAPI MsiCloseAllHandles(void);