From b7dc53d462b639132439d8dd6f8b0885718dcc7f Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Tue, 5 Jul 2005 21:00:06 +0000 Subject: [PATCH] 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. --- dlls/msi/Makefile.in | 1 + dlls/msi/files.c | 98 +++++++- dlls/msi/msipriv.h | 1 + dlls/msi/source.c | 567 +++++++++++++++++++++++++++++++++++++++++++ include/msi.h | 38 +++ 5 files changed, 699 insertions(+), 6 deletions(-) create mode 100644 dlls/msi/source.c diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in index 57b4c060e6a..f484e5d9e9d 100644 --- a/dlls/msi/Makefile.in +++ b/dlls/msi/Makefile.in @@ -33,6 +33,7 @@ C_SRCS = \ registry.c \ regsvr.c \ select.c \ + source.c \ string.c \ suminfo.c \ table.c \ diff --git a/dlls/msi/files.c b/dlls/msi/files.c index a524f25b2f9..382a0af38b2 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -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 szRemoveDuplicateFiles[]; 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 @@ static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, MSICOMPONENT* 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 @@ static BOOL check_volume(LPCWSTR path, LPCWSTR want_volume, LPWSTR volume) 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 BOOL check_for_sourcefile(LPCWSTR source) } 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 UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, 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 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, return ERROR_SUCCESS; } + count ++; row = MSI_QueryGetRecord(package->db, ExecSeqQuery, file->Sequence); if (!row) { @@ -478,6 +488,7 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, 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 @@ 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); - 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 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, /* 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 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, { 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 @@ 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); - 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 ACTION_InstallFiles(MSIPACKAGE *package) { UINT rc = ERROR_SUCCESS; DWORD index; + LPWSTR ptr; if (!package) return ERROR_INVALID_HANDLE; @@ -584,6 +658,18 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package) /* 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++) { diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 4aa39ceb1b5..968e9a9fefb 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -217,6 +217,7 @@ typedef struct tagMSIPACKAGE LPWSTR PackagePath; LPWSTR msiFilePath; + LPWSTR ProductCode; UINT CurrentInstallState; msi_dialog *dialog; diff --git a/dlls/msi/source.c b/dlls/msi/source.c new file mode 100644 index 00000000000..b1db1b27a20 --- /dev/null +++ b/dlls/msi/source.c @@ -0,0 +1,567 @@ +/* + * 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 + +#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; + HeapFree( GetProcessHeap(), 0, buffer ); + } + 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); + HeapFree( GetProcessHeap(), 0, buffer ); + + RegCloseKey(sourcekey); + RegCloseKey(mediakey); + + return ERROR_SUCCESS; +} diff --git a/include/msi.h b/include/msi.h index 1c1278272c4..dc4aa91a353 100644 --- a/include/msi.h +++ b/include/msi.h @@ -148,6 +148,31 @@ typedef enum tagINSTALLTYPE 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); @@ -326,6 +351,19 @@ UINT WINAPI MsiCloseHandle(MSIHANDLE); UINT WINAPI MsiCloseAllHandles(void); INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL, HWND*); +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) + #ifdef __cplusplus } #endif