diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index c1044600a24..4b2fd150c93 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -561,6 +561,18 @@ UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine) return rc; } +UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode) +{ + FIXME("%s 0x%08lx\n", debugstr_a(szProduct), dwReinstallMode); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode) +{ + FIXME("%s 0x%08lx\n", debugstr_w(szProduct), dwReinstallMode); + return ERROR_CALL_NOT_IMPLEMENTED; +} + UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState) { LPWSTR szwProduct = NULL; diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec index 7153fc78c1b..8bc8cf26a02 100644 --- a/dlls/msi/msi.spec +++ b/dlls/msi/msi.spec @@ -127,8 +127,8 @@ 127 stub MsiReinstallFeatureFromDescriptorA 128 stub MsiReinstallFeatureFromDescriptorW 129 stub MsiReinstallFeatureW -130 stub MsiReinstallProductA -131 stub MsiReinstallProductW +130 stdcall MsiReinstallProductA(str long) +131 stdcall MsiReinstallProductW(wstr long) 132 stub MsiSequenceA 133 stub MsiSequenceW 134 stub MsiSetComponentStateA diff --git a/include/msi.h b/include/msi.h index 72f67fee989..5f86f091fa7 100644 --- a/include/msi.h +++ b/include/msi.h @@ -77,6 +77,21 @@ typedef enum tagINSTALLMESSAGE INSTALLMESSAGE_SHOWDIALOG = 0x0e000000 } INSTALLMESSAGE; +typedef enum tagREINSTALLMODE +{ + REINSTALLMODE_REPAIR = 0x00000001, + REINSTALLMODE_FILEMISSING = 0x00000002, + REINSTALLMODE_FILEOLDERVERSION = 0x00000004, + REINSTALLMODE_FILEEQUALVERSION = 0x00000008, + REINSTALLMODE_FILEEXACT = 0x00000010, + REINSTALLMODE_FILEVERIFY = 0x00000020, + REINSTALLMODE_FILEREPLACE = 0x00000040, + REINSTALLMODE_MACHINEDATA = 0x00000080, + REINSTALLMODE_USERDATA = 0x00000100, + REINSTALLMODE_SHORTCUT = 0x00000200, + REINSTALLMODE_PACKAGE = 0x00000400 +} REINSTALLMODE; + typedef enum tagINSTALLLOGMODE { INSTALLLOGMODE_FATALEXIT = (1 << (INSTALLMESSAGE_FATALEXIT >> 24)), @@ -113,6 +128,10 @@ UINT WINAPI MsiInstallProductA(LPCSTR, LPCSTR); UINT WINAPI MsiInstallProductW(LPCWSTR, LPCWSTR); #define MsiInstallProduct WINELIB_NAME_AW(MsiInstallProduct) +UINT WINAPI MsiReinstallProductA(LPCSTR, DWORD); +UINT WINAPI MsiReinstallProductW(LPCWSTR, DWORD); +#define MsiReinstallProduct WINELIB_NAME_AW(MsiReinstallProduct) + UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid); UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid); #define MsiEnumProducts WINELIB_NAME_AW(MsiEnumProducts) diff --git a/programs/msiexec/msiexec.c b/programs/msiexec/msiexec.c index 79b546a4a85..21cd9c2eea3 100644 --- a/programs/msiexec/msiexec.c +++ b/programs/msiexec/msiexec.c @@ -123,6 +123,7 @@ int main(int argc, char *argv[]) { int i; BOOL FunctionInstall = FALSE; + BOOL FunctionRepair = FALSE; BOOL FunctionDllRegisterServer = FALSE; BOOL FunctionDllUnregisterServer = FALSE; @@ -132,6 +133,8 @@ int main(int argc, char *argv[]) LPSTR Properties = HeapAlloc(GetProcessHeap(), 0, 1); LPSTR TempStr = NULL; + DWORD RepairMode = 0; + LPSTR DllName = NULL; Properties[0] = 0; @@ -172,11 +175,68 @@ int main(int argc, char *argv[]) } else if(!strncasecmp(argv[i], "/f", 2)) { + int j; + int len = strlen(argv[i]); + FunctionRepair = TRUE; + for(j = 2; j < len; j++) + { + switch(argv[i][j]) + { + case 'P': + case 'p': + RepairMode |= REINSTALLMODE_FILEMISSING; + break; + case 'O': + case 'o': + RepairMode |= REINSTALLMODE_FILEOLDERVERSION; + break; + case 'E': + case 'e': + RepairMode |= REINSTALLMODE_FILEEQUALVERSION; + break; + case 'D': + case 'd': + RepairMode |= REINSTALLMODE_FILEEXACT; + break; + case 'C': + case 'c': + RepairMode |= REINSTALLMODE_FILEVERIFY; + break; + case 'A': + case 'a': + RepairMode |= REINSTALLMODE_FILEREPLACE; + break; + case 'U': + case 'u': + RepairMode |= REINSTALLMODE_USERDATA; + break; + case 'M': + case 'm': + RepairMode |= REINSTALLMODE_MACHINEDATA; + break; + case 'S': + case 's': + RepairMode |= REINSTALLMODE_SHORTCUT; + break; + case 'V': + case 'v': + RepairMode |= REINSTALLMODE_PACKAGE; + break; + default: + fprintf(stderr, "Unknown option \"%c\" in Repair mode\n", argv[i][j]); + break; + } + } i++; if(i >= argc) ShowUsage(1); - WINE_FIXME("Repair not implemented yet\n"); - ExitProcess(1); + GotProductCode = GetProductCode(argv[i], ProductCode); + if(!GotProductCode) + { + HeapFree(GetProcessHeap(), 0, ProductCode); + ProductCode = NULL; + PackageName = argv[i]; + } } else if(!strcasecmp(argv[i], "/x")) { @@ -311,6 +371,22 @@ int main(int argc, char *argv[]) } } } + else if(FunctionRepair) + { + if(GotProductCode) + { + WINE_FIXME("Product code treatment not implemented yet\n"); + ExitProcess(1); + } + else + { + if(MsiReinstallProductA(PackageName, RepairMode) != ERROR_SUCCESS) + { + fprintf(stderr, "Repair of %s (0x%08lx) failed.\n", PackageName, RepairMode); + ExitProcess(1); + } + } + } else if(FunctionDllRegisterServer) { DllRegisterServer(DllName);