msi: SourceList

Aric Stewart aric at codeweavers.com
Thu Jun 30 16:10:15 CDT 2005


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
-------------- next part --------------
Index: include/msi.h
===================================================================
RCS file: /home/wine/wine/include/msi.h,v
retrieving revision 1.23
diff -u -r1.23 msi.h
--- include/msi.h	30 May 2005 11:12:24 -0000	1.23
+++ include/msi.h	30 Jun 2005 21:06:27 -0000
@@ -148,6 +148,31 @@
     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
 
 typedef INT (CALLBACK *INSTALLUI_HANDLERA)(LPVOID, UINT, LPCSTR);
@@ -325,6 +350,11 @@
 UINT WINAPI MsiCloseHandle(MSIHANDLE);
 UINT WINAPI MsiCloseAllHandles(void);
 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL, HWND*);
+
+UINT WINAPI MsiSourceListGetInfoW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, LPWSTR, LPDWORD);
+UINT WINAPI MsiSourceListSetInfoW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, LPCWSTR);
+UINT WINAPI MsiSourceListAddSourceExW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, LPCWSTR, DWORD);
+UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPCWSTR, LPCWSTR);
 
 #ifdef __cplusplus
 }
Index: dlls/msi/files.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/files.c,v
retrieving revision 1.5
diff -u -r1.5 files.c
--- dlls/msi/files.c	29 Jun 2005 19:19:09 -0000	1.5
+++ dlls/msi/files.c	30 Jun 2005 21:06:27 -0000
@@ -37,6 +37,7 @@
 #include "winerror.h"
 #include "wine/debug.h"
 #include "fdi.h"
+#include "msi.h"
 #include "msidefs.h"
 #include "msvcrt/fcntl.h"
 #include "msipriv.h"
@@ -54,6 +55,8 @@
 extern const WCHAR szRemoveFiles[];
 
 static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
+static const WCHAR INSTALLPROPERTY_LASTUSEDSOURCE[] = {'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
+static const WCHAR INSTALLPROPERTY_PACKAGENAME[] = {'P','a','c','k','a','g','e','N','a','m','e',0};
 
 inline static UINT create_component_directory ( MSIPACKAGE* package, INT component)
 {
@@ -359,7 +362,8 @@
         file->SourcePath = build_directory_name(2, path, file->File);
 }
 
-static BOOL check_volume(LPCWSTR path, LPCWSTR want_volume, LPWSTR volume)
+static BOOL check_volume(LPCWSTR path, LPCWSTR want_volume, LPWSTR volume, 
+        UINT *intype)
 {
     WCHAR drive[4];
     WCHAR name[MAX_PATH];
@@ -383,6 +387,8 @@
     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);
 }
 
@@ -393,11 +399,11 @@
 }
 
 static UINT ready_volume(MSIPACKAGE* package, LPCWSTR path, LPWSTR last_volume, 
-                         MSIRECORD *row)
+                         MSIRECORD *row,UINT *type )
 {
     LPWSTR volume = NULL; 
     LPCWSTR want_volume = MSI_RecordGetString(row, 5);
-    BOOL ok = check_volume(path, want_volume, volume);
+    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));
 
@@ -449,6 +455,9 @@
     static LPWSTR last_volume = NULL;
     static LPWSTR last_path = NULL;
     MSIFILE* file = NULL;
+    UINT type;
+    LPCWSTR prompt;
+    static DWORD count = 0;
 
     /* cleanup signal */
     if (!package)
@@ -467,6 +476,7 @@
         return ERROR_SUCCESS;
     }
 
+    count ++;
     row = MSI_QueryGetRecord(package->db, ExecSeqQuery, file->Sequence);
     if (!row)
     {
@@ -478,6 +488,7 @@
     last_sequence = seq;
 
     volume = MSI_RecordGetString(row, 5);
+    prompt = MSI_RecordGetString(row, 3);
 
     HeapFree(GetProcessHeap(),0,last_path);
     last_path = NULL;
@@ -486,7 +497,23 @@
     {
         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);
+        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_LASTUSEDSOURCE, last_path);
+        else
+            MsiSourceListSetInfoW(package->ProductCode, NULL, 
+                MSIINSTALLCONTEXT_USERMANAGED, 
+                MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                INSTALLPROPERTY_LASTUSEDSOURCE, last_path);
         msiobj_release(&row->hdr);
         return rc;
     }
@@ -498,9 +525,25 @@
         /* 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;
+
+            path = strdupW(package->PackagePath);
+            *strrchrW(path,'\\')=0;
+
+            MsiSourceListAddMediaDiskW(package->ProductCode, NULL, 
+                MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, count,
+                volume, prompt);
+
+            MsiSourceListSetInfoW(package->ProductCode, NULL,
+                MSIINSTALLCONTEXT_USERMANAGED,
+                MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                INSTALLPROPERTY_LASTUSEDSOURCE, path);
+
+            HeapFree(GetProcessHeap(),0,path);
         }
         else
         {
@@ -515,12 +558,25 @@
             {
                 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_LASTUSEDSOURCE, last_path);
+                else
+                    MsiSourceListSetInfoW(package->ProductCode, NULL,
+                            MSIINSTALLCONTEXT_USERMANAGED,
+                            MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                            INSTALLPROPERTY_LASTUSEDSOURCE, last_path);
+
                 /* extract the cab file into a folder in the temp folder */
                 sz = MAX_PATH;
                 if (MSI_GetPropertyW(package, cszTempFolder,last_path, &sz) 
                                     != ERROR_SUCCESS)
                     GetTempPathW(MAX_PATH,last_path);
-                rc = ready_volume(package, source, last_volume, row);
             }
         }
         rc = !extract_cabinet_file(package, source, last_path);
@@ -533,9 +589,26 @@
         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);
+        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_LASTUSEDSOURCE, last_path);
+        else
+            MsiSourceListSetInfoW(package->ProductCode, NULL,
+                    MSIINSTALLCONTEXT_USERMANAGED,
+                    MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
+                    INSTALLPROPERTY_LASTUSEDSOURCE, 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;
@@ -577,6 +650,7 @@
 {
     UINT rc = ERROR_SUCCESS;
     DWORD index;
+    LPWSTR ptr;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -584,6 +658,18 @@
     /* 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_PACKAGENAME, ptr);
+    }
+    FIXME("Write DiskPrompt\n");
+    
     /* Pass 1 */
     for (index = 0; index < package->loaded_files; index++)
     {
Index: dlls/msi/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msi/Makefile.in,v
retrieving revision 1.33
diff -u -r1.33 Makefile.in
--- dlls/msi/Makefile.in	23 Jun 2005 16:43:38 -0000	1.33
+++ dlls/msi/Makefile.in	30 Jun 2005 21:06:27 -0000
@@ -33,6 +33,7 @@
 	registry.c \
 	regsvr.c \
 	select.c \
+	source.c \
 	string.c \
 	suminfo.c \
 	table.c \
--- /dev/null	2005-03-17 08:20:53.000000000 -0600
+++ dlls/msi/source.c	2005-06-30 15:09:14.000000000 -0500
@@ -0,0 +1,565 @@
+/*
+ * 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
+ */
+
+static const WCHAR INSTALLPROPERTY_MEDIAPACKAGEPATH[] = {'M','e','d','i','a','P','a','c','k','a','g','e','P','a','t','h',0};
+static const WCHAR INSTALLPROPERTY_DISKPROMPT[] = {'D','i','s','k','P','r','o','m','p','t',0};
+static const WCHAR INSTALLPROPERTY_LASTUSEDSOURCE[] = {'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
+static const WCHAR INSTALLPROPERTY_LASTUSEDTYPE[] = {'L','a','s','t','U','s','e','d','T','y','p','e',0};
+static const WCHAR INSTALLPROPERTY_PACKAGENAME[] = {'P','a','c','k','a','g','e','N','a','m','e',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_MEDIAPACKAGEPATH) == 0)
+    {
+        HKEY key;
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegQueryValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATH, 0, 0,
+                    (LPBYTE)szValue, pcchValue);
+        if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPT) ==0)
+    {
+        HKEY key;
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegQueryValueExW(key, INSTALLPROPERTY_DISKPROMPT, 0, 0,
+                    (LPBYTE)szValue, pcchValue);
+        if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCE)==0)
+    {
+        LPWSTR buffer;
+        DWORD size = 0;
+
+        RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 0, 0, NULL,
+                &size);
+        if (size == 0)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        else
+        {
+            LPWSTR ptr;
+            buffer = HeapAlloc(GetProcessHeap(),0,size);
+            rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 0,
+                        0, (LPBYTE)buffer,&size); 
+            ptr = strchrW(buffer,';');
+            ptr = strchrW(ptr,';');
+            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_LASTUSEDTYPE, szProperty)==0)
+    {
+        LPWSTR buffer;
+        DWORD size = 0;
+
+        RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 0, 0, NULL,
+                &size);
+        if (size == 0)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        else
+        {
+            buffer = HeapAlloc(GetProcessHeap(),0,size);
+            rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 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_PACKAGENAME, szProperty)==0)
+    {
+        rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAME, 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_MEDIAPACKAGEPATH) == 0)
+    {
+        HKEY key;
+        DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegSetValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATH, 0, 
+                    REG_SZ, (LPBYTE)szValue, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPT) ==0)
+    {
+        HKEY key;
+        DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
+        rc = OpenMediaSubkey(sourcekey, &key, FALSE);
+        if (rc == ERROR_SUCCESS)
+            rc = RegSetValueExW(key, INSTALLPROPERTY_DISKPROMPT, 0, REG_SZ,
+                    (LPBYTE)szValue, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+        RegCloseKey(key);
+    }
+    else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCE)==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_LASTUSEDSOURCE, 0, 
+                REG_EXPAND_SZ, (LPBYTE)buffer, size);
+        if (rc != ERROR_SUCCESS)
+            rc = ERROR_UNKNOWN_PROPERTY;
+    }
+    else if (strcmpW(INSTALLPROPERTY_PACKAGENAME, szProperty)==0)
+    {
+        DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
+        rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAME, 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);
+
+    RegCloseKey(sourcekey);
+    RegCloseKey(mediakey);
+
+    return ERROR_SUCCESS;
+}


More information about the wine-patches mailing list