diff --git a/reactos/lib/msi/Makefile.in b/reactos/lib/msi/Makefile.in index 38098fab66f..e1216aec360 100644 --- a/reactos/lib/msi/Makefile.in +++ b/reactos/lib/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/reactos/lib/msi/action.c b/reactos/lib/msi/action.c index 6f6ca2e12c9..e16f356fb9b 100644 --- a/reactos/lib/msi/action.c +++ b/reactos/lib/msi/action.c @@ -432,7 +432,7 @@ static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, *****************************************************/ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, - LPCWSTR szCommandLine) + LPCWSTR szCommandLine, LPCWSTR msiFilePath) { 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->InWhatSequence = SEQUENCE_INSTALL; + + package->msiFilePath= strdupW(msiFilePath); + if (szPackagePath) { LPWSTR p, check, path; @@ -538,10 +542,14 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, { if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED) { + package->script->InWhatSequence |= SEQUENCE_UI; rc = ACTION_ProcessUISequence(package); ui = TRUE; if (rc == ERROR_SUCCESS) + { + package->script->InWhatSequence |= SEQUENCE_EXEC; rc = ACTION_ProcessExecSequence(package,TRUE); + } } 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); + msi_dialog_check_messages( NULL ); + + if (iap->package->CurrentInstallState != ERROR_SUCCESS ) + rc = iap->package->CurrentInstallState; + if (rc == ERROR_FUNCTION_NOT_CALLED) rc = ERROR_SUCCESS; @@ -814,18 +827,6 @@ static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, 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 ) { @@ -868,7 +869,6 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force) rc = ERROR_FUNCTION_NOT_CALLED; } - package->CurrentInstallState = 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_HandleDialogBox(package, action, &rc); - - msi_dialog_check_messages( NULL ); + if( !handled && ACTION_DialogBox(package,action) == ERROR_SUCCESS ) + handled = TRUE; if (!handled) { @@ -895,7 +893,6 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action) rc = ERROR_FUNCTION_NOT_CALLED; } - package->CurrentInstallState = 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 (srcdir && srcdir[0] == '.' && srcdir[1] == 0) - srcdir = NULL; - 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; - LPWSTR productcode; - - productcode = load_dynamic_property(package,szProductCode,NULL); 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; @@ -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)); - RegSetValueExW(hkey, deformated, 0, type, value_data, size); + RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value_data, size); } 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) - RegSetValueExW(hkey, deformated, 0, type, value_data, size); + RegSetValueExW(hkey, deformated, 0, type, (LPBYTE) value_data, size); } } RegCloseKey(hkey); @@ -2500,7 +2491,6 @@ static void ACTION_RefCountComponent( MSIPACKAGE* package, UINT index) */ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) { - LPWSTR productcode; 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 */ - productcode = load_dynamic_property(package,szProductCode,&rc); - if (!productcode) - return rc; 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++) { @@ -2555,7 +2542,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) 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 & @@ -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, - (LPVOID)keypath, + (LPBYTE)keypath, (strlenW(keypath)+1)*sizeof(WCHAR)); } @@ -2575,7 +2562,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) /* 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); @@ -2602,7 +2589,7 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) /* 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); @@ -2611,7 +2598,6 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) } } end: - HeapFree(GetProcessHeap(), 0, productcode); 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 */ - LPWSTR productcode; 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 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 szVersion[] = - {'V','e','r','s','i','o','n',0}; 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 */ - 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; - rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE); + rc = MSIREG_OpenUserProductsKey(package->ProductCode,&hukey,TRUE); 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); - 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); - 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); @@ -3087,7 +3060,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) 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); @@ -3096,7 +3070,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) { 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); @@ -3119,8 +3094,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) 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 { @@ -3137,7 +3112,6 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) end: - HeapFree(GetProcessHeap(),0,productcode); RegCloseKey(hkey); RegCloseKey(hukey); @@ -3331,7 +3305,6 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package) static UINT ACTION_PublishFeatures(MSIPACKAGE *package) { - LPWSTR productcode; UINT rc; DWORD i; HKEY hkey=0; @@ -3340,15 +3313,11 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) 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; - rc = MSIREG_OpenUserFeaturesKey(productcode,&hukey,TRUE); + rc = MSIREG_OpenUserFeaturesKey(package->ProductCode,&hukey,TRUE); 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, - (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, - (LPSTR)package->features[i].Feature_Parent,size); + (LPBYTE)package->features[i].Feature_Parent,size); } 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, - (LPSTR)data,size); + (LPBYTE)data,size); HeapFree(GetProcessHeap(),0,data); } } @@ -3425,7 +3394,6 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) end: RegCloseKey(hkey); RegCloseKey(hukey); - HeapFree(GetProcessHeap(), 0, productcode); return rc; } @@ -3433,7 +3401,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) { HKEY hkey=0; LPWSTR buffer = NULL; - LPWSTR productcode; 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}; - 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[] = @@ -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}; - 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 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}; @@ -3520,11 +3475,7 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) 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; @@ -3538,14 +3489,14 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) 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); - 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; @@ -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)); - if (!CopyFileW(package->PackagePath,packagefile,FALSE)) + if (!CopyFileW(package->msiFilePath,packagefile,FALSE)) 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); - 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); - 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; - 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); - 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); - 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); @@ -3611,9 +3565,12 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) 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); @@ -3624,11 +3581,11 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) 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); - squash_guid(productcode,squashed); + squash_guid(package->ProductCode,squashed); RegSetValueExW(hkey2, squashed, 0,REG_SZ,NULL,0); RegCloseKey(hkey2); @@ -3636,7 +3593,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) } end: - HeapFree(GetProcessHeap(),0,productcode); 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]; - HKEY hkey,hukey; - LPWSTR productcode; + HKEY hkey; WCHAR squished_pc[100]; - INT rc; 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; - 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); @@ -3727,41 +3671,18 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package) 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); - sprintfW(buffer,install_fmt,productcode,squished_pc); + sprintfW(buffer,install_fmt,package->ProductCode,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); - 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; } @@ -3776,11 +3697,8 @@ UINT ACTION_ResolveSource(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; - LPWSTR productcode; LPWSTR productid; UINT rc,i; DWORD size; @@ -3804,15 +3722,12 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package) 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; - 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; @@ -3823,7 +3738,7 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package) 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); @@ -3831,7 +3746,6 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package) } end: - HeapFree(GetProcessHeap(),0,productcode); 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); + package->script->InWhatSequence |= SEQUENCE_EXEC; rc = ACTION_ProcessExecSequence(package,FALSE); MSI_SetPropertyW(package,szUILevel,level); HeapFree(GetProcessHeap(),0,level); diff --git a/reactos/lib/msi/action.h b/reactos/lib/msi/action.h index 9c472a53f15..b8914074b9c 100644 --- a/reactos/lib/msi/action.h +++ b/reactos/lib/msi/action.h @@ -187,13 +187,19 @@ enum SCRIPTS { 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; - BOOL FindRelatedProductsRun; BOOL CurrentlyScripting; + UINT InWhatSequence; + LPWSTR *UniqueActions; + UINT UniqueActionsCount; }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); +UINT register_unique_action(MSIPACKAGE *, LPCWSTR); +BOOL check_unique_action(MSIPACKAGE *, LPCWSTR); +WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... ); /* control event stuff */ diff --git a/reactos/lib/msi/appsearch.c b/reactos/lib/msi/appsearch.c index 42ea8a44de9..4f080fa4c61 100644 --- a/reactos/lib/msi/appsearch.c +++ b/reactos/lib/msi/appsearch.c @@ -334,6 +334,13 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, BOOL *appFound, goto end; } + /* bail out if the registry key is empty */ + if (sz == 0) + { + rc = ERROR_SUCCESS; + goto end; + } + switch (regType) { case REG_SZ: diff --git a/reactos/lib/msi/custom.c b/reactos/lib/msi/custom.c index 17645e999cc..5475fa5b3ea 100644 --- a/reactos/lib/msi/custom.c +++ b/reactos/lib/msi/custom.c @@ -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 "msidefs.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 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; @@ -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 */ - 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); @@ -114,7 +160,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) } if (!execute) { - if (type & 0x200) + if (type & msidbCustomActionTypeCommit) { 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 szBlank[] = {0}; 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) { @@ -304,7 +355,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type, { UINT rc = ERROR_SUCCESS; - if (!(type & 0x80)) + if (!(type & msidbCustomActionTypeAsync)) { /* 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); - if (!(type & 0x40)) + if (!(type & msidbCustomActionTypeContinue)) { 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 */ - if (type & 0x40) + if (type & msidbCustomActionTypeContinue) { if (ProcessHandle) { diff --git a/reactos/lib/msi/dialog.c b/reactos/lib/msi/dialog.c index 69e2b1e6fd7..be98cbc9f7a 100644 --- a/reactos/lib/msi/dialog.c +++ b/reactos/lib/msi/dialog.c @@ -53,8 +53,9 @@ struct msi_control_tag msi_handler handler; LPWSTR property; LPWSTR value; - IPicture *pic; + HBITMAP hBitmap; HICON hIcon; + LPWSTR tabnext; WCHAR name[1]; }; @@ -76,6 +77,7 @@ struct msi_dialog_tag LPWSTR default_font; msi_font *font_list; msi_control *control_list; + HWND hWndFocus; WCHAR name[1]; }; @@ -143,6 +145,8 @@ static msi_control *msi_dialog_find_control( msi_dialog *dialog, LPCWSTR name ) { 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; @@ -297,8 +301,9 @@ static msi_control *msi_dialog_create_window( msi_dialog *dialog, control->handler = NULL; control->property = NULL; control->value = NULL; - control->pic = NULL; + control->hBitmap = NULL; control->hIcon = NULL; + control->tabnext = strdupW( MSI_RecordGetString( rec, 11) ); 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; } +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 ) @@ -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; + UINT attributes, style; + LPCWSTR text; 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; + /* 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; } @@ -611,161 +723,56 @@ static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec ) 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 ) { - IPicture *pic = NULL; + UINT cx, cy, flags, style, attributes; msi_control *control; - OLE_HANDLE hBitmap = 0; 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 ) + flags = LR_LOADFROMFILE; + style = SS_BITMAP | SS_LEFT | WS_GROUP; + + attributes = MSI_RecordGetInteger( rec, 8 ); + if( attributes & msidbControlAttributesFixedSize ) { - r = IPicture_get_Handle( pic, &hBitmap ); - if( SUCCEEDED( r ) ) - SendMessageW( control->hwnd, STM_SETIMAGE, IMAGE_BITMAP, hBitmap ); - control->pic = pic; + flags |= LR_DEFAULTSIZE; + style |= SS_CENTERIMAGE; } + + 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 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 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 ) - { - 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 ); - } - - HeapFree( GetProcessHeap(), 0, tmp ); - - return r; -} - static UINT msi_dialog_icon_control( msi_dialog *dialog, MSIRECORD *rec ) { msi_control *control; DWORD attributes; - HICON hIcon = 0; LPCWSTR text; - UINT r; 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 ); - 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; @@ -853,6 +860,28 @@ static void msi_mask_control_change( struct msi_maskedit_info *info ) 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; inum_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) { @@ -869,7 +898,10 @@ MSIMaskedEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { case WM_COMMAND: if (HIWORD(wParam) == EN_CHANGE) + { msi_mask_control_change( info ); + msi_mask_next_control( info, (HWND) lParam ); + } 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; } +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[] = { @@ -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 ); - msiobj_release( &rec->hdr ); 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; } @@ -1617,6 +1684,16 @@ static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd 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 ) { @@ -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_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 ); @@ -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 ); - if( t->pic ) - IPicture_Release( t->pic ); + if( t->hBitmap ) + DeleteObject( t->hBitmap ); if( t->hIcon ) DestroyIcon( t->hIcon ); + HeapFree( GetProcessHeap(), 0, t->tabnext ); HeapFree( GetProcessHeap(), 0, t ); } diff --git a/reactos/lib/msi/events.c b/reactos/lib/msi/events.c index 6d6682bb91f..1c44b9577b2 100644 --- a/reactos/lib/msi/events.c +++ b/reactos/lib/msi/events.c @@ -57,21 +57,23 @@ UINT ControlEvent_HandleControlEvent(MSIPACKAGE *, LPCWSTR, LPCWSTR, msi_dialog* /* * 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; - /* 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 ) { + /* 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 ) @@ -139,7 +141,8 @@ static UINT ControlEvent_NewDialog(MSIPACKAGE* package, LPCWSTR argument, 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; @@ -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. */ - 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; - r = event_do_dialog( package, name ); + r = event_do_dialog( package, name, TRUE ); HeapFree( GetProcessHeap(), 0, name ); } diff --git a/reactos/lib/msi/files.c b/reactos/lib/msi/files.c index a4fd40e493d..c7f0862c109 100644 --- a/reactos/lib/msi/files.c +++ b/reactos/lib/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" @@ -359,7 +360,81 @@ static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, MSICOMPONENT* 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; @@ -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}; - LPCWSTR cab; + LPCWSTR cab, volume; DWORD sz; INT seq; static UINT last_sequence = 0; + 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) { 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; } @@ -394,6 +479,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) { @@ -404,6 +490,9 @@ static UINT ready_media_for_file(MSIPACKAGE *package, int fileindex, 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; @@ -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); + 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; } @@ -422,9 +528,24 @@ 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 = 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 { @@ -439,6 +560,20 @@ 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_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) @@ -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); + 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); + + MsiSourceListAddMediaDiskW(package->ProductCode, NULL, + MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, count, volume, + prompt); + msiobj_release(&row->hdr); return rc; @@ -499,6 +652,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package) { UINT rc = ERROR_SUCCESS; DWORD index; + LPWSTR ptr; 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); + /* 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++) { diff --git a/reactos/lib/msi/helpers.c b/reactos/lib/msi/helpers.c index e9e12f12214..f44e339e22e 100644 --- a/reactos/lib/msi/helpers.c +++ b/reactos/lib/msi/helpers.c @@ -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}; -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}; @@ -88,10 +87,8 @@ DWORD build_version_dword(LPCWSTR version_string) UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, LPWSTR *FilePath) { - LPWSTR ProductCode; LPWSTR SystemFolder; LPWSTR dest; - UINT rc; 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}; - ProductCode = load_dynamic_property(package,szProductCode,&rc); - if (!ProductCode) - return rc; - 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); - HeapFree(GetProcessHeap(),0,ProductCode); 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]); } + + 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->msiFilePath); + HeapFree(GetProcessHeap(),0,package->ProductCode); /* 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 productid=NULL; 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)); - productid = load_dynamic_property(package,szProductCode,NULL); - CLSIDFromString(productid, &clsid); + CLSIDFromString(package->ProductCode, &clsid); 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); - - HeapFree(GetProcessHeap(),0,productid); return output; } @@ -911,3 +906,91 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature) 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; +} diff --git a/reactos/lib/msi/install.c b/reactos/lib/msi/install.c index 9b9ea41dcf7..78f02d0f435 100644 --- a/reactos/lib/msi/install.c +++ b/reactos/lib/msi/install.c @@ -585,3 +585,26 @@ UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent, 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; +} diff --git a/reactos/lib/msi/msi.c b/reactos/lib/msi/msi.c index bec3ccbf05a..cf3bf608d3a 100644 --- a/reactos/lib/msi/msi.c +++ b/reactos/lib/msi/msi.c @@ -83,9 +83,6 @@ UINT WINAPI MsiOpenProductA(LPCSTR 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; @@ -102,7 +99,7 @@ UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) /* 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 ) { @@ -115,7 +112,7 @@ UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) if( !path ) goto end; - r = RegQueryValueExW( hKeyProduct, szLocalPackage, + r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW, 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; + 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)); @@ -209,16 +209,31 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine) 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) + { + DeleteFileW(filename); return r; + } handle = alloc_msihandle( &package->hdr ); - r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine); + r = ACTION_DoTopLevelINSTALL(package, szPackagePath, szCommandLine, + filename); MsiCloseHandle(handle); msiobj_release( &package->hdr ); + + DeleteFileW(filename); return r; } @@ -256,13 +271,9 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, MSIHANDLE handle = -1; MSIPACKAGE* package; UINT rc; - HKEY hkey=0,hkey1=0; 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; @@ -277,20 +288,17 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, return ERROR_CALL_NOT_IMPLEMENTED; } - rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE); - if (rc != ERROR_SUCCESS) - goto end; - - rc = RegOpenKeyW(hkey,szSouceList,&hkey1); - if (rc != ERROR_SUCCESS) - goto end; - sz = sizeof(sourcepath); - rc = RegQueryValueExW(hkey1, szLUS, NULL, NULL,(LPBYTE)sourcepath, &sz); - if (rc != ERROR_SUCCESS) - goto end; + MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, + &sz); + + sz = sizeof(filename); + MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); + + 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 @@ -324,13 +332,12 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, 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: - RegCloseKey(hkey); if (handle != -1) MsiCloseHandle(handle); @@ -509,16 +516,8 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, { 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 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}; @@ -531,7 +530,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, 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]; @@ -542,7 +541,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, 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) { @@ -563,7 +562,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, 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) @@ -572,7 +571,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, 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) @@ -584,7 +583,7 @@ UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, *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) @@ -835,14 +834,14 @@ LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer, 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) { - FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf); + FIXME("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf); 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; - 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, @@ -1584,13 +1580,15 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf, 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; - rc = RegQueryValueExW( hkey, szOwner, NULL, NULL, NULL, &sz); + rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL, + NULL, NULL, &sz); } if (pcchUserNameBuf) @@ -1599,13 +1597,14 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf, 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; - rc2 = RegQueryValueExW( hkey, szCompany, NULL, NULL, NULL, &sz); + rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL, + NULL, NULL, &sz); } if (pcchOrgNameBuf) @@ -1621,13 +1620,14 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf, 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; - rc = RegQueryValueExW( hkey, szSerial, NULL, NULL, NULL, &sz); + rc = RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL, + NULL, NULL, &sz); } if (pcchSerialBuf) *pcchSerialBuf = sz / sizeof(WCHAR); diff --git a/reactos/lib/msi/msi.spec b/reactos/lib/msi/msi.spec index ecb7621ff39..1cd59449ec6 100644 --- a/reactos/lib/msi/msi.spec +++ b/reactos/lib/msi/msi.spec @@ -60,7 +60,7 @@ 60 stdcall MsiGetFeatureUsageW(wstr wstr ptr ptr) 61 stub MsiGetFeatureValidStatesA 62 stub MsiGetFeatureValidStatesW -63 stub MsiGetLanguage +63 stdcall MsiGetLanguage(long) 64 stdcall MsiGetMode(long long) 65 stdcall MsiGetProductCodeA(str str) 66 stdcall MsiGetProductCodeW(wstr wstr) diff --git a/reactos/lib/msi/msi.xml b/reactos/lib/msi/msi.xml index 81bb068d370..ed7fdd280b4 100644 --- a/reactos/lib/msi/msi.xml +++ b/reactos/lib/msi/msi.xml @@ -47,6 +47,7 @@ registry.c regsvr.c select.c + source.c sql.tab.c string.c suminfo.c diff --git a/reactos/lib/msi/msipriv.h b/reactos/lib/msi/msipriv.h index dde612992fe..eaef4f50883 100644 --- a/reactos/lib/msi/msipriv.h +++ b/reactos/lib/msi/msipriv.h @@ -55,7 +55,7 @@ struct tagMSIOBJECTHDR { UINT magic; UINT type; - DWORD refcount; + LONG refcount; msihandledestructor destructor; struct tagMSIOBJECTHDR *next; struct tagMSIOBJECTHDR *prev; @@ -216,6 +216,8 @@ typedef struct tagMSIPACKAGE UINT RunningActionCount; LPWSTR PackagePath; + LPWSTR msiFilePath; + LPWSTR ProductCode; UINT CurrentInstallState; msi_dialog *dialog; @@ -281,8 +283,8 @@ extern HRESULT init_string_table( IStorage *stg ); /* 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 ); @@ -307,7 +309,7 @@ extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname, 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); diff --git a/reactos/lib/msi/package.c b/reactos/lib/msi/package.c index 54a692452eb..d3114df8f10 100644 --- a/reactos/lib/msi/package.c +++ b/reactos/lib/msi/package.c @@ -408,6 +408,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) 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); @@ -445,6 +447,13 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) 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; @@ -454,18 +463,40 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP { 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); + /* 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); - ret = MSI_OpenPackageW( szPackage, &package); + ret = MSI_OpenPackageW( filename, &package); if( ret == ERROR_SUCCESS ) { *phPackage = alloc_msihandle( &package->hdr ); msiobj_release( &package->hdr ); } + + if( szPackage[0] != '#' ) + DeleteFileW(filename); + return ret; } @@ -862,6 +893,10 @@ UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, 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; @@ -889,6 +924,10 @@ UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, 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; diff --git a/reactos/lib/msi/registry.c b/reactos/lib/msi/registry.c index 012986115c2..c96a766fcfa 100644 --- a/reactos/lib/msi/registry.c +++ b/reactos/lib/msi/registry.c @@ -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); + 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); - if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA) + if (rc == ERROR_SUCCESS) { if (lpApplicationDataBuf && pcchApplicationDataBuf) { @@ -898,6 +907,8 @@ UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex, debugstr_w(lpApplicationDataBuf)); } + HeapFree(GetProcessHeap(),0,full_buffer); + return rc; } diff --git a/reactos/lib/msi/source.c b/reactos/lib/msi/source.c new file mode 100644 index 00000000000..136d492fa48 --- /dev/null +++ b/reactos/lib/msi/source.c @@ -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 + +#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; +} diff --git a/reactos/lib/msi/string.c b/reactos/lib/msi/string.c index 4222894c58a..62a73310e07 100644 --- a/reactos/lib/msi/string.c +++ b/reactos/lib/msi/string.c @@ -142,7 +142,7 @@ static void st_mark_entry_used( string_table *st, UINT n ) 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; @@ -190,7 +190,7 @@ int msi_addstring( string_table *st, int n, const CHAR *data, int len, UINT refc 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) ); */ diff --git a/reactos/lib/msi/suminfo.c b/reactos/lib/msi/suminfo.c index cd507f2c082..f7692a4c828 100644 --- a/reactos/lib/msi/suminfo.c +++ b/reactos/lib/msi/suminfo.c @@ -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 ) - lstrcpyA( &data[ofs + 4], str ); + memcpy( &data[ofs + 4], str, len ); return (7 + len) & ~3; } diff --git a/reactos/lib/msi/upgrade.c b/reactos/lib/msi/upgrade.c index 7a066ca621a..e96a8e4aadc 100644 --- a/reactos/lib/msi/upgrade.c +++ b/reactos/lib/msi/upgrade.c @@ -136,10 +136,6 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param) 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); @@ -151,8 +147,8 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param) } 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); @@ -179,8 +175,8 @@ static UINT ITERATE_FindRelatedProducts(MSIRECORD *rec, LPVOID param) /* 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, @@ -211,12 +207,14 @@ UINT ACTION_FindRelatedProducts(MSIPACKAGE *package) 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; + } + 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; diff --git a/reactos/w32api/include/msi.h b/reactos/w32api/include/msi.h index 1c1278272c4..38e37251f99 100644 --- a/reactos/w32api/include/msi.h +++ b/reactos/w32api/include/msi.h @@ -148,8 +148,192 @@ 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 +/* 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); @@ -189,10 +373,6 @@ UINT WINAPI MsiEnumClientsA(LPCSTR, DWORD, LPSTR); 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) @@ -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 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) @@ -321,6 +497,22 @@ INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR, LPSTR, DWORD *); 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);