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