diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Common/Dlgcode.c | 219 | ||||
-rw-r--r-- | src/Common/Dlgcode.h | 21 | ||||
-rw-r--r-- | src/Setup/Setup.c | 18 |
3 files changed, 256 insertions, 2 deletions
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 4738e6e1..8b1db616 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -591,18 +591,27 @@ BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD bytesWritten; BOOL res = TRUE; DWORD dwLastError = 0; +#if defined(SETUP) && !defined (PORTABLE) + BOOL securityModified = FALSE; + SECURITY_INFO_BACKUP secBackup = { 0 }; + const wchar_t* existingFile = destinationFile; +#endif dst = CreateFile (destinationFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); dwLastError = GetLastError(); - if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION)) + if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION || GetLastError() == ERROR_ACCESS_DENIED)) { wchar_t renamedPath[TC_MAX_PATH + 1]; StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile); StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX); +#if defined(SETUP) && !defined (PORTABLE) + // Take ownership of the file + securityModified = ModifyFileSecurityPermissions(destinationFile, &secBackup); +#endif /* rename the locked file in order to be able to create a new one */ if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING)) { @@ -617,10 +626,20 @@ BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, } else { +#if defined(SETUP) && !defined (PORTABLE) + existingFile = renamedPath; +#endif /* delete the renamed file when the machine reboots */ MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } } +#if defined(SETUP) && !defined (PORTABLE) + if (securityModified) + { + RestoreSecurityInfo(existingFile, &secBackup); + FreeSecurityBackup(&secBackup); + } +#endif } if (dst == INVALID_HANDLE_VALUE) @@ -15762,3 +15781,201 @@ DWORD FastResizeFile (const wchar_t* filePath, __int64 fileSize) return dwRet; } #endif // VC_COMREG + +#if defined(SETUP) && !defined (PORTABLE) + +// Helper function to save the current state of the required privileges +BOOL SaveCurrentPrivilegeState(PPRIVILEGE_STATE state) { + if (!state) return FALSE; + + state->takeOwnership = IsPrivilegeEnabled(SE_TAKE_OWNERSHIP_NAME); + state->backup = IsPrivilegeEnabled(SE_BACKUP_NAME); + state->restore = IsPrivilegeEnabled(SE_RESTORE_NAME); + + return TRUE; +} + +// Helper function to restore the saved state of the required privileges +BOOL RestorePrivilegeState(const PPRIVILEGE_STATE state) { + if (!state) return FALSE; + + BOOL result = TRUE; + result &= SetPrivilege(SE_TAKE_OWNERSHIP_NAME, state->takeOwnership); + result &= SetPrivilege(SE_BACKUP_NAME, state->backup); + result &= SetPrivilege(SE_RESTORE_NAME, state->restore); + + return result; +} + +// Helper function to enable required privileges for file operations +BOOL EnableRequiredSetupPrivileges(PPRIVILEGE_STATE currentState) +{ + BOOL result = TRUE; + + // save the current state of the required privileges + ZeroMemory(currentState, sizeof(PRIVILEGE_STATE)); + SaveCurrentPrivilegeState(currentState); + + // Enable required privileges using the existing SetPrivilege function + result &= SetPrivilege(SE_TAKE_OWNERSHIP_NAME, TRUE); + result &= SetPrivilege(SE_BACKUP_NAME, TRUE); + result &= SetPrivilege(SE_RESTORE_NAME, TRUE); + + return result; +} + +// Helper function to backup security information +BOOL BackupSecurityInfo(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup) +{ + BOOL result = FALSE; + PSECURITY_DESCRIPTOR pSD = NULL; + DWORD dwRes; + + ZeroMemory(pBackup, sizeof(SECURITY_INFO_BACKUP)); + + // Get the security descriptor + dwRes = GetNamedSecurityInfoW( + (LPWSTR)filePath, + SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, + &pBackup->pOrigOwner, + &pBackup->pOrigGroup, + &pBackup->pOrigDacl, + &pBackup->pOrigSacl, + &pSD); + + if (dwRes == ERROR_SUCCESS) + { + // The individual pointers (pOrigOwner, etc.) are now valid + // and point to the copied data + result = TRUE; + } + + if (pSD) + LocalFree(pSD); + + return result; +} + +// Helper function to restore security information +BOOL RestoreSecurityInfo(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup) +{ + DWORD dwRes; + SECURITY_INFORMATION secInfo = 0; + + if (pBackup->pOrigOwner) + secInfo |= OWNER_SECURITY_INFORMATION; + if (pBackup->pOrigGroup) + secInfo |= GROUP_SECURITY_INFORMATION; + if (pBackup->pOrigDacl) + secInfo |= DACL_SECURITY_INFORMATION; + if (pBackup->pOrigSacl) + secInfo |= SACL_SECURITY_INFORMATION; + + if (secInfo == 0) + return TRUE; // Nothing to restore + + dwRes = SetNamedSecurityInfoW( + (LPWSTR)filePath, + SE_FILE_OBJECT, + secInfo, + pBackup->pOrigOwner, + pBackup->pOrigGroup, + pBackup->pOrigDacl, + pBackup->pOrigSacl); + + return (dwRes == ERROR_SUCCESS); +} + +// Helper function to free security backup +void FreeSecurityBackup(PSECURITY_INFO_BACKUP pBackup) +{ + if (pBackup->pOrigOwner) + LocalFree(pBackup->pOrigOwner); + if (pBackup->pOrigGroup) + LocalFree(pBackup->pOrigGroup); + if (pBackup->pOrigDacl) + LocalFree(pBackup->pOrigDacl); + if (pBackup->pOrigSacl) + LocalFree(pBackup->pOrigSacl); + ZeroMemory(pBackup, sizeof(SECURITY_INFO_BACKUP)); +} + +// Helper function to take ownership and modify file permissions +BOOL ModifyFileSecurityPermissions(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup) +{ + BOOL result = FALSE; + PSID pAdminSID = NULL; + PACL pNewDACL = NULL; + BOOL bBackupDone = FALSE; + + // Get Administrator SID + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + if (!AllocateAndInitializeSid(&SIDAuthNT, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdminSID)) + { + goto cleanup; + } + + // Backup original security info + if (!BackupSecurityInfo(filePath, pBackup)) + goto cleanup; + + bBackupDone = TRUE; + + // Take ownership + DWORD dwRes = SetNamedSecurityInfoW( + (LPWSTR)filePath, + SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, + pAdminSID, + NULL, + NULL, + NULL); + + if (dwRes != ERROR_SUCCESS) + goto cleanup; + + // Modify DACL + EXPLICIT_ACCESS ea; + ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); + ea.grfAccessPermissions = GENERIC_ALL; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea.Trustee.ptstrName = (LPTSTR)pAdminSID; + + dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDACL); + if (dwRes != ERROR_SUCCESS) + goto cleanup; + + // Apply new DACL + dwRes = SetNamedSecurityInfoW( + (LPWSTR)filePath, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + pNewDACL, + NULL); + + result = (dwRes == ERROR_SUCCESS); + +cleanup: + if (!result && bBackupDone) + { + FreeSecurityBackup(pBackup); + } + if (pNewDACL) + LocalFree(pNewDACL); + if (pAdminSID) + FreeSid(pAdminSID); + + return result; +} +#endif
\ No newline at end of file diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index ecf1bbd4..2bc95ae9 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -598,6 +598,27 @@ DWORD FastResizeFile (const wchar_t* filePath, __int64 fileSize); void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed); #endif BOOL IsInternetConnected(); +#if defined(SETUP) && !defined (PORTABLE) +typedef struct _SECURITY_INFO_BACKUP { + PSID pOrigOwner; + PSID pOrigGroup; + PACL pOrigDacl; + PACL pOrigSacl; +} SECURITY_INFO_BACKUP, * PSECURITY_INFO_BACKUP; + +typedef struct _PRIVILEGE_STATE { + BOOL takeOwnership; + BOOL backup; + BOOL restore; +} PRIVILEGE_STATE, * PPRIVILEGE_STATE; + +BOOL RestoreSecurityInfo(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup); +void FreeSecurityBackup(PSECURITY_INFO_BACKUP pBackup); +BOOL SaveCurrentPrivilegeState(PPRIVILEGE_STATE state); +BOOL RestorePrivilegeState(const PPRIVILEGE_STATE state); +BOOL EnableRequiredSetupPrivileges(PPRIVILEGE_STATE currentState); +BOOL ModifyFileSecurityPermissions(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup); +#endif #ifdef __cplusplus } diff --git a/src/Setup/Setup.c b/src/Setup/Setup.c index 0a66dccd..ed236616 100644 --- a/src/Setup/Setup.c +++ b/src/Setup/Setup.c @@ -765,6 +765,9 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir) BOOL bOK = TRUE; int i, x, fileNo; wchar_t curFileName [TC_MAX_PATH] = {0}; +#ifndef PORTABLE + PRIVILEGE_STATE originalPrivileges = { 0 }; +#endif if (!bUninstall && !bDevm) { @@ -783,6 +786,10 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir) if (szDestDir[x - 1] != L'\\') StringCbCatW (szDestDir, MAX_PATH, L"\\"); +#ifndef PORTABLE + EnableRequiredSetupPrivileges(&originalPrivileges); +#endif + for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++) { BOOL bResult, zipFile = FALSE; @@ -1114,10 +1121,19 @@ err: if (lpMsgBuf) LocalFree (lpMsgBuf); - if (!Silent && MessageBoxW (hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES) + if (!Silent && MessageBoxW(hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES) + { +#ifndef PORTABLE + RestorePrivilegeState(&originalPrivileges); +#endif return FALSE; + } } } + +#ifndef PORTABLE + RestorePrivilegeState(&originalPrivileges); +#endif if (bUninstall == FALSE) { |