diff options
Diffstat (limited to 'onlineupdate')
40 files changed, 5373 insertions, 4429 deletions
diff --git a/onlineupdate/source/libmar/sign/nss_secutil.h b/onlineupdate/source/libmar/sign/nss_secutil.h index 363c64918068..f599fcce573d 100644 --- a/onlineupdate/source/libmar/sign/nss_secutil.h +++ b/onlineupdate/source/libmar/sign/nss_secutil.h @@ -16,14 +16,16 @@ #include "key.h" #include <stdint.h> -typedef struct { - enum { - PW_NONE = 0, - PW_FROMFILE = 1, - PW_PLAINTEXT = 2, - PW_EXTERNAL = 3 - } source; - char *data; +typedef struct +{ + enum + { + PW_NONE = 0, + PW_FROMFILE = 1, + PW_PLAINTEXT = 2, + PW_EXTERNAL = 3 + } source; + char *data; } secuPWData; #if( defined(_WINDOWS) && !defined(_WIN32_WCE)) diff --git a/onlineupdate/source/libmar/verify/cryptox.h b/onlineupdate/source/libmar/verify/cryptox.h index d08ef159a83c..eb8548fa7a4f 100644 --- a/onlineupdate/source/libmar/verify/cryptox.h +++ b/onlineupdate/source/libmar/verify/cryptox.h @@ -77,9 +77,9 @@ CryptoX_Result CryptoMac_LoadPublicKey(const unsigned char* aCertData, unsigned int aDataSize, CryptoX_PublicKey* aPublicKey); CryptoX_Result CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData, - CryptoX_PublicKey* aPublicKey, - const unsigned char* aSignature, - unsigned int aSignatureLen); + CryptoX_PublicKey* aPublicKey, + const unsigned char* aSignature, + unsigned int aSignatureLen); void CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData); void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey); #ifdef __cplusplus @@ -118,9 +118,9 @@ CryptoX_Result CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash); CryptoX_Result CryptoAPI_VerifyUpdate(HCRYPTHASH* hash, BYTE *buf, DWORD len); CryptoX_Result CyprtoAPI_VerifySignature(HCRYPTHASH *hash, - HCRYPTKEY *pubKey, - const BYTE *signature, - DWORD signatureLen); + HCRYPTKEY *pubKey, + const BYTE *signature, + DWORD signatureLen); #define CryptoX_InvalidHandleValue ((ULONG_PTR)NULL) #define CryptoX_ProviderHandle HCRYPTPROV diff --git a/onlineupdate/source/service/certificatecheck.cxx b/onlineupdate/source/service/certificatecheck.cxx index 3a9eba020ccb..58d70162f40c 100644 --- a/onlineupdate/source/service/certificatecheck.cxx +++ b/onlineupdate/source/service/certificatecheck.cxx @@ -28,87 +28,97 @@ DWORD CheckCertificateForPEFile(LPCWSTR filePath, CertificateCheckInfo &infoToMatch) { - HCERTSTORE certStore = nullptr; - HCRYPTMSG cryptMsg = nullptr; - PCCERT_CONTEXT certContext = nullptr; - PCMSG_SIGNER_INFO signerInfo = nullptr; - DWORD lastError = ERROR_SUCCESS; + HCERTSTORE certStore = nullptr; + HCRYPTMSG cryptMsg = nullptr; + PCCERT_CONTEXT certContext = nullptr; + PCMSG_SIGNER_INFO signerInfo = nullptr; + DWORD lastError = ERROR_SUCCESS; - // Get the HCERTSTORE and HCRYPTMSG from the signed file. - DWORD encoding, contentType, formatType; - BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE, - filePath, - CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, - CERT_QUERY_CONTENT_FLAG_ALL, - 0, &encoding, &contentType, - &formatType, &certStore, &cryptMsg, nullptr); - if (!result) { - lastError = GetLastError(); - LOG_WARN(("CryptQueryObject failed. (%d)", lastError)); - goto cleanup; - } + // Get the HCERTSTORE and HCRYPTMSG from the signed file. + DWORD encoding, contentType, formatType; + BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE, + filePath, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_CONTENT_FLAG_ALL, + 0, &encoding, &contentType, + &formatType, &certStore, &cryptMsg, nullptr); + if (!result) + { + lastError = GetLastError(); + LOG_WARN(("CryptQueryObject failed. (%d)", lastError)); + goto cleanup; + } - // Pass in nullptr to get the needed signer information size. - DWORD signerInfoSize; - result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0, - nullptr, &signerInfoSize); - if (!result) { - lastError = GetLastError(); - LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError)); - goto cleanup; - } + // Pass in nullptr to get the needed signer information size. + DWORD signerInfoSize; + result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0, + nullptr, &signerInfoSize); + if (!result) + { + lastError = GetLastError(); + LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError)); + goto cleanup; + } - // Allocate the needed size for the signer information. - signerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, signerInfoSize); - if (!signerInfo) { - lastError = GetLastError(); - LOG_WARN(("Unable to allocate memory for Signer Info. (%d)", lastError)); - goto cleanup; - } + // Allocate the needed size for the signer information. + signerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, signerInfoSize); + if (!signerInfo) + { + lastError = GetLastError(); + LOG_WARN(("Unable to allocate memory for Signer Info. (%d)", lastError)); + goto cleanup; + } - // Get the signer information (PCMSG_SIGNER_INFO). - // In particular we want the issuer and serial number. - result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0, - (PVOID)signerInfo, &signerInfoSize); - if (!result) { - lastError = GetLastError(); - LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError)); - goto cleanup; - } + // Get the signer information (PCMSG_SIGNER_INFO). + // In particular we want the issuer and serial number. + result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0, + (PVOID)signerInfo, &signerInfoSize); + if (!result) + { + lastError = GetLastError(); + LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError)); + goto cleanup; + } - // Search for the signer certificate in the certificate store. - CERT_INFO certInfo; - certInfo.Issuer = signerInfo->Issuer; - certInfo.SerialNumber = signerInfo->SerialNumber; - certContext = CertFindCertificateInStore(certStore, ENCODING, 0, - CERT_FIND_SUBJECT_CERT, - (PVOID)&certInfo, nullptr); - if (!certContext) { - lastError = GetLastError(); - LOG_WARN(("CertFindCertificateInStore failed. (%d)", lastError)); - goto cleanup; - } + // Search for the signer certificate in the certificate store. + CERT_INFO certInfo; + certInfo.Issuer = signerInfo->Issuer; + certInfo.SerialNumber = signerInfo->SerialNumber; + certContext = CertFindCertificateInStore(certStore, ENCODING, 0, + CERT_FIND_SUBJECT_CERT, + (PVOID)&certInfo, nullptr); + if (!certContext) + { + lastError = GetLastError(); + LOG_WARN(("CertFindCertificateInStore failed. (%d)", lastError)); + goto cleanup; + } - if (!DoCertificateAttributesMatch(certContext, infoToMatch)) { - lastError = ERROR_NOT_FOUND; - LOG_WARN(("Certificate did not match issuer or name. (%d)", lastError)); - goto cleanup; - } + if (!DoCertificateAttributesMatch(certContext, infoToMatch)) + { + lastError = ERROR_NOT_FOUND; + LOG_WARN(("Certificate did not match issuer or name. (%d)", lastError)); + goto cleanup; + } cleanup: - if (signerInfo) { - LocalFree(signerInfo); - } - if (certContext) { - CertFreeCertificateContext(certContext); - } - if (certStore) { - CertCloseStore(certStore, 0); - } - if (cryptMsg) { - CryptMsgClose(cryptMsg); - } - return lastError; + if (signerInfo) + { + LocalFree(signerInfo); + } + if (certContext) + { + CertFreeCertificateContext(certContext); + } + if (certStore) + { + CertCloseStore(certStore, 0); + } + if (cryptMsg) + { + CryptMsgClose(cryptMsg); + } + return lastError; } /** @@ -122,86 +132,96 @@ BOOL DoCertificateAttributesMatch(PCCERT_CONTEXT certContext, CertificateCheckInfo &infoToMatch) { - DWORD dwData; - LPTSTR szName = nullptr; + DWORD dwData; + LPTSTR szName = nullptr; - if (infoToMatch.issuer) { - // Pass in nullptr to get the needed size of the issuer buffer. - dwData = CertGetNameString(certContext, - CERT_NAME_SIMPLE_DISPLAY_TYPE, - CERT_NAME_ISSUER_FLAG, nullptr, - nullptr, 0); + if (infoToMatch.issuer) + { + // Pass in nullptr to get the needed size of the issuer buffer. + dwData = CertGetNameString(certContext, + CERT_NAME_SIMPLE_DISPLAY_TYPE, + CERT_NAME_ISSUER_FLAG, nullptr, + nullptr, 0); - if (!dwData) { - LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); - return FALSE; - } + if (!dwData) + { + LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); + return FALSE; + } - // Allocate memory for Issuer name buffer. - LPTSTR szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR)); - if (!szName) { - LOG_WARN(("Unable to allocate memory for issuer name. (%d)", - GetLastError())); - return FALSE; - } + // Allocate memory for Issuer name buffer. + LPTSTR szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR)); + if (!szName) + { + LOG_WARN(("Unable to allocate memory for issuer name. (%d)", + GetLastError())); + return FALSE; + } - // Get Issuer name. - if (!CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, - CERT_NAME_ISSUER_FLAG, nullptr, szName, dwData)) { - LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); - LocalFree(szName); - return FALSE; - } + // Get Issuer name. + if (!CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, + CERT_NAME_ISSUER_FLAG, nullptr, szName, dwData)) + { + LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); + LocalFree(szName); + return FALSE; + } - // If the issuer does not match, return a failure. - if (!infoToMatch.issuer || - wcscmp(szName, infoToMatch.issuer)) { - LocalFree(szName); - return FALSE; + // If the issuer does not match, return a failure. + if (!infoToMatch.issuer || + wcscmp(szName, infoToMatch.issuer)) + { + LocalFree(szName); + return FALSE; + } + + LocalFree(szName); + szName = nullptr; } - LocalFree(szName); - szName = nullptr; - } + if (infoToMatch.name) + { + // Pass in nullptr to get the needed size of the name buffer. + dwData = CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, + 0, nullptr, nullptr, 0); + if (!dwData) + { + LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); + return FALSE; + } - if (infoToMatch.name) { - // Pass in nullptr to get the needed size of the name buffer. - dwData = CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, - 0, nullptr, nullptr, 0); - if (!dwData) { - LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); - return FALSE; - } + // Allocate memory for the name buffer. + szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR)); + if (!szName) + { + LOG_WARN(("Unable to allocate memory for subject name. (%d)", + GetLastError())); + return FALSE; + } - // Allocate memory for the name buffer. - szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR)); - if (!szName) { - LOG_WARN(("Unable to allocate memory for subject name. (%d)", - GetLastError())); - return FALSE; - } + // Obtain the name. + if (!(CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, + nullptr, szName, dwData))) + { + LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); + LocalFree(szName); + return FALSE; + } - // Obtain the name. - if (!(CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, - nullptr, szName, dwData))) { - LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); - LocalFree(szName); - return FALSE; - } + // If the issuer does not match, return a failure. + if (!infoToMatch.name || + wcscmp(szName, infoToMatch.name)) + { + LocalFree(szName); + return FALSE; + } - // If the issuer does not match, return a failure. - if (!infoToMatch.name || - wcscmp(szName, infoToMatch.name)) { - LocalFree(szName); - return FALSE; + // We have a match! + LocalFree(szName); } - // We have a match! - LocalFree(szName); - } - - // If there were any errors we would have aborted by now. - return TRUE; + // If there were any errors we would have aborted by now. + return TRUE; } /** @@ -213,12 +233,13 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext, LPWSTR AllocateAndCopyWideString(LPCWSTR inputString) { - LPWSTR outputString = - (LPWSTR)LocalAlloc(LPTR, (wcslen(inputString) + 1) * sizeof(WCHAR)); - if (outputString) { - lstrcpyW(outputString, inputString); - } - return outputString; + LPWSTR outputString = + (LPWSTR)LocalAlloc(LPTR, (wcslen(inputString) + 1) * sizeof(WCHAR)); + if (outputString) + { + lstrcpyW(outputString, inputString); + } + return outputString; } /** @@ -230,41 +251,42 @@ AllocateAndCopyWideString(LPCWSTR inputString) DWORD VerifyCertificateTrustForFile(LPCWSTR filePath) { - // Setup the file to check. - WINTRUST_FILE_INFO fileToCheck; - ZeroMemory(&fileToCheck, sizeof(fileToCheck)); - fileToCheck.cbStruct = sizeof(WINTRUST_FILE_INFO); - fileToCheck.pcwszFilePath = filePath; + // Setup the file to check. + WINTRUST_FILE_INFO fileToCheck; + ZeroMemory(&fileToCheck, sizeof(fileToCheck)); + fileToCheck.cbStruct = sizeof(WINTRUST_FILE_INFO); + fileToCheck.pcwszFilePath = filePath; - // Setup what to check, we want to check it is signed and trusted. - WINTRUST_DATA trustData; - ZeroMemory(&trustData, sizeof(trustData)); - trustData.cbStruct = sizeof(trustData); - trustData.pPolicyCallbackData = nullptr; - trustData.pSIPClientData = nullptr; - trustData.dwUIChoice = WTD_UI_NONE; - trustData.fdwRevocationChecks = WTD_REVOKE_NONE; - trustData.dwUnionChoice = WTD_CHOICE_FILE; - trustData.dwStateAction = 0; - trustData.hWVTStateData = nullptr; - trustData.pwszURLReference = nullptr; - // no UI - trustData.dwUIContext = 0; - trustData.pFile = &fileToCheck; + // Setup what to check, we want to check it is signed and trusted. + WINTRUST_DATA trustData; + ZeroMemory(&trustData, sizeof(trustData)); + trustData.cbStruct = sizeof(trustData); + trustData.pPolicyCallbackData = nullptr; + trustData.pSIPClientData = nullptr; + trustData.dwUIChoice = WTD_UI_NONE; + trustData.fdwRevocationChecks = WTD_REVOKE_NONE; + trustData.dwUnionChoice = WTD_CHOICE_FILE; + trustData.dwStateAction = 0; + trustData.hWVTStateData = nullptr; + trustData.pwszURLReference = nullptr; + // no UI + trustData.dwUIContext = 0; + trustData.pFile = &fileToCheck; - GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2; - // Check if the file is signed by something that is trusted. - LONG ret = WinVerifyTrust(nullptr, &policyGUID, &trustData); - if (ERROR_SUCCESS == ret) { - // The hash that represents the subject is trusted and there were no - // verification errors. No publisher nor time stamp chain errors. - LOG(("The file \"%ls\" is signed and the signature was verified.", - filePath)); - return ERROR_SUCCESS; - } + GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2; + // Check if the file is signed by something that is trusted. + LONG ret = WinVerifyTrust(nullptr, &policyGUID, &trustData); + if (ERROR_SUCCESS == ret) + { + // The hash that represents the subject is trusted and there were no + // verification errors. No publisher nor time stamp chain errors. + LOG(("The file \"%ls\" is signed and the signature was verified.", + filePath)); + return ERROR_SUCCESS; + } - DWORD lastError = GetLastError(); - LOG_WARN(("There was an error validating trust of the certificate for file" - " \"%ls\". Returned: %d. (%d)", filePath, ret, lastError)); - return ret; + DWORD lastError = GetLastError(); + LOG_WARN(("There was an error validating trust of the certificate for file" + " \"%ls\". Returned: %d. (%d)", filePath, ret, lastError)); + return ret; } diff --git a/onlineupdate/source/service/certificatecheck.hxx b/onlineupdate/source/service/certificatecheck.hxx index 43a7c85b6b77..1efbcb153a65 100644 --- a/onlineupdate/source/service/certificatecheck.hxx +++ b/onlineupdate/source/service/certificatecheck.hxx @@ -9,14 +9,14 @@ struct CertificateCheckInfo { - LPCWSTR name; - LPCWSTR issuer; + LPCWSTR name; + LPCWSTR issuer; }; -BOOL DoCertificateAttributesMatch(PCCERT_CONTEXT pCertContext, +BOOL DoCertificateAttributesMatch(PCCERT_CONTEXT pCertContext, CertificateCheckInfo &infoToMatch); DWORD VerifyCertificateTrustForFile(LPCWSTR filePath); -DWORD CheckCertificateForPEFile(LPCWSTR filePath, +DWORD CheckCertificateForPEFile(LPCWSTR filePath, CertificateCheckInfo &infoToMatch); #endif diff --git a/onlineupdate/source/service/maintenanceservice.cxx b/onlineupdate/source/service/maintenanceservice.cxx index 8471bdbd56c5..036bfe25192f 100644 --- a/onlineupdate/source/service/maintenanceservice.cxx +++ b/onlineupdate/source/service/maintenanceservice.cxx @@ -33,92 +33,106 @@ BOOL GetLogDirectoryPath(WCHAR *path); int wmain(int argc, WCHAR **argv) { - if (argc < 2) - { - LOG_WARN(("missing mandatory command line argument")); - return 1; - } - // If command-line parameter is "install", install the service - // or upgrade if already installed - // If command line parameter is "forceinstall", install the service - // even if it is older than what is already installed. - // If command-line parameter is "upgrade", upgrade the service - // but do not install it if it is not already installed. - // If command line parameter is "uninstall", uninstall the service. - // Otherwise, the service is probably being started by the SCM. - bool forceInstall = !lstrcmpi(argv[1], L"forceinstall"); - if (!lstrcmpi(argv[1], L"install") || forceInstall) { - WCHAR updatePath[MAX_PATH + 1]; - if (GetLogDirectoryPath(updatePath)) { - LogInit(updatePath, L"maintenanceservice-install.log"); + if (argc < 2) + { + LOG_WARN(("missing mandatory command line argument")); + return 1; } - - SvcInstallAction action = InstallSvc; - if (forceInstall) { - action = ForceInstallSvc; - LOG(("Installing service with force specified...")); - } else { - LOG(("Installing service...")); + // If command-line parameter is "install", install the service + // or upgrade if already installed + // If command line parameter is "forceinstall", install the service + // even if it is older than what is already installed. + // If command-line parameter is "upgrade", upgrade the service + // but do not install it if it is not already installed. + // If command line parameter is "uninstall", uninstall the service. + // Otherwise, the service is probably being started by the SCM. + bool forceInstall = !lstrcmpi(argv[1], L"forceinstall"); + if (!lstrcmpi(argv[1], L"install") || forceInstall) + { + WCHAR updatePath[MAX_PATH + 1]; + if (GetLogDirectoryPath(updatePath)) + { + LogInit(updatePath, L"maintenanceservice-install.log"); + } + + SvcInstallAction action = InstallSvc; + if (forceInstall) + { + action = ForceInstallSvc; + LOG(("Installing service with force specified...")); + } + else + { + LOG(("Installing service...")); + } + + bool ret = SvcInstall(action); + if (!ret) + { + LOG_WARN(("Could not install service. (%d)", GetLastError())); + LogFinish(); + return 1; + } + + LOG(("The service was installed successfully")); + LogFinish(); + return 0; } - bool ret = SvcInstall(action); - if (!ret) { - LOG_WARN(("Could not install service. (%d)", GetLastError())); - LogFinish(); - return 1; + if (!lstrcmpi(argv[1], L"upgrade")) + { + WCHAR updatePath[MAX_PATH + 1]; + if (GetLogDirectoryPath(updatePath)) + { + LogInit(updatePath, L"maintenanceservice-install.log"); + } + + LOG(("Upgrading service if installed...")); + if (!SvcInstall(UpgradeSvc)) + { + LOG_WARN(("Could not upgrade service. (%d)", GetLastError())); + LogFinish(); + return 1; + } + + LOG(("The service was upgraded successfully")); + LogFinish(); + return 0; } - LOG(("The service was installed successfully")); - LogFinish(); - return 0; - } - - if (!lstrcmpi(argv[1], L"upgrade")) { - WCHAR updatePath[MAX_PATH + 1]; - if (GetLogDirectoryPath(updatePath)) { - LogInit(updatePath, L"maintenanceservice-install.log"); + if (!lstrcmpi(argv[1], L"uninstall")) + { + WCHAR updatePath[MAX_PATH + 1]; + if (GetLogDirectoryPath(updatePath)) + { + LogInit(updatePath, L"maintenanceservice-uninstall.log"); + } + LOG(("Uninstalling service...")); + if (!SvcUninstall()) + { + LOG_WARN(("Could not uninstall service. (%d)", GetLastError())); + LogFinish(); + return 1; + } + LOG(("The service was uninstalled successfully")); + LogFinish(); + return 0; } - LOG(("Upgrading service if installed...")); - if (!SvcInstall(UpgradeSvc)) { - LOG_WARN(("Could not upgrade service. (%d)", GetLastError())); - LogFinish(); - return 1; + SERVICE_TABLE_ENTRYW DispatchTable[] = + { + { SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain }, + { nullptr, nullptr } + }; + + // This call returns when the service has stopped. + // The process should simply terminate when the call returns. + if (!StartServiceCtrlDispatcherW(DispatchTable)) + { + LOG_WARN(("StartServiceCtrlDispatcher failed. (%d)", GetLastError())); } - LOG(("The service was upgraded successfully")); - LogFinish(); return 0; - } - - if (!lstrcmpi(argv[1], L"uninstall")) { - WCHAR updatePath[MAX_PATH + 1]; - if (GetLogDirectoryPath(updatePath)) { - LogInit(updatePath, L"maintenanceservice-uninstall.log"); - } - LOG(("Uninstalling service...")); - if (!SvcUninstall()) { - LOG_WARN(("Could not uninstall service. (%d)", GetLastError())); - LogFinish(); - return 1; - } - LOG(("The service was uninstalled successfully")); - LogFinish(); - return 0; - } - - SERVICE_TABLE_ENTRYW DispatchTable[] = { - { SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain }, - { nullptr, nullptr } - }; - - // This call returns when the service has stopped. - // The process should simply terminate when the call returns. - if (!StartServiceCtrlDispatcherW(DispatchTable)) { - LOG_WARN(("StartServiceCtrlDispatcher failed. (%d)", GetLastError())); - } - - return 0; } /** @@ -130,24 +144,27 @@ wmain(int argc, WCHAR **argv) BOOL GetLogDirectoryPath(WCHAR *path) { - HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr, - SHGFP_TYPE_CURRENT, path); - if (FAILED(hr)) { - return FALSE; - } - - if (!PathAppendSafe(path, L"Mozilla")) { - return FALSE; - } - // The directory should already be created from the installer, but - // just to be safe in case someone deletes. - CreateDirectoryW(path, nullptr); - - if (!PathAppendSafe(path, L"logs")) { - return FALSE; - } - CreateDirectoryW(path, nullptr); - return TRUE; + HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr, + SHGFP_TYPE_CURRENT, path); + if (FAILED(hr)) + { + return FALSE; + } + + if (!PathAppendSafe(path, L"Mozilla")) + { + return FALSE; + } + // The directory should already be created from the installer, but + // just to be safe in case someone deletes. + CreateDirectoryW(path, nullptr); + + if (!PathAppendSafe(path, L"logs")) + { + return FALSE; + } + CreateDirectoryW(path, nullptr); + return TRUE; } /** @@ -161,16 +178,19 @@ GetLogDirectoryPath(WCHAR *path) BOOL GetBackupLogPath(LPWSTR path, LPCWSTR basePath, int logNumber) { - WCHAR logName[64] = { L'\0' }; - wcsncpy(path, basePath, sizeof(logName) / sizeof(logName[0]) - 1); - if (logNumber <= 0) { - swprintf(logName, sizeof(logName) / sizeof(logName[0]), - L"maintenanceservice.log"); - } else { - swprintf(logName, sizeof(logName) / sizeof(logName[0]), - L"maintenanceservice-%d.log", logNumber); - } - return PathAppendSafe(path, logName); + WCHAR logName[64] = { L'\0' }; + wcsncpy(path, basePath, sizeof(logName) / sizeof(logName[0]) - 1); + if (logNumber <= 0) + { + swprintf(logName, sizeof(logName) / sizeof(logName[0]), + L"maintenanceservice.log"); + } + else + { + swprintf(logName, sizeof(logName) / sizeof(logName[0]), + L"maintenanceservice-%d.log", logNumber); + } + return PathAppendSafe(path, logName); } /** @@ -187,21 +207,25 @@ GetBackupLogPath(LPWSTR path, LPCWSTR basePath, int logNumber) void BackupOldLogs(LPCWSTR basePath, int numLogsToKeep) { - WCHAR oldPath[MAX_PATH + 1]; - WCHAR newPath[MAX_PATH + 1]; - for (int i = numLogsToKeep; i >= 1; i--) { - if (!GetBackupLogPath(oldPath, basePath, i -1)) { - continue; - } - - if (!GetBackupLogPath(newPath, basePath, i)) { - continue; + WCHAR oldPath[MAX_PATH + 1]; + WCHAR newPath[MAX_PATH + 1]; + for (int i = numLogsToKeep; i >= 1; i--) + { + if (!GetBackupLogPath(oldPath, basePath, i -1)) + { + continue; + } + + if (!GetBackupLogPath(newPath, basePath, i)) + { + continue; + } + + if (!MoveFileExW(oldPath, newPath, MOVEFILE_REPLACE_EXISTING)) + { + continue; + } } - - if (!MoveFileExW(oldPath, newPath, MOVEFILE_REPLACE_EXISTING)) { - continue; - } - } } /** @@ -221,20 +245,21 @@ BackupOldLogs(LPCWSTR basePath, int numLogsToKeep) DWORD WINAPI EnsureProcessTerminatedThread(LPVOID) { - Sleep(5000); - exit(0); + Sleep(5000); + exit(0); } void StartTerminationThread() { - // If the process does not self terminate like it should, this thread - // will terminate the process after 5 seconds. - HANDLE thread = CreateThread(nullptr, 0, EnsureProcessTerminatedThread, - nullptr, 0, nullptr); - if (thread) { - CloseHandle(thread); - } + // If the process does not self terminate like it should, this thread + // will terminate the process after 5 seconds. + HANDLE thread = CreateThread(nullptr, 0, EnsureProcessTerminatedThread, + nullptr, 0, nullptr); + if (thread) + { + CloseHandle(thread); + } } /** @@ -243,61 +268,65 @@ StartTerminationThread() void WINAPI SvcMain(DWORD argc, LPWSTR *argv) { - // Setup logging, and backup the old logs - WCHAR updatePath[MAX_PATH + 1]; - if (GetLogDirectoryPath(updatePath)) { - BackupOldLogs(updatePath, LOGS_TO_KEEP); - LogInit(updatePath, L"maintenanceservice.log"); - } - - // Disable every privilege we don't need. Processes started using - // CreateProcess will use the same token as this process. - UACHelper::DisablePrivileges(nullptr); - - // Register the handler function for the service - gSvcStatusHandle = RegisterServiceCtrlHandlerW(SVC_NAME, SvcCtrlHandler); - if (!gSvcStatusHandle) { - LOG_WARN(("RegisterServiceCtrlHandler failed. (%d)", GetLastError())); - ExecuteServiceCommand(argc, argv); - LogFinish(); - exit(1); - } - - // These values will be re-used later in calls involving gSvcStatus - gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - gSvcStatus.dwServiceSpecificExitCode = 0; + // Setup logging, and backup the old logs + WCHAR updatePath[MAX_PATH + 1]; + if (GetLogDirectoryPath(updatePath)) + { + BackupOldLogs(updatePath, LOGS_TO_KEEP); + LogInit(updatePath, L"maintenanceservice.log"); + } - // Report initial status to the SCM - ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); + // Disable every privilege we don't need. Processes started using + // CreateProcess will use the same token as this process. + UACHelper::DisablePrivileges(nullptr); + + // Register the handler function for the service + gSvcStatusHandle = RegisterServiceCtrlHandlerW(SVC_NAME, SvcCtrlHandler); + if (!gSvcStatusHandle) + { + LOG_WARN(("RegisterServiceCtrlHandler failed. (%d)", GetLastError())); + ExecuteServiceCommand(argc, argv); + LogFinish(); + exit(1); + } - // This event will be used to tell the SvcCtrlHandler when the work is - // done for when a stop comamnd is manually issued. - gWorkDoneEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); - if (!gWorkDoneEvent) { - ReportSvcStatus(SERVICE_STOPPED, 1, 0); - StartTerminationThread(); - return; - } + // These values will be re-used later in calls involving gSvcStatus + gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + gSvcStatus.dwServiceSpecificExitCode = 0; + + // Report initial status to the SCM + ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); + + // This event will be used to tell the SvcCtrlHandler when the work is + // done for when a stop comamnd is manually issued. + gWorkDoneEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (!gWorkDoneEvent) + { + ReportSvcStatus(SERVICE_STOPPED, 1, 0); + StartTerminationThread(); + return; + } - // Initialization complete and we're about to start working on - // the actual command. Report the service state as running to the SCM. - ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); + // Initialization complete and we're about to start working on + // the actual command. Report the service state as running to the SCM. + ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); - // The service command was executed, stop logging and set an event - // to indicate the work is done in case someone is waiting on a - // service stop operation. - ExecuteServiceCommand(argc, argv); - LogFinish(); + // The service command was executed, stop logging and set an event + // to indicate the work is done in case someone is waiting on a + // service stop operation. + ExecuteServiceCommand(argc, argv); + LogFinish(); - SetEvent(gWorkDoneEvent); + SetEvent(gWorkDoneEvent); - // If we aren't already in a stopping state then tell the SCM we're stopped - // now. If we are already in a stopping state then the SERVICE_STOPPED state - // will be set by the SvcCtrlHandler. - if (!gServiceControlStopping) { - ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); - StartTerminationThread(); - } + // If we aren't already in a stopping state then tell the SCM we're stopped + // now. If we are already in a stopping state then the SERVICE_STOPPED state + // will be set by the SvcCtrlHandler. + if (!gServiceControlStopping) + { + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); + StartTerminationThread(); + } } /** @@ -312,29 +341,35 @@ ReportSvcStatus(DWORD currentState, DWORD exitCode, DWORD waitHint) { - static DWORD dwCheckPoint = 1; - - gSvcStatus.dwCurrentState = currentState; - gSvcStatus.dwWin32ExitCode = exitCode; - gSvcStatus.dwWaitHint = waitHint; - - if (SERVICE_START_PENDING == currentState || - SERVICE_STOP_PENDING == currentState) { - gSvcStatus.dwControlsAccepted = 0; - } else { - gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | - SERVICE_ACCEPT_SHUTDOWN; - } - - if ((SERVICE_RUNNING == currentState) || - (SERVICE_STOPPED == currentState)) { - gSvcStatus.dwCheckPoint = 0; - } else { - gSvcStatus.dwCheckPoint = dwCheckPoint++; - } - - // Report the status of the service to the SCM. - SetServiceStatus(gSvcStatusHandle, &gSvcStatus); + static DWORD dwCheckPoint = 1; + + gSvcStatus.dwCurrentState = currentState; + gSvcStatus.dwWin32ExitCode = exitCode; + gSvcStatus.dwWaitHint = waitHint; + + if (SERVICE_START_PENDING == currentState || + SERVICE_STOP_PENDING == currentState) + { + gSvcStatus.dwControlsAccepted = 0; + } + else + { + gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN; + } + + if ((SERVICE_RUNNING == currentState) || + (SERVICE_STOPPED == currentState)) + { + gSvcStatus.dwCheckPoint = 0; + } + else + { + gSvcStatus.dwCheckPoint = dwCheckPoint++; + } + + // Report the status of the service to the SCM. + SetServiceStatus(gSvcStatusHandle, &gSvcStatus); } /** @@ -344,14 +379,16 @@ ReportSvcStatus(DWORD currentState, DWORD WINAPI StopServiceAndWaitForCommandThread(LPVOID) { - do { - ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 1000); - } while(WaitForSingleObject(gWorkDoneEvent, 100) == WAIT_TIMEOUT); - CloseHandle(gWorkDoneEvent); - gWorkDoneEvent = nullptr; - ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); - StartTerminationThread(); - return 0; + do + { + ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 1000); + } + while (WaitForSingleObject(gWorkDoneEvent, 100) == WAIT_TIMEOUT); + CloseHandle(gWorkDoneEvent); + gWorkDoneEvent = nullptr; + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); + StartTerminationThread(); + return 0; } /** @@ -361,35 +398,41 @@ StopServiceAndWaitForCommandThread(LPVOID) void WINAPI SvcCtrlHandler(DWORD dwCtrl) { - // After a SERVICE_CONTROL_STOP there should be no more commands sent to - // the SvcCtrlHandler. - if (gServiceControlStopping) { - return; - } - - // Handle the requested control code. - switch(dwCtrl) { - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: { - gServiceControlStopping = true; - ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 1000); - - // The SvcCtrlHandler thread should not spend more than 30 seconds in - // shutdown so we spawn a new thread for stopping the service - HANDLE thread = CreateThread(nullptr, 0, - StopServiceAndWaitForCommandThread, - nullptr, 0, nullptr); - if (thread) { - CloseHandle(thread); - } else { - // Couldn't start the thread so just call the stop ourselves. - // If it happens to take longer than 30 seconds the caller will - // get an error. - StopServiceAndWaitForCommandThread(nullptr); - } + // After a SERVICE_CONTROL_STOP there should be no more commands sent to + // the SvcCtrlHandler. + if (gServiceControlStopping) + { + return; + } + + // Handle the requested control code. + switch (dwCtrl) + { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + { + gServiceControlStopping = true; + ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 1000); + + // The SvcCtrlHandler thread should not spend more than 30 seconds in + // shutdown so we spawn a new thread for stopping the service + HANDLE thread = CreateThread(nullptr, 0, + StopServiceAndWaitForCommandThread, + nullptr, 0, nullptr); + if (thread) + { + CloseHandle(thread); + } + else + { + // Couldn't start the thread so just call the stop ourselves. + // If it happens to take longer than 30 seconds the caller will + // get an error. + StopServiceAndWaitForCommandThread(nullptr); + } + } + break; + default: + break; } - break; - default: - break; - } } diff --git a/onlineupdate/source/service/maintenanceservice.hxx b/onlineupdate/source/service/maintenanceservice.hxx index 9e02914a0e7b..af5db9e29dae 100644 --- a/onlineupdate/source/service/maintenanceservice.hxx +++ b/onlineupdate/source/service/maintenanceservice.hxx @@ -5,6 +5,6 @@ void WINAPI SvcMain(DWORD dwArgc, LPWSTR *lpszArgv); void SvcInit(DWORD dwArgc, LPWSTR *lpszArgv); void WINAPI SvcCtrlHandler(DWORD dwCtrl); -void ReportSvcStatus(DWORD dwCurrentState, - DWORD dwWin32ExitCode, +void ReportSvcStatus(DWORD dwCurrentState, + DWORD dwWin32ExitCode, DWORD dwWaitHint); diff --git a/onlineupdate/source/service/registrycertificates.cxx b/onlineupdate/source/service/registrycertificates.cxx index f44fb3427d00..ea0905cea888 100644 --- a/onlineupdate/source/service/registrycertificates.cxx +++ b/onlineupdate/source/service/registrycertificates.cxx @@ -55,115 +55,127 @@ struct AutoRegKey BOOL DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath) { - WCHAR maintenanceServiceKey[MAX_PATH + 1]; - if (!CalculateRegistryPathFromFilePath(basePathForUpdate, - maintenanceServiceKey)) { - return FALSE; - } - - // We use KEY_WOW64_64KEY to always force 64-bit view. - // The user may have both x86 and x64 applications installed - // which each register information. We need a consistent place - // to put those certificate attributes in and hence why we always - // force the non redirected registry under Wow6432Node. - // This flag is ignored on 32bit systems. - HKEY baseKeyRaw; - LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - maintenanceServiceKey, 0, - KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not open key. (%d)", retCode)); - // Our tests run with a different apply directory for each test. - // We use this registry key on our test slaves to store the - // allowed name/issuers. - retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - TEST_ONLY_FALLBACK_KEY_PATH, 0, - KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not open fallback key. (%d)", retCode)); - return FALSE; - } - } - AutoRegKey baseKey(baseKeyRaw); - - // Get the number of subkeys. - DWORD subkeyCount = 0; - retCode = RegQueryInfoKeyW(baseKey.get(), nullptr, nullptr, nullptr, &subkeyCount, - nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not query info key. (%d)", retCode)); - return FALSE; - } - - // Enumerate the subkeys, each subkey represents an allowed certificate. - for (DWORD i = 0; i < subkeyCount; i++) { - WCHAR subkeyBuffer[MAX_KEY_LENGTH]; - DWORD subkeyBufferCount = MAX_KEY_LENGTH; - retCode = RegEnumKeyExW(baseKey.get(), i, subkeyBuffer, - &subkeyBufferCount, nullptr, - nullptr, nullptr, nullptr); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not enum certs. (%d)", retCode)); - return FALSE; + WCHAR maintenanceServiceKey[MAX_PATH + 1]; + if (!CalculateRegistryPathFromFilePath(basePathForUpdate, + maintenanceServiceKey)) + { + return FALSE; } - // Open the subkey for the current certificate - HKEY subKeyRaw; - retCode = RegOpenKeyExW(baseKey.get(), - subkeyBuffer, - 0, - KEY_READ | KEY_WOW64_64KEY, - &subKeyRaw); - AutoRegKey subKey(subKeyRaw); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not open subkey. (%d)", retCode)); - continue; // Try the next subkey + // We use KEY_WOW64_64KEY to always force 64-bit view. + // The user may have both x86 and x64 applications installed + // which each register information. We need a consistent place + // to put those certificate attributes in and hence why we always + // force the non redirected registry under Wow6432Node. + // This flag is ignored on 32bit systems. + HKEY baseKeyRaw; + LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + maintenanceServiceKey, 0, + KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not open key. (%d)", retCode)); + // Our tests run with a different apply directory for each test. + // We use this registry key on our test slaves to store the + // allowed name/issuers. + retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TEST_ONLY_FALLBACK_KEY_PATH, 0, + KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not open fallback key. (%d)", retCode)); + return FALSE; + } } - - const int MAX_CHAR_COUNT = 256; - DWORD valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR); - WCHAR name[MAX_CHAR_COUNT] = { L'\0' }; - WCHAR issuer[MAX_CHAR_COUNT] = { L'\0' }; - - // Get the name from the registry - retCode = RegQueryValueExW(subKey.get(), L"name", 0, nullptr, - (LPBYTE)name, &valueBufSize); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not obtain name from registry. (%d)", retCode)); - continue; // Try the next subkey + AutoRegKey baseKey(baseKeyRaw); + + // Get the number of subkeys. + DWORD subkeyCount = 0; + retCode = RegQueryInfoKeyW(baseKey.get(), nullptr, nullptr, nullptr, &subkeyCount, + nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not query info key. (%d)", retCode)); + return FALSE; } - // Get the issuer from the registry - valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR); - retCode = RegQueryValueExW(subKey.get(), L"issuer", 0, nullptr, - (LPBYTE)issuer, &valueBufSize); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Could not obtain issuer from registry. (%d)", retCode)); - continue; // Try the next subkey - } + // Enumerate the subkeys, each subkey represents an allowed certificate. + for (DWORD i = 0; i < subkeyCount; i++) + { + WCHAR subkeyBuffer[MAX_KEY_LENGTH]; + DWORD subkeyBufferCount = MAX_KEY_LENGTH; + retCode = RegEnumKeyExW(baseKey.get(), i, subkeyBuffer, + &subkeyBufferCount, nullptr, + nullptr, nullptr, nullptr); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not enum certs. (%d)", retCode)); + return FALSE; + } - CertificateCheckInfo allowedCertificate = { - name, - issuer, - }; + // Open the subkey for the current certificate + HKEY subKeyRaw; + retCode = RegOpenKeyExW(baseKey.get(), + subkeyBuffer, + 0, + KEY_READ | KEY_WOW64_64KEY, + &subKeyRaw); + AutoRegKey subKey(subKeyRaw); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not open subkey. (%d)", retCode)); + continue; // Try the next subkey + } - retCode = CheckCertificateForPEFile(filePath, allowedCertificate); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Error on certificate check. (%d)", retCode)); - continue; // Try the next subkey - } + const int MAX_CHAR_COUNT = 256; + DWORD valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR); + WCHAR name[MAX_CHAR_COUNT] = { L'\0' }; + WCHAR issuer[MAX_CHAR_COUNT] = { L'\0' }; - retCode = VerifyCertificateTrustForFile(filePath); - if (retCode != ERROR_SUCCESS) { - LOG_WARN(("Error on certificate trust check. (%d)", retCode)); - continue; // Try the next subkey - } + // Get the name from the registry + retCode = RegQueryValueExW(subKey.get(), L"name", 0, nullptr, + (LPBYTE)name, &valueBufSize); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not obtain name from registry. (%d)", retCode)); + continue; // Try the next subkey + } + + // Get the issuer from the registry + valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR); + retCode = RegQueryValueExW(subKey.get(), L"issuer", 0, nullptr, + (LPBYTE)issuer, &valueBufSize); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Could not obtain issuer from registry. (%d)", retCode)); + continue; // Try the next subkey + } + + CertificateCheckInfo allowedCertificate = + { + name, + issuer, + }; - // Raise the roof, we found a match! - return TRUE; - } + retCode = CheckCertificateForPEFile(filePath, allowedCertificate); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Error on certificate check. (%d)", retCode)); + continue; // Try the next subkey + } + + retCode = VerifyCertificateTrustForFile(filePath); + if (retCode != ERROR_SUCCESS) + { + LOG_WARN(("Error on certificate trust check. (%d)", retCode)); + continue; // Try the next subkey + } + + // Raise the roof, we found a match! + return TRUE; + } - // No certificates match, :'( - return FALSE; + // No certificates match, :'( + return FALSE; } diff --git a/onlineupdate/source/service/resource.hxx b/onlineupdate/source/service/resource.hxx index 45619457c9aa..f1a1c383665d 100644 --- a/onlineupdate/source/service/resource.hxx +++ b/onlineupdate/source/service/resource.hxx @@ -9,7 +9,7 @@ #define IDI_DIALOG 1003 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 diff --git a/onlineupdate/source/service/servicebase.cxx b/onlineupdate/source/service/servicebase.cxx index 1b4f406f431e..4fb632878cec 100644 --- a/onlineupdate/source/service/servicebase.cxx +++ b/onlineupdate/source/service/servicebase.cxx @@ -18,68 +18,80 @@ BOOL VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent) { - sameContent = FALSE; - AutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ, + sameContent = FALSE; + AutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); - if (file1 == INVALID_HANDLE_VALUE) { - return FALSE; - } - AutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ, + if (file1 == INVALID_HANDLE_VALUE) + { + return FALSE; + } + AutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); - if (file2 == INVALID_HANDLE_VALUE) { - return FALSE; - } - - DWORD fileSize1 = GetFileSize(file1.get(), nullptr); - DWORD fileSize2 = GetFileSize(file2.get(), nullptr); - if (INVALID_FILE_SIZE == fileSize1 || INVALID_FILE_SIZE == fileSize2) { - return FALSE; - } - - if (fileSize1 != fileSize2) { - // sameContent is already set to FALSE - return TRUE; - } - - char buf1[COMPARE_BLOCKSIZE]; - char buf2[COMPARE_BLOCKSIZE]; - DWORD numBlocks = fileSize1 / COMPARE_BLOCKSIZE; - DWORD leftOver = fileSize1 % COMPARE_BLOCKSIZE; - DWORD readAmount; - for (DWORD i = 0; i < numBlocks; i++) { - if (!ReadFile(file1.get(), buf1, COMPARE_BLOCKSIZE, &readAmount, nullptr) || - readAmount != COMPARE_BLOCKSIZE) { - return FALSE; + if (file2 == INVALID_HANDLE_VALUE) + { + return FALSE; } - if (!ReadFile(file2.get(), buf2, COMPARE_BLOCKSIZE, &readAmount, nullptr) || - readAmount != COMPARE_BLOCKSIZE) { - return FALSE; + DWORD fileSize1 = GetFileSize(file1.get(), nullptr); + DWORD fileSize2 = GetFileSize(file2.get(), nullptr); + if (INVALID_FILE_SIZE == fileSize1 || INVALID_FILE_SIZE == fileSize2) + { + return FALSE; } - if (memcmp(buf1, buf2, COMPARE_BLOCKSIZE)) { - // sameContent is already set to FALSE - return TRUE; + if (fileSize1 != fileSize2) + { + // sameContent is already set to FALSE + return TRUE; } - } - if (leftOver) { - if (!ReadFile(file1.get(), buf1, leftOver, &readAmount, nullptr) || - readAmount != leftOver) { - return FALSE; - } + char buf1[COMPARE_BLOCKSIZE]; + char buf2[COMPARE_BLOCKSIZE]; + DWORD numBlocks = fileSize1 / COMPARE_BLOCKSIZE; + DWORD leftOver = fileSize1 % COMPARE_BLOCKSIZE; + DWORD readAmount; + for (DWORD i = 0; i < numBlocks; i++) + { + if (!ReadFile(file1.get(), buf1, COMPARE_BLOCKSIZE, &readAmount, nullptr) || + readAmount != COMPARE_BLOCKSIZE) + { + return FALSE; + } + + if (!ReadFile(file2.get(), buf2, COMPARE_BLOCKSIZE, &readAmount, nullptr) || + readAmount != COMPARE_BLOCKSIZE) + { + return FALSE; + } - if (!ReadFile(file2.get(), buf2, leftOver, &readAmount, nullptr) || - readAmount != leftOver) { - return FALSE; + if (memcmp(buf1, buf2, COMPARE_BLOCKSIZE)) + { + // sameContent is already set to FALSE + return TRUE; + } } - if (memcmp(buf1, buf2, leftOver)) { - // sameContent is already set to FALSE - return TRUE; + if (leftOver) + { + if (!ReadFile(file1.get(), buf1, leftOver, &readAmount, nullptr) || + readAmount != leftOver) + { + return FALSE; + } + + if (!ReadFile(file2.get(), buf2, leftOver, &readAmount, nullptr) || + readAmount != leftOver) + { + return FALSE; + } + + if (memcmp(buf1, buf2, leftOver)) + { + // sameContent is already set to FALSE + return TRUE; + } } - } - sameContent = TRUE; - return TRUE; + sameContent = TRUE; + return TRUE; } diff --git a/onlineupdate/source/service/servicebase.hxx b/onlineupdate/source/service/servicebase.hxx index abf88a122a1d..c47f966ad551 100644 --- a/onlineupdate/source/service/servicebase.hxx +++ b/onlineupdate/source/service/servicebase.hxx @@ -14,7 +14,7 @@ BOOL VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent); #define COMPARE_BLOCKSIZE 32768 // The following string resource value is used to uniquely identify the signed -// Mozilla application as an updater. Before the maintenance service will +// Mozilla application as an updater. Before the maintenance service will // execute the updater it must have this updater identity string in its string // table. No other signed Mozilla product will have this string table value. #define UPDATER_IDENTITY_STRING \ diff --git a/onlineupdate/source/service/serviceinstall.cxx b/onlineupdate/source/service/serviceinstall.cxx index cf7fef354186..a225e9445544 100644 --- a/onlineupdate/source/service/serviceinstall.cxx +++ b/onlineupdate/source/service/serviceinstall.cxx @@ -73,19 +73,20 @@ static int ReadMaintenanceServiceStrings(LPCWSTR path, MaintenanceServiceStringTable *results) { - // Read in the maintenance service description string if specified. - const unsigned int kNumStrings = 1; - const char *kServiceKeys = "MozillaMaintenanceDescription\0"; - char serviceStrings[kNumStrings][MAX_TEXT_LEN]; - int result = ReadStrings(path, kServiceKeys, - kNumStrings, serviceStrings); - if (result != OK) { - serviceStrings[0][0] = '\0'; - } - strncpy(results->serviceDescription, - serviceStrings[0], MAX_TEXT_LEN - 1); - results->serviceDescription[MAX_TEXT_LEN - 1] = '\0'; - return result; + // Read in the maintenance service description string if specified. + const unsigned int kNumStrings = 1; + const char *kServiceKeys = "MozillaMaintenanceDescription\0"; + char serviceStrings[kNumStrings][MAX_TEXT_LEN]; + int result = ReadStrings(path, kServiceKeys, + kNumStrings, serviceStrings); + if (result != OK) + { + serviceStrings[0][0] = '\0'; + } + strncpy(results->serviceDescription, + serviceStrings[0], MAX_TEXT_LEN - 1); + results->serviceDescription[MAX_TEXT_LEN - 1] = '\0'; + return result; } /** @@ -103,30 +104,32 @@ static BOOL GetVersionNumberFromPath(LPWSTR path, DWORD &A, DWORD &B, DWORD &C, DWORD &D) { - DWORD fileVersionInfoSize = GetFileVersionInfoSizeW(path, 0); - std::unique_ptr<char[]> fileVersionInfo(new char[fileVersionInfoSize]); - if (!GetFileVersionInfoW(path, 0, fileVersionInfoSize, - fileVersionInfo.get())) { - LOG_WARN(("Could not obtain file info of old service. (%d)", - GetLastError())); - return FALSE; - } - - VS_FIXEDFILEINFO *fixedFileInfo = - reinterpret_cast<VS_FIXEDFILEINFO *>(fileVersionInfo.get()); - UINT size; - if (!VerQueryValueW(fileVersionInfo.get(), L"\\", - reinterpret_cast<LPVOID*>(&fixedFileInfo), &size)) { - LOG_WARN(("Could not query file version info of old service. (%d)", - GetLastError())); - return FALSE; - } - - A = HIWORD(fixedFileInfo->dwFileVersionMS); - B = LOWORD(fixedFileInfo->dwFileVersionMS); - C = HIWORD(fixedFileInfo->dwFileVersionLS); - D = LOWORD(fixedFileInfo->dwFileVersionLS); - return TRUE; + DWORD fileVersionInfoSize = GetFileVersionInfoSizeW(path, 0); + std::unique_ptr<char[]> fileVersionInfo(new char[fileVersionInfoSize]); + if (!GetFileVersionInfoW(path, 0, fileVersionInfoSize, + fileVersionInfo.get())) + { + LOG_WARN(("Could not obtain file info of old service. (%d)", + GetLastError())); + return FALSE; + } + + VS_FIXEDFILEINFO *fixedFileInfo = + reinterpret_cast<VS_FIXEDFILEINFO *>(fileVersionInfo.get()); + UINT size; + if (!VerQueryValueW(fileVersionInfo.get(), L"\\", + reinterpret_cast<LPVOID*>(&fixedFileInfo), &size)) + { + LOG_WARN(("Could not query file version info of old service. (%d)", + GetLastError())); + return FALSE; + } + + A = HIWORD(fixedFileInfo->dwFileVersionMS); + B = LOWORD(fixedFileInfo->dwFileVersionMS); + C = HIWORD(fixedFileInfo->dwFileVersionLS); + D = LOWORD(fixedFileInfo->dwFileVersionLS); + return TRUE; } /** @@ -140,63 +143,70 @@ GetVersionNumberFromPath(LPWSTR path, DWORD &A, DWORD &B, BOOL UpdateServiceDescription(SC_HANDLE serviceHandle) { - WCHAR updaterINIPath[MAX_PATH + 1]; - if (!GetModuleFileNameW(nullptr, updaterINIPath, - sizeof(updaterINIPath) / - sizeof(updaterINIPath[0]))) { - LOG_WARN(("Could not obtain module filename when attempting to " - "modify service description. (%d)", GetLastError())); - return FALSE; - } - - if (!PathRemoveFileSpecW(updaterINIPath)) { - LOG_WARN(("Could not remove file spec when attempting to " - "modify service description. (%d)", GetLastError())); - return FALSE; - } - - if (!PathAppendSafe(updaterINIPath, L"updater.ini")) { - LOG_WARN(("Could not append updater.ini filename when attempting to " - "modify service description. (%d)", GetLastError())); - return FALSE; - } - - if (GetFileAttributesW(updaterINIPath) == INVALID_FILE_ATTRIBUTES) { - LOG_WARN(("updater.ini file does not exist, will not modify " - "service description. (%d)", GetLastError())); - return FALSE; - } - - MaintenanceServiceStringTable serviceStrings; - int rv = ReadMaintenanceServiceStrings(updaterINIPath, &serviceStrings); - if (rv != OK || !strlen(serviceStrings.serviceDescription)) { - LOG_WARN(("updater.ini file does not contain a maintenance " - "service description.")); - return FALSE; - } - - WCHAR serviceDescription[MAX_TEXT_LEN]; - if (!MultiByteToWideChar(CP_UTF8, 0, - serviceStrings.serviceDescription, -1, - serviceDescription, - sizeof(serviceDescription) / - sizeof(serviceDescription[0]))) { - LOG_WARN(("Could not convert description to wide string format. (%d)", - GetLastError())); - return FALSE; - } - - SERVICE_DESCRIPTIONW descriptionConfig; - descriptionConfig.lpDescription = serviceDescription; - if (!ChangeServiceConfig2W(serviceHandle, - SERVICE_CONFIG_DESCRIPTION, - &descriptionConfig)) { - LOG_WARN(("Could not change service config. (%d)", GetLastError())); - return FALSE; - } - - LOG(("The service description was updated successfully.")); - return TRUE; + WCHAR updaterINIPath[MAX_PATH + 1]; + if (!GetModuleFileNameW(nullptr, updaterINIPath, + sizeof(updaterINIPath) / + sizeof(updaterINIPath[0]))) + { + LOG_WARN(("Could not obtain module filename when attempting to " + "modify service description. (%d)", GetLastError())); + return FALSE; + } + + if (!PathRemoveFileSpecW(updaterINIPath)) + { + LOG_WARN(("Could not remove file spec when attempting to " + "modify service description. (%d)", GetLastError())); + return FALSE; + } + + if (!PathAppendSafe(updaterINIPath, L"updater.ini")) + { + LOG_WARN(("Could not append updater.ini filename when attempting to " + "modify service description. (%d)", GetLastError())); + return FALSE; + } + + if (GetFileAttributesW(updaterINIPath) == INVALID_FILE_ATTRIBUTES) + { + LOG_WARN(("updater.ini file does not exist, will not modify " + "service description. (%d)", GetLastError())); + return FALSE; + } + + MaintenanceServiceStringTable serviceStrings; + int rv = ReadMaintenanceServiceStrings(updaterINIPath, &serviceStrings); + if (rv != OK || !strlen(serviceStrings.serviceDescription)) + { + LOG_WARN(("updater.ini file does not contain a maintenance " + "service description.")); + return FALSE; + } + + WCHAR serviceDescription[MAX_TEXT_LEN]; + if (!MultiByteToWideChar(CP_UTF8, 0, + serviceStrings.serviceDescription, -1, + serviceDescription, + sizeof(serviceDescription) / + sizeof(serviceDescription[0]))) + { + LOG_WARN(("Could not convert description to wide string format. (%d)", + GetLastError())); + return FALSE; + } + + SERVICE_DESCRIPTIONW descriptionConfig; + descriptionConfig.lpDescription = serviceDescription; + if (!ChangeServiceConfig2W(serviceHandle, + SERVICE_CONFIG_DESCRIPTION, + &descriptionConfig)) + { + LOG_WARN(("Could not change service config. (%d)", GetLastError())); + return FALSE; + } + + LOG(("The service description was updated successfully.")); + return TRUE; } /** @@ -213,54 +223,58 @@ FixServicePath(SC_HANDLE service, LPCWSTR currentServicePath, BOOL &servicePathWasWrong) { - // When we originally upgraded the MozillaMaintenance service we - // would uninstall the service on each upgrade. This had an - // intermittent error which could cause the service to use the file - // maintenanceservice_tmp.exe as the install path. Only a small number - // of Nightly users would be affected by this, but we check for this - // state here and fix the user if they are affected. - // - // We also fix the path in the case of the path not being quoted. - size_t currentServicePathLen = wcslen(currentServicePath); - bool doesServiceHaveCorrectPath = - currentServicePathLen > 2 && - !wcsstr(currentServicePath, L"maintenanceservice_tmp.exe") && - currentServicePath[0] == L'\"' && - currentServicePath[currentServicePathLen - 1] == L'\"'; - - if (doesServiceHaveCorrectPath) { - LOG(("The MozillaMaintenance service path is correct.")); - servicePathWasWrong = FALSE; + // When we originally upgraded the MozillaMaintenance service we + // would uninstall the service on each upgrade. This had an + // intermittent error which could cause the service to use the file + // maintenanceservice_tmp.exe as the install path. Only a small number + // of Nightly users would be affected by this, but we check for this + // state here and fix the user if they are affected. + // + // We also fix the path in the case of the path not being quoted. + size_t currentServicePathLen = wcslen(currentServicePath); + bool doesServiceHaveCorrectPath = + currentServicePathLen > 2 && + !wcsstr(currentServicePath, L"maintenanceservice_tmp.exe") && + currentServicePath[0] == L'\"' && + currentServicePath[currentServicePathLen - 1] == L'\"'; + + if (doesServiceHaveCorrectPath) + { + LOG(("The MozillaMaintenance service path is correct.")); + servicePathWasWrong = FALSE; + return TRUE; + } + // This is a recoverable situation so not logging as a warning + LOG(("The MozillaMaintenance path is NOT correct. It was: %ls", + currentServicePath)); + + servicePathWasWrong = TRUE; + WCHAR fixedPath[MAX_PATH + 1] = { L'\0' }; + wcsncpy(fixedPath, currentServicePath, MAX_PATH); + PathUnquoteSpacesW(fixedPath); + if (!PathRemoveFileSpecW(fixedPath)) + { + LOG_WARN(("Couldn't remove file spec. (%d)", GetLastError())); + return FALSE; + } + if (!PathAppendSafe(fixedPath, L"maintenanceservice.exe")) + { + LOG_WARN(("Couldn't append file spec. (%d)", GetLastError())); + return FALSE; + } + PathQuoteSpacesW(fixedPath); + + + if (!ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, + SERVICE_NO_CHANGE, fixedPath, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr)) + { + LOG_WARN(("Could not fix service path. (%d)", GetLastError())); + return FALSE; + } + + LOG(("Fixed service path to: %ls.", fixedPath)); return TRUE; - } - // This is a recoverable situation so not logging as a warning - LOG(("The MozillaMaintenance path is NOT correct. It was: %ls", - currentServicePath)); - - servicePathWasWrong = TRUE; - WCHAR fixedPath[MAX_PATH + 1] = { L'\0' }; - wcsncpy(fixedPath, currentServicePath, MAX_PATH); - PathUnquoteSpacesW(fixedPath); - if (!PathRemoveFileSpecW(fixedPath)) { - LOG_WARN(("Couldn't remove file spec. (%d)", GetLastError())); - return FALSE; - } - if (!PathAppendSafe(fixedPath, L"maintenanceservice.exe")) { - LOG_WARN(("Couldn't append file spec. (%d)", GetLastError())); - return FALSE; - } - PathQuoteSpacesW(fixedPath); - - - if (!ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, - SERVICE_NO_CHANGE, fixedPath, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr)) { - LOG_WARN(("Could not fix service path. (%d)", GetLastError())); - return FALSE; - } - - LOG(("Fixed service path to: %ls.", fixedPath)); - return TRUE; } /** @@ -274,263 +288,299 @@ FixServicePath(SC_HANDLE service, BOOL SvcInstall(SvcInstallAction action) { - // Get a handle to the local computer SCM database with full access rights. - AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr, - SC_MANAGER_ALL_ACCESS)); - if (!schSCManager) { - LOG_WARN(("Could not open service manager. (%d)", GetLastError())); - return FALSE; - } - - WCHAR newServiceBinaryPath[MAX_PATH + 1]; - if (!GetModuleFileNameW(nullptr, newServiceBinaryPath, - sizeof(newServiceBinaryPath) / - sizeof(newServiceBinaryPath[0]))) { - LOG_WARN(("Could not obtain module filename when attempting to " - "install service. (%d)", - GetLastError())); - return FALSE; - } - - // Check if we already have the service installed. - AutoServiceHandle schService(OpenServiceW(schSCManager.get(), - SVC_NAME, - SERVICE_ALL_ACCESS)); - DWORD lastError = GetLastError(); - if (!schService && ERROR_SERVICE_DOES_NOT_EXIST != lastError) { - // The service exists but we couldn't open it - LOG_WARN(("Could not open service. (%d)", GetLastError())); - return FALSE; - } - - if (schService) { - // The service exists but it may not have the correct permissions. - // This could happen if the permissions were not set correctly originally - // or have been changed after the installation. This will reset the - // permissions back to allow limited user accounts. - if (!SetUserAccessServiceDACL(schService.get())) { - LOG_WARN(("Could not reset security ACE on service handle. It might not be " - "possible to start the service. This error should never " - "happen. (%d)", GetLastError())); - } - - // The service exists and we opened it - DWORD bytesNeeded; - if (!QueryServiceConfigW(schService.get(), nullptr, 0, &bytesNeeded) && - GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - LOG_WARN(("Could not determine buffer size for query service config. (%d)", - GetLastError())); - return FALSE; - } - - // Get the service config information, in particular we want the binary - // path of the service. - std::unique_ptr<char[]> serviceConfigBuffer(new char[bytesNeeded]); - if (!QueryServiceConfigW(schService.get(), - reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()), - bytesNeeded, &bytesNeeded)) { - LOG_WARN(("Could open service but could not query service config. (%d)", - GetLastError())); - return FALSE; - } - QUERY_SERVICE_CONFIGW &serviceConfig = - *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()); - - // Check if we need to fix the service path - BOOL servicePathWasWrong; - static BOOL alreadyCheckedFixServicePath = FALSE; - if (!alreadyCheckedFixServicePath) { - if (!FixServicePath(schService.get(), serviceConfig.lpBinaryPathName, - servicePathWasWrong)) { - LOG_WARN(("Could not fix service path. This should never happen. (%d)", + // Get a handle to the local computer SCM database with full access rights. + AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr, + SC_MANAGER_ALL_ACCESS)); + if (!schSCManager) + { + LOG_WARN(("Could not open service manager. (%d)", GetLastError())); + return FALSE; + } + + WCHAR newServiceBinaryPath[MAX_PATH + 1]; + if (!GetModuleFileNameW(nullptr, newServiceBinaryPath, + sizeof(newServiceBinaryPath) / + sizeof(newServiceBinaryPath[0]))) + { + LOG_WARN(("Could not obtain module filename when attempting to " + "install service. (%d)", GetLastError())); - // True is returned because the service is pointing to - // maintenanceservice_tmp.exe so it actually was upgraded to the - // newest installed service. - return TRUE; - } else if (servicePathWasWrong) { - // Now that the path is fixed we should re-attempt the install. - // This current process' image path is maintenanceservice_tmp.exe. - // The service used to point to maintenanceservice_tmp.exe. - // The service was just fixed to point to maintenanceservice.exe. - // Re-attempting an install from scratch will work as normal. - alreadyCheckedFixServicePath = TRUE; - LOG(("Restarting install action: %d", action)); - return SvcInstall(action); - } - } - - // Ensure the service path is not quoted. We own this memory and know it to - // be large enough for the quoted path, so it is large enough for the - // unquoted path. This function cannot fail. - PathUnquoteSpacesW(serviceConfig.lpBinaryPathName); - - // Obtain the existing maintenanceservice file's version number and - // the new file's version number. Versions are in the format of - // A.B.C.D. - DWORD existingA, existingB, existingC, existingD; - DWORD newA, newB, newC, newD; - BOOL obtainedExistingVersionInfo = - GetVersionNumberFromPath(serviceConfig.lpBinaryPathName, - existingA, existingB, - existingC, existingD); - if (!GetVersionNumberFromPath(newServiceBinaryPath, newA, - newB, newC, newD)) { - LOG_WARN(("Could not obtain version number from new path")); - return FALSE; - } - - // Check if we need to replace the old binary with the new one - // If we couldn't get the old version info then we assume we should - // replace it. - if (ForceInstallSvc == action || - !obtainedExistingVersionInfo || - (existingA < newA) || - (existingA == newA && existingB < newB) || - (existingA == newA && existingB == newB && - existingC < newC) || - (existingA == newA && existingB == newB && - existingC == newC && existingD < newD)) { - - // We have a newer updater, so update the description from the INI file. - UpdateServiceDescription(schService.get()); - - schService.reset(); - if (!StopService()) { return FALSE; - } + } - if (!wcscmp(newServiceBinaryPath, serviceConfig.lpBinaryPathName)) { - LOG(("File is already in the correct location, no action needed for " - "upgrade. The path is: \"%ls\"", newServiceBinaryPath)); - return TRUE; - } - - BOOL result = TRUE; - - // Attempt to copy the new binary over top the existing binary. - // If there is an error we try to move it out of the way and then - // copy it in. First try the safest / easiest way to overwrite the file. - if (!CopyFileW(newServiceBinaryPath, - serviceConfig.lpBinaryPathName, FALSE)) { - LOG_WARN(("Could not overwrite old service binary file. " - "This should never happen, but if it does the next " - "upgrade will fix it, the service is not a critical " - "component that needs to be installed for upgrades " - "to work. (%d)", GetLastError())); - - // We rename the last 3 filename chars in an unsafe way. Manually - // verify there are more than 3 chars for safe failure in MoveFileExW. - const size_t len = wcslen(serviceConfig.lpBinaryPathName); - if (len > 3) { - // Calculate the temp file path that we're moving the file to. This - // is the same as the proper service path but with a .old extension. - LPWSTR oldServiceBinaryTempPath = - new WCHAR[len + 1]; - memset(oldServiceBinaryTempPath, 0, (len + 1) * sizeof (WCHAR)); - wcsncpy(oldServiceBinaryTempPath, serviceConfig.lpBinaryPathName, len); - // Rename the last 3 chars to 'old' - wcsncpy(oldServiceBinaryTempPath + len - 3, L"old", 3); - - // Move the current (old) service file to the temp path. - if (MoveFileExW(serviceConfig.lpBinaryPathName, - oldServiceBinaryTempPath, - MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { - // The old binary is moved out of the way, copy in the new one. + // Check if we already have the service installed. + AutoServiceHandle schService(OpenServiceW(schSCManager.get(), + SVC_NAME, + SERVICE_ALL_ACCESS)); + DWORD lastError = GetLastError(); + if (!schService && ERROR_SERVICE_DOES_NOT_EXIST != lastError) + { + // The service exists but we couldn't open it + LOG_WARN(("Could not open service. (%d)", GetLastError())); + return FALSE; + } + + if (schService) + { + // The service exists but it may not have the correct permissions. + // This could happen if the permissions were not set correctly originally + // or have been changed after the installation. This will reset the + // permissions back to allow limited user accounts. + if (!SetUserAccessServiceDACL(schService.get())) + { + LOG_WARN(("Could not reset security ACE on service handle. It might not be " + "possible to start the service. This error should never " + "happen. (%d)", GetLastError())); + } + + // The service exists and we opened it + DWORD bytesNeeded; + if (!QueryServiceConfigW(schService.get(), nullptr, 0, &bytesNeeded) && + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + LOG_WARN(("Could not determine buffer size for query service config. (%d)", + GetLastError())); + return FALSE; + } + + // Get the service config information, in particular we want the binary + // path of the service. + std::unique_ptr<char[]> serviceConfigBuffer(new char[bytesNeeded]); + if (!QueryServiceConfigW(schService.get(), + reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()), + bytesNeeded, &bytesNeeded)) + { + LOG_WARN(("Could open service but could not query service config. (%d)", + GetLastError())); + return FALSE; + } + QUERY_SERVICE_CONFIGW &serviceConfig = + *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()); + + // Check if we need to fix the service path + BOOL servicePathWasWrong; + static BOOL alreadyCheckedFixServicePath = FALSE; + if (!alreadyCheckedFixServicePath) + { + if (!FixServicePath(schService.get(), serviceConfig.lpBinaryPathName, + servicePathWasWrong)) + { + LOG_WARN(("Could not fix service path. This should never happen. (%d)", + GetLastError())); + // True is returned because the service is pointing to + // maintenanceservice_tmp.exe so it actually was upgraded to the + // newest installed service. + return TRUE; + } + else if (servicePathWasWrong) + { + // Now that the path is fixed we should re-attempt the install. + // This current process' image path is maintenanceservice_tmp.exe. + // The service used to point to maintenanceservice_tmp.exe. + // The service was just fixed to point to maintenanceservice.exe. + // Re-attempting an install from scratch will work as normal. + alreadyCheckedFixServicePath = TRUE; + LOG(("Restarting install action: %d", action)); + return SvcInstall(action); + } + } + + // Ensure the service path is not quoted. We own this memory and know it to + // be large enough for the quoted path, so it is large enough for the + // unquoted path. This function cannot fail. + PathUnquoteSpacesW(serviceConfig.lpBinaryPathName); + + // Obtain the existing maintenanceservice file's version number and + // the new file's version number. Versions are in the format of + // A.B.C.D. + DWORD existingA, existingB, existingC, existingD; + DWORD newA, newB, newC, newD; + BOOL obtainedExistingVersionInfo = + GetVersionNumberFromPath(serviceConfig.lpBinaryPathName, + existingA, existingB, + existingC, existingD); + if (!GetVersionNumberFromPath(newServiceBinaryPath, newA, + newB, newC, newD)) + { + LOG_WARN(("Could not obtain version number from new path")); + return FALSE; + } + + // Check if we need to replace the old binary with the new one + // If we couldn't get the old version info then we assume we should + // replace it. + if (ForceInstallSvc == action || + !obtainedExistingVersionInfo || + (existingA < newA) || + (existingA == newA && existingB < newB) || + (existingA == newA && existingB == newB && + existingC < newC) || + (existingA == newA && existingB == newB && + existingC == newC && existingD < newD)) + { + + // We have a newer updater, so update the description from the INI file. + UpdateServiceDescription(schService.get()); + + schService.reset(); + if (!StopService()) + { + return FALSE; + } + + if (!wcscmp(newServiceBinaryPath, serviceConfig.lpBinaryPathName)) + { + LOG(("File is already in the correct location, no action needed for " + "upgrade. The path is: \"%ls\"", newServiceBinaryPath)); + return TRUE; + } + + BOOL result = TRUE; + + // Attempt to copy the new binary over top the existing binary. + // If there is an error we try to move it out of the way and then + // copy it in. First try the safest / easiest way to overwrite the file. if (!CopyFileW(newServiceBinaryPath, - serviceConfig.lpBinaryPathName, FALSE)) { - // It is best to leave the old service binary in this condition. - LOG_WARN(("The new service binary could not be copied in." - " The service will not be upgraded.")); - result = FALSE; - } else { - LOG(("The new service binary was copied in by first moving the" - " old one out of the way.")); + serviceConfig.lpBinaryPathName, FALSE)) + { + LOG_WARN(("Could not overwrite old service binary file. " + "This should never happen, but if it does the next " + "upgrade will fix it, the service is not a critical " + "component that needs to be installed for upgrades " + "to work. (%d)", GetLastError())); + + // We rename the last 3 filename chars in an unsafe way. Manually + // verify there are more than 3 chars for safe failure in MoveFileExW. + const size_t len = wcslen(serviceConfig.lpBinaryPathName); + if (len > 3) + { + // Calculate the temp file path that we're moving the file to. This + // is the same as the proper service path but with a .old extension. + LPWSTR oldServiceBinaryTempPath = + new WCHAR[len + 1]; + memset(oldServiceBinaryTempPath, 0, (len + 1) * sizeof (WCHAR)); + wcsncpy(oldServiceBinaryTempPath, serviceConfig.lpBinaryPathName, len); + // Rename the last 3 chars to 'old' + wcsncpy(oldServiceBinaryTempPath + len - 3, L"old", 3); + + // Move the current (old) service file to the temp path. + if (MoveFileExW(serviceConfig.lpBinaryPathName, + oldServiceBinaryTempPath, + MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) + { + // The old binary is moved out of the way, copy in the new one. + if (!CopyFileW(newServiceBinaryPath, + serviceConfig.lpBinaryPathName, FALSE)) + { + // It is best to leave the old service binary in this condition. + LOG_WARN(("The new service binary could not be copied in." + " The service will not be upgraded.")); + result = FALSE; + } + else + { + LOG(("The new service binary was copied in by first moving the" + " old one out of the way.")); + } + + // Attempt to get rid of the old service temp path. + if (DeleteFileW(oldServiceBinaryTempPath)) + { + LOG(("The old temp service path was deleted: %ls.", + oldServiceBinaryTempPath)); + } + else + { + // The old temp path could not be removed. It will be removed + // the next time the user can't copy the binary in or on uninstall. + LOG_WARN(("The old temp service path was not deleted.")); + } + } + else + { + // It is best to leave the old service binary in this condition. + LOG_WARN(("Could not move old service file out of the way from:" + " \"%ls\" to \"%ls\". Service will not be upgraded. (%d)", + serviceConfig.lpBinaryPathName, + oldServiceBinaryTempPath, GetLastError())); + result = FALSE; + } + delete[] oldServiceBinaryTempPath; + } + else + { + // It is best to leave the old service binary in this condition. + LOG_WARN(("Service binary path was less than 3, service will" + " not be updated. This should never happen.")); + result = FALSE; + } + } + else + { + LOG(("The new service binary was copied in.")); } - // Attempt to get rid of the old service temp path. - if (DeleteFileW(oldServiceBinaryTempPath)) { - LOG(("The old temp service path was deleted: %ls.", - oldServiceBinaryTempPath)); - } else { - // The old temp path could not be removed. It will be removed - // the next time the user can't copy the binary in or on uninstall. - LOG_WARN(("The old temp service path was not deleted.")); + // We made a copy of ourselves to the existing location. + // The tmp file (the process of which we are executing right now) will be + // left over. Attempt to delete the file on the next reboot. + if (MoveFileExW(newServiceBinaryPath, nullptr, + MOVEFILE_DELAY_UNTIL_REBOOT)) + { + LOG(("Deleting the old file path on the next reboot: %ls.", + newServiceBinaryPath)); + } + else + { + LOG_WARN(("Call to delete the old file path failed: %ls.", + newServiceBinaryPath)); } - } else { - // It is best to leave the old service binary in this condition. - LOG_WARN(("Could not move old service file out of the way from:" - " \"%ls\" to \"%ls\". Service will not be upgraded. (%d)", - serviceConfig.lpBinaryPathName, - oldServiceBinaryTempPath, GetLastError())); - result = FALSE; - } - delete[] oldServiceBinaryTempPath; - } else { - // It is best to leave the old service binary in this condition. - LOG_WARN(("Service binary path was less than 3, service will" - " not be updated. This should never happen.")); - result = FALSE; + + return result; } - } else { - LOG(("The new service binary was copied in.")); - } - - // We made a copy of ourselves to the existing location. - // The tmp file (the process of which we are executing right now) will be - // left over. Attempt to delete the file on the next reboot. - if (MoveFileExW(newServiceBinaryPath, nullptr, - MOVEFILE_DELAY_UNTIL_REBOOT)) { - LOG(("Deleting the old file path on the next reboot: %ls.", - newServiceBinaryPath)); - } else { - LOG_WARN(("Call to delete the old file path failed: %ls.", - newServiceBinaryPath)); - } - - return result; - } - - // We don't need to copy ourselves to the existing location. - // The tmp file (the process of which we are executing right now) will be - // left over. Attempt to delete the file on the next reboot. - MoveFileExW(newServiceBinaryPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT); - - // nothing to do, we already have a newer service installed - return TRUE; - } - // If the service does not exist and we are upgrading, don't install it. - if (UpgradeSvc == action) { - // The service does not exist and we are upgrading, so don't install it + // We don't need to copy ourselves to the existing location. + // The tmp file (the process of which we are executing right now) will be + // left over. Attempt to delete the file on the next reboot. + MoveFileExW(newServiceBinaryPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT); + + // nothing to do, we already have a newer service installed + return TRUE; + } + + // If the service does not exist and we are upgrading, don't install it. + if (UpgradeSvc == action) + { + // The service does not exist and we are upgrading, so don't install it + return TRUE; + } + + // Quote the path only if it contains spaces. + PathQuoteSpacesW(newServiceBinaryPath); + // The service does not already exist so create the service as on demand + schService.reset(CreateServiceW(schSCManager.get(), SVC_NAME, SVC_DISPLAY_NAME, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + newServiceBinaryPath, nullptr, nullptr, + nullptr, nullptr, nullptr)); + if (!schService) + { + LOG_WARN(("Could not create Windows service. " + "This error should never happen since a service install " + "should only be called when elevated. (%d)", GetLastError())); + return FALSE; + } + + if (!SetUserAccessServiceDACL(schService.get())) + { + LOG_WARN(("Could not set security ACE on service handle, the service will not " + "be able to be started from unelevated processes. " + "This error should never happen. (%d)", + GetLastError())); + } + + UpdateServiceDescription(schService.get()); + return TRUE; - } - - // Quote the path only if it contains spaces. - PathQuoteSpacesW(newServiceBinaryPath); - // The service does not already exist so create the service as on demand - schService.reset(CreateServiceW(schSCManager.get(), SVC_NAME, SVC_DISPLAY_NAME, - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, - newServiceBinaryPath, nullptr, nullptr, - nullptr, nullptr, nullptr)); - if (!schService) { - LOG_WARN(("Could not create Windows service. " - "This error should never happen since a service install " - "should only be called when elevated. (%d)", GetLastError())); - return FALSE; - } - - if (!SetUserAccessServiceDACL(schService.get())) { - LOG_WARN(("Could not set security ACE on service handle, the service will not " - "be able to be started from unelevated processes. " - "This error should never happen. (%d)", - GetLastError())); - } - - UpdateServiceDescription(schService.get()); - - return TRUE; } /** @@ -541,42 +591,45 @@ SvcInstall(SvcInstallAction action) BOOL StopService() { - // Get a handle to the local computer SCM database with full access rights. - AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr, - SC_MANAGER_ALL_ACCESS)); - if (!schSCManager) { - LOG_WARN(("Could not open service manager. (%d)", GetLastError())); - return FALSE; - } - - // Open the service - AutoServiceHandle schService(OpenServiceW(schSCManager.get(), SVC_NAME, - SERVICE_ALL_ACCESS)); - if (!schService) { - LOG_WARN(("Could not open service. (%d)", GetLastError())); - return FALSE; - } - - LOG(("Sending stop request...")); - SERVICE_STATUS status; - SetLastError(ERROR_SUCCESS); - if (!ControlService(schService.get(), SERVICE_CONTROL_STOP, &status) && - GetLastError() != ERROR_SERVICE_NOT_ACTIVE) { - LOG_WARN(("Error sending stop request. (%d)", GetLastError())); - } - - schSCManager.reset(); - schService.reset(); - - LOG(("Waiting for service stop...")); - DWORD lastState = WaitForServiceStop(SVC_NAME, 30); - - // The service can be in a stopped state but the exe still in use - // so make sure the process is really gone before proceeding - WaitForProcessExit(L"maintenanceservice.exe", 30); - LOG(("Done waiting for service stop, last service state: %d", lastState)); - - return lastState == SERVICE_STOPPED; + // Get a handle to the local computer SCM database with full access rights. + AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr, + SC_MANAGER_ALL_ACCESS)); + if (!schSCManager) + { + LOG_WARN(("Could not open service manager. (%d)", GetLastError())); + return FALSE; + } + + // Open the service + AutoServiceHandle schService(OpenServiceW(schSCManager.get(), SVC_NAME, + SERVICE_ALL_ACCESS)); + if (!schService) + { + LOG_WARN(("Could not open service. (%d)", GetLastError())); + return FALSE; + } + + LOG(("Sending stop request...")); + SERVICE_STATUS status; + SetLastError(ERROR_SUCCESS); + if (!ControlService(schService.get(), SERVICE_CONTROL_STOP, &status) && + GetLastError() != ERROR_SERVICE_NOT_ACTIVE) + { + LOG_WARN(("Error sending stop request. (%d)", GetLastError())); + } + + schSCManager.reset(); + schService.reset(); + + LOG(("Waiting for service stop...")); + DWORD lastState = WaitForServiceStop(SVC_NAME, 30); + + // The service can be in a stopped state but the exe still in use + // so make sure the process is really gone before proceeding + WaitForProcessExit(L"maintenanceservice.exe", 30); + LOG(("Done waiting for service stop, last service state: %d", lastState)); + + return lastState == SERVICE_STOPPED; } /** @@ -587,46 +640,55 @@ StopService() BOOL SvcUninstall() { - // Get a handle to the local computer SCM database with full access rights. - AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr, - SC_MANAGER_ALL_ACCESS)); - if (!schSCManager) { - LOG_WARN(("Could not open service manager. (%d)", GetLastError())); - return FALSE; - } - - // Open the service - AutoServiceHandle schService(OpenServiceW(schSCManager.get(), SVC_NAME, - SERVICE_ALL_ACCESS)); - if (!schService) { - LOG_WARN(("Could not open service. (%d)", GetLastError())); - return FALSE; - } - - //Stop the service so it deletes faster and so the uninstaller - // can actually delete its EXE. - DWORD totalWaitTime = 0; - SERVICE_STATUS status; - static const int maxWaitTime = 1000 * 60; // Never wait more than a minute - if (ControlService(schService.get(), SERVICE_CONTROL_STOP, &status)) { - do { - Sleep(status.dwWaitHint); - totalWaitTime += (status.dwWaitHint + 10); - if (status.dwCurrentState == SERVICE_STOPPED) { - break; - } else if (totalWaitTime > maxWaitTime) { - break; - } - } while (QueryServiceStatus(schService.get(), &status)); - } - - // Delete the service or mark it for deletion - BOOL deleted = DeleteService(schService.get()); - if (!deleted) { - deleted = (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE); - } - - return deleted; + // Get a handle to the local computer SCM database with full access rights. + AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr, + SC_MANAGER_ALL_ACCESS)); + if (!schSCManager) + { + LOG_WARN(("Could not open service manager. (%d)", GetLastError())); + return FALSE; + } + + // Open the service + AutoServiceHandle schService(OpenServiceW(schSCManager.get(), SVC_NAME, + SERVICE_ALL_ACCESS)); + if (!schService) + { + LOG_WARN(("Could not open service. (%d)", GetLastError())); + return FALSE; + } + + //Stop the service so it deletes faster and so the uninstaller + // can actually delete its EXE. + DWORD totalWaitTime = 0; + SERVICE_STATUS status; + static const int maxWaitTime = 1000 * 60; // Never wait more than a minute + if (ControlService(schService.get(), SERVICE_CONTROL_STOP, &status)) + { + do + { + Sleep(status.dwWaitHint); + totalWaitTime += (status.dwWaitHint + 10); + if (status.dwCurrentState == SERVICE_STOPPED) + { + break; + } + else if (totalWaitTime > maxWaitTime) + { + break; + } + } + while (QueryServiceStatus(schService.get(), &status)); + } + + // Delete the service or mark it for deletion + BOOL deleted = DeleteService(schService.get()); + if (!deleted) + { + deleted = (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE); + } + + return deleted; } /** @@ -638,16 +700,18 @@ SvcUninstall() BOOL SetUserAccessServiceDACL(SC_HANDLE hService) { - PACL pNewAcl = nullptr; - PSECURITY_DESCRIPTOR psd = nullptr; - DWORD lastError = SetUserAccessServiceDACL(hService, pNewAcl, psd); - if (pNewAcl) { - LocalFree((HLOCAL)pNewAcl); - } - if (psd) { - LocalFree((LPVOID)psd); - } - return ERROR_SUCCESS == lastError; + PACL pNewAcl = nullptr; + PSECURITY_DESCRIPTOR psd = nullptr; + DWORD lastError = SetUserAccessServiceDACL(hService, pNewAcl, psd); + if (pNewAcl) + { + LocalFree((HLOCAL)pNewAcl); + } + if (psd) + { + LocalFree((LPVOID)psd); + } + return ERROR_SUCCESS == lastError; } /** @@ -662,112 +726,124 @@ DWORD SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl, PSECURITY_DESCRIPTOR psd) { - // Get the current security descriptor needed size - DWORD needed = 0; - if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, - &psd, 0, &needed)) { - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - LOG_WARN(("Could not query service object security size. (%d)", - GetLastError())); - return GetLastError(); + // Get the current security descriptor needed size + DWORD needed = 0; + if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, + &psd, 0, &needed)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + LOG_WARN(("Could not query service object security size. (%d)", + GetLastError())); + return GetLastError(); + } + + DWORD size = needed; + psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, size); + if (!psd) + { + LOG_WARN(("Could not allocate security descriptor. (%d)", + GetLastError())); + return ERROR_INSUFFICIENT_BUFFER; + } + + // Get the actual security descriptor now + if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, + psd, size, &needed)) + { + LOG_WARN(("Could not allocate security descriptor. (%d)", + GetLastError())); + return GetLastError(); + } } - DWORD size = needed; - psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, size); - if (!psd) { - LOG_WARN(("Could not allocate security descriptor. (%d)", - GetLastError())); - return ERROR_INSUFFICIENT_BUFFER; + // Get the current DACL from the security descriptor. + PACL pacl = nullptr; + BOOL bDaclPresent = FALSE; + BOOL bDaclDefaulted = FALSE; + if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, + &bDaclDefaulted)) + { + LOG_WARN(("Could not obtain DACL. (%d)", GetLastError())); + return GetLastError(); } - // Get the actual security descriptor now - if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, - psd, size, &needed)) { - LOG_WARN(("Could not allocate security descriptor. (%d)", - GetLastError())); - return GetLastError(); - } - } - - // Get the current DACL from the security descriptor. - PACL pacl = nullptr; - BOOL bDaclPresent = FALSE; - BOOL bDaclDefaulted = FALSE; - if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, - &bDaclDefaulted)) { - LOG_WARN(("Could not obtain DACL. (%d)", GetLastError())); - return GetLastError(); - } - - PSID sid; - DWORD SIDSize = SECURITY_MAX_SID_SIZE; - sid = LocalAlloc(LMEM_FIXED, SIDSize); - if (!sid) { - LOG_WARN(("Could not allocate SID memory. (%d)", GetLastError())); - return GetLastError(); - } - - if (!CreateWellKnownSid(WinBuiltinUsersSid, nullptr, sid, &SIDSize)) { - DWORD lastError = GetLastError(); - LOG_WARN(("Could not create well known SID. (%d)", lastError)); - LocalFree(sid); - return lastError; - } - - // Lookup the account name, the function fails if you don't pass in - // a buffer for the domain name but it's not used since we're using - // the built in account Sid. - SID_NAME_USE accountType; - WCHAR accountName[UNLEN + 1] = { L'\0' }; - WCHAR domainName[DNLEN + 1] = { L'\0' }; - DWORD accountNameSize = UNLEN + 1; - DWORD domainNameSize = DNLEN + 1; - if (!LookupAccountSidW(nullptr, sid, accountName, - &accountNameSize, - domainName, &domainNameSize, &accountType)) { - LOG_WARN(("Could not lookup account Sid, will try Users. (%d)", - GetLastError())); - wcsncpy(accountName, L"Users", UNLEN); - } - - // We already have the group name so we can get rid of the SID - FreeSid(sid); - sid = nullptr; - - // Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged. - EXPLICIT_ACCESS ea; - BuildExplicitAccessWithNameW(&ea, accountName, - SERVICE_START | SERVICE_STOP | GENERIC_READ, - SET_ACCESS, NO_INHERITANCE); - DWORD lastError = SetEntriesInAclW(1, (PEXPLICIT_ACCESS)&ea, pacl, &pNewAcl); - if (ERROR_SUCCESS != lastError) { - LOG_WARN(("Could not set entries in ACL. (%d)", lastError)); - return lastError; - } - - // Initialize a new security descriptor. - SECURITY_DESCRIPTOR sd; - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - LOG_WARN(("Could not initialize security descriptor. (%d)", - GetLastError())); - return GetLastError(); - } - - // Set the new DACL in the security descriptor. - if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) { - LOG_WARN(("Could not set security descriptor DACL. (%d)", - GetLastError())); - return GetLastError(); - } - - // Set the new security descriptor for the service object. - if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &sd)) { - LOG_WARN(("Could not set object security. (%d)", - GetLastError())); - return GetLastError(); - } - - // Woohoo, raise the roof - LOG(("User access was set successfully on the service.")); - return ERROR_SUCCESS; + PSID sid; + DWORD SIDSize = SECURITY_MAX_SID_SIZE; + sid = LocalAlloc(LMEM_FIXED, SIDSize); + if (!sid) + { + LOG_WARN(("Could not allocate SID memory. (%d)", GetLastError())); + return GetLastError(); + } + + if (!CreateWellKnownSid(WinBuiltinUsersSid, nullptr, sid, &SIDSize)) + { + DWORD lastError = GetLastError(); + LOG_WARN(("Could not create well known SID. (%d)", lastError)); + LocalFree(sid); + return lastError; + } + + // Lookup the account name, the function fails if you don't pass in + // a buffer for the domain name but it's not used since we're using + // the built in account Sid. + SID_NAME_USE accountType; + WCHAR accountName[UNLEN + 1] = { L'\0' }; + WCHAR domainName[DNLEN + 1] = { L'\0' }; + DWORD accountNameSize = UNLEN + 1; + DWORD domainNameSize = DNLEN + 1; + if (!LookupAccountSidW(nullptr, sid, accountName, + &accountNameSize, + domainName, &domainNameSize, &accountType)) + { + LOG_WARN(("Could not lookup account Sid, will try Users. (%d)", + GetLastError())); + wcsncpy(accountName, L"Users", UNLEN); + } + + // We already have the group name so we can get rid of the SID + FreeSid(sid); + sid = nullptr; + + // Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged. + EXPLICIT_ACCESS ea; + BuildExplicitAccessWithNameW(&ea, accountName, + SERVICE_START | SERVICE_STOP | GENERIC_READ, + SET_ACCESS, NO_INHERITANCE); + DWORD lastError = SetEntriesInAclW(1, (PEXPLICIT_ACCESS)&ea, pacl, &pNewAcl); + if (ERROR_SUCCESS != lastError) + { + LOG_WARN(("Could not set entries in ACL. (%d)", lastError)); + return lastError; + } + + // Initialize a new security descriptor. + SECURITY_DESCRIPTOR sd; + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) + { + LOG_WARN(("Could not initialize security descriptor. (%d)", + GetLastError())); + return GetLastError(); + } + + // Set the new DACL in the security descriptor. + if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) + { + LOG_WARN(("Could not set security descriptor DACL. (%d)", + GetLastError())); + return GetLastError(); + } + + // Set the new security descriptor for the service object. + if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &sd)) + { + LOG_WARN(("Could not set object security. (%d)", + GetLastError())); + return GetLastError(); + } + + // Woohoo, raise the roof + LOG(("User access was set successfully on the service.")); + return ERROR_SUCCESS; } diff --git a/onlineupdate/source/service/serviceinstall.hxx b/onlineupdate/source/service/serviceinstall.hxx index d8532a968e42..1afaada84519 100644 --- a/onlineupdate/source/service/serviceinstall.hxx +++ b/onlineupdate/source/service/serviceinstall.hxx @@ -11,11 +11,11 @@ BOOL SvcInstall(SvcInstallAction action); BOOL SvcUninstall(); BOOL StopService(); BOOL SetUserAccessServiceDACL(SC_HANDLE hService); -DWORD SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl, +DWORD SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl, PSECURITY_DESCRIPTOR psd); struct MaintenanceServiceStringTable { - char serviceDescription[MAX_TEXT_LEN]; + char serviceDescription[MAX_TEXT_LEN]; }; diff --git a/onlineupdate/source/service/workmonitor.cxx b/onlineupdate/source/service/workmonitor.cxx index 76bbe1c911d7..05cf2481e7ce 100644 --- a/onlineupdate/source/service/workmonitor.cxx +++ b/onlineupdate/source/service/workmonitor.cxx @@ -45,38 +45,41 @@ BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, static BOOL IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying) { - isApplying = FALSE; - WCHAR updateStatusFilePath[MAX_PATH + 1] = {L'\0'}; - wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH); - if (!PathAppendSafe(updateStatusFilePath, L"update.status")) { - LOG_WARN(("Could not append path for update.status file")); - return FALSE; - } - - AutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ, + isApplying = FALSE; + WCHAR updateStatusFilePath[MAX_PATH + 1] = {L'\0'}; + wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH); + if (!PathAppendSafe(updateStatusFilePath, L"update.status")) + { + LOG_WARN(("Could not append path for update.status file")); + return FALSE; + } + + AutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, 0, nullptr)); - if (statusFile == INVALID_HANDLE_VALUE) { - LOG_WARN(("Could not open update.status file")); - return FALSE; - } + if (statusFile == INVALID_HANDLE_VALUE) + { + LOG_WARN(("Could not open update.status file")); + return FALSE; + } - char buf[32] = { 0 }; - DWORD read; - if (!ReadFile(statusFile.get(), buf, sizeof(buf), &read, nullptr)) { - LOG_WARN(("Could not read from update.status file")); - return FALSE; - } + char buf[32] = { 0 }; + DWORD read; + if (!ReadFile(statusFile.get(), buf, sizeof(buf), &read, nullptr)) + { + LOG_WARN(("Could not read from update.status file")); + return FALSE; + } - LOG(("updater.exe returned status: %s", buf)); + LOG(("updater.exe returned status: %s", buf)); - const char kApplying[] = "applying"; - isApplying = strncmp(buf, kApplying, - sizeof(kApplying) - 1) == 0; - return TRUE; + const char kApplying[] = "applying"; + isApplying = strncmp(buf, kApplying, + sizeof(kApplying) - 1) == 0; + return TRUE; } /** @@ -89,9 +92,9 @@ IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying) static bool IsUpdateBeingStaged(int argc, LPWSTR *argv) { - // PID will be set to -1 if we're supposed to stage an update. - return argc == 4 && !wcscmp(argv[3], L"-1") || - argc == 5 && !wcscmp(argv[4], L"-1"); + // PID will be set to -1 if we're supposed to stage an update. + return argc == 4 && !wcscmp(argv[3], L"-1") || + argc == 5 && !wcscmp(argv[4], L"-1"); } /** @@ -103,12 +106,14 @@ IsUpdateBeingStaged(int argc, LPWSTR *argv) static bool IsDigits(WCHAR *str) { - while (*str) { - if (!iswdigit(*str++)) { - return FALSE; + while (*str) + { + if (!iswdigit(*str++)) + { + return FALSE; + } } - } - return TRUE; + return TRUE; } /** @@ -124,8 +129,8 @@ IsDigits(WCHAR *str) static bool IsOldCommandline(int argc, LPWSTR *argv) { - return argc == 4 && !wcscmp(argv[3], L"-1") || - argc >= 4 && (wcsstr(argv[3], L"/replace") || IsDigits(argv[3])); + return argc == 4 && !wcscmp(argv[3], L"-1") || + argc >= 4 && (wcsstr(argv[3], L"/replace") || IsDigits(argv[3])); } /** @@ -138,31 +143,36 @@ IsOldCommandline(int argc, LPWSTR *argv) static BOOL GetInstallationDir(int argcTmp, LPWSTR *argvTmp, WCHAR aResultDir[MAX_PATH + 1]) { - int index = 3; - if (IsOldCommandline(argcTmp, argvTmp)) { - index = 2; - } - - if (argcTmp < index) { - return FALSE; - } - - wcsncpy(aResultDir, argvTmp[2], MAX_PATH); - WCHAR* backSlash = wcsrchr(aResultDir, L'\\'); - // Make sure that the path does not include trailing backslashes - if (backSlash && (backSlash[1] == L'\0')) { - *backSlash = L'\0'; - } - - // The new command line's argv[2] is always the installation directory. - if (index == 2) { - bool backgroundUpdate = IsUpdateBeingStaged(argcTmp, argvTmp); - bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L"/replace")); - if (backgroundUpdate || replaceRequest) { - return PathRemoveFileSpecW(aResultDir); - } - } - return TRUE; + int index = 3; + if (IsOldCommandline(argcTmp, argvTmp)) + { + index = 2; + } + + if (argcTmp < index) + { + return FALSE; + } + + wcsncpy(aResultDir, argvTmp[2], MAX_PATH); + WCHAR* backSlash = wcsrchr(aResultDir, L'\\'); + // Make sure that the path does not include trailing backslashes + if (backSlash && (backSlash[1] == L'\0')) + { + *backSlash = L'\0'; + } + + // The new command line's argv[2] is always the installation directory. + if (index == 2) + { + bool backgroundUpdate = IsUpdateBeingStaged(argcTmp, argvTmp); + bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L"/replace")); + if (backgroundUpdate || replaceRequest) + { + return PathRemoveFileSpecW(aResultDir); + } + } + return TRUE; } /** @@ -180,150 +190,172 @@ StartUpdateProcess(int argc, LPCWSTR installDir, BOOL &processStarted) { - LOG(("Starting update process as the service in session 0.")); - STARTUPINFO si = {0}; - si.cb = sizeof(STARTUPINFO); - si.lpDesktop = L"winsta0\\Default"; - PROCESS_INFORMATION pi = {0}; - - // The updater command line is of the form: - // updater.exe update-dir apply [wait-pid [callback-dir callback-path args]] - LPWSTR cmdLine = MakeCommandLine(argc, argv); - - int index = 3; - if (IsOldCommandline(argc, argv)) { - index = 2; - } - - // If we're about to start the update process from session 0, - // then we should not show a GUI. This only really needs to be done - // on Vista and higher, but it's better to keep everything consistent - // across all OS if it's of no harm. - if (argc >= index) { - // Setting the desktop to blank will ensure no GUI is displayed - si.lpDesktop = L""; - si.dwFlags |= STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - } - - // We move the updater.ini file out of the way because we will handle - // executing PostUpdate through the service. We handle PostUpdate from - // the service because there are some per user things that happen that - // can't run in session 0 which we run updater.exe in. - // Once we are done running updater.exe we rename updater.ini back so - // that if there were any errors the next updater.exe will run correctly. - WCHAR updaterINI[MAX_PATH + 1]; - WCHAR updaterINITemp[MAX_PATH + 1]; - BOOL selfHandlePostUpdate = FALSE; - // We use the updater.ini from the same directory as the updater.exe - // because of background updates. - if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") && - PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp")) { - selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp, - MOVEFILE_REPLACE_EXISTING); - } - - // Add an env var for USING_SERVICE so the updater.exe can - // do anything special that it needs to do for service updates. - // Search in updater.cpp for more info on USING_SERVICE. - putenv(const_cast<char*>("USING_SERVICE=1")); - LOG(("Starting service with cmdline: %ls", cmdLine)); - processStarted = CreateProcessW(argv[0], cmdLine, - nullptr, nullptr, FALSE, - CREATE_DEFAULT_ERROR_MODE, - nullptr, - nullptr, &si, &pi); - // Empty value on putenv is how you remove an env variable in Windows - putenv(const_cast<char*>("USING_SERVICE=")); - - BOOL updateWasSuccessful = FALSE; - if (processStarted) { - // Wait for the updater process to finish - LOG(("Process was started... waiting on result.")); - DWORD waitRes = WaitForSingleObject(pi.hProcess, TIME_TO_WAIT_ON_UPDATER); - if (WAIT_TIMEOUT == waitRes) { - // We waited a long period of time for updater.exe and it never finished - // so kill it. - TerminateProcess(pi.hProcess, 1); - } else { - // Check the return code of updater.exe to make sure we get 0 - DWORD returnCode; - if (GetExitCodeProcess(pi.hProcess, &returnCode)) { - LOG(("Process finished with return code %d.", returnCode)); - // updater returns 0 if successful. - updateWasSuccessful = (returnCode == 0); - } else { - LOG_WARN(("Process finished but could not obtain return code.")); - } - } - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - // Check just in case updater.exe didn't change the status from - // applying. If this is the case we report an error. - BOOL isApplying = FALSE; - if (IsStatusApplying(argv[1], isApplying) && isApplying) { - if (updateWasSuccessful) { - LOG(("update.status is still applying even know update " - " was successful.")); - if (!WriteStatusFailure(argv[1], - SERVICE_STILL_APPLYING_ON_SUCCESS)) { - LOG_WARN(("Could not write update.status still applying on" - " success error.")); + LOG(("Starting update process as the service in session 0.")); + STARTUPINFO si = {0}; + si.cb = sizeof(STARTUPINFO); + si.lpDesktop = L"winsta0\\Default"; + PROCESS_INFORMATION pi = {0}; + + // The updater command line is of the form: + // updater.exe update-dir apply [wait-pid [callback-dir callback-path args]] + LPWSTR cmdLine = MakeCommandLine(argc, argv); + + int index = 3; + if (IsOldCommandline(argc, argv)) + { + index = 2; + } + + // If we're about to start the update process from session 0, + // then we should not show a GUI. This only really needs to be done + // on Vista and higher, but it's better to keep everything consistent + // across all OS if it's of no harm. + if (argc >= index) + { + // Setting the desktop to blank will ensure no GUI is displayed + si.lpDesktop = L""; + si.dwFlags |= STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + } + + // We move the updater.ini file out of the way because we will handle + // executing PostUpdate through the service. We handle PostUpdate from + // the service because there are some per user things that happen that + // can't run in session 0 which we run updater.exe in. + // Once we are done running updater.exe we rename updater.ini back so + // that if there were any errors the next updater.exe will run correctly. + WCHAR updaterINI[MAX_PATH + 1]; + WCHAR updaterINITemp[MAX_PATH + 1]; + BOOL selfHandlePostUpdate = FALSE; + // We use the updater.ini from the same directory as the updater.exe + // because of background updates. + if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") && + PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp")) + { + selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp, + MOVEFILE_REPLACE_EXISTING); + } + + // Add an env var for USING_SERVICE so the updater.exe can + // do anything special that it needs to do for service updates. + // Search in updater.cpp for more info on USING_SERVICE. + putenv(const_cast<char*>("USING_SERVICE=1")); + LOG(("Starting service with cmdline: %ls", cmdLine)); + processStarted = CreateProcessW(argv[0], cmdLine, + nullptr, nullptr, FALSE, + CREATE_DEFAULT_ERROR_MODE, + nullptr, + nullptr, &si, &pi); + // Empty value on putenv is how you remove an env variable in Windows + putenv(const_cast<char*>("USING_SERVICE=")); + + BOOL updateWasSuccessful = FALSE; + if (processStarted) + { + // Wait for the updater process to finish + LOG(("Process was started... waiting on result.")); + DWORD waitRes = WaitForSingleObject(pi.hProcess, TIME_TO_WAIT_ON_UPDATER); + if (WAIT_TIMEOUT == waitRes) + { + // We waited a long period of time for updater.exe and it never finished + // so kill it. + TerminateProcess(pi.hProcess, 1); } - // Since we still had applying we know updater.exe didn't do its - // job correctly. - updateWasSuccessful = FALSE; - } else { - LOG_WARN(("update.status is still applying and update was not successful.")); - if (!WriteStatusFailure(argv[1], - SERVICE_STILL_APPLYING_ON_FAILURE)) { - LOG_WARN(("Could not write update.status still applying on" - " success error.")); + else + { + // Check the return code of updater.exe to make sure we get 0 + DWORD returnCode; + if (GetExitCodeProcess(pi.hProcess, &returnCode)) + { + LOG(("Process finished with return code %d.", returnCode)); + // updater returns 0 if successful. + updateWasSuccessful = (returnCode == 0); + } + else + { + LOG_WARN(("Process finished but could not obtain return code.")); + } + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + // Check just in case updater.exe didn't change the status from + // applying. If this is the case we report an error. + BOOL isApplying = FALSE; + if (IsStatusApplying(argv[1], isApplying) && isApplying) + { + if (updateWasSuccessful) + { + LOG(("update.status is still applying even know update " + " was successful.")); + if (!WriteStatusFailure(argv[1], + SERVICE_STILL_APPLYING_ON_SUCCESS)) + { + LOG_WARN(("Could not write update.status still applying on" + " success error.")); + } + // Since we still had applying we know updater.exe didn't do its + // job correctly. + updateWasSuccessful = FALSE; + } + else + { + LOG_WARN(("update.status is still applying and update was not successful.")); + if (!WriteStatusFailure(argv[1], + SERVICE_STILL_APPLYING_ON_FAILURE)) + { + LOG_WARN(("Could not write update.status still applying on" + " success error.")); + } + } } - } - } - } else { - DWORD lastError = GetLastError(); - LOG_WARN(("Could not create process as current user, " - "updaterPath: %ls; cmdLine: %ls. (%d)", - argv[0], cmdLine, lastError)); - } - - // Now that we're done with the update, restore back the updater.ini file - // We use it ourselves, and also we want it back in case we had any type - // of error so that the normal update process can use it. - if (selfHandlePostUpdate) { - MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING); - - // Only run the PostUpdate if the update was successful - if (updateWasSuccessful && argc > index) { - LPCWSTR updateInfoDir = argv[1]; - bool stagingUpdate = IsUpdateBeingStaged(argc, argv); - - // Launch the PostProcess with admin access in session 0. This is - // actually launching the post update process but it takes in the - // callback app path to figure out where to apply to. - // The PostUpdate process with user only access will be done inside - // the unelevated updater.exe after the update process is complete - // from the service. We don't know here which session to start - // the user PostUpdate process from. - // Note that we don't need to do this if we're just staging the - // update in the background, as the PostUpdate step runs when - // performing the replacing in that case. - if (!stagingUpdate) { - LOG(("Launching post update process as the service in session 0.")); - if (!LaunchWinPostProcess(installDir, updateInfoDir, true, nullptr)) { - LOG_WARN(("The post update process could not be launched." - " installDir: %ls, updateInfoDir: %ls", - installDir, updateInfoDir)); + } + else + { + DWORD lastError = GetLastError(); + LOG_WARN(("Could not create process as current user, " + "updaterPath: %ls; cmdLine: %ls. (%d)", + argv[0], cmdLine, lastError)); + } + + // Now that we're done with the update, restore back the updater.ini file + // We use it ourselves, and also we want it back in case we had any type + // of error so that the normal update process can use it. + if (selfHandlePostUpdate) + { + MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING); + + // Only run the PostUpdate if the update was successful + if (updateWasSuccessful && argc > index) + { + LPCWSTR updateInfoDir = argv[1]; + bool stagingUpdate = IsUpdateBeingStaged(argc, argv); + + // Launch the PostProcess with admin access in session 0. This is + // actually launching the post update process but it takes in the + // callback app path to figure out where to apply to. + // The PostUpdate process with user only access will be done inside + // the unelevated updater.exe after the update process is complete + // from the service. We don't know here which session to start + // the user PostUpdate process from. + // Note that we don't need to do this if we're just staging the + // update in the background, as the PostUpdate step runs when + // performing the replacing in that case. + if (!stagingUpdate) + { + LOG(("Launching post update process as the service in session 0.")); + if (!LaunchWinPostProcess(installDir, updateInfoDir, true, nullptr)) + { + LOG_WARN(("The post update process could not be launched." + " installDir: %ls, updateInfoDir: %ls", + installDir, updateInfoDir)); + } + } } - } } - } - free(cmdLine); - return updateWasSuccessful; + free(cmdLine); + return updateWasSuccessful; } /** @@ -337,185 +369,219 @@ StartUpdateProcess(int argc, BOOL ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv) { - BOOL result = TRUE; - if (argc < 3) { - LOG_WARN(("Not enough command line parameters specified. " - "Updating update.status.")); - - // We can only update update.status if argv[1] exists. argv[1] is - // the directory where the update.status file exists. - if (argc < 2 || - !WriteStatusFailure(argv[1], - SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS)) { - LOG_WARN(("Could not write update.status service update failure. (%d)", - GetLastError())); - } - return FALSE; - } - - WCHAR installDir[MAX_PATH + 1] = {L'\0'}; - if (!GetInstallationDir(argc, argv, installDir)) { - LOG_WARN(("Could not get the installation directory")); - if (!WriteStatusFailure(argv[1], - SERVICE_INSTALLDIR_ERROR)) { - LOG_WARN(("Could not write update.status for GetInstallationDir failure.")); - } - return FALSE; - } - - // Make sure the path to the updater to use for the update is local. - // We do this check to make sure that file locking is available for - // race condition security checks. - BOOL isLocal = FALSE; - if (!IsLocalFile(argv[0], isLocal) || !isLocal) { - LOG_WARN(("Filesystem in path %ls is not supported (%d)", - argv[0], GetLastError())); - if (!WriteStatusFailure(argv[1], - SERVICE_UPDATER_NOT_FIXED_DRIVE)) { - LOG_WARN(("Could not write update.status service update failure. (%d)", - GetLastError())); - } - return FALSE; - } - - AutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ, + BOOL result = TRUE; + if (argc < 3) + { + LOG_WARN(("Not enough command line parameters specified. " + "Updating update.status.")); + + // We can only update update.status if argv[1] exists. argv[1] is + // the directory where the update.status file exists. + if (argc < 2 || + !WriteStatusFailure(argv[1], + SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS)) + { + LOG_WARN(("Could not write update.status service update failure. (%d)", + GetLastError())); + } + return FALSE; + } + + WCHAR installDir[MAX_PATH + 1] = {L'\0'}; + if (!GetInstallationDir(argc, argv, installDir)) + { + LOG_WARN(("Could not get the installation directory")); + if (!WriteStatusFailure(argv[1], + SERVICE_INSTALLDIR_ERROR)) + { + LOG_WARN(("Could not write update.status for GetInstallationDir failure.")); + } + return FALSE; + } + + // Make sure the path to the updater to use for the update is local. + // We do this check to make sure that file locking is available for + // race condition security checks. + BOOL isLocal = FALSE; + if (!IsLocalFile(argv[0], isLocal) || !isLocal) + { + LOG_WARN(("Filesystem in path %ls is not supported (%d)", + argv[0], GetLastError())); + if (!WriteStatusFailure(argv[1], + SERVICE_UPDATER_NOT_FIXED_DRIVE)) + { + LOG_WARN(("Could not write update.status service update failure. (%d)", + GetLastError())); + } + return FALSE; + } + + AutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); - if (noWriteLock == INVALID_HANDLE_VALUE) { - LOG_WARN(("Could not set no write sharing access on file. (%d)", - GetLastError())); - if (!WriteStatusFailure(argv[1], - SERVICE_COULD_NOT_LOCK_UPDATER)) { - LOG_WARN(("Could not write update.status service update failure. (%d)", - GetLastError())); - } - return FALSE; - } - - // Verify that the updater.exe that we are executing is the same - // as the one in the installation directory which we are updating. - // The installation dir that we are installing to is installDir. - WCHAR installDirUpdater[MAX_PATH + 1] = { L'\0' }; - wcsncpy(installDirUpdater, installDir, MAX_PATH); - if (!PathAppendSafe(installDirUpdater, L"updater.exe")) { - LOG_WARN(("Install directory updater could not be determined.")); - result = FALSE; - } - - BOOL updaterIsCorrect = FALSE; - if (result && !VerifySameFiles(argv[0], installDirUpdater, - updaterIsCorrect)) { - LOG_WARN(("Error checking if the updaters are the same.\n" - "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater)); - result = FALSE; - } - - if (result && !updaterIsCorrect) { - LOG_WARN(("The updaters do not match, updater will not run.\n" - "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater)); - result = FALSE; - } - - if (result) { - LOG(("updater.exe was compared successfully to the installation directory" - " updater.exe.")); - } else { - if (!WriteStatusFailure(argv[1], - SERVICE_UPDATER_COMPARE_ERROR)) { - LOG_WARN(("Could not write update.status updater compare failure.")); - } - return FALSE; - } - - // Check to make sure the updater.exe module has the unique updater identity. - // This is a security measure to make sure that the signed executable that - // we will run is actually an updater. - HMODULE updaterModule = LoadLibraryEx(argv[0], nullptr, - LOAD_LIBRARY_AS_DATAFILE); - if (!updaterModule) { - LOG_WARN(("updater.exe module could not be loaded. (%d)", GetLastError())); - result = FALSE; - } else { - char updaterIdentity[64]; - if (!LoadStringA(updaterModule, IDS_UPDATER_IDENTITY, - updaterIdentity, sizeof(updaterIdentity))) { - LOG_WARN(("The updater.exe application does not contain the Mozilla" - " updater identity.")); - result = FALSE; - } - - if (strcmp(updaterIdentity, UPDATER_IDENTITY_STRING)) { - LOG_WARN(("The updater.exe identity string is not valid.")); - result = FALSE; - } - FreeLibrary(updaterModule); - } - - if (result) { - LOG(("The updater.exe application contains the Mozilla" - " updater identity.")); - } else { - if (!WriteStatusFailure(argv[1], - SERVICE_UPDATER_IDENTITY_ERROR)) { - LOG_WARN(("Could not write update.status no updater identity.")); + if (noWriteLock == INVALID_HANDLE_VALUE) + { + LOG_WARN(("Could not set no write sharing access on file. (%d)", + GetLastError())); + if (!WriteStatusFailure(argv[1], + SERVICE_COULD_NOT_LOCK_UPDATER)) + { + LOG_WARN(("Could not write update.status service update failure. (%d)", + GetLastError())); + } + return FALSE; } - return TRUE; - } - // Check for updater.exe sign problems - BOOL updaterSignProblem = FALSE; -#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK - updaterSignProblem = !DoesBinaryMatchAllowedCertificates(installDir, - argv[0]); -#endif + // Verify that the updater.exe that we are executing is the same + // as the one in the installation directory which we are updating. + // The installation dir that we are installing to is installDir. + WCHAR installDirUpdater[MAX_PATH + 1] = { L'\0' }; + wcsncpy(installDirUpdater, installDir, MAX_PATH); + if (!PathAppendSafe(installDirUpdater, L"updater.exe")) + { + LOG_WARN(("Install directory updater could not be determined.")); + result = FALSE; + } + + BOOL updaterIsCorrect = FALSE; + if (result && !VerifySameFiles(argv[0], installDirUpdater, + updaterIsCorrect)) + { + LOG_WARN(("Error checking if the updaters are the same.\n" + "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater)); + result = FALSE; + } + + if (result && !updaterIsCorrect) + { + LOG_WARN(("The updaters do not match, updater will not run.\n" + "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater)); + result = FALSE; + } - // Only proceed with the update if we have no signing problems - if (!updaterSignProblem) { - BOOL updateProcessWasStarted = FALSE; - if (StartUpdateProcess(argc, argv, installDir, - updateProcessWasStarted)) { - LOG(("updater.exe was launched and run successfully!")); - LogFlush(); - - // Don't attempt to update the service when the update is being staged. - if (!IsUpdateBeingStaged(argc, argv)) { - // We might not execute code after StartServiceUpdate because - // the service installer will stop the service if it is running. - StartServiceUpdate(installDir); - } - } else { - result = FALSE; - LOG_WARN(("Error running update process. Updating update.status (%d)", - GetLastError())); - LogFlush(); - - // If the update process was started, then updater.exe is responsible for - // setting the failure code. If it could not be started then we do the - // work. We set an error instead of directly setting status pending - // so that the app.update.service.errors pref can be updated when - // the callback app restarts. - if (!updateProcessWasStarted) { + if (result) + { + LOG(("updater.exe was compared successfully to the installation directory" + " updater.exe.")); + } + else + { if (!WriteStatusFailure(argv[1], - SERVICE_UPDATER_COULD_NOT_BE_STARTED)) { - LOG_WARN(("Could not write update.status service update failure. (%d)", - GetLastError())); + SERVICE_UPDATER_COMPARE_ERROR)) + { + LOG_WARN(("Could not write update.status updater compare failure.")); + } + return FALSE; + } + + // Check to make sure the updater.exe module has the unique updater identity. + // This is a security measure to make sure that the signed executable that + // we will run is actually an updater. + HMODULE updaterModule = LoadLibraryEx(argv[0], nullptr, + LOAD_LIBRARY_AS_DATAFILE); + if (!updaterModule) + { + LOG_WARN(("updater.exe module could not be loaded. (%d)", GetLastError())); + result = FALSE; + } + else + { + char updaterIdentity[64]; + if (!LoadStringA(updaterModule, IDS_UPDATER_IDENTITY, + updaterIdentity, sizeof(updaterIdentity))) + { + LOG_WARN(("The updater.exe application does not contain the Mozilla" + " updater identity.")); + result = FALSE; + } + + if (strcmp(updaterIdentity, UPDATER_IDENTITY_STRING)) + { + LOG_WARN(("The updater.exe identity string is not valid.")); + result = FALSE; } - } + FreeLibrary(updaterModule); } - } else { - result = FALSE; - LOG_WARN(("Could not start process due to certificate check error on " - "updater.exe. Updating update.status. (%d)", GetLastError())); - // When there is a certificate check error on the updater.exe application, - // we want to write out the error. - if (!WriteStatusFailure(argv[1], - SERVICE_UPDATER_SIGN_ERROR)) { - LOG_WARN(("Could not write pending state to update.status. (%d)", - GetLastError())); + if (result) + { + LOG(("The updater.exe application contains the Mozilla" + " updater identity.")); + } + else + { + if (!WriteStatusFailure(argv[1], + SERVICE_UPDATER_IDENTITY_ERROR)) + { + LOG_WARN(("Could not write update.status no updater identity.")); + } + return TRUE; + } + + // Check for updater.exe sign problems + BOOL updaterSignProblem = FALSE; +#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK + updaterSignProblem = !DoesBinaryMatchAllowedCertificates(installDir, + argv[0]); +#endif + + // Only proceed with the update if we have no signing problems + if (!updaterSignProblem) + { + BOOL updateProcessWasStarted = FALSE; + if (StartUpdateProcess(argc, argv, installDir, + updateProcessWasStarted)) + { + LOG(("updater.exe was launched and run successfully!")); + LogFlush(); + + // Don't attempt to update the service when the update is being staged. + if (!IsUpdateBeingStaged(argc, argv)) + { + // We might not execute code after StartServiceUpdate because + // the service installer will stop the service if it is running. + StartServiceUpdate(installDir); + } + } + else + { + result = FALSE; + LOG_WARN(("Error running update process. Updating update.status (%d)", + GetLastError())); + LogFlush(); + + // If the update process was started, then updater.exe is responsible for + // setting the failure code. If it could not be started then we do the + // work. We set an error instead of directly setting status pending + // so that the app.update.service.errors pref can be updated when + // the callback app restarts. + if (!updateProcessWasStarted) + { + if (!WriteStatusFailure(argv[1], + SERVICE_UPDATER_COULD_NOT_BE_STARTED)) + { + LOG_WARN(("Could not write update.status service update failure. (%d)", + GetLastError())); + } + } + } + } + else + { + result = FALSE; + LOG_WARN(("Could not start process due to certificate check error on " + "updater.exe. Updating update.status. (%d)", GetLastError())); + + // When there is a certificate check error on the updater.exe application, + // we want to write out the error. + if (!WriteStatusFailure(argv[1], + SERVICE_UPDATER_SIGN_ERROR)) + { + LOG_WARN(("Could not write pending state to update.status. (%d)", + GetLastError())); + } } - } - return result; + return result; } /** @@ -530,33 +596,37 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv) BOOL GetSecureUpdaterPath(WCHAR serviceUpdaterPath[MAX_PATH + 1]) { - if (!GetModuleFileNameW(nullptr, serviceUpdaterPath, MAX_PATH)) { - LOG_WARN(("Could not obtain module filename when attempting to " - "use a secure updater path. (%d)", GetLastError())); - return FALSE; - } - - if (!PathRemoveFileSpecW(serviceUpdaterPath)) { - LOG_WARN(("Couldn't remove file spec when attempting to use a secure " - "updater path. (%d)", GetLastError())); - return FALSE; - } - - if (!PathAppendSafe(serviceUpdaterPath, L"update")) { - LOG_WARN(("Couldn't append file spec when attempting to use a secure " - "updater path. (%d)", GetLastError())); - return FALSE; - } - - CreateDirectoryW(serviceUpdaterPath, nullptr); - - if (!PathAppendSafe(serviceUpdaterPath, L"updater.exe")) { - LOG_WARN(("Couldn't append file spec when attempting to use a secure " - "updater path. (%d)", GetLastError())); - return FALSE; - } - - return TRUE; + if (!GetModuleFileNameW(nullptr, serviceUpdaterPath, MAX_PATH)) + { + LOG_WARN(("Could not obtain module filename when attempting to " + "use a secure updater path. (%d)", GetLastError())); + return FALSE; + } + + if (!PathRemoveFileSpecW(serviceUpdaterPath)) + { + LOG_WARN(("Couldn't remove file spec when attempting to use a secure " + "updater path. (%d)", GetLastError())); + return FALSE; + } + + if (!PathAppendSafe(serviceUpdaterPath, L"update")) + { + LOG_WARN(("Couldn't append file spec when attempting to use a secure " + "updater path. (%d)", GetLastError())); + return FALSE; + } + + CreateDirectoryW(serviceUpdaterPath, nullptr); + + if (!PathAppendSafe(serviceUpdaterPath, L"updater.exe")) + { + LOG_WARN(("Couldn't append file spec when attempting to use a secure " + "updater path. (%d)", GetLastError())); + return FALSE; + } + + return TRUE; } /** @@ -568,27 +638,31 @@ GetSecureUpdaterPath(WCHAR serviceUpdaterPath[MAX_PATH + 1]) BOOL DeleteSecureUpdater(WCHAR serviceUpdaterPath[MAX_PATH + 1]) { - BOOL result = FALSE; - if (serviceUpdaterPath[0]) { - result = DeleteFileW(serviceUpdaterPath); - if (!result && GetLastError() != ERROR_PATH_NOT_FOUND && - GetLastError() != ERROR_FILE_NOT_FOUND) { - LOG_WARN(("Could not delete service updater path: '%ls'.", - serviceUpdaterPath)); - } - - WCHAR updaterINIPath[MAX_PATH + 1] = { L'\0' }; - if (PathGetSiblingFilePath(updaterINIPath, serviceUpdaterPath, - L"updater.ini")) { - result = DeleteFileW(updaterINIPath); - if (!result && GetLastError() != ERROR_PATH_NOT_FOUND && - GetLastError() != ERROR_FILE_NOT_FOUND) { - LOG_WARN(("Could not delete service updater INI path: '%ls'.", - updaterINIPath)); - } - } - } - return result; + BOOL result = FALSE; + if (serviceUpdaterPath[0]) + { + result = DeleteFileW(serviceUpdaterPath); + if (!result && GetLastError() != ERROR_PATH_NOT_FOUND && + GetLastError() != ERROR_FILE_NOT_FOUND) + { + LOG_WARN(("Could not delete service updater path: '%ls'.", + serviceUpdaterPath)); + } + + WCHAR updaterINIPath[MAX_PATH + 1] = { L'\0' }; + if (PathGetSiblingFilePath(updaterINIPath, serviceUpdaterPath, + L"updater.ini")) + { + result = DeleteFileW(updaterINIPath); + if (!result && GetLastError() != ERROR_PATH_NOT_FOUND && + GetLastError() != ERROR_FILE_NOT_FOUND) + { + LOG_WARN(("Could not delete service updater INI path: '%ls'.", + updaterINIPath)); + } + } + } + return result; } /** @@ -604,81 +678,93 @@ DeleteSecureUpdater(WCHAR serviceUpdaterPath[MAX_PATH + 1]) BOOL ExecuteServiceCommand(int argc, LPWSTR *argv) { - if (argc < 3) { - LOG_WARN(("Not enough command line arguments to execute a service command")); - return FALSE; - } - - // The tests work by making sure the log has changed, so we put a - // unique ID in the log. - RPC_WSTR guidString = RPC_WSTR(L""); - GUID guid; - HRESULT hr = CoCreateGuid(&guid); - if (SUCCEEDED(hr)) { - UuidToString(&guid, &guidString); - } - LOG(("Executing service command %ls, ID: %ls", - argv[2], reinterpret_cast<LPCWSTR>(guidString))); - RpcStringFree(&guidString); - - BOOL result = FALSE; - if (!lstrcmpi(argv[2], L"software-update")) { - - // Use the passed in command line arguments for the update, except for the - // path to updater.exe. We copy updater.exe to a the directory of the - // MozillaMaintenance service so that a low integrity process cannot - // replace the updater.exe at any point and use that for the update. - // It also makes DLL injection attacks harder. - LPWSTR oldUpdaterPath = argv[3]; - WCHAR secureUpdaterPath[MAX_PATH + 1] = { L'\0' }; - result = GetSecureUpdaterPath(secureUpdaterPath); // Does its own logging - if (result) { - LOG(("Passed in path: '%ls'; Using this path for updating: '%ls'.", - oldUpdaterPath, secureUpdaterPath)); - DeleteSecureUpdater(secureUpdaterPath); - result = CopyFileW(oldUpdaterPath, secureUpdaterPath, FALSE); - } - - if (!result) { - LOG_WARN(("Could not copy path to secure location. (%d)", - GetLastError())); - if (argc > 4 && !WriteStatusFailure(argv[4], - SERVICE_COULD_NOT_COPY_UPDATER)) { - LOG_WARN(("Could not write update.status could not copy updater error")); - } - } else { - - // We obtained the path and copied it successfully, update the path to - // use for the service update. - argv[3] = secureUpdaterPath; - - WCHAR oldUpdaterINIPath[MAX_PATH + 1] = { L'\0' }; - WCHAR secureUpdaterINIPath[MAX_PATH + 1] = { L'\0' }; - if (PathGetSiblingFilePath(secureUpdaterINIPath, secureUpdaterPath, - L"updater.ini") && - PathGetSiblingFilePath(oldUpdaterINIPath, oldUpdaterPath, - L"updater.ini")) { - // This is non fatal if it fails there is no real harm - if (!CopyFileW(oldUpdaterINIPath, secureUpdaterINIPath, FALSE)) { - LOG_WARN(("Could not copy updater.ini from: '%ls' to '%ls'. (%d)", - oldUpdaterINIPath, secureUpdaterINIPath, GetLastError())); - } - } + if (argc < 3) + { + LOG_WARN(("Not enough command line arguments to execute a service command")); + return FALSE; + } - result = ProcessSoftwareUpdateCommand(argc - 3, argv + 3); - DeleteSecureUpdater(secureUpdaterPath); + // The tests work by making sure the log has changed, so we put a + // unique ID in the log. + RPC_WSTR guidString = RPC_WSTR(L""); + GUID guid; + HRESULT hr = CoCreateGuid(&guid); + if (SUCCEEDED(hr)) + { + UuidToString(&guid, &guidString); } + LOG(("Executing service command %ls, ID: %ls", + argv[2], reinterpret_cast<LPCWSTR>(guidString))); + RpcStringFree(&guidString); + + BOOL result = FALSE; + if (!lstrcmpi(argv[2], L"software-update")) + { + + // Use the passed in command line arguments for the update, except for the + // path to updater.exe. We copy updater.exe to a the directory of the + // MozillaMaintenance service so that a low integrity process cannot + // replace the updater.exe at any point and use that for the update. + // It also makes DLL injection attacks harder. + LPWSTR oldUpdaterPath = argv[3]; + WCHAR secureUpdaterPath[MAX_PATH + 1] = { L'\0' }; + result = GetSecureUpdaterPath(secureUpdaterPath); // Does its own logging + if (result) + { + LOG(("Passed in path: '%ls'; Using this path for updating: '%ls'.", + oldUpdaterPath, secureUpdaterPath)); + DeleteSecureUpdater(secureUpdaterPath); + result = CopyFileW(oldUpdaterPath, secureUpdaterPath, FALSE); + } - // We might not reach here if the service install succeeded - // because the service self updates itself and the service - // installer will stop the service. - LOG(("Service command %ls complete.", argv[2])); - } else { - LOG_WARN(("Service command not recognized: %ls.", argv[2])); - // result is already set to FALSE - } + if (!result) + { + LOG_WARN(("Could not copy path to secure location. (%d)", + GetLastError())); + if (argc > 4 && !WriteStatusFailure(argv[4], + SERVICE_COULD_NOT_COPY_UPDATER)) + { + LOG_WARN(("Could not write update.status could not copy updater error")); + } + } + else + { + + // We obtained the path and copied it successfully, update the path to + // use for the service update. + argv[3] = secureUpdaterPath; + + WCHAR oldUpdaterINIPath[MAX_PATH + 1] = { L'\0' }; + WCHAR secureUpdaterINIPath[MAX_PATH + 1] = { L'\0' }; + if (PathGetSiblingFilePath(secureUpdaterINIPath, secureUpdaterPath, + L"updater.ini") && + PathGetSiblingFilePath(oldUpdaterINIPath, oldUpdaterPath, + L"updater.ini")) + { + // This is non fatal if it fails there is no real harm + if (!CopyFileW(oldUpdaterINIPath, secureUpdaterINIPath, FALSE)) + { + LOG_WARN(("Could not copy updater.ini from: '%ls' to '%ls'. (%d)", + oldUpdaterINIPath, secureUpdaterINIPath, GetLastError())); + } + } + + result = ProcessSoftwareUpdateCommand(argc - 3, argv + 3); + DeleteSecureUpdater(secureUpdaterPath); + } - LOG(("service command %ls complete with result: %ls.", - argv[1], (result ? L"Success" : L"Failure"))); - return TRUE; + // We might not reach here if the service install succeeded + // because the service self updates itself and the service + // installer will stop the service. + LOG(("Service command %ls complete.", argv[2])); + } + else + { + LOG_WARN(("Service command not recognized: %ls.", argv[2])); + // result is already set to FALSE + } + + LOG(("service command %ls complete with result: %ls.", + argv[1], (result ? L"Success" : L"Failure"))); + return TRUE; } diff --git a/onlineupdate/source/update/common/pathhash.cxx b/onlineupdate/source/update/common/pathhash.cxx index 3c3c1f5d31f0..67e53fa35bea 100644 --- a/onlineupdate/source/update/common/pathhash.cxx +++ b/onlineupdate/source/update/common/pathhash.cxx @@ -20,11 +20,12 @@ static void BinaryDataToHexString(const BYTE *hash, DWORD &hashSize, LPWSTR hexString) { - WCHAR *p = hexString; - for (DWORD i = 0; i < hashSize; ++i) { - wsprintfW(p, L"%.2x", hash[i]); - p += 2; - } + WCHAR *p = hexString; + for (DWORD i = 0; i < hashSize; ++i) + { + wsprintfW(p, L"%.2x", hash[i]); + p += 2; + } } /** @@ -40,52 +41,61 @@ static BOOL CalculateMD5(const char *data, DWORD dataSize, BYTE **hash, DWORD &hashSize) { - HCRYPTPROV hProv = 0; - HCRYPTHASH hHash = 0; + HCRYPTPROV hProv = 0; + HCRYPTHASH hHash = 0; - if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - if (NTE_BAD_KEYSET != GetLastError()) { - return FALSE; + if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + { + if (NTE_BAD_KEYSET != GetLastError()) + { + return FALSE; + } + + // Maybe it doesn't exist, try to create it. + if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) + { + return FALSE; + } } - // Maybe it doesn't exist, try to create it. - if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) { - return FALSE; + if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) + { + return FALSE; + } + + if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(data), + dataSize, 0)) + { + return FALSE; + } + + DWORD dwCount = sizeof(DWORD); + if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, + &dwCount, 0)) + { + return FALSE; + } + + *hash = new BYTE[hashSize]; + ZeroMemory(*hash, hashSize); + if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) + { + return FALSE; + } + + if (hHash) + { + CryptDestroyHash(hHash); + } + + if (hProv) + { + CryptReleaseContext(hProv,0); } - } - - if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { - return FALSE; - } - - if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(data), - dataSize, 0)) { - return FALSE; - } - - DWORD dwCount = sizeof(DWORD); - if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, - &dwCount, 0)) { - return FALSE; - } - - *hash = new BYTE[hashSize]; - ZeroMemory(*hash, hashSize); - if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) { - return FALSE; - } - - if (hHash) { - CryptDestroyHash(hHash); - } - - if (hProv) { - CryptReleaseContext(hProv,0); - } - - return TRUE; + + return TRUE; } /** @@ -100,41 +110,44 @@ BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath, LPWSTR registryPath) { - size_t filePathLen = wcslen(filePath); - if (!filePathLen) { - return FALSE; - } - - // If the file path ends in a slash, ignore that character - if (filePath[filePathLen -1] == L'\\' || - filePath[filePathLen - 1] == L'/') { - filePathLen--; - } - - // Copy in the full path into our own buffer. - // Copying in the extra slash is OK because we calculate the hash - // based on the filePathLen which excludes the slash. - // +2 to account for the possibly trailing slash and the null terminator. - WCHAR *lowercasePath = new WCHAR[filePathLen + 2]; - memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR)); - wcsncpy(lowercasePath, filePath, filePathLen + 1); - _wcslwr(lowercasePath); - - BYTE *hash; - DWORD hashSize = 0; - if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath), - filePathLen * 2, - &hash, hashSize)) { + size_t filePathLen = wcslen(filePath); + if (!filePathLen) + { + return FALSE; + } + + // If the file path ends in a slash, ignore that character + if (filePath[filePathLen -1] == L'\\' || + filePath[filePathLen - 1] == L'/') + { + filePathLen--; + } + + // Copy in the full path into our own buffer. + // Copying in the extra slash is OK because we calculate the hash + // based on the filePathLen which excludes the slash. + // +2 to account for the possibly trailing slash and the null terminator. + WCHAR *lowercasePath = new WCHAR[filePathLen + 2]; + memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR)); + wcsncpy(lowercasePath, filePath, filePathLen + 1); + _wcslwr(lowercasePath); + + BYTE *hash; + DWORD hashSize = 0; + if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath), + filePathLen * 2, + &hash, hashSize)) + { + delete[] lowercasePath; + return FALSE; + } delete[] lowercasePath; - return FALSE; - } - delete[] lowercasePath; - - LPCWSTR baseRegPath = L"SOFTWARE\\LibreOffice\\MaintenanceService\\"; - wcsncpy(registryPath, baseRegPath, MAX_PATH); - BinaryDataToHexString(hash, hashSize, - registryPath + wcslen(baseRegPath)); - delete[] hash; - return TRUE; + + LPCWSTR baseRegPath = L"SOFTWARE\\LibreOffice\\MaintenanceService\\"; + wcsncpy(registryPath, baseRegPath, MAX_PATH); + BinaryDataToHexString(hash, hashSize, + registryPath + wcslen(baseRegPath)); + delete[] hash; + return TRUE; } #endif diff --git a/onlineupdate/source/update/common/readstrings.cxx b/onlineupdate/source/update/common/readstrings.cxx index d2792117773e..e1366cdddaed 100644 --- a/onlineupdate/source/update/common/readstrings.cxx +++ b/onlineupdate/source/update/common/readstrings.cxx @@ -19,22 +19,39 @@ #endif // stack based FILE wrapper to ensure that fclose is called. -class AutoFILE { +class AutoFILE +{ public: - explicit AutoFILE(FILE *fp) : fp_(fp) {} - ~AutoFILE() { if (fp_) fclose(fp_); } - operator FILE *() { return fp_; } + explicit AutoFILE(FILE *fp) : fp_(fp) {} + ~AutoFILE() + { + if (fp_) fclose(fp_); + } + operator FILE *() + { + return fp_; + } private: - FILE *fp_; + FILE *fp_; }; -class AutoCharArray { +class AutoCharArray +{ public: - explicit AutoCharArray(size_t len) { ptr_ = new char[len]; } - ~AutoCharArray() { delete[] ptr_; } - operator char *() { return ptr_; } + explicit AutoCharArray(size_t len) + { + ptr_ = new char[len]; + } + ~AutoCharArray() + { + delete[] ptr_; + } + operator char *() + { + return ptr_; + } private: - char *ptr_; + char *ptr_; }; static const char kNL[] = "\r\n"; @@ -45,46 +62,55 @@ static const char kRBracket[] = "]"; static const char* NS_strspnp(const char *delims, const char *str) { - const char *d; - do { - for (d = delims; *d != '\0'; ++d) { - if (*str == *d) { - ++str; - break; - } + const char *d; + do + { + for (d = delims; *d != '\0'; ++d) + { + if (*str == *d) + { + ++str; + break; + } + } } - } while (*d); + while (*d); - return str; + return str; } static char* NS_strtok(const char *delims, char **str) { - if (!*str) - return nullptr; - - char *ret = (char*) NS_strspnp(delims, *str); - - if (!*ret) { - *str = ret; - return nullptr; - } - - char *i = ret; - do { - for (const char *d = delims; *d != '\0'; ++d) { - if (*i == *d) { - *i = '\0'; - *str = ++i; - return ret; - } + if (!*str) + return nullptr; + + char *ret = (char*) NS_strspnp(delims, *str); + + if (!*ret) + { + *str = ret; + return nullptr; } - ++i; - } while (*i); - *str = nullptr; - return ret; + char *i = ret; + do + { + for (const char *d = delims; *d != '\0'; ++d) + { + if (*i == *d) + { + *i = '\0'; + *str = ++i; + return ret; + } + } + ++i; + } + while (*i); + + *str = nullptr; + return ret; } /** @@ -94,22 +120,22 @@ NS_strtok(const char *delims, char **str) static int find_key(const char *keyList, char* key) { - if (!keyList) - return -1; + if (!keyList) + return -1; - int index = 0; - const char *p = keyList; - while (*p) - { - if (strcmp(key, p) == 0) - return index; + int index = 0; + const char *p = keyList; + while (*p) + { + if (strcmp(key, p) == 0) + return index; - p += strlen(p) + 1; - index++; - } + p += strlen(p) + 1; + index++; + } - // The key was not found if we came here - return -1; + // The key was not found if we came here + return -1; } /** @@ -129,91 +155,96 @@ ReadStrings(const NS_tchar *path, char results[][MAX_TEXT_LEN], const char *section) { - AutoFILE fp(NS_tfopen(path, OPEN_MODE)); - - if (!fp) - return READ_ERROR; - - /* get file size */ - if (fseek(fp, 0, SEEK_END) != 0) - return READ_ERROR; - - long len = ftell(fp); - if (len <= 0) - return READ_ERROR; - - size_t flen = size_t(len); - AutoCharArray fileContents(flen + 1); - if (!fileContents) - return READ_STRINGS_MEM_ERROR; - - /* read the file in one swoop */ - if (fseek(fp, 0, SEEK_SET) != 0) - return READ_ERROR; - - size_t rd = fread(fileContents, sizeof(char), flen, fp); - if (rd != flen) - return READ_ERROR; - - fileContents[flen] = '\0'; - - char *buffer = fileContents; - bool inStringsSection = false; - - unsigned int read = 0; - - while (char *token = NS_strtok(kNL, &buffer)) { - if (token[0] == '#' || token[0] == ';') // it's a comment - continue; - - token = (char*) NS_strspnp(kWhitespace, token); - if (!*token) // empty line - continue; - - if (token[0] == '[') { // section header! - ++token; - char const * currSection = token; - - char *rb = NS_strtok(kRBracket, &token); - if (!rb || NS_strtok(kWhitespace, &token)) { - // there's either an unclosed [Section or a [Section]Moretext! - // we could frankly decide that this INI file is malformed right - // here and stop, but we won't... keep going, looking for - // a well-formed [section] to continue working with - inStringsSection = false; - } - else { - if (section) - inStringsSection = strcmp(currSection, section) == 0; - else - inStringsSection = strcmp(currSection, "Strings") == 0; - } - - continue; - } + AutoFILE fp(NS_tfopen(path, OPEN_MODE)); - if (!inStringsSection) { - // If we haven't found a section header (or we found a malformed - // section header), or this isn't the [Strings] section don't bother - // parsing this line. - continue; - } + if (!fp) + return READ_ERROR; + + /* get file size */ + if (fseek(fp, 0, SEEK_END) != 0) + return READ_ERROR; + + long len = ftell(fp); + if (len <= 0) + return READ_ERROR; + + size_t flen = size_t(len); + AutoCharArray fileContents(flen + 1); + if (!fileContents) + return READ_STRINGS_MEM_ERROR; + + /* read the file in one swoop */ + if (fseek(fp, 0, SEEK_SET) != 0) + return READ_ERROR; + + size_t rd = fread(fileContents, sizeof(char), flen, fp); + if (rd != flen) + return READ_ERROR; + + fileContents[flen] = '\0'; + + char *buffer = fileContents; + bool inStringsSection = false; - char *key = token; - char *e = NS_strtok(kEquals, &token); - if (!e) - continue; + unsigned int read = 0; - int keyIndex = find_key(keyList, key); - if (keyIndex >= 0 && (unsigned int)keyIndex < numStrings) + while (char *token = NS_strtok(kNL, &buffer)) { - strncpy(results[keyIndex], token, MAX_TEXT_LEN - 1); - results[keyIndex][MAX_TEXT_LEN - 1] = '\0'; - read++; + if (token[0] == '#' || token[0] == ';') // it's a comment + continue; + + token = (char*) NS_strspnp(kWhitespace, token); + if (!*token) // empty line + continue; + + if (token[0] == '[') // section header! + { + ++token; + char const * currSection = token; + + char *rb = NS_strtok(kRBracket, &token); + if (!rb || NS_strtok(kWhitespace, &token)) + { + // there's either an unclosed [Section or a [Section]Moretext! + // we could frankly decide that this INI file is malformed right + // here and stop, but we won't... keep going, looking for + // a well-formed [section] to continue working with + inStringsSection = false; + } + else + { + if (section) + inStringsSection = strcmp(currSection, section) == 0; + else + inStringsSection = strcmp(currSection, "Strings") == 0; + } + + continue; + } + + if (!inStringsSection) + { + // If we haven't found a section header (or we found a malformed + // section header), or this isn't the [Strings] section don't bother + // parsing this line. + continue; + } + + char *key = token; + char *e = NS_strtok(kEquals, &token); + if (!e) + continue; + + int keyIndex = find_key(keyList, key); + if (keyIndex >= 0 && (unsigned int)keyIndex < numStrings) + { + strncpy(results[keyIndex], token, MAX_TEXT_LEN - 1); + results[keyIndex][MAX_TEXT_LEN - 1] = '\0'; + read++; + } } - } - return (read == numStrings) ? OK : PARSE_ERROR; + return (read == numStrings) ? OK : PARSE_ERROR; } // A wrapper function to read strings for the updater. @@ -221,16 +252,16 @@ ReadStrings(const NS_tchar *path, int ReadStrings(const NS_tchar *path, StringTable *results) { - const unsigned int kNumStrings = 2; - const char *kUpdaterKeys = "Title\0Info\0"; - char updater_strings[kNumStrings][MAX_TEXT_LEN]; + const unsigned int kNumStrings = 2; + const char *kUpdaterKeys = "Title\0Info\0"; + char updater_strings[kNumStrings][MAX_TEXT_LEN]; - int result = ReadStrings(path, kUpdaterKeys, kNumStrings, updater_strings); + int result = ReadStrings(path, kUpdaterKeys, kNumStrings, updater_strings); - strncpy(results->title, updater_strings[0], MAX_TEXT_LEN - 1); - results->title[MAX_TEXT_LEN - 1] = '\0'; - strncpy(results->info, updater_strings[1], MAX_TEXT_LEN - 1); - results->info[MAX_TEXT_LEN - 1] = '\0'; + strncpy(results->title, updater_strings[0], MAX_TEXT_LEN - 1); + results->title[MAX_TEXT_LEN - 1] = '\0'; + strncpy(results->info, updater_strings[1], MAX_TEXT_LEN - 1); + results->info[MAX_TEXT_LEN - 1] = '\0'; - return result; + return result; } diff --git a/onlineupdate/source/update/common/readstrings.h b/onlineupdate/source/update/common/readstrings.h index 47a9c171756d..bc837ef326b5 100644 --- a/onlineupdate/source/update/common/readstrings.h +++ b/onlineupdate/source/update/common/readstrings.h @@ -11,9 +11,9 @@ #ifdef _WIN32 # include <windows.h> - typedef WCHAR NS_tchar; +typedef WCHAR NS_tchar; #else - typedef char NS_tchar; +typedef char NS_tchar; #endif #ifndef NULL @@ -22,8 +22,8 @@ struct StringTable { - char title[MAX_TEXT_LEN]; - char info[MAX_TEXT_LEN]; + char title[MAX_TEXT_LEN]; + char info[MAX_TEXT_LEN]; }; /** diff --git a/onlineupdate/source/update/common/uachelper.cxx b/onlineupdate/source/update/common/uachelper.cxx index 4cae3ad4e5fc..831b12680719 100644 --- a/onlineupdate/source/update/common/uachelper.cxx +++ b/onlineupdate/source/update/common/uachelper.cxx @@ -11,48 +11,49 @@ // See the MSDN documentation with title: Privilege Constants // At the time of this writing, this documentation is located at: // http://msdn.microsoft.com/en-us/library/windows/desktop/bb530716%28v=vs.85%29.aspx -LPCTSTR UACHelper::PrivsToDisable[] = { - SE_ASSIGNPRIMARYTOKEN_NAME, - SE_AUDIT_NAME, - SE_BACKUP_NAME, - // CreateProcess will succeed but the app will fail to launch on some WinXP - // machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens - // for limited user accounts on those machines. The define is kept here as a - // reminder that it should never be re-added. - // This permission is for directory watching but also from MSDN: "This - // privilege also causes the system to skip all traversal access checks." - // SE_CHANGE_NOTIFY_NAME, - SE_CREATE_GLOBAL_NAME, - SE_CREATE_PAGEFILE_NAME, - SE_CREATE_PERMANENT_NAME, - SE_CREATE_SYMBOLIC_LINK_NAME, - SE_CREATE_TOKEN_NAME, - SE_DEBUG_NAME, - SE_ENABLE_DELEGATION_NAME, - SE_IMPERSONATE_NAME, - SE_INC_BASE_PRIORITY_NAME, - SE_INCREASE_QUOTA_NAME, - SE_INC_WORKING_SET_NAME, - SE_LOAD_DRIVER_NAME, - SE_LOCK_MEMORY_NAME, - SE_MACHINE_ACCOUNT_NAME, - SE_MANAGE_VOLUME_NAME, - SE_PROF_SINGLE_PROCESS_NAME, - SE_RELABEL_NAME, - SE_REMOTE_SHUTDOWN_NAME, - SE_RESTORE_NAME, - SE_SECURITY_NAME, - SE_SHUTDOWN_NAME, - SE_SYNC_AGENT_NAME, - SE_SYSTEM_ENVIRONMENT_NAME, - SE_SYSTEM_PROFILE_NAME, - SE_SYSTEMTIME_NAME, - SE_TAKE_OWNERSHIP_NAME, - SE_TCB_NAME, - SE_TIME_ZONE_NAME, - SE_TRUSTED_CREDMAN_ACCESS_NAME, - SE_UNDOCK_NAME, - SE_UNSOLICITED_INPUT_NAME +LPCTSTR UACHelper::PrivsToDisable[] = +{ + SE_ASSIGNPRIMARYTOKEN_NAME, + SE_AUDIT_NAME, + SE_BACKUP_NAME, + // CreateProcess will succeed but the app will fail to launch on some WinXP + // machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens + // for limited user accounts on those machines. The define is kept here as a + // reminder that it should never be re-added. + // This permission is for directory watching but also from MSDN: "This + // privilege also causes the system to skip all traversal access checks." + // SE_CHANGE_NOTIFY_NAME, + SE_CREATE_GLOBAL_NAME, + SE_CREATE_PAGEFILE_NAME, + SE_CREATE_PERMANENT_NAME, + SE_CREATE_SYMBOLIC_LINK_NAME, + SE_CREATE_TOKEN_NAME, + SE_DEBUG_NAME, + SE_ENABLE_DELEGATION_NAME, + SE_IMPERSONATE_NAME, + SE_INC_BASE_PRIORITY_NAME, + SE_INCREASE_QUOTA_NAME, + SE_INC_WORKING_SET_NAME, + SE_LOAD_DRIVER_NAME, + SE_LOCK_MEMORY_NAME, + SE_MACHINE_ACCOUNT_NAME, + SE_MANAGE_VOLUME_NAME, + SE_PROF_SINGLE_PROCESS_NAME, + SE_RELABEL_NAME, + SE_REMOTE_SHUTDOWN_NAME, + SE_RESTORE_NAME, + SE_SECURITY_NAME, + SE_SHUTDOWN_NAME, + SE_SYNC_AGENT_NAME, + SE_SYSTEM_ENVIRONMENT_NAME, + SE_SYSTEM_PROFILE_NAME, + SE_SYSTEMTIME_NAME, + SE_TAKE_OWNERSHIP_NAME, + SE_TCB_NAME, + SE_TIME_ZONE_NAME, + SE_TRUSTED_CREDMAN_ACCESS_NAME, + SE_UNDOCK_NAME, + SE_UNSOLICITED_INPUT_NAME }; /** @@ -65,15 +66,16 @@ LPCTSTR UACHelper::PrivsToDisable[] = { HANDLE UACHelper::OpenUserToken(DWORD sessionID) { - HMODULE module = LoadLibraryW(L"wtsapi32.dll"); - HANDLE token = nullptr; - decltype(WTSQueryUserToken)* wtsQueryUserToken = - (decltype(WTSQueryUserToken)*) GetProcAddress(module, "WTSQueryUserToken"); - if (wtsQueryUserToken) { - wtsQueryUserToken(sessionID, &token); - } - FreeLibrary(module); - return token; + HMODULE module = LoadLibraryW(L"wtsapi32.dll"); + HANDLE token = nullptr; + decltype(WTSQueryUserToken)* wtsQueryUserToken = + (decltype(WTSQueryUserToken)*) GetProcAddress(module, "WTSQueryUserToken"); + if (wtsQueryUserToken) + { + wtsQueryUserToken(sessionID, &token); + } + FreeLibrary(module); + return token; } /** @@ -86,19 +88,20 @@ UACHelper::OpenUserToken(DWORD sessionID) HANDLE UACHelper::OpenLinkedToken(HANDLE token) { - // Magic below... - // UAC creates 2 tokens. One is the restricted token which we have. - // the other is the UAC elevated one. Since we are running as a service - // as the system account we have access to both. - TOKEN_LINKED_TOKEN tlt; - HANDLE hNewLinkedToken = nullptr; - DWORD len; - if (GetTokenInformation(token, (TOKEN_INFORMATION_CLASS)TokenLinkedToken, - &tlt, sizeof(TOKEN_LINKED_TOKEN), &len)) { - token = tlt.LinkedToken; - hNewLinkedToken = token; - } - return hNewLinkedToken; + // Magic below... + // UAC creates 2 tokens. One is the restricted token which we have. + // the other is the UAC elevated one. Since we are running as a service + // as the system account we have access to both. + TOKEN_LINKED_TOKEN tlt; + HANDLE hNewLinkedToken = nullptr; + DWORD len; + if (GetTokenInformation(token, (TOKEN_INFORMATION_CLASS)TokenLinkedToken, + &tlt, sizeof(TOKEN_LINKED_TOKEN), &len)) + { + token = tlt.LinkedToken; + hNewLinkedToken = token; + } + return hNewLinkedToken; } @@ -113,23 +116,25 @@ UACHelper::OpenLinkedToken(HANDLE token) BOOL UACHelper::SetPrivilege(HANDLE token, LPCTSTR priv, BOOL enable) { - LUID luidOfPriv; - if (!LookupPrivilegeValue(nullptr, priv, &luidOfPriv)) { - return FALSE; - } - - TOKEN_PRIVILEGES tokenPriv; - tokenPriv.PrivilegeCount = 1; - tokenPriv.Privileges[0].Luid = luidOfPriv; - tokenPriv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - - SetLastError(ERROR_SUCCESS); - if (!AdjustTokenPrivileges(token, false, &tokenPriv, - sizeof(tokenPriv), nullptr, nullptr)) { - return FALSE; - } - - return GetLastError() == ERROR_SUCCESS; + LUID luidOfPriv; + if (!LookupPrivilegeValue(nullptr, priv, &luidOfPriv)) + { + return FALSE; + } + + TOKEN_PRIVILEGES tokenPriv; + tokenPriv.PrivilegeCount = 1; + tokenPriv.Privileges[0].Luid = luidOfPriv; + tokenPriv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; + + SetLastError(ERROR_SUCCESS); + if (!AdjustTokenPrivileges(token, false, &tokenPriv, + sizeof(tokenPriv), nullptr, nullptr)) + { + return FALSE; + } + + return GetLastError() == ERROR_SUCCESS; } /** @@ -147,34 +152,41 @@ UACHelper::DisableUnneededPrivileges(HANDLE token, LPCTSTR *unneededPrivs, size_t count) { - HANDLE obtainedToken = nullptr; - if (!token) { - // Note: This handle is a pseudo-handle and need not be closed - HANDLE process = GetCurrentProcess(); - if (!OpenProcessToken(process, TOKEN_ALL_ACCESS_P, &obtainedToken)) { - LOG_WARN(("Could not obtain token for current process, no " - "privileges changed. (%d)", GetLastError())); - return FALSE; + HANDLE obtainedToken = nullptr; + if (!token) + { + // Note: This handle is a pseudo-handle and need not be closed + HANDLE process = GetCurrentProcess(); + if (!OpenProcessToken(process, TOKEN_ALL_ACCESS_P, &obtainedToken)) + { + LOG_WARN(("Could not obtain token for current process, no " + "privileges changed. (%d)", GetLastError())); + return FALSE; + } + token = obtainedToken; } - token = obtainedToken; - } - - BOOL result = TRUE; - for (size_t i = 0; i < count; i++) { - if (SetPrivilege(token, unneededPrivs[i], FALSE)) { - LOG(("Disabled unneeded token privilege: %s.", - unneededPrivs[i])); - } else { - LOG(("Could not disable token privilege value: %s. (%d)", - unneededPrivs[i], GetLastError())); - result = FALSE; + + BOOL result = TRUE; + for (size_t i = 0; i < count; i++) + { + if (SetPrivilege(token, unneededPrivs[i], FALSE)) + { + LOG(("Disabled unneeded token privilege: %s.", + unneededPrivs[i])); + } + else + { + LOG(("Could not disable token privilege value: %s. (%d)", + unneededPrivs[i], GetLastError())); + result = FALSE; + } } - } - if (obtainedToken) { - CloseHandle(obtainedToken); - } - return result; + if (obtainedToken) + { + CloseHandle(obtainedToken); + } + return result; } /** @@ -190,11 +202,11 @@ UACHelper::DisableUnneededPrivileges(HANDLE token, BOOL UACHelper::DisablePrivileges(HANDLE token) { - static const size_t PrivsToDisableSize = - sizeof(UACHelper::PrivsToDisable) / sizeof(UACHelper::PrivsToDisable[0]); + static const size_t PrivsToDisableSize = + sizeof(UACHelper::PrivsToDisable) / sizeof(UACHelper::PrivsToDisable[0]); - return DisableUnneededPrivileges(token, UACHelper::PrivsToDisable, - PrivsToDisableSize); + return DisableUnneededPrivileges(token, UACHelper::PrivsToDisable, + PrivsToDisableSize); } /** @@ -206,19 +218,20 @@ UACHelper::DisablePrivileges(HANDLE token) bool UACHelper::CanUserElevate() { - HANDLE token; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { - return false; - } - - TOKEN_ELEVATION_TYPE elevationType; - DWORD len; - bool canElevate = GetTokenInformation(token, TokenElevationType, - &elevationType, - sizeof(elevationType), &len) && - (elevationType == TokenElevationTypeLimited); - CloseHandle(token); - - return canElevate; + HANDLE token; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) + { + return false; + } + + TOKEN_ELEVATION_TYPE elevationType; + DWORD len; + bool canElevate = GetTokenInformation(token, TokenElevationType, + &elevationType, + sizeof(elevationType), &len) && + (elevationType == TokenElevationTypeLimited); + CloseHandle(token); + + return canElevate; } #endif diff --git a/onlineupdate/source/update/common/uachelper.h b/onlineupdate/source/update/common/uachelper.h index 810d79d79f24..4e8d1c84239a 100644 --- a/onlineupdate/source/update/common/uachelper.h +++ b/onlineupdate/source/update/common/uachelper.h @@ -8,16 +8,16 @@ class UACHelper { public: - static HANDLE OpenUserToken(DWORD sessionID); - static HANDLE OpenLinkedToken(HANDLE token); - static BOOL DisablePrivileges(HANDLE token); - static bool CanUserElevate(); + static HANDLE OpenUserToken(DWORD sessionID); + static HANDLE OpenLinkedToken(HANDLE token); + static BOOL DisablePrivileges(HANDLE token); + static bool CanUserElevate(); private: - static BOOL SetPrivilege(HANDLE token, LPCTSTR privs, BOOL enable); - static BOOL DisableUnneededPrivileges(HANDLE token, - LPCTSTR *unneededPrivs, size_t count); - static LPCTSTR PrivsToDisable[]; + static BOOL SetPrivilege(HANDLE token, LPCTSTR privs, BOOL enable); + static BOOL DisableUnneededPrivileges(HANDLE token, + LPCTSTR *unneededPrivs, size_t count); + static LPCTSTR PrivsToDisable[]; }; #endif diff --git a/onlineupdate/source/update/common/updatedefines.h b/onlineupdate/source/update/common/updatedefines.h index 95969b169426..acca6887f422 100644 --- a/onlineupdate/source/update/common/updatedefines.h +++ b/onlineupdate/source/update/common/updatedefines.h @@ -47,13 +47,13 @@ static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt, ...) { - size_t _count = count - 1; - va_list varargs; - va_start(varargs, fmt); - int result = _vsnwprintf(dest, count - 1, fmt, varargs); - va_end(varargs); - dest[_count] = L'\0'; - return result; + size_t _count = count - 1; + va_list varargs; + va_start(varargs, fmt); + int result = _vsnwprintf(dest, count - 1, fmt, varargs); + va_end(varargs); + dest[_count] = L'\0'; + return result; } #define NS_tsnprintf mywcsprintf # define NS_taccess _waccess diff --git a/onlineupdate/source/update/common/updatehelper.cxx b/onlineupdate/source/update/common/updatehelper.cxx index c19b830e36e1..ab9e77f00979 100644 --- a/onlineupdate/source/update/common/updatehelper.cxx +++ b/onlineupdate/source/update/common/updatehelper.cxx @@ -35,20 +35,23 @@ PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, LPCWSTR newFileName) { - if (wcslen(siblingFilePath) >= MAX_PATH) { - return FALSE; - } + if (wcslen(siblingFilePath) >= MAX_PATH) + { + return FALSE; + } - wcsncpy(destinationBuffer, siblingFilePath, MAX_PATH); - if (!PathRemoveFileSpecW(destinationBuffer)) { - return FALSE; - } + wcsncpy(destinationBuffer, siblingFilePath, MAX_PATH); + if (!PathRemoveFileSpecW(destinationBuffer)) + { + return FALSE; + } - if (wcslen(destinationBuffer) + wcslen(newFileName) >= MAX_PATH) { - return FALSE; - } + if (wcslen(destinationBuffer) + wcslen(newFileName) >= MAX_PATH) + { + return FALSE; + } - return PathAppendSafe(destinationBuffer, newFileName); + return PathAppendSafe(destinationBuffer, newFileName); } /** @@ -71,115 +74,128 @@ LaunchWinPostProcess(const WCHAR *installationDir, bool forceSync, HANDLE userToken) { - WCHAR workingDirectory[MAX_PATH + 1] = { L'\0' }; - wcsncpy(workingDirectory, installationDir, MAX_PATH); - - // Launch helper.exe to perform post processing (e.g. registry and log file - // modifications) for the update. - WCHAR inifile[MAX_PATH + 1] = { L'\0' }; - wcsncpy(inifile, installationDir, MAX_PATH); - if (!PathAppendSafe(inifile, L"updater.ini")) { - return FALSE; - } - - WCHAR exefile[MAX_PATH + 1]; - WCHAR exearg[MAX_PATH + 1]; - WCHAR exeasync[10]; - bool async = true; - if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", nullptr, - exefile, MAX_PATH + 1, inifile)) { - return FALSE; - } - - if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", nullptr, exearg, - MAX_PATH + 1, inifile)) { - return FALSE; - } - - if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE", - exeasync, - sizeof(exeasync)/sizeof(exeasync[0]), - inifile)) { - return FALSE; - } - - WCHAR exefullpath[MAX_PATH + 1] = { L'\0' }; - wcsncpy(exefullpath, installationDir, MAX_PATH); - if (!PathAppendSafe(exefullpath, exefile)) { - return false; - } - - WCHAR dlogFile[MAX_PATH + 1]; - if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) { - return FALSE; - } - - WCHAR slogFile[MAX_PATH + 1] = { L'\0' }; - wcsncpy(slogFile, updateInfoDir, MAX_PATH); - if (!PathAppendSafe(slogFile, L"update.log")) { - return FALSE; - } - - WCHAR dummyArg[14] = { L'\0' }; - wcsncpy(dummyArg, L"argv0ignored ", sizeof(dummyArg) / sizeof(dummyArg[0]) - 1); - - size_t len = wcslen(exearg) + wcslen(dummyArg); - WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR)); - if (!cmdline) { - return FALSE; - } - - wcsncpy(cmdline, dummyArg, len); - wcscat(cmdline, exearg); - - if (forceSync || - !_wcsnicmp(exeasync, L"false", 6) || - !_wcsnicmp(exeasync, L"0", 2)) { - async = false; - } - - // We want to launch the post update helper app to update the Windows - // registry even if there is a failure with removing the uninstall.update - // file or copying the update.log file. - CopyFileW(slogFile, dlogFile, false); - - STARTUPINFOW si = {sizeof(si), 0}; - si.lpDesktop = L""; - PROCESS_INFORMATION pi = {0}; - - bool ok; - if (userToken) { - ok = CreateProcessAsUserW(userToken, - exefullpath, - cmdline, - nullptr, // no special security attributes - nullptr, // no special thread attributes - false, // don't inherit filehandles - 0, // No special process creation flags - nullptr, // inherit my environment - workingDirectory, - &si, - &pi); - } else { - ok = CreateProcessW(exefullpath, - cmdline, - nullptr, // no special security attributes - nullptr, // no special thread attributes - false, // don't inherit filehandles - 0, // No special process creation flags - nullptr, // inherit my environment - workingDirectory, - &si, - &pi); - } - free(cmdline); - if (ok) { - if (!async) - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - return ok; + WCHAR workingDirectory[MAX_PATH + 1] = { L'\0' }; + wcsncpy(workingDirectory, installationDir, MAX_PATH); + + // Launch helper.exe to perform post processing (e.g. registry and log file + // modifications) for the update. + WCHAR inifile[MAX_PATH + 1] = { L'\0' }; + wcsncpy(inifile, installationDir, MAX_PATH); + if (!PathAppendSafe(inifile, L"updater.ini")) + { + return FALSE; + } + + WCHAR exefile[MAX_PATH + 1]; + WCHAR exearg[MAX_PATH + 1]; + WCHAR exeasync[10]; + bool async = true; + if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", nullptr, + exefile, MAX_PATH + 1, inifile)) + { + return FALSE; + } + + if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", nullptr, exearg, + MAX_PATH + 1, inifile)) + { + return FALSE; + } + + if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE", + exeasync, + sizeof(exeasync)/sizeof(exeasync[0]), + inifile)) + { + return FALSE; + } + + WCHAR exefullpath[MAX_PATH + 1] = { L'\0' }; + wcsncpy(exefullpath, installationDir, MAX_PATH); + if (!PathAppendSafe(exefullpath, exefile)) + { + return false; + } + + WCHAR dlogFile[MAX_PATH + 1]; + if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) + { + return FALSE; + } + + WCHAR slogFile[MAX_PATH + 1] = { L'\0' }; + wcsncpy(slogFile, updateInfoDir, MAX_PATH); + if (!PathAppendSafe(slogFile, L"update.log")) + { + return FALSE; + } + + WCHAR dummyArg[14] = { L'\0' }; + wcsncpy(dummyArg, L"argv0ignored ", sizeof(dummyArg) / sizeof(dummyArg[0]) - 1); + + size_t len = wcslen(exearg) + wcslen(dummyArg); + WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR)); + if (!cmdline) + { + return FALSE; + } + + wcsncpy(cmdline, dummyArg, len); + wcscat(cmdline, exearg); + + if (forceSync || + !_wcsnicmp(exeasync, L"false", 6) || + !_wcsnicmp(exeasync, L"0", 2)) + { + async = false; + } + + // We want to launch the post update helper app to update the Windows + // registry even if there is a failure with removing the uninstall.update + // file or copying the update.log file. + CopyFileW(slogFile, dlogFile, false); + + STARTUPINFOW si = {sizeof(si), 0}; + si.lpDesktop = L""; + PROCESS_INFORMATION pi = {0}; + + bool ok; + if (userToken) + { + ok = CreateProcessAsUserW(userToken, + exefullpath, + cmdline, + nullptr, // no special security attributes + nullptr, // no special thread attributes + false, // don't inherit filehandles + 0, // No special process creation flags + nullptr, // inherit my environment + workingDirectory, + &si, + &pi); + } + else + { + ok = CreateProcessW(exefullpath, + cmdline, + nullptr, // no special security attributes + nullptr, // no special thread attributes + false, // don't inherit filehandles + 0, // No special process creation flags + nullptr, // inherit my environment + workingDirectory, + &si, + &pi); + } + free(cmdline); + if (ok) + { + if (!async) + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + return ok; } /** @@ -193,89 +209,96 @@ LaunchWinPostProcess(const WCHAR *installationDir, BOOL StartServiceUpdate(LPCWSTR installDir) { - // Get a handle to the local computer SCM database - SC_HANDLE manager = OpenSCManager(nullptr, nullptr, - SC_MANAGER_ALL_ACCESS); - if (!manager) { - return FALSE; - } - - // Open the service - SC_HANDLE svc = OpenServiceW(manager, SVC_NAME, - SERVICE_ALL_ACCESS); - if (!svc) { + // Get a handle to the local computer SCM database + SC_HANDLE manager = OpenSCManager(nullptr, nullptr, + SC_MANAGER_ALL_ACCESS); + if (!manager) + { + return FALSE; + } + + // Open the service + SC_HANDLE svc = OpenServiceW(manager, SVC_NAME, + SERVICE_ALL_ACCESS); + if (!svc) + { + CloseServiceHandle(manager); + return FALSE; + } + + // If we reach here, then the service is installed, so + // proceed with upgrading it. + CloseServiceHandle(manager); - return FALSE; - } - // If we reach here, then the service is installed, so - // proceed with upgrading it. + // The service exists and we opened it, get the config bytes needed + DWORD bytesNeeded; + if (!QueryServiceConfigW(svc, nullptr, 0, &bytesNeeded) && + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseServiceHandle(svc); + return FALSE; + } - CloseServiceHandle(manager); + // Get the service config information, in particular we want the binary + // path of the service. + std::unique_ptr<char[]> serviceConfigBuffer = std::make_unique<char[]>(bytesNeeded); + if (!QueryServiceConfigW(svc, + reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()), + bytesNeeded, &bytesNeeded)) + { + CloseServiceHandle(svc); + return FALSE; + } - // The service exists and we opened it, get the config bytes needed - DWORD bytesNeeded; - if (!QueryServiceConfigW(svc, nullptr, 0, &bytesNeeded) && - GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - CloseServiceHandle(svc); - return FALSE; - } - - // Get the service config information, in particular we want the binary - // path of the service. - std::unique_ptr<char[]> serviceConfigBuffer = std::make_unique<char[]>(bytesNeeded); - if (!QueryServiceConfigW(svc, - reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()), - bytesNeeded, &bytesNeeded)) { CloseServiceHandle(svc); - return FALSE; - } - - CloseServiceHandle(svc); - - QUERY_SERVICE_CONFIGW &serviceConfig = - *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()); - - PathUnquoteSpacesW(serviceConfig.lpBinaryPathName); - - // Obtain the temp path of the maintenance service binary - WCHAR tmpService[MAX_PATH + 1] = { L'\0' }; - if (!PathGetSiblingFilePath(tmpService, serviceConfig.lpBinaryPathName, - L"maintenanceservice_tmp.exe")) { - return FALSE; - } - - // Get the new maintenance service path from the install dir - WCHAR newMaintServicePath[MAX_PATH + 1] = { L'\0' }; - wcsncpy(newMaintServicePath, installDir, MAX_PATH); - PathAppendSafe(newMaintServicePath, - L"maintenanceservice.exe"); - - // Copy the temp file in alongside the maintenance service. - // This is a requirement for maintenance service upgrades. - if (!CopyFileW(newMaintServicePath, tmpService, FALSE)) { - return FALSE; - } - - // Start the upgrade comparison process - STARTUPINFOW si = {0}; - si.cb = sizeof(STARTUPINFOW); - // No particular desktop because no UI - si.lpDesktop = L""; - PROCESS_INFORMATION pi = {0}; - WCHAR cmdLine[64] = { '\0' }; - wcsncpy(cmdLine, L"dummyparam.exe upgrade", - sizeof(cmdLine) / sizeof(cmdLine[0]) - 1); - BOOL svcUpdateProcessStarted = CreateProcessW(tmpService, - cmdLine, - nullptr, nullptr, FALSE, - 0, - nullptr, installDir, &si, &pi); - if (svcUpdateProcessStarted) { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - return svcUpdateProcessStarted; + + QUERY_SERVICE_CONFIGW &serviceConfig = + *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()); + + PathUnquoteSpacesW(serviceConfig.lpBinaryPathName); + + // Obtain the temp path of the maintenance service binary + WCHAR tmpService[MAX_PATH + 1] = { L'\0' }; + if (!PathGetSiblingFilePath(tmpService, serviceConfig.lpBinaryPathName, + L"maintenanceservice_tmp.exe")) + { + return FALSE; + } + + // Get the new maintenance service path from the install dir + WCHAR newMaintServicePath[MAX_PATH + 1] = { L'\0' }; + wcsncpy(newMaintServicePath, installDir, MAX_PATH); + PathAppendSafe(newMaintServicePath, + L"maintenanceservice.exe"); + + // Copy the temp file in alongside the maintenace service. + // This is a requirement for maintenance service upgrades. + if (!CopyFileW(newMaintServicePath, tmpService, FALSE)) + { + return FALSE; + } + + // Start the upgrade comparison process + STARTUPINFOW si = {0}; + si.cb = sizeof(STARTUPINFOW); + // No particular desktop because no UI + si.lpDesktop = L""; + PROCESS_INFORMATION pi = {0}; + WCHAR cmdLine[64] = { '\0' }; + wcsncpy(cmdLine, L"dummyparam.exe upgrade", + sizeof(cmdLine) / sizeof(cmdLine[0]) - 1); + BOOL svcUpdateProcessStarted = CreateProcessW(tmpService, + cmdLine, + nullptr, nullptr, FALSE, + 0, + nullptr, installDir, &si, &pi); + if (svcUpdateProcessStarted) + { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + return svcUpdateProcessStarted; } #endif @@ -295,47 +318,54 @@ StartServiceUpdate(LPCWSTR installDir) DWORD StartServiceCommand(int argc, LPCWSTR* argv) { - DWORD lastState = WaitForServiceStop(SVC_NAME, 5); - if (lastState != SERVICE_STOPPED) { - return 20000 + lastState; - } - - // Get a handle to the SCM database. - SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr, - SC_MANAGER_CONNECT | - SC_MANAGER_ENUMERATE_SERVICE); - if (!serviceManager) { - return 17001; - } - - // Get a handle to the service. - SC_HANDLE service = OpenServiceW(serviceManager, - SVC_NAME, - SERVICE_START); - if (!service) { + DWORD lastState = WaitForServiceStop(SVC_NAME, 5); + if (lastState != SERVICE_STOPPED) + { + return 20000 + lastState; + } + + // Get a handle to the SCM database. + SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr, + SC_MANAGER_CONNECT | + SC_MANAGER_ENUMERATE_SERVICE); + if (!serviceManager) + { + return 17001; + } + + // Get a handle to the service. + SC_HANDLE service = OpenServiceW(serviceManager, + SVC_NAME, + SERVICE_START); + if (!service) + { + CloseServiceHandle(serviceManager); + return 17002; + } + + // Wait at most 5 seconds trying to start the service in case of errors + // like ERROR_SERVICE_DATABASE_LOCKED or ERROR_SERVICE_REQUEST_TIMEOUT. + const DWORD maxWaitMS = 5000; + DWORD currentWaitMS = 0; + DWORD lastError = ERROR_SUCCESS; + while (currentWaitMS < maxWaitMS) + { + BOOL result = StartServiceW(service, argc, argv); + if (result) + { + lastError = ERROR_SUCCESS; + break; + } + else + { + lastError = GetLastError(); + } + Sleep(100); + currentWaitMS += 100; + } + CloseServiceHandle(service); CloseServiceHandle(serviceManager); - return 17002; - } - - // Wait at most 5 seconds trying to start the service in case of errors - // like ERROR_SERVICE_DATABASE_LOCKED or ERROR_SERVICE_REQUEST_TIMEOUT. - const DWORD maxWaitMS = 5000; - DWORD currentWaitMS = 0; - DWORD lastError = ERROR_SUCCESS; - while (currentWaitMS < maxWaitMS) { - BOOL result = StartServiceW(service, argc, argv); - if (result) { - lastError = ERROR_SUCCESS; - break; - } else { - lastError = GetLastError(); - } - Sleep(100); - currentWaitMS += 100; - } - CloseServiceHandle(service); - CloseServiceHandle(serviceManager); - return lastError; + return lastError; } #ifndef ONLY_SERVICE_LAUNCHING @@ -353,22 +383,23 @@ StartServiceCommand(int argc, LPCWSTR* argv) DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv) { - // The service command is the same as the updater.exe command line except - // it has 2 extra args: 1) The Path to updater.exe, and 2) the command - // being executed which is "software-update" - LPCWSTR *updaterServiceArgv = new LPCWSTR[argc + 2]; - updaterServiceArgv[0] = L"MozillaMaintenance"; - updaterServiceArgv[1] = L"software-update"; - - for (int i = 0; i < argc; ++i) { - updaterServiceArgv[i + 2] = argv[i]; - } - - // Execute the service command by starting the service with - // the passed in arguments. - DWORD ret = StartServiceCommand(argc + 2, updaterServiceArgv); - delete[] updaterServiceArgv; - return ret; + // The service command is the same as the updater.exe command line except + // it has 2 extra args: 1) The Path to updater.exe, and 2) the command + // being executed which is "software-update" + LPCWSTR *updaterServiceArgv = new LPCWSTR[argc + 2]; + updaterServiceArgv[0] = L"MozillaMaintenance"; + updaterServiceArgv[1] = L"software-update"; + + for (int i = 0; i < argc; ++i) + { + updaterServiceArgv[i + 2] = argv[i]; + } + + // Execute the service command by starting the service with + // the passed in arguments. + DWORD ret = StartServiceCommand(argc + 2, updaterServiceArgv); + delete[] updaterServiceArgv; + return ret; } /** @@ -381,11 +412,12 @@ LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv) BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra) { - if (wcslen(base) + wcslen(extra) >= MAX_PATH) { - return FALSE; - } + if (wcslen(base) + wcslen(extra) >= MAX_PATH) + { + return FALSE; + } - return PathAppendW(base, extra); + return PathAppendW(base, extra); } /** @@ -398,24 +430,26 @@ PathAppendSafe(LPWSTR base, LPCWSTR extra) BOOL WriteStatusPending(LPCWSTR updateDirPath) { - WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' }; - wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH); - if (!PathAppendSafe(updateStatusFilePath, L"update.status")) { - return FALSE; - } - - const char pending[] = "pending"; - HANDLE statusFile = CreateFileW(updateStatusFilePath, GENERIC_WRITE, 0, - nullptr, CREATE_ALWAYS, 0, nullptr); - if (statusFile == INVALID_HANDLE_VALUE) { - return FALSE; - } - - DWORD wrote; - BOOL ok = WriteFile(statusFile, pending, - sizeof(pending) - 1, &wrote, nullptr); - CloseHandle(statusFile); - return ok && (wrote == sizeof(pending) - 1); + WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' }; + wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH); + if (!PathAppendSafe(updateStatusFilePath, L"update.status")) + { + return FALSE; + } + + const char pending[] = "pending"; + HANDLE statusFile = CreateFileW(updateStatusFilePath, GENERIC_WRITE, 0, + nullptr, CREATE_ALWAYS, 0, nullptr); + if (statusFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + DWORD wrote; + BOOL ok = WriteFile(statusFile, pending, + sizeof(pending) - 1, &wrote, nullptr); + CloseHandle(statusFile); + return ok && (wrote == sizeof(pending) - 1); } /** @@ -427,26 +461,28 @@ WriteStatusPending(LPCWSTR updateDirPath) BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode) { - WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' }; - wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH); - if (!PathAppendSafe(updateStatusFilePath, L"update.status")) { - return FALSE; - } - - HANDLE statusFile = CreateFileW(updateStatusFilePath, GENERIC_WRITE, 0, - nullptr, CREATE_ALWAYS, 0, nullptr); - if (statusFile == INVALID_HANDLE_VALUE) { - return FALSE; - } - char failure[32]; - sprintf(failure, "failed: %d", errorCode); - - DWORD toWrite = strlen(failure); - DWORD wrote; - BOOL ok = WriteFile(statusFile, failure, - toWrite, &wrote, nullptr); - CloseHandle(statusFile); - return ok && wrote == toWrite; + WCHAR updateStatusFilePath[MAX_PATH + 1] = { L'\0' }; + wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH); + if (!PathAppendSafe(updateStatusFilePath, L"update.status")) + { + return FALSE; + } + + HANDLE statusFile = CreateFileW(updateStatusFilePath, GENERIC_WRITE, 0, + nullptr, CREATE_ALWAYS, 0, nullptr); + if (statusFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + char failure[32]; + sprintf(failure, "failed: %d", errorCode); + + DWORD toWrite = strlen(failure); + DWORD wrote; + BOOL ok = WriteFile(statusFile, failure, + toWrite, &wrote, nullptr); + CloseHandle(statusFile); + return ok && wrote == toWrite; } #endif @@ -486,101 +522,109 @@ WriteStatusFailure(LPCWSTR updateDirPath, int errorCode) DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds) { - // 0x000000CF is defined above to be not set - DWORD lastServiceState = 0x000000CF; - - // Get a handle to the SCM database. - SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr, - SC_MANAGER_CONNECT | - SC_MANAGER_ENUMERATE_SERVICE); - if (!serviceManager) { - DWORD lastError = GetLastError(); - switch(lastError) { - case ERROR_ACCESS_DENIED: - return 0x000000FD; - case ERROR_DATABASE_DOES_NOT_EXIST: - return 0x000000FE; - default: - return 0x000000FF; - } - } - - // Get a handle to the service. - SC_HANDLE service = OpenServiceW(serviceManager, - serviceName, - SERVICE_QUERY_STATUS); - if (!service) { - DWORD lastError = GetLastError(); - CloseServiceHandle(serviceManager); - switch(lastError) { - case ERROR_ACCESS_DENIED: - return 0x000000EB; - case ERROR_INVALID_HANDLE: - return 0x000000EC; - case ERROR_INVALID_NAME: - return 0x000000ED; - case ERROR_SERVICE_DOES_NOT_EXIST: - return 0x000000EE; - default: - return 0x000000EF; - } - } - - DWORD currentWaitMS = 0; - SERVICE_STATUS_PROCESS ssp; - ssp.dwCurrentState = lastServiceState; - while (currentWaitMS < maxWaitSeconds * 1000) { - DWORD bytesNeeded; - if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, - sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) { - DWORD lastError = GetLastError(); - switch (lastError) { - case ERROR_INVALID_HANDLE: - ssp.dwCurrentState = 0x000000D9; - break; - case ERROR_ACCESS_DENIED: - ssp.dwCurrentState = 0x000000DA; - break; - case ERROR_INSUFFICIENT_BUFFER: - ssp.dwCurrentState = 0x000000DB; - break; - case ERROR_INVALID_PARAMETER: - ssp.dwCurrentState = 0x000000DC; - break; - case ERROR_INVALID_LEVEL: - ssp.dwCurrentState = 0x000000DD; - break; - case ERROR_SHUTDOWN_IN_PROGRESS: - ssp.dwCurrentState = 0x000000DE; - break; - // These 3 errors can occur when the service is not yet stopped but - // it is stopping. - case ERROR_INVALID_SERVICE_CONTROL: - case ERROR_SERVICE_CANNOT_ACCEPT_CTRL: - case ERROR_SERVICE_NOT_ACTIVE: - currentWaitMS += 50; - Sleep(50); - continue; - default: - ssp.dwCurrentState = 0x000000DF; - } + // 0x000000CF is defined above to be not set + DWORD lastServiceState = 0x000000CF; + + // Get a handle to the SCM database. + SC_HANDLE serviceManager = OpenSCManager(nullptr, nullptr, + SC_MANAGER_CONNECT | + SC_MANAGER_ENUMERATE_SERVICE); + if (!serviceManager) + { + DWORD lastError = GetLastError(); + switch (lastError) + { + case ERROR_ACCESS_DENIED: + return 0x000000FD; + case ERROR_DATABASE_DOES_NOT_EXIST: + return 0x000000FE; + default: + return 0x000000FF; + } + } - // We couldn't query the status so just break out - break; + // Get a handle to the service. + SC_HANDLE service = OpenServiceW(serviceManager, + serviceName, + SERVICE_QUERY_STATUS); + if (!service) + { + DWORD lastError = GetLastError(); + CloseServiceHandle(serviceManager); + switch (lastError) + { + case ERROR_ACCESS_DENIED: + return 0x000000EB; + case ERROR_INVALID_HANDLE: + return 0x000000EC; + case ERROR_INVALID_NAME: + return 0x000000ED; + case ERROR_SERVICE_DOES_NOT_EXIST: + return 0x000000EE; + default: + return 0x000000EF; + } } - // The service is already in use. - if (ssp.dwCurrentState == SERVICE_STOPPED) { - break; + DWORD currentWaitMS = 0; + SERVICE_STATUS_PROCESS ssp; + ssp.dwCurrentState = lastServiceState; + while (currentWaitMS < maxWaitSeconds * 1000) + { + DWORD bytesNeeded; + if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, + sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) + { + DWORD lastError = GetLastError(); + switch (lastError) + { + case ERROR_INVALID_HANDLE: + ssp.dwCurrentState = 0x000000D9; + break; + case ERROR_ACCESS_DENIED: + ssp.dwCurrentState = 0x000000DA; + break; + case ERROR_INSUFFICIENT_BUFFER: + ssp.dwCurrentState = 0x000000DB; + break; + case ERROR_INVALID_PARAMETER: + ssp.dwCurrentState = 0x000000DC; + break; + case ERROR_INVALID_LEVEL: + ssp.dwCurrentState = 0x000000DD; + break; + case ERROR_SHUTDOWN_IN_PROGRESS: + ssp.dwCurrentState = 0x000000DE; + break; + // These 3 errors can occur when the service is not yet stopped but + // it is stopping. + case ERROR_INVALID_SERVICE_CONTROL: + case ERROR_SERVICE_CANNOT_ACCEPT_CTRL: + case ERROR_SERVICE_NOT_ACTIVE: + currentWaitMS += 50; + Sleep(50); + continue; + default: + ssp.dwCurrentState = 0x000000DF; + } + + // We couldn't query the status so just break out + break; + } + + // The service is already in use. + if (ssp.dwCurrentState == SERVICE_STOPPED) + { + break; + } + currentWaitMS += 50; + Sleep(50); } - currentWaitMS += 50; - Sleep(50); - } - lastServiceState = ssp.dwCurrentState; - CloseServiceHandle(service); - CloseServiceHandle(serviceManager); - return lastServiceState; + lastServiceState = ssp.dwCurrentState; + CloseServiceHandle(service); + CloseServiceHandle(serviceManager); + return lastServiceState; } #ifndef ONLY_SERVICE_LAUNCHING @@ -597,28 +641,33 @@ WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds) DWORD IsProcessRunning(LPCWSTR filename) { - // Take a snapshot of all processes in the system. - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (INVALID_HANDLE_VALUE == snapshot) { - return GetLastError(); - } - - PROCESSENTRY32W processEntry; - processEntry.dwSize = sizeof(PROCESSENTRY32W); - if (!Process32FirstW(snapshot, &processEntry)) { - DWORD lastError = GetLastError(); - CloseHandle(snapshot); - return lastError; - } + // Take a snapshot of all processes in the system. + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (INVALID_HANDLE_VALUE == snapshot) + { + return GetLastError(); + } - do { - if (wcsicmp(filename, processEntry.szExeFile) == 0) { - CloseHandle(snapshot); - return ERROR_SUCCESS; + PROCESSENTRY32W processEntry; + processEntry.dwSize = sizeof(PROCESSENTRY32W); + if (!Process32FirstW(snapshot, &processEntry)) + { + DWORD lastError = GetLastError(); + CloseHandle(snapshot); + return lastError; } - } while (Process32NextW(snapshot, &processEntry)); - CloseHandle(snapshot); - return ERROR_NOT_FOUND; + + do + { + if (wcsicmp(filename, processEntry.szExeFile) == 0) + { + CloseHandle(snapshot); + return ERROR_SUCCESS; + } + } + while (Process32NextW(snapshot, &processEntry)); + CloseHandle(snapshot); + return ERROR_NOT_FOUND; } /** @@ -634,20 +683,23 @@ IsProcessRunning(LPCWSTR filename) DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds) { - DWORD applicationRunningError = WAIT_TIMEOUT; - for(DWORD i = 0; i < maxSeconds; i++) { - DWORD applicationRunningError = IsProcessRunning(filename); - if (ERROR_NOT_FOUND == applicationRunningError) { - return ERROR_SUCCESS; + DWORD applicationRunningError = WAIT_TIMEOUT; + for (DWORD i = 0; i < maxSeconds; i++) + { + DWORD applicationRunningError = IsProcessRunning(filename); + if (ERROR_NOT_FOUND == applicationRunningError) + { + return ERROR_SUCCESS; + } + Sleep(1000); } - Sleep(1000); - } - if (ERROR_SUCCESS == applicationRunningError) { - return WAIT_TIMEOUT; - } + if (ERROR_SUCCESS == applicationRunningError) + { + return WAIT_TIMEOUT; + } - return applicationRunningError; + return applicationRunningError; } /** @@ -658,16 +710,17 @@ WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds) BOOL DoesFallbackKeyExist() { - HKEY testOnlyFallbackKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - TEST_ONLY_FALLBACK_KEY_PATH, 0, - KEY_READ | KEY_WOW64_64KEY, - &testOnlyFallbackKey) != ERROR_SUCCESS) { - return FALSE; - } - - RegCloseKey(testOnlyFallbackKey); - return TRUE; + HKEY testOnlyFallbackKey; + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TEST_ONLY_FALLBACK_KEY_PATH, 0, + KEY_READ | KEY_WOW64_64KEY, + &testOnlyFallbackKey) != ERROR_SUCCESS) + { + return FALSE; + } + + RegCloseKey(testOnlyFallbackKey); + return TRUE; } #endif @@ -681,15 +734,16 @@ DoesFallbackKeyExist() BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal) { - WCHAR rootPath[MAX_PATH + 1] = { L'\0' }; - if (wcslen(file) > MAX_PATH) { - return FALSE; - } - - wcsncpy(rootPath, file, MAX_PATH); - PathStripToRootW(rootPath); - isLocal = GetDriveTypeW(rootPath) == DRIVE_FIXED; - return TRUE; + WCHAR rootPath[MAX_PATH + 1] = { L'\0' }; + if (wcslen(file) > MAX_PATH) + { + return FALSE; + } + + wcsncpy(rootPath, file, MAX_PATH); + PathStripToRootW(rootPath); + isLocal = GetDriveTypeW(rootPath) == DRIVE_FIXED; + return TRUE; } @@ -704,11 +758,11 @@ IsLocalFile(LPCWSTR file, BOOL &isLocal) static BOOL GetDWORDValue(HKEY key, LPCWSTR valueName, DWORD &retValue) { - DWORD regDWORDValueSize = sizeof(DWORD); - LONG retCode = RegQueryValueExW(key, valueName, 0, nullptr, - reinterpret_cast<LPBYTE>(&retValue), - ®DWORDValueSize); - return ERROR_SUCCESS == retCode; + DWORD regDWORDValueSize = sizeof(DWORD); + LONG retCode = RegQueryValueExW(key, valueName, 0, nullptr, + reinterpret_cast<LPBYTE>(&retValue), + ®DWORDValueSize); + return ERROR_SUCCESS == retCode; } /** @@ -723,29 +777,31 @@ GetDWORDValue(HKEY key, LPCWSTR valueName, DWORD &retValue) BOOL IsUnpromptedElevation(BOOL &isUnpromptedElevation) { - if (!UACHelper::CanUserElevate()) { - return FALSE; - } - - LPCWSTR UACBaseRegKey = - L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; - HKEY baseKey; - LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - UACBaseRegKey, 0, - KEY_READ, &baseKey); - if (retCode != ERROR_SUCCESS) { - return FALSE; - } - - DWORD consent; - DWORD secureDesktop = 0; - BOOL success = GetDWORDValue(baseKey, L"ConsentPromptBehaviorAdmin", - consent); - success = success && - GetDWORDValue(baseKey, L"PromptOnSecureDesktop", secureDesktop); - isUnpromptedElevation = !consent && !secureDesktop; - - RegCloseKey(baseKey); - return success; + if (!UACHelper::CanUserElevate()) + { + return FALSE; + } + + LPCWSTR UACBaseRegKey = + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; + HKEY baseKey; + LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + UACBaseRegKey, 0, + KEY_READ, &baseKey); + if (retCode != ERROR_SUCCESS) + { + return FALSE; + } + + DWORD consent; + DWORD secureDesktop = 0; + BOOL success = GetDWORDValue(baseKey, L"ConsentPromptBehaviorAdmin", + consent); + success = success && + GetDWORDValue(baseKey, L"PromptOnSecureDesktop", secureDesktop); + isUnpromptedElevation = !consent && !secureDesktop; + + RegCloseKey(baseKey); + return success; } #endif diff --git a/onlineupdate/source/update/common/updatelogging.cxx b/onlineupdate/source/update/common/updatelogging.cxx index 22a74e17e953..ed055cd47072 100644 --- a/onlineupdate/source/update/common/updatelogging.cxx +++ b/onlineupdate/source/update/common/updatelogging.cxx @@ -25,60 +25,61 @@ void UpdateLog::Init(NS_tchar* sourcePathParam, const NS_tchar* alternateFileName, bool append) { - if (logFP) - return; + if (logFP) + return; - sourcePath = sourcePathParam; - NS_tchar logFile[MAXPATHLEN]; - NS_tsnprintf(logFile, sizeof(logFile)/sizeof(logFile[0]), - NS_T("%s/%s"), sourcePathParam, fileName); - - if (alternateFileName && NS_taccess(logFile, F_OK)) { + sourcePath = sourcePathParam; + NS_tchar logFile[MAXPATHLEN]; NS_tsnprintf(logFile, sizeof(logFile)/sizeof(logFile[0]), - NS_T("%s/%s"), sourcePathParam, alternateFileName); - } + NS_T("%s/%s"), sourcePathParam, fileName); + + if (alternateFileName && NS_taccess(logFile, F_OK)) + { + NS_tsnprintf(logFile, sizeof(logFile)/sizeof(logFile[0]), + NS_T("%s/%s"), sourcePathParam, alternateFileName); + } - logFP = NS_tfopen(logFile, append ? NS_T("a") : NS_T("w")); + logFP = NS_tfopen(logFile, append ? NS_T("a") : NS_T("w")); } void UpdateLog::Finish() { - if (!logFP) - return; + if (!logFP) + return; - fclose(logFP); - logFP = nullptr; + fclose(logFP); + logFP = nullptr; } void UpdateLog::Flush() { - if (!logFP) - return; + if (!logFP) + return; - fflush(logFP); + fflush(logFP); } void UpdateLog::Printf(const char *fmt, ... ) { - if (!logFP) - return; - - va_list ap; - va_start(ap, fmt); - vfprintf(logFP, fmt, ap); - fprintf(logFP, "\n"); - va_end(ap); + if (!logFP) + return; + + va_list ap; + va_start(ap, fmt); + vfprintf(logFP, fmt, ap); + fprintf(logFP, "\n"); + va_end(ap); } void UpdateLog::WarnPrintf(const char *fmt, ... ) { - if (!logFP) - return; - - va_list ap; - va_start(ap, fmt); - fprintf(logFP, "*** Warning: "); - vfprintf(logFP, fmt, ap); - fprintf(logFP, "***\n"); - va_end(ap); + if (!logFP) + return; + + va_list ap; + va_start(ap, fmt); + fprintf(logFP, "*** Warning: "); + vfprintf(logFP, fmt, ap); + fprintf(logFP, "***\n"); + va_end(ap); } diff --git a/onlineupdate/source/update/common/updatelogging.h b/onlineupdate/source/update/common/updatelogging.h index 8cdf0396df95..591cb3f4f2c2 100644 --- a/onlineupdate/source/update/common/updatelogging.h +++ b/onlineupdate/source/update/common/updatelogging.h @@ -11,28 +11,28 @@ class UpdateLog { public: - static UpdateLog & GetPrimaryLog() - { - static UpdateLog primaryLog; - return primaryLog; - } - - void Init(NS_tchar* sourcePath, const NS_tchar* fileName, - const NS_tchar* alternateFileName, bool append); - void Finish(); - void Flush(); - void Printf(const char *fmt, ... ); - void WarnPrintf(const char *fmt, ... ); - - ~UpdateLog() - { - Finish(); - } + static UpdateLog & GetPrimaryLog() + { + static UpdateLog primaryLog; + return primaryLog; + } + + void Init(NS_tchar* sourcePath, const NS_tchar* fileName, + const NS_tchar* alternateFileName, bool append); + void Finish(); + void Flush(); + void Printf(const char *fmt, ... ); + void WarnPrintf(const char *fmt, ... ); + + ~UpdateLog() + { + Finish(); + } protected: - UpdateLog(); - FILE *logFP; - NS_tchar* sourcePath; + UpdateLog(); + FILE *logFP; + NS_tchar* sourcePath; }; #define LOG_WARN(args) UpdateLog::GetPrimaryLog().WarnPrintf args diff --git a/onlineupdate/source/update/common/win_dirent.h b/onlineupdate/source/update/common/win_dirent.h index a2281557e25a..ee2ab6c67bd5 100644 --- a/onlineupdate/source/update/common/win_dirent.h +++ b/onlineupdate/source/update/common/win_dirent.h @@ -9,16 +9,18 @@ #ifdef _WIN32 #include <windows.h> -struct DIR { - explicit DIR(const WCHAR* path); - ~DIR(); - HANDLE findHandle; - WCHAR name[MAX_PATH]; +struct DIR +{ + explicit DIR(const WCHAR* path); + ~DIR(); + HANDLE findHandle; + WCHAR name[MAX_PATH]; }; -struct dirent { - dirent(); - WCHAR d_name[MAX_PATH]; +struct dirent +{ + dirent(); + WCHAR d_name[MAX_PATH]; }; DIR* opendir(const WCHAR* path); diff --git a/onlineupdate/source/update/updater/archivereader.cxx b/onlineupdate/source/update/updater/archivereader.cxx index e62b65b1e4ba..b0395d14094e 100644 --- a/onlineupdate/source/update/updater/archivereader.cxx +++ b/onlineupdate/source/update/updater/archivereader.cxx @@ -52,18 +52,19 @@ template<uint32_t SIZE> int VerifyLoadedCert(MarFile *archive, const uint8_t (&certData)[SIZE]) { - (void)archive; - (void)certData; + (void)archive; + (void)certData; #ifdef VERIFY_MAR_SIGNATURE - const uint32_t size = SIZE; - const uint8_t* const data = &certData[0]; - if (mar_verify_signatures(archive, &data, &size, 1)) { - return CERT_VERIFY_ERROR; - } + const uint32_t size = SIZE; + const uint8_t* const data = &certData[0]; + if (mar_verify_signatures(archive, &data, &size, 1)) + { + return CERT_VERIFY_ERROR; + } #endif - return OK; + return OK; } /** @@ -77,22 +78,24 @@ VerifyLoadedCert(MarFile *archive, const uint8_t (&certData)[SIZE]) int ArchiveReader::VerifySignature() { - if (!mArchive) { - return ARCHIVE_NOT_OPEN; - } + if (!mArchive) + { + return ARCHIVE_NOT_OPEN; + } #ifndef VERIFY_MAR_SIGNATURE - return OK; + return OK; #else #ifdef TEST_UPDATER - int rv = VerifyLoadedCert(mArchive, xpcshellCertData); + int rv = VerifyLoadedCert(mArchive, xpcshellCertData); #else - int rv = VerifyLoadedCert(mArchive, primaryCertData); - if (rv != OK) { - rv = VerifyLoadedCert(mArchive, secondaryCertData); - } + int rv = VerifyLoadedCert(mArchive, primaryCertData); + if (rv != OK) + { + rv = VerifyLoadedCert(mArchive, secondaryCertData); + } #endif - return rv; + return rv; #endif } @@ -121,203 +124,224 @@ int ArchiveReader::VerifyProductInformation(const char *MARChannelID, const char *appVersion) { - if (!mArchive) { - return ARCHIVE_NOT_OPEN; - } - - ProductInformationBlock productInfoBlock; - int rv = mar_read_product_info_block(mArchive, - &productInfoBlock); - if (rv != OK) { - return COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR; - } - - // Only check the MAR channel name if specified, it should be passed in from - // the update-settings.ini file. - if (MARChannelID && strlen(MARChannelID)) { - // Check for at least one match in the comma separated list of values. - const char *delimiter = " ,\t"; - // Make a copy of the string in case a read only memory buffer - // was specified. strtok modifies the input buffer. - char channelCopy[512] = { 0 }; - strncpy(channelCopy, MARChannelID, sizeof(channelCopy) - 1); - char *channel = strtok(channelCopy, delimiter); - rv = MAR_CHANNEL_MISMATCH_ERROR; - while(channel) { - if (!strcmp(channel, productInfoBlock.MARChannelID)) { - rv = OK; - break; - } - channel = strtok(nullptr, delimiter); + if (!mArchive) + { + return ARCHIVE_NOT_OPEN; + } + + ProductInformationBlock productInfoBlock; + int rv = mar_read_product_info_block(mArchive, + &productInfoBlock); + if (rv != OK) + { + return COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR; + } + + // Only check the MAR channel name if specified, it should be passed in from + // the update-settings.ini file. + if (MARChannelID && strlen(MARChannelID)) + { + // Check for at least one match in the comma separated list of values. + const char *delimiter = " ,\t"; + // Make a copy of the string in case a read only memory buffer + // was specified. strtok modifies the input buffer. + char channelCopy[512] = { 0 }; + strncpy(channelCopy, MARChannelID, sizeof(channelCopy) - 1); + char *channel = strtok(channelCopy, delimiter); + rv = MAR_CHANNEL_MISMATCH_ERROR; + while (channel) + { + if (!strcmp(channel, productInfoBlock.MARChannelID)) + { + rv = OK; + break; + } + channel = strtok(nullptr, delimiter); + } } - } - - if (rv == OK) { - /* Compare both versions to ensure we don't have a downgrade - -1 if appVersion is older than productInfoBlock.productVersion - 1 if appVersion is newer than productInfoBlock.productVersion - 0 if appVersion is the same as productInfoBlock.productVersion - This even works with strings like: - - 12.0a1 being older than 12.0a2 - - 12.0a2 being older than 12.0b1 - - 12.0a1 being older than 12.0 - - 12.0 being older than 12.1a1 */ - int versionCompareResult = - mozilla::CompareVersions(appVersion, productInfoBlock.productVersion); - if (1 == versionCompareResult) { - rv = VERSION_DOWNGRADE_ERROR; + + if (rv == OK) + { + /* Compare both versions to ensure we don't have a downgrade + -1 if appVersion is older than productInfoBlock.productVersion + 1 if appVersion is newer than productInfoBlock.productVersion + 0 if appVersion is the same as productInfoBlock.productVersion + This even works with strings like: + - 12.0a1 being older than 12.0a2 + - 12.0a2 being older than 12.0b1 + - 12.0a1 being older than 12.0 + - 12.0 being older than 12.1a1 */ + int versionCompareResult = + mozilla::CompareVersions(appVersion, productInfoBlock.productVersion); + if (1 == versionCompareResult) + { + rv = VERSION_DOWNGRADE_ERROR; + } } - } - free((void *)productInfoBlock.MARChannelID); - free((void *)productInfoBlock.productVersion); - return rv; + free((void *)productInfoBlock.MARChannelID); + free((void *)productInfoBlock.productVersion); + return rv; } int ArchiveReader::Open(const NS_tchar *path) { - if (mArchive) - Close(); - - if (!inbuf) { - inbuf = (char *)malloc(inbuf_size); - if (!inbuf) { - // Try again with a smaller buffer. - inbuf_size = 1024; - inbuf = (char *)malloc(inbuf_size); - if (!inbuf) - return ARCHIVE_READER_MEM_ERROR; + if (mArchive) + Close(); + + if (!inbuf) + { + inbuf = (char *)malloc(inbuf_size); + if (!inbuf) + { + // Try again with a smaller buffer. + inbuf_size = 1024; + inbuf = (char *)malloc(inbuf_size); + if (!inbuf) + return ARCHIVE_READER_MEM_ERROR; + } } - } - - if (!outbuf) { - outbuf = (char *)malloc(outbuf_size); - if (!outbuf) { - // Try again with a smaller buffer. - outbuf_size = 1024; - outbuf = (char *)malloc(outbuf_size); - if (!outbuf) - return ARCHIVE_READER_MEM_ERROR; + + if (!outbuf) + { + outbuf = (char *)malloc(outbuf_size); + if (!outbuf) + { + // Try again with a smaller buffer. + outbuf_size = 1024; + outbuf = (char *)malloc(outbuf_size); + if (!outbuf) + return ARCHIVE_READER_MEM_ERROR; + } } - } #ifdef _WIN32 - mArchive = mar_wopen(path); + mArchive = mar_wopen(path); #else - mArchive = mar_open(path); + mArchive = mar_open(path); #endif - if (!mArchive) - return READ_ERROR; + if (!mArchive) + return READ_ERROR; - return OK; + return OK; } void ArchiveReader::Close() { - if (mArchive) { - mar_close(mArchive); - mArchive = nullptr; - } - - if (inbuf) { - free(inbuf); - inbuf = nullptr; - } - - if (outbuf) { - free(outbuf); - outbuf = nullptr; - } + if (mArchive) + { + mar_close(mArchive); + mArchive = nullptr; + } + + if (inbuf) + { + free(inbuf); + inbuf = nullptr; + } + + if (outbuf) + { + free(outbuf); + outbuf = nullptr; + } } int ArchiveReader::ExtractFile(const char *name, const NS_tchar *dest) { - const MarItem *item = mar_find_item(mArchive, name); - if (!item) - return READ_ERROR; + const MarItem *item = mar_find_item(mArchive, name); + if (!item) + return READ_ERROR; #ifdef _WIN32 - FILE* fp = _wfopen(dest, L"wb+"); + FILE* fp = _wfopen(dest, L"wb+"); #else - int fd = creat(dest, item->flags); - if (fd == -1) - return WRITE_ERROR; + int fd = creat(dest, item->flags); + if (fd == -1) + return WRITE_ERROR; - FILE *fp = fdopen(fd, "wb"); + FILE *fp = fdopen(fd, "wb"); #endif - if (!fp) - return WRITE_ERROR; + if (!fp) + return WRITE_ERROR; - int rv = ExtractItemToStream(item, fp); + int rv = ExtractItemToStream(item, fp); - fclose(fp); - return rv; + fclose(fp); + return rv; } int ArchiveReader::ExtractFileToStream(const char *name, FILE *fp) { - const MarItem *item = mar_find_item(mArchive, name); - if (!item) - return READ_ERROR; + const MarItem *item = mar_find_item(mArchive, name); + if (!item) + return READ_ERROR; - return ExtractItemToStream(item, fp); + return ExtractItemToStream(item, fp); } int ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp) { - /* decompress the data chunk by chunk */ - - bz_stream strm; - int offset, inlen, ret = OK; - - memset(&strm, 0, sizeof(strm)); - if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK) - return UNEXPECTED_BZIP_ERROR; - - offset = 0; - for (;;) { - if (!item->length) { - ret = UNEXPECTED_MAR_ERROR; - break; - } - - if (offset < (int) item->length && strm.avail_in == 0) { - inlen = mar_read(mArchive, item, offset, inbuf, inbuf_size); - if (inlen <= 0) - return READ_ERROR; - offset += inlen; - strm.next_in = inbuf; - strm.avail_in = inlen; - } - - strm.next_out = outbuf; - strm.avail_out = outbuf_size; - - ret = BZ2_bzDecompress(&strm); - if (ret != BZ_OK && ret != BZ_STREAM_END) { - ret = UNEXPECTED_BZIP_ERROR; - break; - } - - int outlen = outbuf_size - strm.avail_out; - if (outlen) { - if (fwrite(outbuf, outlen, 1, fp) != 1) { - ret = WRITE_ERROR_EXTRACT; - break; - } - } - - if (ret == BZ_STREAM_END) { - ret = OK; - break; + /* decompress the data chunk by chunk */ + + bz_stream strm; + int offset, inlen, ret = OK; + + memset(&strm, 0, sizeof(strm)); + if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK) + return UNEXPECTED_BZIP_ERROR; + + offset = 0; + for (;;) + { + if (!item->length) + { + ret = UNEXPECTED_MAR_ERROR; + break; + } + + if (offset < (int) item->length && strm.avail_in == 0) + { + inlen = mar_read(mArchive, item, offset, inbuf, inbuf_size); + if (inlen <= 0) + return READ_ERROR; + offset += inlen; + strm.next_in = inbuf; + strm.avail_in = inlen; + } + + strm.next_out = outbuf; + strm.avail_out = outbuf_size; + + ret = BZ2_bzDecompress(&strm); + if (ret != BZ_OK && ret != BZ_STREAM_END) + { + ret = UNEXPECTED_BZIP_ERROR; + break; + } + + int outlen = outbuf_size - strm.avail_out; + if (outlen) + { + if (fwrite(outbuf, outlen, 1, fp) != 1) + { + ret = WRITE_ERROR_EXTRACT; + break; + } + } + + if (ret == BZ_STREAM_END) + { + ret = OK; + break; + } } - } - BZ2_bzDecompressEnd(&strm); - return ret; + BZ2_bzDecompressEnd(&strm); + return ret; } diff --git a/onlineupdate/source/update/updater/archivereader.h b/onlineupdate/source/update/updater/archivereader.h index f045566b772b..9b7885dc0103 100644 --- a/onlineupdate/source/update/updater/archivereader.h +++ b/onlineupdate/source/update/updater/archivereader.h @@ -11,31 +11,34 @@ #include <onlineupdate/mar.h> #ifdef _WIN32 - typedef WCHAR NS_tchar; +typedef WCHAR NS_tchar; #else - typedef char NS_tchar; +typedef char NS_tchar; #endif // This class provides an API to extract files from an update archive. class ArchiveReader { public: - ArchiveReader() : mArchive(nullptr) {} - ~ArchiveReader() { Close(); } + ArchiveReader() : mArchive(nullptr) {} + ~ArchiveReader() + { + Close(); + } - int Open(const NS_tchar *path); - int VerifySignature(); - int VerifyProductInformation(const char *MARChannelID, - const char *appVersion); - void Close(); + int Open(const NS_tchar *path); + int VerifySignature(); + int VerifyProductInformation(const char *MARChannelID, + const char *appVersion); + void Close(); - int ExtractFile(const char *item, const NS_tchar *destination); - int ExtractFileToStream(const char *item, FILE *fp); + int ExtractFile(const char *item, const NS_tchar *destination); + int ExtractFileToStream(const char *item, FILE *fp); private: - int ExtractItemToStream(const MarItem *item, FILE *fp); + int ExtractItemToStream(const MarItem *item, FILE *fp); - MarFile *mArchive; + MarFile *mArchive; }; #endif // ArchiveReader_h__ diff --git a/onlineupdate/source/update/updater/bspatch.cxx b/onlineupdate/source/update/updater/bspatch.cxx index 09a3c4354fcb..b39c50f92627 100644 --- a/onlineupdate/source/update/updater/bspatch.cxx +++ b/onlineupdate/source/update/updater/bspatch.cxx @@ -58,130 +58,140 @@ int MBS_ReadHeader(FILE* file, MBSPatchHeader *header) { - size_t s = fread(header, 1, sizeof(MBSPatchHeader), file); - if (s != sizeof(MBSPatchHeader)) - return READ_ERROR; - - header->slen = ntohl(header->slen); - header->scrc32 = ntohl(header->scrc32); - header->dlen = ntohl(header->dlen); - header->cblen = ntohl(header->cblen); - header->difflen = ntohl(header->difflen); - header->extralen = ntohl(header->extralen); - - struct stat hs; - s = fstat(fileno(file), &hs); - if (s) - return READ_ERROR; - - if (memcmp(header->tag, "MBDIFF10", 8) != 0) - return UNEXPECTED_BSPATCH_ERROR; - - if (sizeof(MBSPatchHeader) + - header->cblen + - header->difflen + - header->extralen != uint32_t(hs.st_size)) - return UNEXPECTED_BSPATCH_ERROR; - - return OK; + size_t s = fread(header, 1, sizeof(MBSPatchHeader), file); + if (s != sizeof(MBSPatchHeader)) + return READ_ERROR; + + header->slen = ntohl(header->slen); + header->scrc32 = ntohl(header->scrc32); + header->dlen = ntohl(header->dlen); + header->cblen = ntohl(header->cblen); + header->difflen = ntohl(header->difflen); + header->extralen = ntohl(header->extralen); + + struct stat hs; + s = fstat(fileno(file), &hs); + if (s) + return READ_ERROR; + + if (memcmp(header->tag, "MBDIFF10", 8) != 0) + return UNEXPECTED_BSPATCH_ERROR; + + if (sizeof(MBSPatchHeader) + + header->cblen + + header->difflen + + header->extralen != uint32_t(hs.st_size)) + return UNEXPECTED_BSPATCH_ERROR; + + return OK; } int MBS_ApplyPatch(const MBSPatchHeader *header, FILE* patchFile, unsigned char *fbuffer, FILE* file) { - unsigned char *fbufend = fbuffer + header->slen; - - unsigned char *buf = (unsigned char*) malloc(header->cblen + - header->difflen + - header->extralen); - if (!buf) - return BSPATCH_MEM_ERROR; - - int rv = OK; - - size_t r = header->cblen + header->difflen + header->extralen; - unsigned char *wb = buf; - while (r) { - const size_t count = (r > SSIZE_MAX) ? SSIZE_MAX : r; - size_t c = fread(wb, 1, count, patchFile); - if (c != count) { - rv = READ_ERROR; - goto end; + unsigned char *fbufend = fbuffer + header->slen; + + unsigned char *buf = (unsigned char*) malloc(header->cblen + + header->difflen + + header->extralen); + if (!buf) + return BSPATCH_MEM_ERROR; + + int rv = OK; + + size_t r = header->cblen + header->difflen + header->extralen; + unsigned char *wb = buf; + while (r) + { + const size_t count = (r > SSIZE_MAX) ? SSIZE_MAX : r; + size_t c = fread(wb, 1, count, patchFile); + if (c != count) + { + rv = READ_ERROR; + goto end; + } + + r -= c; + wb += c; } - r -= c; - wb += c; - } + { + MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf; + unsigned char *diffsrc = buf + header->cblen; + unsigned char *extrasrc = diffsrc + header->difflen; - { - MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf; - unsigned char *diffsrc = buf + header->cblen; - unsigned char *extrasrc = diffsrc + header->difflen; + MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc; + unsigned char *diffend = extrasrc; + unsigned char *extraend = extrasrc + header->extralen; - MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc; - unsigned char *diffend = extrasrc; - unsigned char *extraend = extrasrc + header->extralen; - - do { - ctrlsrc->x = ntohl(ctrlsrc->x); - ctrlsrc->y = ntohl(ctrlsrc->y); - ctrlsrc->z = ntohl(ctrlsrc->z); + do + { + ctrlsrc->x = ntohl(ctrlsrc->x); + ctrlsrc->y = ntohl(ctrlsrc->y); + ctrlsrc->z = ntohl(ctrlsrc->z); #ifdef DEBUG_bsmedberg - printf("Applying block:\n" - " x: %u\n" - " y: %u\n" - " z: %i\n", - ctrlsrc->x, - ctrlsrc->y, - ctrlsrc->z); + printf("Applying block:\n" + " x: %u\n" + " y: %u\n" + " z: %i\n", + ctrlsrc->x, + ctrlsrc->y, + ctrlsrc->z); #endif - /* Add x bytes from oldfile to x bytes from the diff block */ - - if (fbuffer + ctrlsrc->x > fbufend || - diffsrc + ctrlsrc->x > diffend) { - rv = UNEXPECTED_BSPATCH_ERROR; - goto end; - } - for (uint32_t i = 0; i < ctrlsrc->x; ++i) { - diffsrc[i] += fbuffer[i]; - } - if ((uint32_t) fwrite(diffsrc, 1, ctrlsrc->x, file) != ctrlsrc->x) { - rv = WRITE_ERROR_PATCH_FILE; - goto end; - } - fbuffer += ctrlsrc->x; - diffsrc += ctrlsrc->x; - - /* Copy y bytes from the extra block */ - - if (extrasrc + ctrlsrc->y > extraend) { - rv = UNEXPECTED_BSPATCH_ERROR; - goto end; - } - if ((uint32_t) fwrite(extrasrc, 1, ctrlsrc->y, file) != ctrlsrc->y) { - rv = WRITE_ERROR_PATCH_FILE; - goto end; - } - extrasrc += ctrlsrc->y; - - /* "seek" forwards in oldfile by z bytes */ - - if (fbuffer + ctrlsrc->z > fbufend) { - rv = UNEXPECTED_BSPATCH_ERROR; - goto end; - } - fbuffer += ctrlsrc->z; - - /* and on to the next control block */ - - ++ctrlsrc; - } while (ctrlsrc < ctrlend); - } + /* Add x bytes from oldfile to x bytes from the diff block */ + + if (fbuffer + ctrlsrc->x > fbufend || + diffsrc + ctrlsrc->x > diffend) + { + rv = UNEXPECTED_BSPATCH_ERROR; + goto end; + } + for (uint32_t i = 0; i < ctrlsrc->x; ++i) + { + diffsrc[i] += fbuffer[i]; + } + if ((uint32_t) fwrite(diffsrc, 1, ctrlsrc->x, file) != ctrlsrc->x) + { + rv = WRITE_ERROR_PATCH_FILE; + goto end; + } + fbuffer += ctrlsrc->x; + diffsrc += ctrlsrc->x; + + /* Copy y bytes from the extra block */ + + if (extrasrc + ctrlsrc->y > extraend) + { + rv = UNEXPECTED_BSPATCH_ERROR; + goto end; + } + if ((uint32_t) fwrite(extrasrc, 1, ctrlsrc->y, file) != ctrlsrc->y) + { + rv = WRITE_ERROR_PATCH_FILE; + goto end; + } + extrasrc += ctrlsrc->y; + + /* "seek" forwards in oldfile by z bytes */ + + if (fbuffer + ctrlsrc->z > fbufend) + { + rv = UNEXPECTED_BSPATCH_ERROR; + goto end; + } + fbuffer += ctrlsrc->z; + + /* and on to the next control block */ + + ++ctrlsrc; + } + while (ctrlsrc < ctrlend); + } end: - free(buf); - return rv; + free(buf); + return rv; } diff --git a/onlineupdate/source/update/updater/bspatch.h b/onlineupdate/source/update/updater/bspatch.h index 2b5fb338726f..ff1a8072964f 100644 --- a/onlineupdate/source/update/updater/bspatch.h +++ b/onlineupdate/source/update/updater/bspatch.h @@ -35,31 +35,32 @@ #include <stdint.h> #include <stdio.h> -typedef struct MBSPatchHeader_ { - /* "MBDIFF10" */ - char tag[8]; +typedef struct MBSPatchHeader_ +{ + /* "MBDIFF10" */ + char tag[8]; - /* Length of the file to be patched */ - uint32_t slen; + /* Length of the file to be patched */ + uint32_t slen; - /* CRC32 of the file to be patched */ - uint32_t scrc32; + /* CRC32 of the file to be patched */ + uint32_t scrc32; - /* Length of the result file */ - uint32_t dlen; + /* Length of the result file */ + uint32_t dlen; - /* Length of the control block in bytes */ - uint32_t cblen; + /* Length of the control block in bytes */ + uint32_t cblen; - /* Length of the diff block in bytes */ - uint32_t difflen; + /* Length of the diff block in bytes */ + uint32_t difflen; - /* Length of the extra block in bytes */ - uint32_t extralen; + /* Length of the extra block in bytes */ + uint32_t extralen; - /* Control block (MBSPatchTriple[]) */ - /* Diff block (binary data) */ - /* Extra block (binary data) */ + /* Control block (MBSPatchTriple[]) */ + /* Diff block (binary data) */ + /* Extra block (binary data) */ } MBSPatchHeader; /** @@ -84,10 +85,11 @@ int MBS_ReadHeader(FILE* file, MBSPatchHeader *header); int MBS_ApplyPatch(const MBSPatchHeader *header, FILE* patchFile, unsigned char *fbuffer, FILE* file); -typedef struct MBSPatchTriple_ { - uint32_t x; /* add x bytes from oldfile to x bytes from the diff block */ - uint32_t y; /* copy y bytes from the extra block */ - int32_t z; /* seek forwards in oldfile by z bytes */ +typedef struct MBSPatchTriple_ +{ + uint32_t x; /* add x bytes from oldfile to x bytes from the diff block */ + uint32_t y; /* copy y bytes from the extra block */ + int32_t z; /* seek forwards in oldfile by z bytes */ } MBSPatchTriple; #endif // bspatch_h__ diff --git a/onlineupdate/source/update/updater/loaddlls.cxx b/onlineupdate/source/update/updater/loaddlls.cxx index 94a4222136b5..246d9f86bf79 100644 --- a/onlineupdate/source/update/updater/loaddlls.cxx +++ b/onlineupdate/source/update/updater/loaddlls.cxx @@ -15,95 +15,104 @@ // system directory. struct AutoLoadSystemDependencies { - AutoLoadSystemDependencies() - { - // Remove the current directory from the search path for dynamically loaded - // DLLs as a precaution. This call has no effect for delay load DLLs. - SetDllDirectory(L""); + AutoLoadSystemDependencies() + { + // Remove the current directory from the search path for dynamically loaded + // DLLs as a precaution. This call has no effect for delay load DLLs. + SetDllDirectory(L""); - HMODULE module = ::GetModuleHandleW(L"kernel32.dll"); - if (module) { - // SetDefaultDllDirectories is always available on Windows 8 and above. It - // is also available on Windows Vista, Windows Server 2008, and - // Windows 7 when MS KB2533623 has been applied. - decltype(SetDefaultDllDirectories)* setDefaultDllDirectories = - (decltype(SetDefaultDllDirectories)*) GetProcAddress(module, "SetDefaultDllDirectories"); - if (setDefaultDllDirectories) { - setDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); - return; - } - } + HMODULE module = ::GetModuleHandleW(L"kernel32.dll"); + if (module) + { + // SetDefaultDllDirectories is always available on Windows 8 and above. It + // is also available on Windows Vista, Windows Server 2008, and + // Windows 7 when MS KB2533623 has been applied. + decltype(SetDefaultDllDirectories)* setDefaultDllDirectories = + (decltype(SetDefaultDllDirectories)*) GetProcAddress(module, "SetDefaultDllDirectories"); + if (setDefaultDllDirectories) + { + setDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); + return; + } + } - // When SetDefaultDllDirectories is not available, fallback to preloading - // dlls. The order that these are loaded does not matter since they are - // loaded using the LOAD_WITH_ALTERED_SEARCH_PATH flag. + // When SetDefaultDllDirectories is not available, fallback to preloading + // dlls. The order that these are loaded does not matter since they are + // loaded using the LOAD_WITH_ALTERED_SEARCH_PATH flag. #ifdef HAVE_64BIT_BUILD - // DLLs for Firefox x64 on Windows 7 (x64). - // Note: dwmapi.dll is preloaded since a crash will try to load it from the - // application's directory. - static LPCWSTR delayDLLs[] = { L"apphelp.dll", - L"cryptbase.dll", - L"cryptsp.dll", - L"dwmapi.dll", - L"mpr.dll", - L"ntmarta.dll", - L"profapi.dll", - L"propsys.dll", - L"sspicli.dll", - L"wsock32.dll" }; + // DLLs for Firefox x64 on Windows 7 (x64). + // Note: dwmapi.dll is preloaded since a crash will try to load it from the + // application's directory. + static LPCWSTR delayDLLs[] = { L"apphelp.dll", + L"cryptbase.dll", + L"cryptsp.dll", + L"dwmapi.dll", + L"mpr.dll", + L"ntmarta.dll", + L"profapi.dll", + L"propsys.dll", + L"sspicli.dll", + L"wsock32.dll" + }; #else - // DLLs for Firefox x86 on Windows XP through Windows 7 (x86 and x64). - // Note: dwmapi.dll is preloaded since a crash will try to load it from the - // application's directory. - static LPCWSTR delayDLLs[] = { L"apphelp.dll", - L"crypt32.dll", - L"cryptbase.dll", - L"cryptsp.dll", - L"dwmapi.dll", - L"mpr.dll", - L"msasn1.dll", - L"ntmarta.dll", - L"profapi.dll", - L"propsys.dll", - L"psapi.dll", - L"secur32.dll", - L"sspicli.dll", - L"userenv.dll", - L"uxtheme.dll", - L"ws2_32.dll", - L"ws2help.dll", - L"wsock32.dll" }; + // DLLs for Firefox x86 on Windows XP through Windows 7 (x86 and x64). + // Note: dwmapi.dll is preloaded since a crash will try to load it from the + // application's directory. + static LPCWSTR delayDLLs[] = { L"apphelp.dll", + L"crypt32.dll", + L"cryptbase.dll", + L"cryptsp.dll", + L"dwmapi.dll", + L"mpr.dll", + L"msasn1.dll", + L"ntmarta.dll", + L"profapi.dll", + L"propsys.dll", + L"psapi.dll", + L"secur32.dll", + L"sspicli.dll", + L"userenv.dll", + L"uxtheme.dll", + L"ws2_32.dll", + L"ws2help.dll", + L"wsock32.dll" + }; #endif - WCHAR systemDirectory[MAX_PATH + 1] = { L'\0' }; - // If GetSystemDirectory fails we accept that we'll load the DLLs from the - // normal search path. - GetSystemDirectoryW(systemDirectory, MAX_PATH + 1); - size_t systemDirLen = wcslen(systemDirectory); + WCHAR systemDirectory[MAX_PATH + 1] = { L'\0' }; + // If GetSystemDirectory fails we accept that we'll load the DLLs from the + // normal search path. + GetSystemDirectoryW(systemDirectory, MAX_PATH + 1); + size_t systemDirLen = wcslen(systemDirectory); - // Make the system directory path terminate with a slash - if (systemDirectory[systemDirLen - 1] != L'\\' && systemDirLen) { - systemDirectory[systemDirLen] = L'\\'; - ++systemDirLen; - // No need to re-null terminate - } + // Make the system directory path terminate with a slash + if (systemDirectory[systemDirLen - 1] != L'\\' && systemDirLen) + { + systemDirectory[systemDirLen] = L'\\'; + ++systemDirLen; + // No need to re-null terminate + } - // For each known DLL ensure it is loaded from the system32 directory - for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i) { - size_t fileLen = wcslen(delayDLLs[i]); - wcsncpy(systemDirectory + systemDirLen, delayDLLs[i], - MAX_PATH - systemDirLen); - if (systemDirLen + fileLen <= MAX_PATH) { - systemDirectory[systemDirLen + fileLen] = L'\0'; - } else { - systemDirectory[MAX_PATH] = L'\0'; - } - LPCWSTR fullModulePath = systemDirectory; // just for code readability - // LOAD_WITH_ALTERED_SEARCH_PATH makes a dll look in its own directory for - // dependencies and is only available on Win 7 and below. - LoadLibraryExW(fullModulePath, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); + // For each known DLL ensure it is loaded from the system32 directory + for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i) + { + size_t fileLen = wcslen(delayDLLs[i]); + wcsncpy(systemDirectory + systemDirLen, delayDLLs[i], + MAX_PATH - systemDirLen); + if (systemDirLen + fileLen <= MAX_PATH) + { + systemDirectory[systemDirLen + fileLen] = L'\0'; + } + else + { + systemDirectory[MAX_PATH] = L'\0'; + } + LPCWSTR fullModulePath = systemDirectory; // just for code readability + // LOAD_WITH_ALTERED_SEARCH_PATH makes a dll look in its own directory for + // dependencies and is only available on Win 7 and below. + LoadLibraryExW(fullModulePath, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); + } } - } } loadDLLs; #endif diff --git a/onlineupdate/source/update/updater/primaryCert.h b/onlineupdate/source/update/updater/primaryCert.h index f161aa3816b1..e46af0b59814 100644 --- a/onlineupdate/source/update/updater/primaryCert.h +++ b/onlineupdate/source/update/updater/primaryCert.h @@ -1,3 +1,4 @@ -const uint8_t primaryCertData[] = { +const uint8_t primaryCertData[] = +{ 0x30, 0x82, 0x02, 0xc3, 0x30, 0x82, 0x01, 0xab, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, 0xa7, 0x67, 0xe2, 0xee, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb3, 0x63, 0x91, 0x44, 0xf6, 0xf1, 0xd7, 0x7f, 0xc9, 0x3d, 0xee, 0x39, 0x44, 0xba, 0xd5, 0x1b, 0x68, 0x10, 0xfd, 0x2e, 0xb3, 0xe9, 0x17, 0xd8, 0x78, 0x18, 0xff, 0xbb, 0x63, 0x6f, 0x21, 0xd9, 0xb3, 0x55, 0x83, 0xe2, 0x90, 0x18, 0xba, 0x1e, 0x3b, 0x57, 0xbb, 0x4a, 0xc7, 0x4a, 0x3b, 0x49, 0x14, 0x1b, 0xe0, 0xc5, 0x01, 0x8e, 0xb3, 0xfc, 0xe0, 0x31, 0x21, 0xea, 0x6b, 0xc6, 0x5f, 0x70, 0x3c, 0x1f, 0x40, 0x9e, 0x6f, 0xf1, 0x37, 0xa0, 0x74, 0xc5, 0x55, 0xc7, 0x4d, 0x9c, 0xdd, 0x6b, 0xb4, 0xd3, 0x17, 0x22, 0x9e, 0x27, 0xea, 0x57, 0x45, 0x58, 0x19, 0x39, 0x18, 0x42, 0x37, 0x94, 0x8d, 0x11, 0xa1, 0xa9, 0xcb, 0xdd, 0x45, 0x7e, 0x82, 0xbf, 0x93, 0x75, 0xcc, 0x8d, 0x95, 0x04, 0x74, 0xc0, 0x84, 0x2e, 0x7d, 0xbc, 0x56, 0x2d, 0xd1, 0x0e, 0x2e, 0xbf, 0x0e, 0x52, 0x22, 0x0c, 0x65, 0xb2, 0x7a, 0x12, 0x14, 0x27, 0x0b, 0xc9, 0x37, 0x30, 0x48, 0xbc, 0xf0, 0xb8, 0x6d, 0x6f, 0x38, 0xda, 0x98, 0xd0, 0x1c, 0x87, 0xfe, 0x69, 0xc4, 0xc7, 0x73, 0xed, 0x78, 0x01, 0xa5, 0xea, 0x48, 0x08, 0x28, 0xcc, 0x0e, 0x52, 0x20, 0x1f, 0x46, 0x42, 0x83, 0x2e, 0xa6, 0xfd, 0x30, 0xc6, 0x48, 0x55, 0x78, 0xff, 0xd6, 0xac, 0xdd, 0x61, 0xd3, 0xb9, 0xdb, 0x49, 0x6b, 0x93, 0x5a, 0x5b, 0x37, 0xf5, 0xcb, 0x09, 0x4a, 0x6c, 0xa3, 0x85, 0x1f, 0xeb, 0x33, 0x3f, 0xd0, 0xda, 0x55, 0xc3, 0xb2, 0x56, 0x7d, 0x13, 0x16, 0x23, 0x2b, 0x1c, 0x3f, 0xdd, 0x1a, 0xf9, 0x90, 0xf7, 0x43, 0x63, 0x80, 0xa5, 0x71, 0xce, 0x23, 0x56, 0x1b, 0xbf, 0x51, 0x3a, 0xfe, 0x6b, 0x48, 0xfd, 0x42, 0x50, 0xc0, 0x09, 0x30, 0x32, 0x27, 0x20, 0x0d, 0xda, 0x32, 0x02, 0x23, 0x92, 0x10, 0x85, 0xbf, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0xb2, 0x3f, 0x45, 0x2c, 0xf5, 0x75, 0xeb, 0x20, 0x2f, 0x76, 0x6f, 0x18, 0x06, 0x42, 0x20, 0x83, 0x39, 0x50, 0x64, 0x07, 0xbb, 0xb1, 0x38, 0x74, 0xbe, 0xbb, 0xf4, 0x25, 0x11, 0x72, 0xf9, 0x4a, 0xf0, 0x9a, 0x0b, 0xe7, 0x45, 0x22, 0x59, 0x04, 0x7b, 0xa4, 0xe8, 0x46, 0xe5, 0x67, 0xdb, 0x9a, 0x9e, 0x27, 0x94, 0x5e, 0x60, 0x8b, 0xf5, 0xb1, 0x3f, 0xf2, 0xab, 0x1c, 0x54, 0xc8, 0xbc, 0x2b, 0x83, 0xf9, 0xa7, 0x18, 0x02, 0xb6, 0x95, 0xfa, 0xde, 0x16, 0x49, 0xca, 0xbd, 0x2e, 0xfc, 0xb6, 0x36, 0x9a, 0x9a, 0x7a, 0x1f, 0xc8, 0x91, 0xce, 0x30, 0xe2, 0x89, 0x58, 0x05, 0xee, 0xf3, 0xd1, 0xed, 0x79, 0x45, 0x20, 0xbd, 0x84, 0x48, 0xb0, 0x56, 0x8e, 0x04, 0xc8, 0xb7, 0x7e, 0x46, 0x2a, 0x2e, 0xb3, 0xca, 0xc1, 0xb6, 0x0b, 0xd4, 0x31, 0x6e, 0x83, 0x13, 0xe9, 0xa5, 0xbd, 0x17, 0x0e, 0x47, 0x34, 0x99, 0xc9, 0x5b, 0xb2, 0x53, 0x73, 0x57, 0xeb, 0x30, 0x0d, 0x2d, 0xaa, 0x25, 0xbb, 0xab, 0xac, 0xe8, 0xda, 0xf0, 0xf1, 0xd7, 0x2d, 0x17, 0x70, 0x9e, 0x30, 0x3c, 0x38, 0x59, 0xbf, 0x40, 0x3f, 0x6e, 0xe4, 0x22, 0x84, 0x94, 0x59, 0xf6, 0x32, 0xc1, 0xcb, 0x9c, 0x56, 0x52, 0x04, 0xeb, 0xf6, 0xa3, 0x75, 0xf8, 0xcb, 0xed, 0xaf, 0x17, 0x57, 0x8f, 0x98, 0x56, 0xa4, 0x9d, 0x85, 0x16, 0xc8, 0xf7, 0xd6, 0x97, 0xed, 0xab, 0xe0, 0x4c, 0x1a, 0x44, 0x5c, 0x68, 0x30, 0x26, 0x40, 0x6b, 0xe9, 0x88, 0x6a, 0x37, 0x1e, 0xbf, 0x25, 0x38, 0x55, 0xd9, 0x84, 0x8d, 0x55, 0x08, 0xe6, 0x18, 0xc3, 0xd7, 0x96, 0xfa, 0xd0, 0x2f, 0x17, 0x9b, 0xb6, 0x40, 0xc3, 0x47, 0xb3, 0x30, 0x01, 0x59, 0xec, 0x7c, 0x8d, 0x7e, 0x0a, 0x0d, 0xeb, 0xc4, 0x3b, 0x06, 0x4e, 0x97, 0x41, 0x5e }; diff --git a/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx b/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx index f77d0af6338a..c855e548efe0 100644 --- a/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx +++ b/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx @@ -20,34 +20,35 @@ using namespace std; int InitProgressUI(int *argc, char ***argv) { - return 0; + return 0; } int ShowProgressUI() { - LOG("Starting to apply update ...\n"); - return 0; + LOG("Starting to apply update ...\n"); + return 0; } void QuitProgressUI() { - LOG("Finished applying update\n"); + LOG("Finished applying update\n"); } void UpdateProgressUI(float progress) { - assert(0.0f <= progress && progress <= 100.0f); - - static const size_t kProgressBarLength = 50; - static size_t sLastNumBars; - size_t numBars = size_t(float(kProgressBarLength) * progress / 100.0f); - if (numBars == sLastNumBars) { - return; - } - sLastNumBars = numBars; - - size_t numSpaces = kProgressBarLength - numBars; - string bars(numBars, '='); - string spaces(numSpaces, ' '); - LOG("Progress [ %s%s ]\n", bars.c_str(), spaces.c_str()); + assert(0.0f <= progress && progress <= 100.0f); + + static const size_t kProgressBarLength = 50; + static size_t sLastNumBars; + size_t numBars = size_t(float(kProgressBarLength) * progress / 100.0f); + if (numBars == sLastNumBars) + { + return; + } + sLastNumBars = numBars; + + size_t numSpaces = kProgressBarLength - numBars; + string bars(numBars, '='); + string spaces(numSpaces, ' '); + LOG("Progress [ %s%s ]\n", bars.c_str(), spaces.c_str()); } diff --git a/onlineupdate/source/update/updater/progressui.h b/onlineupdate/source/update/updater/progressui.h index 7392ac167bc4..455ae125180a 100644 --- a/onlineupdate/source/update/updater/progressui.h +++ b/onlineupdate/source/update/updater/progressui.h @@ -10,23 +10,23 @@ #include "updatedefines.h" #if defined(_WIN32) - typedef WCHAR NS_tchar; - #define NS_main wmain +typedef WCHAR NS_tchar; +#define NS_main wmain #else - typedef char NS_tchar; - #define NS_main main +typedef char NS_tchar; +#define NS_main main #endif // Called to perform any initialization of the widget toolkit int InitProgressUI(int *argc, NS_tchar ***argv); #if defined(_WIN32) - // Called on the main thread at startup - int ShowProgressUI(bool indeterminate = false, bool initUIStrings = true); - int InitProgressUIStrings(); +// Called on the main thread at startup +int ShowProgressUI(bool indeterminate = false, bool initUIStrings = true); +int InitProgressUIStrings(); #else - // Called on the main thread at startup - int ShowProgressUI(); +// Called on the main thread at startup +int ShowProgressUI(); #endif // May be called from any thread void QuitProgressUI(); diff --git a/onlineupdate/source/update/updater/progressui_gtk.cxx b/onlineupdate/source/update/updater/progressui_gtk.cxx index 29ed219d9e35..fecd98a8730a 100644 --- a/onlineupdate/source/update/updater/progressui_gtk.cxx +++ b/onlineupdate/source/update/updater/progressui_gtk.cxx @@ -28,106 +28,106 @@ static const char *sProgramPath; static gboolean UpdateDialog(gpointer /*data*/) { - if (sQuit) - { - gtk_widget_hide(sWin); - gtk_main_quit(); - } + if (sQuit) + { + gtk_widget_hide(sWin); + gtk_main_quit(); + } - float progress = sProgressVal; + float progress = sProgressVal; - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sProgressBar), - progress / 100.0); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sProgressBar), + progress / 100.0); - return TRUE; + return TRUE; } static gboolean OnDeleteEvent(GtkWidget * /*widget*/, GdkEvent * /*event*/, gpointer /*user_data*/) { - return TRUE; + return TRUE; } int InitProgressUI(int *pargc, char ***pargv) { - sProgramPath = (*pargv)[0]; + sProgramPath = (*pargv)[0]; - sEnableUI = gtk_init_check(pargc, pargv); - return 0; + sEnableUI = gtk_init_check(pargc, pargv); + return 0; } int ShowProgressUI() { - if (!sEnableUI) - return -1; + if (!sEnableUI) + return -1; - // Only show the Progress UI if the process is taking a significant amount of - // time where a significant amount of time is defined as .5 seconds after - // ShowProgressUI is called sProgress is less than 70. - usleep(500000); + // Only show the Progress UI if the process is taking a significant amount of + // time where a significant amount of time is defined as .5 seconds after + // ShowProgressUI is called sProgress is less than 70. + usleep(500000); - if (sQuit || sProgressVal > 70.0f) - return 0; + if (sQuit || sProgressVal > 70.0f) + return 0; - char ini_path[PATH_MAX]; - snprintf(ini_path, sizeof(ini_path), "%s.ini", sProgramPath); + char ini_path[PATH_MAX]; + snprintf(ini_path, sizeof(ini_path), "%s.ini", sProgramPath); - StringTable strings; - if (ReadStrings(ini_path, &strings) != OK) - return -1; + StringTable strings; + if (ReadStrings(ini_path, &strings) != OK) + return -1; - sWin = gtk_window_new(GTK_WINDOW_TOPLEVEL); - if (!sWin) - return -1; + sWin = gtk_window_new(GTK_WINDOW_TOPLEVEL); + if (!sWin) + return -1; - static GdkPixbuf *pixbuf; - char icon_path[PATH_MAX]; - snprintf(icon_path, sizeof(icon_path), "%s.png", sProgramPath); + static GdkPixbuf *pixbuf; + char icon_path[PATH_MAX]; + snprintf(icon_path, sizeof(icon_path), "%s.png", sProgramPath); - g_signal_connect(G_OBJECT(sWin), "delete_event", - G_CALLBACK(OnDeleteEvent), nullptr); + g_signal_connect(G_OBJECT(sWin), "delete_event", + G_CALLBACK(OnDeleteEvent), nullptr); - gtk_window_set_title(GTK_WINDOW(sWin), strings.title); - gtk_window_set_type_hint(GTK_WINDOW(sWin), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_position(GTK_WINDOW(sWin), GTK_WIN_POS_CENTER_ALWAYS); - gtk_window_set_resizable(GTK_WINDOW(sWin), FALSE); - gtk_window_set_decorated(GTK_WINDOW(sWin), TRUE); - gtk_window_set_deletable(GTK_WINDOW(sWin),FALSE); - pixbuf = gdk_pixbuf_new_from_file (icon_path, nullptr); - gtk_window_set_icon(GTK_WINDOW(sWin), pixbuf); - g_object_unref(pixbuf); + gtk_window_set_title(GTK_WINDOW(sWin), strings.title); + gtk_window_set_type_hint(GTK_WINDOW(sWin), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_window_set_position(GTK_WINDOW(sWin), GTK_WIN_POS_CENTER_ALWAYS); + gtk_window_set_resizable(GTK_WINDOW(sWin), FALSE); + gtk_window_set_decorated(GTK_WINDOW(sWin), TRUE); + gtk_window_set_deletable(GTK_WINDOW(sWin),FALSE); + pixbuf = gdk_pixbuf_new_from_file (icon_path, nullptr); + gtk_window_set_icon(GTK_WINDOW(sWin), pixbuf); + g_object_unref(pixbuf); - GtkWidget *vbox = gtk_vbox_new(TRUE, 6); - sLabel = gtk_label_new(strings.info); - gtk_misc_set_alignment(GTK_MISC(sLabel), 0.0f, 0.0f); - sProgressBar = gtk_progress_bar_new(); + GtkWidget *vbox = gtk_vbox_new(TRUE, 6); + sLabel = gtk_label_new(strings.info); + gtk_misc_set_alignment(GTK_MISC(sLabel), 0.0f, 0.0f); + sProgressBar = gtk_progress_bar_new(); - gtk_box_pack_start(GTK_BOX(vbox), sLabel, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), sProgressBar, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), sLabel, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), sProgressBar, TRUE, TRUE, 0); - sTimerID = g_timeout_add(TIMER_INTERVAL, UpdateDialog, nullptr); + sTimerID = g_timeout_add(TIMER_INTERVAL, UpdateDialog, nullptr); - gtk_container_set_border_width(GTK_CONTAINER(sWin), 10); - gtk_container_add(GTK_CONTAINER(sWin), vbox); - gtk_widget_show_all(sWin); + gtk_container_set_border_width(GTK_CONTAINER(sWin), 10); + gtk_container_add(GTK_CONTAINER(sWin), vbox); + gtk_widget_show_all(sWin); - gtk_main(); - return 0; + gtk_main(); + return 0; } // Called on a background thread void QuitProgressUI() { - sQuit = TRUE; + sQuit = TRUE; } // Called on a background thread void UpdateProgressUI(float progress) { - sProgressVal = progress; // 32-bit writes are atomic + sProgressVal = progress; // 32-bit writes are atomic } #endif // defined(UNIX) || defined(MACOSX) diff --git a/onlineupdate/source/update/updater/progressui_null.cxx b/onlineupdate/source/update/updater/progressui_null.cxx index c4cd6413ff1f..66d294a133a0 100644 --- a/onlineupdate/source/update/updater/progressui_null.cxx +++ b/onlineupdate/source/update/updater/progressui_null.cxx @@ -9,12 +9,12 @@ int InitProgressUI(int *argc, char ***argv) { - return 0; + return 0; } int ShowProgressUI() { - return 0; + return 0; } void QuitProgressUI() diff --git a/onlineupdate/source/update/updater/progressui_win.cxx b/onlineupdate/source/update/updater/progressui_win.cxx index b1f2b99a5eb2..b7ff90acbbbf 100644 --- a/onlineupdate/source/update/updater/progressui_win.cxx +++ b/onlineupdate/source/update/updater/progressui_win.cxx @@ -51,23 +51,23 @@ static StringTable sUIStrings; static BOOL GetStringsFile(WCHAR filename[MAX_PATH]) { - if (!GetModuleFileNameW(nullptr, filename, MAX_PATH)) - return FALSE; + if (!GetModuleFileNameW(nullptr, filename, MAX_PATH)) + return FALSE; - WCHAR *dot = wcsrchr(filename, '.'); - if (!dot || wcsicmp(dot + 1, L"exe")) - return FALSE; + WCHAR *dot = wcsrchr(filename, '.'); + if (!dot || wcsicmp(dot + 1, L"exe")) + return FALSE; - wcscpy(dot + 1, L"ini"); - return TRUE; + wcscpy(dot + 1, L"ini"); + return TRUE; } static void UpdateDialog(HWND hDlg) { - int pos = int(sProgress + 0.5f); - HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS); - SendMessage(hWndPro, PBM_SETPOS, pos, 0L); + int pos = int(sProgress + 0.5f); + HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS); + SendMessage(hWndPro, PBM_SETPOS, pos, 0L); } // The code in this function is from MSDN: @@ -75,139 +75,145 @@ UpdateDialog(HWND hDlg) static void CenterDialog(HWND hDlg) { - RECT rc, rcOwner, rcDlg; + RECT rc, rcOwner, rcDlg; - // Get the owner window and dialog box rectangles. - HWND desktop = GetDesktopWindow(); + // Get the owner window and dialog box rectangles. + HWND desktop = GetDesktopWindow(); - GetWindowRect(desktop, &rcOwner); - GetWindowRect(hDlg, &rcDlg); - CopyRect(&rc, &rcOwner); + GetWindowRect(desktop, &rcOwner); + GetWindowRect(hDlg, &rcDlg); + CopyRect(&rc, &rcOwner); - // Offset the owner and dialog box rectangles so that - // right and bottom values represent the width and - // height, and then offset the owner again to discard - // space taken up by the dialog box. + // Offset the owner and dialog box rectangles so that + // right and bottom values represent the width and + // height, and then offset the owner again to discard + // space taken up by the dialog box. - OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); - OffsetRect(&rc, -rc.left, -rc.top); - OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); + OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); + OffsetRect(&rc, -rc.left, -rc.top); + OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); - // The new position is the sum of half the remaining - // space and the owner's original position. + // The new position is the sum of half the remaining + // space and the owner's original position. - SetWindowPos(hDlg, - HWND_TOP, - rcOwner.left + (rc.right / 2), - rcOwner.top + (rc.bottom / 2), - 0, 0, // ignores size arguments - SWP_NOSIZE); + SetWindowPos(hDlg, + HWND_TOP, + rcOwner.left + (rc.right / 2), + rcOwner.top + (rc.bottom / 2), + 0, 0, // ignores size arguments + SWP_NOSIZE); } static void InitDialog(HWND hDlg) { - WCHAR szwTitle[MAX_TEXT_LEN]; - WCHAR szwInfo[MAX_TEXT_LEN]; - - MultiByteToWideChar(CP_UTF8, 0, sUIStrings.title, -1, szwTitle, - sizeof(szwTitle)/sizeof(szwTitle[0])); - MultiByteToWideChar(CP_UTF8, 0, sUIStrings.info, -1, szwInfo, - sizeof(szwInfo)/sizeof(szwInfo[0])); - - SetWindowTextW(hDlg, szwTitle); - SetWindowTextW(GetDlgItem(hDlg, IDC_INFO), szwInfo); - - // Set dialog icon - HICON hIcon = LoadIcon(GetModuleHandle(nullptr), - MAKEINTRESOURCE(IDI_DIALOG)); - if (hIcon) - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon); - - HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS); - SendMessage(hWndPro, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); - if (sIndeterminate) { - LONG_PTR val = GetWindowLongPtr(hWndPro, GWL_STYLE); - SetWindowLongPtr(hWndPro, GWL_STYLE, val|PBS_MARQUEE); - SendMessage(hWndPro,(UINT) PBM_SETMARQUEE,(WPARAM) TRUE,(LPARAM)50 ); - } + WCHAR szwTitle[MAX_TEXT_LEN]; + WCHAR szwInfo[MAX_TEXT_LEN]; + + MultiByteToWideChar(CP_UTF8, 0, sUIStrings.title, -1, szwTitle, + sizeof(szwTitle)/sizeof(szwTitle[0])); + MultiByteToWideChar(CP_UTF8, 0, sUIStrings.info, -1, szwInfo, + sizeof(szwInfo)/sizeof(szwInfo[0])); + + SetWindowTextW(hDlg, szwTitle); + SetWindowTextW(GetDlgItem(hDlg, IDC_INFO), szwInfo); + + // Set dialog icon + HICON hIcon = LoadIcon(GetModuleHandle(nullptr), + MAKEINTRESOURCE(IDI_DIALOG)); + if (hIcon) + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon); + + HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS); + SendMessage(hWndPro, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); + if (sIndeterminate) + { + LONG_PTR val = GetWindowLongPtr(hWndPro, GWL_STYLE); + SetWindowLongPtr(hWndPro, GWL_STYLE, val|PBS_MARQUEE); + SendMessage(hWndPro,(UINT) PBM_SETMARQUEE,(WPARAM) TRUE,(LPARAM)50 ); + } - // Resize the dialog to fit all of the text if necessary. - RECT infoSize, textSize; - HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO); - - // Get the control's font for calculating the new size for the control - HDC hDCInfo = GetDC(hWndInfo); - HFONT hInfoFont; - HFONT hOldFont = 0; - hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0); - - if (hInfoFont) - hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont); - - // Measure the space needed for the text on a single line. DT_CALCRECT means - // nothing is drawn. - if (DrawText(hDCInfo, szwInfo, -1, &textSize, - DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE)) { - GetClientRect(hWndInfo, &infoSize); - SIZE extra; - // Calculate the additional space needed for the text by subtracting from - // the rectangle returned by DrawText the existing client rectangle's width - // and height. - extra.cx = (textSize.right - textSize.left) - - (infoSize.right - infoSize.left); - extra.cy = (textSize.bottom - textSize.top) - - (infoSize.bottom - infoSize.top); - if (extra.cx < 0) - extra.cx = 0; - if (extra.cy < 0) - extra.cy = 0; - if ((extra.cx > 0) || (extra.cy > 0)) { - RESIZE_WINDOW(hDlg, extra.cx, extra.cy); - RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy); - RESIZE_WINDOW(hWndPro, extra.cx, 0); - MOVE_WINDOW(hWndPro, 0, extra.cy); + // Resize the dialog to fit all of the text if necessary. + RECT infoSize, textSize; + HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO); + + // Get the control's font for calculating the new size for the control + HDC hDCInfo = GetDC(hWndInfo); + HFONT hInfoFont; + HFONT hOldFont = 0; + hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0); + + if (hInfoFont) + hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont); + + // Measure the space needed for the text on a single line. DT_CALCRECT means + // nothing is drawn. + if (DrawText(hDCInfo, szwInfo, -1, &textSize, + DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE)) + { + GetClientRect(hWndInfo, &infoSize); + SIZE extra; + // Calculate the additional space needed for the text by subtracting from + // the rectangle returned by DrawText the existing client rectangle's width + // and height. + extra.cx = (textSize.right - textSize.left) - \ + (infoSize.right - infoSize.left); + extra.cy = (textSize.bottom - textSize.top) - \ + (infoSize.bottom - infoSize.top); + if (extra.cx < 0) + extra.cx = 0; + if (extra.cy < 0) + extra.cy = 0; + if ((extra.cx > 0) || (extra.cy > 0)) + { + RESIZE_WINDOW(hDlg, extra.cx, extra.cy); + RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy); + RESIZE_WINDOW(hWndPro, extra.cx, 0); + MOVE_WINDOW(hWndPro, 0, extra.cy); + } } - } - if (hOldFont) - SelectObject(hDCInfo, hOldFont); + if (hOldFont) + SelectObject(hDCInfo, hOldFont); - ReleaseDC(hWndInfo, hDCInfo); + ReleaseDC(hWndInfo, hDCInfo); - CenterDialog(hDlg); // make dialog appear in the center of the screen + CenterDialog(hDlg); // make dialog appear in the center of the screen - SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, nullptr); + SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, nullptr); } // Message handler for update dialog. static LRESULT CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM /*wParam*/, LPARAM /*lParam*/) { - switch (message) - { - case WM_INITDIALOG: - InitDialog(hDlg); - return TRUE; - - case WM_TIMER: - if (sQuit) { - EndDialog(hDlg, 0); - } else { - UpdateDialog(hDlg); + switch (message) + { + case WM_INITDIALOG: + InitDialog(hDlg); + return TRUE; + + case WM_TIMER: + if (sQuit) + { + EndDialog(hDlg, 0); + } + else + { + UpdateDialog(hDlg); + } + return TRUE; + + case WM_COMMAND: + return TRUE; } - return TRUE; - - case WM_COMMAND: - return TRUE; - } - return FALSE; + return FALSE; } int InitProgressUI(int* /*argc*/, WCHAR*** /*argv*/) { - return 0; + return 0; } /** @@ -216,109 +222,122 @@ InitProgressUI(int* /*argc*/, WCHAR*** /*argv*/) * @return 0 on success, -1 on error */ int -InitProgressUIStrings() { - // If we do not have updater.ini, then we should not bother showing UI. - WCHAR filename[MAX_PATH]; - if (!GetStringsFile(filename)) { - return -1; - } +InitProgressUIStrings() +{ + // If we do not have updater.ini, then we should not bother showing UI. + WCHAR filename[MAX_PATH]; + if (!GetStringsFile(filename)) + { + return -1; + } - if (_waccess(filename, 04)) { - return -1; - } + if (_waccess(filename, 04)) + { + return -1; + } - // If the updater.ini doesn't have the required strings, then we should not - // bother showing UI. - if (ReadStrings(filename, &sUIStrings) != OK) { - return -1; - } + // If the updater.ini doesn't have the required strings, then we should not + // bother showing UI. + if (ReadStrings(filename, &sUIStrings) != OK) + { + return -1; + } - return 0; + return 0; } int ShowProgressUI(bool indeterminate, bool initUIStrings) { - sIndeterminate = indeterminate; - if (!indeterminate) { - // Only show the Progress UI if the process is taking a significant amount of - // time where a significant amount of time is defined as .5 seconds after - // ShowProgressUI is called sProgress is less than 70. - Sleep(500); - - if (sQuit || sProgress > 70.0f) - return 0; - } - - // Don't load the UI if there's an <exe_name>.Local directory for redirection. - WCHAR appPath[MAX_PATH + 1] = { L'\0' }; - if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH)) { - return -1; - } + sIndeterminate = indeterminate; + if (!indeterminate) + { + // Only show the Progress UI if the process is taking a significant amount of + // time where a significant amount of time is defined as .5 seconds after + // ShowProgressUI is called sProgress is less than 70. + Sleep(500); + + if (sQuit || sProgress > 70.0f) + return 0; + } - if (wcslen(appPath) + wcslen(L".Local") >= MAX_PATH) { - return -1; - } + // Don't load the UI if there's an <exe_name>.Local directory for redirection. + WCHAR appPath[MAX_PATH + 1] = { L'\0' }; + if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH)) + { + return -1; + } - wcscat(appPath, L".Local"); + if (wcslen(appPath) + wcslen(L".Local") >= MAX_PATH) + { + return -1; + } - if (!_waccess(appPath, 04)) { - return -1; - } + wcscat(appPath, L".Local"); - // Don't load the UI if the strings for the UI are not provided. - if (initUIStrings && InitProgressUIStrings() == -1) { - return -1; - } - - if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH)) { - return -1; - } + if (!_waccess(appPath, 04)) + { + return -1; + } - // Use an activation context that supports visual styles for the controls. - ACTCTXW actx = {0}; - actx.cbSize = sizeof(ACTCTXW); - actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; - actx.hModule = GetModuleHandle(NULL); // Use the embedded manifest - // This is needed only for Win XP but doesn't cause a problem with other - // versions of Windows. - actx.lpSource = appPath; - actx.lpResourceName = MAKEINTRESOURCE(IDR_COMCTL32_MANIFEST); - - HANDLE hactx = CreateActCtxW(&actx); - ULONG_PTR actxCookie = NULL; - if (hactx != INVALID_HANDLE_VALUE) { - // Push the specified activation context to the top of the activation stack. - ActivateActCtx(hactx, &actxCookie); - } + // Don't load the UI if the strings for the UI are not provided. + if (initUIStrings && InitProgressUIStrings() == -1) + { + return -1; + } - INITCOMMONCONTROLSEX icc = { - sizeof(INITCOMMONCONTROLSEX), - ICC_PROGRESS_CLASS - }; - InitCommonControlsEx(&icc); + if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH)) + { + return -1; + } - DialogBox(GetModuleHandle(nullptr), - MAKEINTRESOURCE(IDD_DIALOG), nullptr, - (DLGPROC) DialogProc); + // Use an activation context that supports visual styles for the controls. + ACTCTXW actx = {0}; + actx.cbSize = sizeof(ACTCTXW); + actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; + actx.hModule = GetModuleHandle(NULL); // Use the embedded manifest + // This is needed only for Win XP but doesn't cause a problem with other + // versions of Windows. + actx.lpSource = appPath; + actx.lpResourceName = MAKEINTRESOURCE(IDR_COMCTL32_MANIFEST); + + HANDLE hactx = CreateActCtxW(&actx); + ULONG_PTR actxCookie = NULL; + if (hactx != INVALID_HANDLE_VALUE) + { + // Push the specified activation context to the top of the activation stack. + ActivateActCtx(hactx, &actxCookie); + } - if (hactx != INVALID_HANDLE_VALUE) { - // Deactivate the context now that the comctl32.dll is loaded. - DeactivateActCtx(0, actxCookie); - } + INITCOMMONCONTROLSEX icc = + { + sizeof(INITCOMMONCONTROLSEX), + ICC_PROGRESS_CLASS + }; + InitCommonControlsEx(&icc); + + DialogBox(GetModuleHandle(nullptr), + MAKEINTRESOURCE(IDD_DIALOG), nullptr, + (DLGPROC) DialogProc); + + if (hactx != INVALID_HANDLE_VALUE) + { + // Deactivate the context now that the comctl32.dll is loaded. + DeactivateActCtx(0, actxCookie); + } - return 0; + return 0; } void QuitProgressUI() { - sQuit = TRUE; + sQuit = TRUE; } void UpdateProgressUI(float progress) { - sProgress = progress; // 32-bit writes are atomic + sProgress = progress; // 32-bit writes are atomic } #endif // WNT diff --git a/onlineupdate/source/update/updater/secondaryCert.h b/onlineupdate/source/update/updater/secondaryCert.h index 7453f27135dc..66e684bd133b 100644 --- a/onlineupdate/source/update/updater/secondaryCert.h +++ b/onlineupdate/source/update/updater/secondaryCert.h @@ -1,3 +1,4 @@ -const uint8_t secondaryCertData[] = { +const uint8_t secondaryCertData[] = +{ 0x30, 0x82, 0x02, 0xc3, 0x30, 0x82, 0x01, 0xab, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, 0xa7, 0x67, 0xe2, 0xee, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb3, 0x63, 0x91, 0x44, 0xf6, 0xf1, 0xd7, 0x7f, 0xc9, 0x3d, 0xee, 0x39, 0x44, 0xba, 0xd5, 0x1b, 0x68, 0x10, 0xfd, 0x2e, 0xb3, 0xe9, 0x17, 0xd8, 0x78, 0x18, 0xff, 0xbb, 0x63, 0x6f, 0x21, 0xd9, 0xb3, 0x55, 0x83, 0xe2, 0x90, 0x18, 0xba, 0x1e, 0x3b, 0x57, 0xbb, 0x4a, 0xc7, 0x4a, 0x3b, 0x49, 0x14, 0x1b, 0xe0, 0xc5, 0x01, 0x8e, 0xb3, 0xfc, 0xe0, 0x31, 0x21, 0xea, 0x6b, 0xc6, 0x5f, 0x70, 0x3c, 0x1f, 0x40, 0x9e, 0x6f, 0xf1, 0x37, 0xa0, 0x74, 0xc5, 0x55, 0xc7, 0x4d, 0x9c, 0xdd, 0x6b, 0xb4, 0xd3, 0x17, 0x22, 0x9e, 0x27, 0xea, 0x57, 0x45, 0x58, 0x19, 0x39, 0x18, 0x42, 0x37, 0x94, 0x8d, 0x11, 0xa1, 0xa9, 0xcb, 0xdd, 0x45, 0x7e, 0x82, 0xbf, 0x93, 0x75, 0xcc, 0x8d, 0x95, 0x04, 0x74, 0xc0, 0x84, 0x2e, 0x7d, 0xbc, 0x56, 0x2d, 0xd1, 0x0e, 0x2e, 0xbf, 0x0e, 0x52, 0x22, 0x0c, 0x65, 0xb2, 0x7a, 0x12, 0x14, 0x27, 0x0b, 0xc9, 0x37, 0x30, 0x48, 0xbc, 0xf0, 0xb8, 0x6d, 0x6f, 0x38, 0xda, 0x98, 0xd0, 0x1c, 0x87, 0xfe, 0x69, 0xc4, 0xc7, 0x73, 0xed, 0x78, 0x01, 0xa5, 0xea, 0x48, 0x08, 0x28, 0xcc, 0x0e, 0x52, 0x20, 0x1f, 0x46, 0x42, 0x83, 0x2e, 0xa6, 0xfd, 0x30, 0xc6, 0x48, 0x55, 0x78, 0xff, 0xd6, 0xac, 0xdd, 0x61, 0xd3, 0xb9, 0xdb, 0x49, 0x6b, 0x93, 0x5a, 0x5b, 0x37, 0xf5, 0xcb, 0x09, 0x4a, 0x6c, 0xa3, 0x85, 0x1f, 0xeb, 0x33, 0x3f, 0xd0, 0xda, 0x55, 0xc3, 0xb2, 0x56, 0x7d, 0x13, 0x16, 0x23, 0x2b, 0x1c, 0x3f, 0xdd, 0x1a, 0xf9, 0x90, 0xf7, 0x43, 0x63, 0x80, 0xa5, 0x71, 0xce, 0x23, 0x56, 0x1b, 0xbf, 0x51, 0x3a, 0xfe, 0x6b, 0x48, 0xfd, 0x42, 0x50, 0xc0, 0x09, 0x30, 0x32, 0x27, 0x20, 0x0d, 0xda, 0x32, 0x02, 0x23, 0x92, 0x10, 0x85, 0xbf, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0xb2, 0x3f, 0x45, 0x2c, 0xf5, 0x75, 0xeb, 0x20, 0x2f, 0x76, 0x6f, 0x18, 0x06, 0x42, 0x20, 0x83, 0x39, 0x50, 0x64, 0x07, 0xbb, 0xb1, 0x38, 0x74, 0xbe, 0xbb, 0xf4, 0x25, 0x11, 0x72, 0xf9, 0x4a, 0xf0, 0x9a, 0x0b, 0xe7, 0x45, 0x22, 0x59, 0x04, 0x7b, 0xa4, 0xe8, 0x46, 0xe5, 0x67, 0xdb, 0x9a, 0x9e, 0x27, 0x94, 0x5e, 0x60, 0x8b, 0xf5, 0xb1, 0x3f, 0xf2, 0xab, 0x1c, 0x54, 0xc8, 0xbc, 0x2b, 0x83, 0xf9, 0xa7, 0x18, 0x02, 0xb6, 0x95, 0xfa, 0xde, 0x16, 0x49, 0xca, 0xbd, 0x2e, 0xfc, 0xb6, 0x36, 0x9a, 0x9a, 0x7a, 0x1f, 0xc8, 0x91, 0xce, 0x30, 0xe2, 0x89, 0x58, 0x05, 0xee, 0xf3, 0xd1, 0xed, 0x79, 0x45, 0x20, 0xbd, 0x84, 0x48, 0xb0, 0x56, 0x8e, 0x04, 0xc8, 0xb7, 0x7e, 0x46, 0x2a, 0x2e, 0xb3, 0xca, 0xc1, 0xb6, 0x0b, 0xd4, 0x31, 0x6e, 0x83, 0x13, 0xe9, 0xa5, 0xbd, 0x17, 0x0e, 0x47, 0x34, 0x99, 0xc9, 0x5b, 0xb2, 0x53, 0x73, 0x57, 0xeb, 0x30, 0x0d, 0x2d, 0xaa, 0x25, 0xbb, 0xab, 0xac, 0xe8, 0xda, 0xf0, 0xf1, 0xd7, 0x2d, 0x17, 0x70, 0x9e, 0x30, 0x3c, 0x38, 0x59, 0xbf, 0x40, 0x3f, 0x6e, 0xe4, 0x22, 0x84, 0x94, 0x59, 0xf6, 0x32, 0xc1, 0xcb, 0x9c, 0x56, 0x52, 0x04, 0xeb, 0xf6, 0xa3, 0x75, 0xf8, 0xcb, 0xed, 0xaf, 0x17, 0x57, 0x8f, 0x98, 0x56, 0xa4, 0x9d, 0x85, 0x16, 0xc8, 0xf7, 0xd6, 0x97, 0xed, 0xab, 0xe0, 0x4c, 0x1a, 0x44, 0x5c, 0x68, 0x30, 0x26, 0x40, 0x6b, 0xe9, 0x88, 0x6a, 0x37, 0x1e, 0xbf, 0x25, 0x38, 0x55, 0xd9, 0x84, 0x8d, 0x55, 0x08, 0xe6, 0x18, 0xc3, 0xd7, 0x96, 0xfa, 0xd0, 0x2f, 0x17, 0x9b, 0xb6, 0x40, 0xc3, 0x47, 0xb3, 0x30, 0x01, 0x59, 0xec, 0x7c, 0x8d, 0x7e, 0x0a, 0x0d, 0xeb, 0xc4, 0x3b, 0x06, 0x4e, 0x97, 0x41, 0x5e }; diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx index 3a44d2bb0fa8..18cf8b2cc966 100644 --- a/onlineupdate/source/update/updater/updater.cxx +++ b/onlineupdate/source/update/updater/updater.cxx @@ -125,8 +125,8 @@ struct UpdateServerThreadArgs #endif BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra); BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, - LPCWSTR siblingFilePath, - LPCWSTR newFileName); + LPCWSTR siblingFilePath, + LPCWSTR newFileName); #include "updatehelper.h" // Closes the handle if valid and if the updater is elevated returns with the @@ -177,26 +177,31 @@ class AutoFile { public: explicit AutoFile(FILE* file = nullptr) - : mFile(file) { - } + : mFile(file) + { + } - ~AutoFile() { + ~AutoFile() + { if (mFile != nullptr) fclose(mFile); } - AutoFile &operator=(FILE* file) { + AutoFile &operator=(FILE* file) + { if (mFile != 0) fclose(mFile); mFile = file; return *this; } - operator FILE*() { + operator FILE*() + { return mFile; } - FILE* get() { + FILE* get() + { return mFile; } @@ -204,7 +209,8 @@ private: FILE* mFile; }; -struct MARChannelStringTable { +struct MARChannelStringTable +{ MARChannelStringTable() { MARChannelID[0] = '\0'; @@ -239,7 +245,8 @@ static const NS_tchar kQuote[] = NS_T("\""); static NS_tchar* mstrtok(const NS_tchar *delims, NS_tchar **str) { - if (!*str || !**str) { + if (!*str || !**str) + { *str = nullptr; return nullptr; } @@ -247,31 +254,40 @@ mstrtok(const NS_tchar *delims, NS_tchar **str) // skip leading "whitespace" NS_tchar *ret = *str; const NS_tchar *d; - do { - for (d = delims; *d != NS_T('\0'); ++d) { - if (*ret == *d) { + do + { + for (d = delims; *d != NS_T('\0'); ++d) + { + if (*ret == *d) + { ++ret; break; } } - } while (*d); + } + while (*d); - if (!*ret) { + if (!*ret) + { *str = ret; return nullptr; } NS_tchar *i = ret; - do { - for (d = delims; *d != NS_T('\0'); ++d) { - if (*i == *d) { + do + { + for (d = delims; *d != NS_T('\0'); ++d) + { + if (*i == *d) + { *i = NS_T('\0'); *str = ++i; return ret; } } ++i; - } while (*i); + } + while (*i); *str = nullptr; return ret; @@ -300,7 +316,8 @@ get_full_path(const NS_tchar *relpath) size_t lendestpath = NS_tstrlen(destpath); size_t lenrelpath = NS_tstrlen(relpath); NS_tchar *s = new NS_tchar[lendestpath + lenrelpath + 2]; - if (!s) { + if (!s) + { return nullptr; } @@ -330,9 +347,11 @@ get_relative_path(const NS_tchar *fullpath) { // If the path isn't absolute, just return it as-is. #ifdef _WIN32 - if (fullpath[1] != ':' && fullpath[2] != '\\') { + if (fullpath[1] != ':' && fullpath[2] != '\\') + { #else - if (fullpath[0] != '/') { + if (fullpath[0] != '/') + { #endif return fullpath; } @@ -340,7 +359,8 @@ get_relative_path(const NS_tchar *fullpath) NS_tchar *prefix = sStagedUpdate ? gWorkingDirPath : gInstallDirPath; // If the path isn't long enough to be absolute, return it as-is. - if (NS_tstrlen(fullpath) <= NS_tstrlen(prefix)) { + if (NS_tstrlen(fullpath) <= NS_tstrlen(prefix)) + { return fullpath; } @@ -361,30 +381,35 @@ static NS_tchar* get_valid_path(NS_tchar **line, bool isdir = false) { NS_tchar *path = mstrtok(kQuote, line); - if (!path) { + if (!path) + { LOG(("get_valid_path: unable to determine path: " LOG_S, line)); return nullptr; } // All paths must be relative from the current working directory - if (path[0] == NS_T('/')) { + if (path[0] == NS_T('/')) + { LOG(("get_valid_path: path must be relative: " LOG_S, path)); return nullptr; } #ifdef _WIN32 // All paths must be relative from the current working directory - if (path[0] == NS_T('\\') || path[1] == NS_T(':')) { + if (path[0] == NS_T('\\') || path[1] == NS_T(':')) + { LOG(("get_valid_path: path must be relative: " LOG_S, path)); return nullptr; } #endif - if (isdir) { + if (isdir) + { // Directory paths must have a trailing forward slash. - if (path[NS_tstrlen(path) - 1] != NS_T('/')) { + if (path[NS_tstrlen(path) - 1] != NS_T('/')) + { LOG(("get_valid_path: directory paths must have a trailing forward " \ - "slash: " LOG_S, path)); + "slash: " LOG_S, path)); return nullptr; } @@ -394,7 +419,8 @@ get_valid_path(NS_tchar **line, bool isdir = false) } // Don't allow relative paths that resolve to a parent directory. - if (NS_tstrstr(path, NS_T("..")) != nullptr) { + if (NS_tstrstr(path, NS_T("..")) != nullptr) + { LOG(("get_valid_path: paths must not contain '..': " LOG_S, path)); return nullptr; } @@ -431,7 +457,8 @@ static void ensure_write_permissions(const NS_tchar *path) (void) _wchmod(path, _S_IREAD | _S_IWRITE); #else struct stat fs; - if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) { + if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) + { (void)chmod(path, fs.st_mode | S_IWUSR); } #endif @@ -443,23 +470,25 @@ static int ensure_remove(const NS_tchar *path) int rv = NS_tremove(path); if (rv) LOG(("ensure_remove: failed to remove file: " LOG_S ", rv: %d, err: %d", - path, rv, errno)); + path, rv, errno)); return rv; } // Remove the directory pointed to by path and all of its files and sub-directories. static int ensure_remove_recursive(const NS_tchar *path, - bool continueEnumOnFailure = false) + bool continueEnumOnFailure = false) { // We use lstat rather than stat here so that we can successfully remove // symlinks. struct NS_tstat_t sInfo; int rv = NS_tlstat(path, &sInfo); - if (rv) { + if (rv) + { // This error is benign return rv; } - if (!S_ISDIR(sInfo.st_mode)) { + if (!S_ISDIR(sInfo.st_mode)) + { return ensure_remove(path); } @@ -467,20 +496,24 @@ static int ensure_remove_recursive(const NS_tchar *path, NS_tdirent *entry; dir = NS_topendir(path); - if (!dir) { + if (!dir) + { LOG(("ensure_remove_recursive: unable to open directory: " LOG_S - ", rv: %d, err: %d", path, rv, errno)); + ", rv: %d, err: %d", path, rv, errno)); return rv; } - while ((entry = NS_treaddir(dir)) != 0) { + while ((entry = NS_treaddir(dir)) != 0) + { if (NS_tstrcmp(entry->d_name, NS_T(".")) && - NS_tstrcmp(entry->d_name, NS_T(".."))) { + NS_tstrcmp(entry->d_name, NS_T(".."))) + { NS_tchar childPath[MAXPATHLEN]; NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]), - NS_T("%s/%s"), path, entry->d_name); + NS_T("%s/%s"), path, entry->d_name); rv = ensure_remove_recursive(childPath); - if (rv && !continueEnumOnFailure) { + if (rv && !continueEnumOnFailure) + { break; } } @@ -488,12 +521,14 @@ static int ensure_remove_recursive(const NS_tchar *path, NS_tclosedir(dir); - if (rv == OK) { + if (rv == OK) + { ensure_write_permissions(path); rv = NS_trmdir(path); - if (rv) { + if (rv) + { LOG(("ensure_remove_recursive: unable to remove directory: " LOG_S - ", rv: %d, err: %d", path, rv, errno)); + ", rv: %d, err: %d", path, rv, errno)); } } return rv; @@ -524,20 +559,25 @@ static FILE* ensure_open(const NS_tchar *path, const NS_tchar *flags, unsigned i { ensure_write_permissions(path); FILE* f = NS_tfopen(path, flags); - if (is_read_only(flags)) { + if (is_read_only(flags)) + { // Don't attempt to modify the file permissions if the file is being opened // in read-only mode. return f; } - if (NS_tchmod(path, options) != 0) { - if (f != nullptr) { + if (NS_tchmod(path, options) != 0) + { + if (f != nullptr) + { fclose(f); } return nullptr; } struct NS_tstat_t ss; - if (NS_tstat(path, &ss) != 0 || ss.st_mode != options) { - if (f != nullptr) { + if (NS_tstat(path, &ss) != 0 || ss.st_mode != options) + { + if (f != nullptr) + { fclose(f); } return nullptr; @@ -551,18 +591,23 @@ static int ensure_parent_dir(const NS_tchar *path) int rv = OK; NS_tchar *slash = (NS_tchar *) NS_tstrrchr(path, NS_T('/')); - if (slash) { + if (slash) + { *slash = NS_T('\0'); rv = ensure_parent_dir(path); // Only attempt to create the directory if we're not at the root - if (rv == OK && *path) { + if (rv == OK && *path) + { rv = NS_tmkdir(path, 0755); // If the directory already exists, then ignore the error. - if (rv < 0 && errno != EEXIST) { + if (rv < 0 && errno != EEXIST) + { LOG(("ensure_parent_dir: failed to create directory: " LOG_S ", " \ - "err: %d", path, errno)); + "err: %d", path, errno)); rv = WRITE_ERROR; - } else { + } + else + { rv = OK; } } @@ -577,15 +622,17 @@ static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest) // Copy symlinks by creating a new symlink to the same target NS_tchar target[MAXPATHLEN + 1] = {NS_T('\0')}; int rv = readlink(path, target, MAXPATHLEN); - if (rv == -1) { + if (rv == -1) + { LOG(("ensure_copy_symlink: failed to read the link: " LOG_S ", err: %d", - path, errno)); + path, errno)); return READ_ERROR; } rv = symlink(target, dest); - if (rv == -1) { + if (rv == -1) + { LOG(("ensure_copy_symlink: failed to create the new link: " LOG_S ", target: " LOG_S " err: %d", - dest, target, errno)); + dest, target, errno)); return READ_ERROR; } return 0; @@ -603,7 +650,8 @@ static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest) static int create_hard_link(const NS_tchar *srcFilename, const NS_tchar *destFilename) { - if (link(srcFilename, destFilename) < 0) { + if (link(srcFilename, destFilename) < 0) + { LOG(("link(%s, %s) failed errno = %d", srcFilename, destFilename, errno)); return WRITE_ERROR; } @@ -617,30 +665,35 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest) #ifdef _WIN32 // Fast path for Windows bool result = CopyFileW(path, dest, false); - if (!result) { + if (!result) + { LOG(("ensure_copy: failed to copy the file " LOG_S " over to " LOG_S ", lasterr: %x", - path, dest, GetLastError())); + path, dest, GetLastError())); return WRITE_ERROR_FILE_COPY; } return OK; #else struct NS_tstat_t ss; int rv = NS_tlstat(path, &ss); - if (rv) { + if (rv) + { LOG(("ensure_copy: failed to read file status info: " LOG_S ", err: %d", - path, errno)); + path, errno)); return READ_ERROR; } #ifdef UNIX - if (S_ISLNK(ss.st_mode)) { + if (S_ISLNK(ss.st_mode)) + { return ensure_copy_symlink(path, dest); } #endif #if MAYBE_USE_HARD_LINKS - if (sUseHardLinks) { - if (!create_hard_link(path, dest)) { + if (sUseHardLinks) + { + if (!create_hard_link(path, dest)) + { return OK; } // Since we failed to create the hard link, fall through and copy the file. @@ -649,15 +702,17 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest) #endif AutoFile infile(ensure_open(path, NS_T("rb"), ss.st_mode)); - if (!infile) { + if (!infile) + { LOG(("ensure_copy: failed to open the file for reading: " LOG_S ", err: %d", - path, errno)); + path, errno)); return READ_ERROR; } AutoFile outfile(ensure_open(dest, NS_T("wb"), ss.st_mode)); - if (!outfile) { + if (!outfile) + { LOG(("ensure_copy: failed to open the file for writing: " LOG_S ", err: %d", - dest, errno)); + dest, errno)); return WRITE_ERROR; } @@ -669,22 +724,26 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest) if (!buffer) return UPDATER_MEM_ERROR; - while (!feof(infile.get())) { + while (!feof(infile.get())) + { size_t read = fread(buffer, 1, blockSize, infile); - if (ferror(infile.get())) { + if (ferror(infile.get())) + { LOG(("ensure_copy: failed to read the file: " LOG_S ", err: %d", - path, errno)); + path, errno)); free(buffer); return READ_ERROR; } size_t written = 0; - while (written < read) { + while (written < read) + { size_t chunkWritten = fwrite(buffer, 1, read - written, outfile); - if (chunkWritten <= 0) { + if (chunkWritten <= 0) + { LOG(("ensure_copy: failed to write the file: " LOG_S ", err: %d", - dest, errno)); + dest, errno)); free(buffer); return WRITE_ERROR_FILE_COPY; } @@ -701,16 +760,21 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest) } template <unsigned N> -struct copy_recursive_skiplist { +struct copy_recursive_skiplist +{ NS_tchar paths[N][MAXPATHLEN]; - void append(unsigned index, const NS_tchar *path, const NS_tchar *suffix) { + void append(unsigned index, const NS_tchar *path, const NS_tchar *suffix) + { NS_tsnprintf(paths[index], MAXPATHLEN, NS_T("%s/%s"), path, suffix); } - bool find(const NS_tchar *path) { - for (int i = 0; i < static_cast<int>(N); ++i) { - if (!NS_tstricmp(paths[i], path)) { + bool find(const NS_tchar *path) + { + for (int i = 0; i < static_cast<int>(N); ++i) + { + if (!NS_tstricmp(paths[i], path)) + { return true; } } @@ -722,30 +786,34 @@ struct copy_recursive_skiplist { // The path names in the skiplist will be skipped and will not be copied. template <unsigned N> static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest, - copy_recursive_skiplist<N>& skiplist) + copy_recursive_skiplist<N>& skiplist) { struct NS_tstat_t sInfo; int rv = NS_tlstat(path, &sInfo); - if (rv) { + if (rv) + { LOG(("ensure_copy_recursive: path doesn't exist: " LOG_S ", rv: %d, err: %d", - path, rv, errno)); + path, rv, errno)); return READ_ERROR; } #ifdef UNIX - if (S_ISLNK(sInfo.st_mode)) { + if (S_ISLNK(sInfo.st_mode)) + { return ensure_copy_symlink(path, dest); } #endif - if (!S_ISDIR(sInfo.st_mode)) { + if (!S_ISDIR(sInfo.st_mode)) + { return ensure_copy(path, dest); } rv = NS_tmkdir(dest, sInfo.st_mode); - if (rv < 0 && errno != EEXIST) { + if (rv < 0 && errno != EEXIST) + { LOG(("ensure_copy_recursive: could not create destination directory: " LOG_S ", rv: %d, err: %d", - path, rv, errno)); + path, rv, errno)); return WRITE_ERROR; } @@ -753,26 +821,31 @@ static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest, NS_tdirent *entry; dir = NS_topendir(path); - if (!dir) { + if (!dir) + { LOG(("ensure_copy_recursive: path is not a directory: " LOG_S ", rv: %d, err: %d", - path, rv, errno)); + path, rv, errno)); return READ_ERROR; } - while ((entry = NS_treaddir(dir)) != 0) { + while ((entry = NS_treaddir(dir)) != 0) + { if (NS_tstrcmp(entry->d_name, NS_T(".")) && - NS_tstrcmp(entry->d_name, NS_T(".."))) { + NS_tstrcmp(entry->d_name, NS_T(".."))) + { NS_tchar childPath[MAXPATHLEN]; NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]), - NS_T("%s/%s"), path, entry->d_name); - if (skiplist.find(childPath)) { + NS_T("%s/%s"), path, entry->d_name); + if (skiplist.find(childPath)) + { continue; } NS_tchar childPathDest[MAXPATHLEN]; NS_tsnprintf(childPathDest, sizeof(childPathDest)/sizeof(childPathDest[0]), - NS_T("%s/%s"), dest, entry->d_name); + NS_T("%s/%s"), dest, entry->d_name); rv = ensure_copy_recursive(childPath, childPathDest, skiplist); - if (rv) { + if (rv) + { break; } } @@ -784,7 +857,7 @@ static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest, // Renames the specified file to the new file specified. If the destination file // exists it is removed. static int rename_file(const NS_tchar *spath, const NS_tchar *dpath, - bool allowDirs = false) + bool allowDirs = false) { int rv = ensure_parent_dir(dpath); if (rv) @@ -792,33 +865,41 @@ static int rename_file(const NS_tchar *spath, const NS_tchar *dpath, struct NS_tstat_t spathInfo; rv = NS_tstat(spath, &spathInfo); - if (rv) { + if (rv) + { LOG(("rename_file: failed to read file status info: " LOG_S ", " \ - "err: %d", spath, errno)); + "err: %d", spath, errno)); return READ_ERROR; } - if (!S_ISREG(spathInfo.st_mode)) { - if (allowDirs && !S_ISDIR(spathInfo.st_mode)) { + if (!S_ISREG(spathInfo.st_mode)) + { + if (allowDirs && !S_ISDIR(spathInfo.st_mode)) + { LOG(("rename_file: path present, but not a file: " LOG_S ", err: %d", - spath, errno)); + spath, errno)); return RENAME_ERROR_EXPECTED_FILE; - } else { + } + else + { LOG(("rename_file: proceeding to rename the directory")); } } - if (!NS_taccess(dpath, F_OK)) { - if (ensure_remove(dpath)) { + if (!NS_taccess(dpath, F_OK)) + { + if (ensure_remove(dpath)) + { LOG(("rename_file: destination file exists and could not be " \ - "removed: " LOG_S, dpath)); + "removed: " LOG_S, dpath)); return WRITE_ERROR_DELETE_FILE; } } - if (NS_trename(spath, dpath) != 0) { + if (NS_trename(spath, dpath) != 0) + { LOG(("rename_file: failed to rename file - src: " LOG_S ", " \ - "dst:" LOG_S ", err: %d", spath, dpath, errno)); + "dst:" LOG_S ", err: %d", spath, dpath, errno)); return WRITE_ERROR; } @@ -833,22 +914,27 @@ static int remove_recursive_on_reboot(const NS_tchar *path, const NS_tchar *dele { struct NS_tstat_t sInfo; int rv = NS_tlstat(path, &sInfo); - if (rv) { + if (rv) + { // This error is benign return rv; } - if (!S_ISDIR(sInfo.st_mode)) { + if (!S_ISDIR(sInfo.st_mode)) + { NS_tchar tmpDeleteFile[MAXPATHLEN]; GetTempFileNameW(deleteDir, L"rep", 0, tmpDeleteFile); NS_tremove(tmpDeleteFile); rv = rename_file(path, tmpDeleteFile, false); - if (MoveFileEx(rv ? path : tmpDeleteFile, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) { + if (MoveFileEx(rv ? path : tmpDeleteFile, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) + { LOG(("remove_recursive_on_reboot: file will be removed on OS reboot: " - LOG_S, rv ? path : tmpDeleteFile)); - } else { + LOG_S, rv ? path : tmpDeleteFile)); + } + else + { LOG(("remove_recursive_on_reboot: failed to schedule OS reboot removal of " - "file: " LOG_S, rv ? path : tmpDeleteFile)); + "file: " LOG_S, rv ? path : tmpDeleteFile)); } return rv; } @@ -857,19 +943,22 @@ static int remove_recursive_on_reboot(const NS_tchar *path, const NS_tchar *dele NS_tdirent *entry; dir = NS_topendir(path); - if (!dir) { + if (!dir) + { LOG(("remove_recursive_on_reboot: unable to open directory: " LOG_S - ", rv: %d, err: %d", - path, rv, errno)); + ", rv: %d, err: %d", + path, rv, errno)); return rv; } - while ((entry = NS_treaddir(dir)) != 0) { + while ((entry = NS_treaddir(dir)) != 0) + { if (NS_tstrcmp(entry->d_name, NS_T(".")) && - NS_tstrcmp(entry->d_name, NS_T(".."))) { + NS_tstrcmp(entry->d_name, NS_T(".."))) + { NS_tchar childPath[MAXPATHLEN]; NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]), - NS_T("%s/%s"), path, entry->d_name); + NS_T("%s/%s"), path, entry->d_name); // There is no need to check the return value of this call since this // function is only called after an update is successful and there is not // much that can be done to recover if it isn't successful. There is also @@ -880,12 +969,14 @@ static int remove_recursive_on_reboot(const NS_tchar *path, const NS_tchar *dele NS_tclosedir(dir); - if (rv == OK) { + if (rv == OK) + { ensure_write_permissions(path); rv = NS_trmdir(path); - if (rv) { + if (rv) + { LOG(("remove_recursive_on_reboot: unable to remove directory: " LOG_S - ", rv: %d, err: %d", path, rv, errno)); + ", rv: %d, err: %d", path, rv, errno)); } } return rv; @@ -899,7 +990,7 @@ static int backup_create(const NS_tchar *path) { NS_tchar backup[MAXPATHLEN]; NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]), - NS_T("%s") BACKUP_EXT, path); + NS_T("%s") BACKUP_EXT, path); return rename_file(path, backup); } @@ -910,13 +1001,14 @@ static int backup_restore(const NS_tchar *path, const NS_tchar *relPath) { NS_tchar backup[MAXPATHLEN]; NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]), - NS_T("%s") BACKUP_EXT, path); + NS_T("%s") BACKUP_EXT, path); NS_tchar relBackup[MAXPATHLEN]; NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]), - NS_T("%s") BACKUP_EXT, relPath); + NS_T("%s") BACKUP_EXT, relPath); - if (NS_taccess(backup, F_OK)) { + if (NS_taccess(backup, F_OK)) + { LOG(("backup_restore: backup file doesn't exist: " LOG_S, relBackup)); return OK; } @@ -929,26 +1021,29 @@ static int backup_discard(const NS_tchar *path, const NS_tchar *relPath) { NS_tchar backup[MAXPATHLEN]; NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]), - NS_T("%s") BACKUP_EXT, path); + NS_T("%s") BACKUP_EXT, path); NS_tchar relBackup[MAXPATHLEN]; NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]), - NS_T("%s") BACKUP_EXT, relPath); + NS_T("%s") BACKUP_EXT, relPath); // Nothing to discard - if (NS_taccess(backup, F_OK)) { + if (NS_taccess(backup, F_OK)) + { return OK; } int rv = ensure_remove(backup); #if defined(_WIN32) - if (rv && !sStagedUpdate && !sReplaceRequest) { + if (rv && !sStagedUpdate && !sReplaceRequest) + { LOG(("backup_discard: unable to remove: " LOG_S, relBackup)); NS_tchar path[MAXPATHLEN]; GetTempFileNameW(gDeleteDirPath, L"moz", 0, path); - if (rename_file(backup, path)) { + if (rename_file(backup, path)) + { LOG(("backup_discard: failed to rename file:" LOG_S ", dst:" LOG_S, - relBackup, relPath)); + relBackup, relPath)); return WRITE_ERROR_DELETE_BACKUP; } // The MoveFileEx call to remove the file on OS reboot will fail if the @@ -956,12 +1051,15 @@ static int backup_discard(const NS_tchar *path, const NS_tchar *relPath) // but this is ok since the installer / uninstaller will delete the // directory containing the file along with its contents after an update is // applied, on reinstall, and on uninstall. - if (MoveFileEx(path, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) { + if (MoveFileEx(path, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) + { LOG(("backup_discard: file renamed and will be removed on OS " \ - "reboot: " LOG_S, relPath)); - } else { + "reboot: " LOG_S, relPath)); + } + else + { LOG(("backup_discard: failed to schedule OS reboot removal of " \ - "file: " LOG_S, relPath)); + "file: " LOG_S, relPath)); } } #else @@ -974,7 +1072,7 @@ static int backup_discard(const NS_tchar *path, const NS_tchar *relPath) // Helper function for post-processing a temporary backup. static void backup_finish(const NS_tchar *path, const NS_tchar *relPath, - int status) + int status) { if (status == OK) backup_discard(path, relPath); @@ -1043,7 +1141,8 @@ RemoveFile::Parse(NS_tchar *line) NS_tstrcpy(mRelPath.get(), validPath); mFile.reset(get_full_path(validPath)); - if (!mFile) { + if (!mFile) + { return PARSE_ERROR; } @@ -1055,7 +1154,8 @@ RemoveFile::Prepare() { // Skip the file if it already doesn't exist. int rv = NS_taccess(mFile.get(), F_OK); - if (rv) { + if (rv) + { mSkip = 1; mProgressCost = 0; return OK; @@ -1066,27 +1166,33 @@ RemoveFile::Prepare() // Make sure that we're actually a file... struct NS_tstat_t fileInfo; rv = NS_tstat(mFile.get(), &fileInfo); - if (rv) { + if (rv) + { LOG(("failed to read file status info: " LOG_S ", err: %d", mFile.get(), - errno)); + errno)); return READ_ERROR; } - if (!S_ISREG(fileInfo.st_mode)) { + if (!S_ISREG(fileInfo.st_mode)) + { LOG(("path present, but not a file: " LOG_S, mFile.get())); return DELETE_ERROR_EXPECTED_FILE; } NS_tchar *slash = (NS_tchar *) NS_tstrrchr(mFile.get(), NS_T('/')); - if (slash) { + if (slash) + { *slash = NS_T('\0'); rv = NS_taccess(mFile.get(), W_OK); *slash = NS_T('/'); - } else { + } + else + { rv = NS_taccess(NS_T("."), W_OK); } - if (rv) { + if (rv) + { LOG(("access failed: %d", errno)); return WRITE_ERROR_FILE_ACCESS_DENIED; } @@ -1105,7 +1211,8 @@ RemoveFile::Execute() // The file is checked for existence here and in Prepare since it might have // been removed by a separate instruction: bug 311099. int rv = NS_taccess(mFile.get(), F_OK); - if (rv) { + if (rv) + { LOG(("file cannot be removed because it does not exist; skipping")); mSkip = 1; return OK; @@ -1113,7 +1220,8 @@ RemoveFile::Execute() // Rename the old file. It will be removed in Finish. rv = backup_create(mFile.get()); - if (rv) { + if (rv) + { LOG(("backup_create failed: %d", rv)); return rv; } @@ -1160,7 +1268,8 @@ RemoveDir::Parse(NS_tchar *line) NS_tstrcpy(mRelPath.get(), validPath); mDir.reset(get_full_path(validPath)); - if (!mDir) { + if (!mDir) + { return PARSE_ERROR; } @@ -1172,7 +1281,8 @@ RemoveDir::Prepare() { // We expect the directory to exist if we are to remove it. int rv = NS_taccess(mDir.get(), F_OK); - if (rv) { + if (rv) + { mSkip = 1; mProgressCost = 0; return OK; @@ -1183,19 +1293,22 @@ RemoveDir::Prepare() // Make sure that we're actually a dir. struct NS_tstat_t dirInfo; rv = NS_tstat(mDir.get(), &dirInfo); - if (rv) { + if (rv) + { LOG(("failed to read directory status info: " LOG_S ", err: %d", mRelPath.get(), - errno)); + errno)); return READ_ERROR; } - if (!S_ISDIR(dirInfo.st_mode)) { + if (!S_ISDIR(dirInfo.st_mode)) + { LOG(("path present, but not a directory: " LOG_S, mRelPath.get())); return DELETE_ERROR_EXPECTED_DIR; } rv = NS_taccess(mDir.get(), W_OK); - if (rv) { + if (rv) + { LOG(("access failed: %d, %d", rv, errno)); return WRITE_ERROR_DIR_ACCESS_DENIED; } @@ -1214,7 +1327,8 @@ RemoveDir::Execute() // The directory is checked for existence at every step since it might have // been removed by a separate instruction: bug 311099. int rv = NS_taccess(mDir.get(), F_OK); - if (rv) { + if (rv) + { LOG(("directory no longer exists; skipping")); mSkip = 1; } @@ -1233,16 +1347,19 @@ RemoveDir::Finish(int status) // The directory is checked for existence at every step since it might have // been removed by a separate instruction: bug 311099. int rv = NS_taccess(mDir.get(), F_OK); - if (rv) { + if (rv) + { LOG(("directory no longer exists; skipping")); return; } - if (status == OK) { - if (NS_trmdir(mDir.get())) { + if (status == OK) + { + if (NS_trmdir(mDir.get())) + { LOG(("non-fatal error removing directory: " LOG_S "/, rv: %d, err: %d", - mRelPath.get(), rv, errno)); + mRelPath.get(), rv, errno)); } } } @@ -1277,7 +1394,8 @@ AddFile::Parse(NS_tchar *line) NS_tstrcpy(mRelPath.get(), validPath); mFile.reset(get_full_path(validPath)); - if (!mFile) { + if (!mFile) + { return PARSE_ERROR; } @@ -1301,11 +1419,14 @@ AddFile::Execute() // First make sure that we can actually get rid of any existing file. rv = NS_taccess(mFile.get(), F_OK); - if (rv == 0) { + if (rv == 0) + { rv = backup_create(mFile.get()); if (rv) return rv; - } else { + } + else + { rv = ensure_parent_dir(mFile.get()); if (rv) return rv; @@ -1314,7 +1435,8 @@ AddFile::Execute() #ifdef _WIN32 char sourcefile[MAXPATHLEN]; if (!WideCharToMultiByte(CP_UTF8, 0, mRelPath.get(), -1, sourcefile, - MAXPATHLEN, nullptr, nullptr)) { + MAXPATHLEN, nullptr, nullptr)) + { LOG(("error converting wchar to utf8: %d", GetLastError())); return STRING_CONVERSION_ERROR; } @@ -1323,7 +1445,8 @@ AddFile::Execute() #else rv = gArchiveReader.ExtractFile(mRelPath.get(), mFile.get()); #endif - if (!rv) { + if (!rv) + { mAdded = true; } return rv; @@ -1376,7 +1499,8 @@ PatchFile::~PatchFile() // Normally this happens at the end of Execute, when we close the stream; // this call is here in case Execute errors out. #ifdef _WIN32 - if (mPatchStream) { + if (mPatchStream) + { UnlockFile((HANDLE)_get_osfhandle(fileno(mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1); } #endif @@ -1394,15 +1518,17 @@ PatchFile::LoadSourceFile(FILE* ofile) { struct stat os; int rv = fstat(fileno((FILE *)ofile), &os); - if (rv) { + if (rv) + { LOG(("LoadSourceFile: unable to stat destination file: " LOG_S ", " \ - "err: %d", mFileRelPath.get(), errno)); + "err: %d", mFileRelPath.get(), errno)); return READ_ERROR; } - if (uint32_t(os.st_size) != header.slen) { + if (uint32_t(os.st_size) != header.slen) + { LOG(("LoadSourceFile: destination file size %d does not match expected size %d", - uint32_t(os.st_size), header.slen)); + uint32_t(os.st_size), header.slen)); return LOADSOURCE_ERROR_WRONG_SIZE; } @@ -1412,12 +1538,14 @@ PatchFile::LoadSourceFile(FILE* ofile) size_t r = header.slen; unsigned char *rb = buf; - while (r) { + while (r) + { const size_t count = std::min<size_t>(SSIZE_MAX, r); size_t c = fread(rb, 1, count, ofile); - if (c != count) { + if (c != count) + { LOG(("LoadSourceFile: error reading destination file: " LOG_S, - mFileRelPath.get())); + mFileRelPath.get())); return READ_ERROR; } @@ -1429,9 +1557,10 @@ PatchFile::LoadSourceFile(FILE* ofile) unsigned int crc = crc32(buf, header.slen); - if (crc != header.scrc32) { + if (crc != header.scrc32) + { LOG(("LoadSourceFile: destination file crc %d does not match expected " \ - "crc %d", crc, header.scrc32)); + "crc %d", crc, header.scrc32)); return CRC_ERROR; } @@ -1460,7 +1589,8 @@ PatchFile::Parse(NS_tchar *line) NS_tstrcpy(mFileRelPath.get(), validPath); mFile.reset(get_full_path(validPath)); - if (!mFile) { + if (!mFile) + { return PARSE_ERROR; } @@ -1476,7 +1606,7 @@ PatchFile::Prepare() mPatchIndex = sPatchIndex++; NS_tsnprintf(spath, sizeof(spath)/sizeof(spath[0]), - NS_T("%s/updating/%d.patch"), gWorkingDirPath, mPatchIndex); + NS_T("%s/updating/%d.patch"), gWorkingDirPath, mPatchIndex); NS_tremove(spath); @@ -1487,14 +1617,16 @@ PatchFile::Prepare() #ifdef _WIN32 // Lock the patch file, so it can't be messed with between // when we're done creating it and when we go to apply it. - if (!LockFile((HANDLE)_get_osfhandle(fileno(mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1)) { + if (!LockFile((HANDLE)_get_osfhandle(fileno(mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1)) + { LOG(("Couldn't lock patch file: %d", GetLastError())); // TODO: moggi: fix the build problem with LOCK_ERROR_PATCH_FILE return WRITE_ERROR; //return LOCK_ERROR_PATCH_FILE; } char sourcefile[MAXPATHLEN]; if (!WideCharToMultiByte(CP_UTF8, 0, mPatchFile, -1, sourcefile, MAXPATHLEN, - nullptr, nullptr)) { + nullptr, nullptr)) + { LOG(("error converting wchar to utf8: %d", GetLastError())); return STRING_CONVERSION_ERROR; } @@ -1520,26 +1652,31 @@ PatchFile::Execute() FILE *origfile = nullptr; #ifdef _WIN32 - if (NS_tstrcmp(mFileRelPath.get(), gCallbackRelPath) == 0) { + if (NS_tstrcmp(mFileRelPath.get(), gCallbackRelPath) == 0) + { // Read from the copy of the callback when patching since the callback can't // be opened for reading to prevent the application from being launched. origfile = NS_tfopen(gCallbackBackupPath, NS_T("rb")); - } else { + } + else + { origfile = NS_tfopen(mFile.get(), NS_T("rb")); } #else origfile = NS_tfopen(mFile.get(), NS_T("rb")); #endif - if (!origfile) { + if (!origfile) + { LOG(("unable to open destination file: " LOG_S ", err: %d", - mFileRelPath.get(), errno)); + mFileRelPath.get(), errno)); return READ_ERROR; } rv = LoadSourceFile(origfile); fclose(origfile); - if (rv) { + if (rv) + { LOG(("LoadSourceFile failed")); return rv; } @@ -1548,9 +1685,10 @@ PatchFile::Execute() // used to restore the file to its original state if there is an error. struct NS_tstat_t ss; rv = NS_tstat(mFile.get(), &ss); - if (rv) { + if (rv) + { LOG(("failed to read file status info: " LOG_S ", err: %d", - mFileRelPath.get(), errno)); + mFileRelPath.get(), errno)); return READ_ERROR; } @@ -1571,51 +1709,57 @@ PatchFile::Execute() // not completely. There are also reports of _get_osfhandle failing on // mingw. HANDLE hfile = CreateFileW(mFile.get(), - GENERIC_WRITE, - 0, - nullptr, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - nullptr); - - if (hfile != INVALID_HANDLE_VALUE) { + GENERIC_WRITE, + 0, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr); + + if (hfile != INVALID_HANDLE_VALUE) + { if (SetFilePointer(hfile, header.dlen, - nullptr, FILE_BEGIN) != INVALID_SET_FILE_POINTER && - SetEndOfFile(hfile) != 0) { + nullptr, FILE_BEGIN) != INVALID_SET_FILE_POINTER && + SetEndOfFile(hfile) != 0) + { shouldTruncate = false; } CloseHandle(hfile); } AutoFile ofile(ensure_open(mFile.get(), shouldTruncate ? NS_T("wb+") : NS_T("rb+"), - ss.st_mode)); + ss.st_mode)); #elif defined(MACOSX) AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode)); // Modified code from FileUtils.cpp fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, header.dlen}; // Try to get a continuous chunk of disk space rv = fcntl(fileno((FILE *)ofile), F_PREALLOCATE, &store); - if (rv == -1) { + if (rv == -1) + { // OK, perhaps we are too fragmented, allocate non-continuous store.fst_flags = F_ALLOCATEALL; rv = fcntl(fileno((FILE *)ofile), F_PREALLOCATE, &store); } - if (rv != -1) { + if (rv != -1) + { ftruncate(fileno((FILE *)ofile), header.dlen); } #else AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode)); #endif - if (ofile == nullptr) { + if (ofile == nullptr) + { LOG(("unable to create new file: " LOG_S ", err: %d", mFileRelPath.get(), - errno)); + errno)); return WRITE_ERROR_OPEN_PATCH_FILE; } #ifdef _WIN32 - if (!shouldTruncate) { + if (!shouldTruncate) + { fseek(ofile, 0, SEEK_SET); } #endif @@ -1679,7 +1823,8 @@ int AddIfFile::Prepare() { // If the test file does not exist, then skip this action. - if (NS_taccess(mTestFile.get(), F_OK)) { + if (NS_taccess(mTestFile.get(), F_OK)) + { mTestFile = nullptr; return OK; } @@ -1738,7 +1883,8 @@ int AddIfNotFile::Prepare() { // If the test file exists, then skip this action. - if (!NS_taccess(mTestFile.get(), F_OK)) { + if (!NS_taccess(mTestFile.get(), F_OK)) + { mTestFile = NULL; return OK; } @@ -1797,7 +1943,8 @@ int PatchIfFile::Prepare() { // If the test file does not exist, then skip this action. - if (NS_taccess(mTestFile.get(), F_OK)) { + if (NS_taccess(mTestFile.get(), F_OK)) + { mTestFile = nullptr; return OK; } @@ -1838,7 +1985,7 @@ PatchIfFile::Finish(int status) */ bool LaunchWinPostProcess(const WCHAR *installationDir, - const WCHAR *updateInfoDir) + const WCHAR *updateInfoDir) { WCHAR workingDirectory[MAX_PATH + 1] = { L'\0' }; wcsncpy(workingDirectory, installationDir, MAX_PATH); @@ -1850,7 +1997,8 @@ LaunchWinPostProcess(const WCHAR *installationDir, // modifications) for the update. WCHAR inifile[MAX_PATH + 1] = { L'\0' }; wcsncpy(inifile, installationDir, MAX_PATH); - if (!PathAppendSafe(inifile, L"updater.ini")) { + if (!PathAppendSafe(inifile, L"updater.ini")) + { return false; } @@ -1859,48 +2007,56 @@ LaunchWinPostProcess(const WCHAR *installationDir, WCHAR exeasync[10]; bool async = true; if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", nullptr, - exefile, MAX_PATH + 1, inifile)) { + exefile, MAX_PATH + 1, inifile)) + { return false; } if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", nullptr, exearg, - MAX_PATH + 1, inifile)) { + MAX_PATH + 1, inifile)) + { return false; } if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE", - exeasync, - sizeof(exeasync)/sizeof(exeasync[0]), - inifile)) { + exeasync, + sizeof(exeasync)/sizeof(exeasync[0]), + inifile)) + { return false; } // Verify that exeFile doesn't contain relative paths - if (wcsstr(exefile, L"..") != nullptr) { + if (wcsstr(exefile, L"..") != nullptr) + { return false; } WCHAR exefullpath[MAX_PATH + 1] = { L'\0' }; wcsncpy(exefullpath, installationDir, MAX_PATH); - if (!PathAppendSafe(exefullpath, exefile)) { + if (!PathAppendSafe(exefullpath, exefile)) + { return false; } #if !defined(TEST_UPDATER) && defined(MAINTENANCE_SERVICE) if (sUsingService && - !DoesBinaryMatchAllowedCertificates(installationDir, exefullpath)) { + !DoesBinaryMatchAllowedCertificates(installationDir, exefullpath)) + { return false; } #endif WCHAR dlogFile[MAX_PATH + 1]; - if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) { + if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) + { return false; } WCHAR slogFile[MAX_PATH + 1] = { L'\0' }; wcsncpy(slogFile, updateInfoDir, MAX_PATH); - if (!PathAppendSafe(slogFile, L"update.log")) { + if (!PathAppendSafe(slogFile, L"update.log")) + { return false; } @@ -1909,7 +2065,8 @@ LaunchWinPostProcess(const WCHAR *installationDir, size_t len = wcslen(exearg) + wcslen(dummyArg); WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR)); - if (!cmdline) { + if (!cmdline) + { return false; } @@ -1918,7 +2075,8 @@ LaunchWinPostProcess(const WCHAR *installationDir, if (sUsingService || !_wcsnicmp(exeasync, L"false", 6) || - !_wcsnicmp(exeasync, L"0", 2)) { + !_wcsnicmp(exeasync, L"0", 2)) + { async = false; } @@ -1932,18 +2090,20 @@ LaunchWinPostProcess(const WCHAR *installationDir, PROCESS_INFORMATION pi = {0}; bool ok = CreateProcessW(exefullpath, - cmdline, - nullptr, // no special security attributes - nullptr, // no special thread attributes - false, // don't inherit filehandles - 0, // No special process creation flags - nullptr, // inherit my environment - workingDirectory, - &si, - &pi); + cmdline, + nullptr, // no special security attributes + nullptr, // no special thread attributes + false, // don't inherit filehandles + 0, // No special process creation flags + nullptr, // inherit my environment + workingDirectory, + &si, + &pi); free(cmdline); - if (ok) { - if (!async) { + if (ok) + { + if (!async) + { WaitForSingleObject(pi.hProcess, INFINITE); } CloseHandle(pi.hProcess); @@ -1956,9 +2116,9 @@ LaunchWinPostProcess(const WCHAR *installationDir, static void LaunchCallbackApp(const NS_tchar *workingDir, - int argc, - NS_tchar **argv, - bool usingService) + int argc, + NS_tchar **argv, + bool usingService) { putenv(const_cast<char*>("NO_EM_RESTART=")); putenv(const_cast<char*>("MOZ_LAUNCHED_CHILD=1")); @@ -1966,19 +2126,22 @@ LaunchCallbackApp(const NS_tchar *workingDir, // Run from the specified working directory (see bug 312360). This is not // necessary on Windows CE since the application that launches the updater // passes the working directory as an --environ: command line argument. - if (NS_tchdir(workingDir) != 0) { + if (NS_tchdir(workingDir) != 0) + { LOG(("Warning: chdir failed")); } #if defined(USE_EXECV) - (void) argc; (void) usingService; // avoid warnings + (void) argc; + (void) usingService; // avoid warnings execv(argv[0], argv); #elif defined(MACOSX) LaunchChild(argc, (const char**)argv); #elif defined(WNT) // Do not allow the callback to run when running an update through the // service as session 0. The unelevated updater.exe will do the launching. - if (!usingService) { + if (!usingService) + { WinLaunchChild(argv[0], argc, argv, nullptr); } #else @@ -1996,7 +2159,7 @@ WriteStatusFile(const char* aStatus) GetTempFileNameW(gPatchDirPath, L"sta", 0, filename); #else NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]), - NS_T("%s/update.status"), gPatchDirPath); + NS_T("%s/update.status"), gPatchDirPath); #endif // Make sure that the directory for the update status file exists @@ -2007,11 +2170,13 @@ WriteStatusFile(const char* aStatus) // move the temp file to the update.status file on Windows. { AutoFile file(NS_tfopen(filename, NS_T("wb+"))); - if (file == nullptr) { + if (file == nullptr) + { return false; } - if (fwrite(aStatus, strlen(aStatus), 1, file) != 1) { + if (fwrite(aStatus, strlen(aStatus), 1, file) != 1) + { return false; } } @@ -2019,8 +2184,9 @@ WriteStatusFile(const char* aStatus) #if defined(_WIN32) NS_tchar dstfilename[MAXPATHLEN] = {NS_T('\0')}; NS_tsnprintf(dstfilename, sizeof(dstfilename)/sizeof(dstfilename[0]), - NS_T("%s\\update.status"), gPatchDirPath); - if (MoveFileExW(filename, dstfilename, MOVEFILE_REPLACE_EXISTING) == 0) { + NS_T("%s\\update.status"), gPatchDirPath); + if (MoveFileExW(filename, dstfilename, MOVEFILE_REPLACE_EXISTING) == 0) + { return false; } #endif @@ -2034,13 +2200,19 @@ WriteStatusFile(int status) const char *text; char buf[32]; - if (status == OK) { - if (sStagedUpdate) { + if (status == OK) + { + if (sStagedUpdate) + { text = "applied\n"; - } else { + } + else + { text = "succeeded\n"; } - } else { + } + else + { snprintf(buf, sizeof(buf)/sizeof(buf[0]), "failed: %d\n", status); text = buf; } @@ -2063,7 +2235,7 @@ IsUpdateStatusPendingService() { NS_tchar filename[MAXPATHLEN]; NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]), - NS_T("%s/update.status"), gPatchDirPath); + NS_T("%s/update.status"), gPatchDirPath); AutoFile file(NS_tfopen(filename, NS_T("rb"))); if (file == nullptr) @@ -2076,9 +2248,9 @@ IsUpdateStatusPendingService() const char kAppliedService[] = "applied-service"; return (strncmp(buf, kPendingService, - sizeof(kPendingService) - 1) == 0) || - (strncmp(buf, kAppliedService, - sizeof(kAppliedService) - 1) == 0); + sizeof(kPendingService) - 1) == 0) || + (strncmp(buf, kAppliedService, + sizeof(kAppliedService) - 1) == 0); } #endif @@ -2097,7 +2269,7 @@ IsUpdateStatusSucceeded(bool &isSucceeded) isSucceeded = false; NS_tchar filename[MAXPATHLEN]; NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]), - NS_T("%s/update.status"), gPatchDirPath); + NS_T("%s/update.status"), gPatchDirPath); AutoFile file(NS_tfopen(filename, NS_T("rb"))); if (file == nullptr) @@ -2108,7 +2280,7 @@ IsUpdateStatusSucceeded(bool &isSucceeded) const char kSucceeded[] = "succeeded"; isSucceeded = strncmp(buf, kSucceeded, - sizeof(kSucceeded) - 1) == 0; + sizeof(kSucceeded) - 1) == 0; return true; } #endif @@ -2159,7 +2331,7 @@ ProcessReplaceRequest() #ifdef MACOSX NS_tchar destDir[MAXPATHLEN]; NS_tsnprintf(destDir, sizeof(destDir)/sizeof(destDir[0]), - NS_T("%s/Contents"), gInstallDirPath); + NS_T("%s/Contents"), gInstallDirPath); #elif defined(WNT) // Windows preserves the case of the file/directory names. We use the // GetLongPathName API in order to get the correct case for the directory @@ -2167,7 +2339,8 @@ ProcessReplaceRequest() // application, the installation directory's name does not change. NS_tchar destDir[MAXPATHLEN]; if (!GetLongPathNameW(gInstallDirPath, destDir, - sizeof(destDir)/sizeof(destDir[0]))) { + sizeof(destDir)/sizeof(destDir[0]))) + { return NO_INSTALLDIR_ERROR; } #else @@ -2176,16 +2349,16 @@ ProcessReplaceRequest() NS_tchar tmpDir[MAXPATHLEN]; NS_tsnprintf(tmpDir, sizeof(tmpDir)/sizeof(tmpDir[0]), - NS_T("%s.bak"), destDir); + NS_T("%s.bak"), destDir); NS_tchar newDir[MAXPATHLEN]; NS_tsnprintf(newDir, sizeof(newDir)/sizeof(newDir[0]), #ifdef MACOSX - NS_T("%s/Contents"), - gWorkingDirPath); + NS_T("%s/Contents"), + gWorkingDirPath); #else - NS_T("%s.bak/updated"), - gInstallDirPath); + NS_T("%s.bak/updated"), + gInstallDirPath); #endif // First try to remove the possibly existing temp directory, because if this @@ -2195,7 +2368,7 @@ ProcessReplaceRequest() ensure_remove_recursive(tmpDir); LOG(("Begin moving destDir (" LOG_S ") to tmpDir (" LOG_S ")", - destDir, tmpDir)); + destDir, tmpDir)); int rv = rename_file(destDir, tmpDir, true); #ifdef _WIN32 // On Windows, if Firefox is launched using the shortcut, it will hold a handle @@ -2204,17 +2377,19 @@ ProcessReplaceRequest() // If it's not released, we just fail to perform the replace request. const int max_retries = 10; int retries = 0; - while (rv == WRITE_ERROR && (retries++ < max_retries)) { + while (rv == WRITE_ERROR && (retries++ < max_retries)) + { LOG(("PerformReplaceRequest: destDir rename attempt %d failed. " \ - "File: " LOG_S ". Last error: %d, err: %d", retries, - destDir, GetLastError(), rv)); + "File: " LOG_S ". Last error: %d, err: %d", retries, + destDir, GetLastError(), rv)); Sleep(100); rv = rename_file(destDir, tmpDir, true); } #endif - if (rv) { + if (rv) + { // The status file will have 'pending' written to it so there is no value in // returning an error specific for this failure. LOG(("Moving destDir to tmpDir failed, err: %d", rv)); @@ -2222,22 +2397,25 @@ ProcessReplaceRequest() } LOG(("Begin moving newDir (" LOG_S ") to destDir (" LOG_S ")", - newDir, destDir)); + newDir, destDir)); rv = rename_file(newDir, destDir, true); #ifdef MACOSX - if (rv) { + if (rv) + { LOG(("Moving failed. Begin copying newDir (" LOG_S ") to destDir (" LOG_S ")", - newDir, destDir)); + newDir, destDir)); copy_recursive_skiplist<0> skiplist; rv = ensure_copy_recursive(newDir, destDir, skiplist); } #endif - if (rv) { + if (rv) + { LOG(("Moving newDir to destDir failed, err: %d", rv)); LOG(("Now, try to move tmpDir back to destDir")); ensure_remove_recursive(destDir); int rv2 = rename_file(tmpDir, destDir, true); - if (rv2) { + if (rv2) + { LOG(("Moving tmpDir back to destDir failed, err: %d", rv2)); } // The status file will be have 'pending' written to it so there is no value @@ -2251,11 +2429,12 @@ ProcessReplaceRequest() // old installation directory to the new installation directory. NS_tchar tmpLog[MAXPATHLEN]; NS_tsnprintf(tmpLog, sizeof(tmpLog)/sizeof(tmpLog[0]), - NS_T("%s/updates/last-update.log"), tmpDir); - if (!NS_taccess(tmpLog, F_OK)) { + NS_T("%s/updates/last-update.log"), tmpDir); + if (!NS_taccess(tmpLog, F_OK)) + { NS_tchar destLog[MAXPATHLEN]; NS_tsnprintf(destLog, sizeof(destLog)/sizeof(destLog[0]), - NS_T("%s/updates/last-update.log"), destDir); + NS_T("%s/updates/last-update.log"), destDir); NS_tremove(destLog); NS_trename(tmpLog, destLog); } @@ -2263,16 +2442,18 @@ ProcessReplaceRequest() LOG(("Now, remove the tmpDir")); rv = ensure_remove_recursive(tmpDir, true); - if (rv) { + if (rv) + { LOG(("Removing tmpDir failed, err: %d", rv)); #ifdef _WIN32 NS_tchar deleteDir[MAXPATHLEN]; NS_tsnprintf(deleteDir, sizeof(deleteDir)/sizeof(deleteDir[0]), - NS_T("%s\\%s"), destDir, DELETE_DIR); + NS_T("%s\\%s"), destDir, DELETE_DIR); // Attempt to remove the tobedeleted directory and then recreate it if it // was successfully removed. _wrmdir(deleteDir); - if (NS_taccess(deleteDir, F_OK)) { + if (NS_taccess(deleteDir, F_OK)) + { NS_tmkdir(deleteDir, 0755); } remove_recursive_on_reboot(tmpDir, deleteDir); @@ -2284,7 +2465,7 @@ ProcessReplaceRequest() // directory has been moved. NS_tchar updatedAppDir[MAXPATHLEN]; NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir)/sizeof(updatedAppDir[0]), - NS_T("%s/Updated.app"), gPatchDirPath); + NS_T("%s/Updated.app"), gPatchDirPath); ensure_remove_recursive(updatedAppDir); #endif @@ -2322,7 +2503,7 @@ ReadMARChannelIDs(const NS_tchar *path, MARChannelStringTable *results) char updater_strings[kNumStrings][MAX_TEXT_LEN]; int result = ReadStrings(path, kUpdaterKeys, kNumStrings, - updater_strings, "Settings"); + updater_strings, "Settings"); strncpy(results->MARChannelID, updater_strings[0], MAX_TEXT_LEN - 1); results->MARChannelID[MAX_TEXT_LEN - 1] = 0; @@ -2337,7 +2518,7 @@ GetUpdateFileName(NS_tchar *fileName, int maxChars) // TODO: moggi: needs adaption for LibreOffice // We would like to store the name inside of an ini file NS_tsnprintf(fileName, maxChars, - NS_T("%s/update.mar"), gPatchDirPath); + NS_T("%s/update.mar"), gPatchDirPath); return OK; } @@ -2346,36 +2527,45 @@ UpdateThreadFunc(void * /*param*/) { // open ZIP archive and process... int rv; - if (sReplaceRequest) { + if (sReplaceRequest) + { rv = ProcessReplaceRequest(); - } else { + } + else + { NS_tchar dataFile[MAXPATHLEN]; rv = GetUpdateFileName(dataFile, sizeof(dataFile)/sizeof(dataFile[0])); - if (rv == OK) { + if (rv == OK) + { rv = gArchiveReader.Open(dataFile); } #ifdef VERIFY_MAR_SIGNATURE - if (rv == OK) { + if (rv == OK) + { #ifdef _WIN32 HKEY baseKey = nullptr; wchar_t valueName[] = L"Image Path"; wchar_t rasenh[] = L"rsaenh.dll"; bool reset = false; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Enhanced Cryptographic Provider v1.0", - 0, KEY_READ | KEY_WRITE, - &baseKey) == ERROR_SUCCESS) { + L"SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Enhanced Cryptographic Provider v1.0", + 0, KEY_READ | KEY_WRITE, + &baseKey) == ERROR_SUCCESS) + { wchar_t path[MAX_PATH + 1]; DWORD size = sizeof(path); DWORD type; if (RegQueryValueExW(baseKey, valueName, 0, &type, - (LPBYTE)path, &size) == ERROR_SUCCESS) { - if (type == REG_SZ && wcscmp(path, rasenh) == 0) { + (LPBYTE)path, &size) == ERROR_SUCCESS) + { + if (type == REG_SZ && wcscmp(path, rasenh) == 0) + { wchar_t rasenhFullPath[] = L"%SystemRoot%\\System32\\rsaenh.dll"; if (RegSetValueExW(baseKey, valueName, 0, REG_SZ, - (const BYTE*)rasenhFullPath, - sizeof(rasenhFullPath)) == ERROR_SUCCESS) { + (const BYTE*)rasenhFullPath, + sizeof(rasenhFullPath)) == ERROR_SUCCESS) + { reset = true; } } @@ -2384,33 +2574,38 @@ UpdateThreadFunc(void * /*param*/) #endif rv = gArchiveReader.VerifySignature(); #ifdef _WIN32 - if (baseKey) { - if (reset) { + if (baseKey) + { + if (reset) + { RegSetValueExW(baseKey, valueName, 0, REG_SZ, - (const BYTE*)rasenh, - sizeof(rasenh)); + (const BYTE*)rasenh, + sizeof(rasenh)); } RegCloseKey(baseKey); } #endif } - if (rv == OK) { - if (rv == OK) { + if (rv == OK) + { + if (rv == OK) + { NS_tchar updateSettingsPath[MAX_TEXT_LEN]; // TODO: moggi: needs adaption for LibreOffice // These paths need to be adapted for us. NS_tsnprintf(updateSettingsPath, - sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]), + sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]), #ifdef MACOSX - NS_T("%s/Contents/Resources/update-settings.ini"), + NS_T("%s/Contents/Resources/update-settings.ini"), #else - NS_T("%s/update-settings.ini"), + NS_T("%s/update-settings.ini"), #endif - gWorkingDirPath); + gWorkingDirPath); MARChannelStringTable MARStrings; - if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) { + if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) + { // If we can't read from update-settings.ini then we shouldn't impose // a MAR restriction. Some installations won't even include this file. MARStrings.MARChannelID[0] = '\0'; @@ -2422,14 +2617,18 @@ UpdateThreadFunc(void * /*param*/) } #endif - if (rv == OK && sStagedUpdate) { + if (rv == OK && sStagedUpdate) + { #ifdef TEST_UPDATER // The MOZ_TEST_SKIP_UPDATE_STAGE environment variable prevents copying // the files in dist/bin in the test updater when staging an update since // this can cause tests to timeout. - if (EnvHasValue("MOZ_TEST_SKIP_UPDATE_STAGE")) { + if (EnvHasValue("MOZ_TEST_SKIP_UPDATE_STAGE")) + { rv = OK; - } else { + } + else + { rv = CopyInstallDirToDestDir(); } #else @@ -2437,23 +2636,27 @@ UpdateThreadFunc(void * /*param*/) #endif } - if (rv == OK) { + if (rv == OK) + { rv = DoUpdate(); gArchiveReader.Close(); NS_tchar updatingDir[MAXPATHLEN]; NS_tsnprintf(updatingDir, sizeof(updatingDir)/sizeof(updatingDir[0]), - NS_T("%s/updating"), gWorkingDirPath); + NS_T("%s/updating"), gWorkingDirPath); ensure_remove_recursive(updatingDir); } } - if (rv && (sReplaceRequest || sStagedUpdate)) { + if (rv && (sReplaceRequest || sStagedUpdate)) + { #ifdef _WIN32 // On Windows, the current working directory of the process should be changed // so that it's not locked. - if (sStagedUpdate) { + if (sStagedUpdate) + { NS_tchar sysDir[MAX_PATH + 1] = { L'\0' }; - if (GetSystemDirectoryW(sysDir, MAX_PATH + 1)) { + if (GetSystemDirectoryW(sysDir, MAX_PATH + 1)) + { NS_tchdir(sysDir); } } @@ -2466,24 +2669,33 @@ UpdateThreadFunc(void * /*param*/) // startup path will see the pending status, and will start the // updater application again in order to apply the update without // staging. - if (sReplaceRequest) { + if (sReplaceRequest) + { WriteStatusFile(sUsingService ? "pending-service" : "pending"); - } else { + } + else + { WriteStatusFile(rv); } #ifdef TEST_UPDATER // Some tests need to use --test-process-updates again. putenv(const_cast<char*>("MOZ_TEST_PROCESS_UPDATES=")); #endif - } else { - if (rv) { + } + else + { + if (rv) + { LOG(("failed: %d", rv)); - } else { + } + else + { #ifdef MACOSX // If the update was successful we need to update the timestamp on the // top-level Mac OS X bundle directory so that Mac OS X's Launch Services // picks up any major changes when the bundle is updated. - if (!sStagedUpdate && utimes(gInstallDirPath, nullptr) != 0) { + if (!sStagedUpdate && utimes(gInstallDirPath, nullptr) != 0) + { LOG(("Couldn't set access/modification time on application bundle.")); } #endif @@ -2503,7 +2715,8 @@ ServeElevatedUpdateThreadFunc(void* param) { UpdateServerThreadArgs* threadArgs = (UpdateServerThreadArgs*)param; gSucceeded = ServeElevatedUpdate(threadArgs->argc, threadArgs->argv); - if (!gSucceeded) { + if (!gSucceeded) + { WriteStatusFile(ELEVATION_CANCELED); } QuitProgressUI(); @@ -2511,7 +2724,8 @@ ServeElevatedUpdateThreadFunc(void* param) void freeArguments(int argc, char** argv) { - for (int i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) + { free(argv[i]); } free(argv); @@ -2519,19 +2733,22 @@ void freeArguments(int argc, char** argv) #endif int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, - int callbackIndex + int callbackIndex #ifdef _WIN32 - , const WCHAR* elevatedLockFilePath - , HANDLE updateLockFileHandle + , const WCHAR* elevatedLockFilePath + , HANDLE updateLockFileHandle #elif defined(MACOSX) - , bool isElevated + , bool isElevated #endif - ) + ) { - if (argc > callbackIndex) { + if (argc > callbackIndex) + { #if defined(_WIN32) - if (gSucceeded) { - if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) { + if (gSucceeded) + { + if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) + { fprintf(stderr, "The post update process was not launched"); } @@ -2542,27 +2759,30 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv, // service if the service failed to apply the update. We want to update // the service to a newer version in that case. If we are not running // through the service, then USING_SERVICE will not exist. - if (!sUsingService) { + if (!sUsingService) + { StartServiceUpdate(gInstallDirPath); } } EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0); #elif defined(MACOSX) - if (!isElevated) { - if (gSucceeded) { + if (!isElevated) + { + if (gSucceeded) + { LaunchMacPostProcess(gInstallDirPath); } #endif - LaunchCallbackApp(argv[5], - argc - callbackIndex, - argv + callbackIndex, - sUsingService); + LaunchCallbackApp(argv[5], + argc - callbackIndex, + argv + callbackIndex, + sUsingService); #ifdef XP_MACOSX - } // if (!isElevated) + } // if (!isElevated) #endif /* XP_MACOSX */ - } - return 0; +} +return 0; } int NS_main(int argc, NS_tchar **argv) @@ -2576,8 +2796,10 @@ int NS_main(int argc, NS_tchar **argv) // TODO: moggi: needs adaption for LibreOffice bool isElevated = strstr(argv[0], "/Library/PrivilegedHelperTools/org.mozilla.updater") != 0; - if (isElevated) { - if (!ObtainUpdaterArguments(&argc, &argv)) { + if (isElevated) + { + if (!ObtainUpdaterArguments(&argc, &argv)) + { // Won't actually get here because ObtainUpdaterArguments will terminate // the current process on failure. return 1; @@ -2590,7 +2812,8 @@ int NS_main(int argc, NS_tchar **argv) // need to initialize NSS at all there. // Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS // databases. - if (NSS_NoDB_Init(NULL) != SECSuccess) { + if (NSS_NoDB_Init(NULL) != SECSuccess) + { PRErrorCode error = PR_GetError(); fprintf(stderr, "Could not initialize NSS: %s (%d)", PR_ErrorToName(error), (int) error); @@ -2599,7 +2822,8 @@ int NS_main(int argc, NS_tchar **argv) #endif #ifdef MACOSX - if (!isElevated) { + if (!isElevated) + { #endif InitProgressUI(&argc, &argv); #ifdef MACOSX @@ -2620,10 +2844,12 @@ int NS_main(int argc, NS_tchar **argv) // arguments are provided whether the update was successful or not. All // remaining arguments are optional and are passed to the callback when it is // launched. - if (argc < 4) { + if (argc < 4) + { fprintf(stderr, "Usage: updater patch-dir install-dir apply-to-dir [wait-pid [callback-working-dir callback-path args...]]\n"); #ifdef MACOSX - if (isElevated) { + if (isElevated) + { freeArguments(argc, argv); CleanupElevatedMacUpdate(true); } @@ -2641,7 +2867,8 @@ int NS_main(int argc, NS_tchar **argv) NS_tstrncpy(gInstallDirPath, argv[2], MAXPATHLEN); gInstallDirPath[MAXPATHLEN - 1] = NS_T('\0'); NS_tchar *slash = NS_tstrrchr(gInstallDirPath, NS_SLASH); - if (slash && !slash[1]) { + if (slash && !slash[1]) + { *slash = NS_T('\0'); } @@ -2665,13 +2892,14 @@ int NS_main(int argc, NS_tchar **argv) // TODO: moggi: needs adaption for LibreOffice HKEY hkApp = nullptr; RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Classes\\Applications", - 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, nullptr, - &hkApp, nullptr); + 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, nullptr, + &hkApp, nullptr); RegCloseKey(hkApp); if (RegCreateKeyExW(HKEY_CURRENT_USER, - L"Software\\Classes\\Applications\\updater.exe", - 0, nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE, nullptr, - &hkApp, nullptr) == ERROR_SUCCESS) { + L"Software\\Classes\\Applications\\updater.exe", + 0, nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE, nullptr, + &hkApp, nullptr) == ERROR_SUCCESS) + { RegSetValueExW(hkApp, L"IsHostApp", 0, REG_NONE, 0, 0); RegSetValueExW(hkApp, L"NoOpenWith", 0, REG_NONE, 0, 0); RegSetValueExW(hkApp, L"NoStartPage", 0, REG_NONE, 0, 0); @@ -2686,17 +2914,21 @@ int NS_main(int argc, NS_tchar **argv) #else int pid = 0; #endif - if (argc > 4) { + if (argc > 4) + { #ifdef _WIN32 pid = _wtoi64(argv[4]); #else pid = atoi(argv[4]); #endif - if (pid == -1) { + if (pid == -1) + { // This is a signal from the parent process that the updater should stage // the update. sStagedUpdate = true; - } else if (NS_tstrstr(argv[4], NS_T("/replace"))) { + } + else if (NS_tstrstr(argv[4], NS_T("/replace"))) + { // We're processing a request to replace the application with a staged // update. sReplaceRequest = true; @@ -2710,12 +2942,14 @@ int NS_main(int argc, NS_tchar **argv) NS_tstrncpy(gWorkingDirPath, argv[3], MAXPATHLEN); gWorkingDirPath[MAXPATHLEN - 1] = NS_T('\0'); slash = NS_tstrrchr(gWorkingDirPath, NS_SLASH); - if (slash && !slash[1]) { + if (slash && !slash[1]) + { *slash = NS_T('\0'); } #ifdef MACOSX - if (!isElevated && !IsRecursivelyWritable(argv[2])) { + if (!isElevated && !IsRecursivelyWritable(argv[2])) + { // If the app directory isn't recursively writeable, an elevated update is // required. UpdateServerThreadArgs threadArgs; @@ -2723,7 +2957,8 @@ int NS_main(int argc, NS_tchar **argv) threadArgs.argv = const_cast<const NS_tchar**>(argv); Thread t1; - if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0) { + if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0) + { // Show an indeterminate progress bar while an elevated update is in // progress. ShowProgressUI(true); @@ -2737,10 +2972,12 @@ int NS_main(int argc, NS_tchar **argv) LogInit(gPatchDirPath, NS_T("update.log")); - if (!WriteStatusFile("applying")) { + if (!WriteStatusFile("applying")) + { LOG(("failed setting status to 'applying'")); #ifdef MACOSX - if (isElevated) { + if (isElevated) + { freeArguments(argc, argv); CleanupElevatedMacUpdate(true); } @@ -2748,9 +2985,12 @@ int NS_main(int argc, NS_tchar **argv) return 1; } - if (sStagedUpdate) { + if (sStagedUpdate) + { LOG(("Performing a staged update")); - } else if (sReplaceRequest) { + } + else if (sReplaceRequest) + { LOG(("Performing a replace request")); } @@ -2759,30 +2999,34 @@ int NS_main(int argc, NS_tchar **argv) LOG(("WORKING DIRECTORY " LOG_S, gWorkingDirPath)); #ifdef _WIN32 - if (_wcsnicmp(gWorkingDirPath, gInstallDirPath, MAX_PATH) != 0) { - if (!sStagedUpdate && !sReplaceRequest) { + if (_wcsnicmp(gWorkingDirPath, gInstallDirPath, MAX_PATH) != 0) + { + if (!sStagedUpdate && !sReplaceRequest) + { WriteStatusFile(INVALID_APPLYTO_DIR_ERROR); LOG(("Installation directory and working directory must be the same " - "for non-staged updates. Exiting.")); + "for non-staged updates. Exiting.")); LogFinish(); return 1; } NS_tchar workingDirParent[MAX_PATH]; NS_tsnprintf(workingDirParent, - sizeof(workingDirParent) / sizeof(workingDirParent[0]), - NS_T("%s"), gWorkingDirPath); - if (!PathRemoveFileSpecW(workingDirParent)) { + sizeof(workingDirParent) / sizeof(workingDirParent[0]), + NS_T("%s"), gWorkingDirPath); + if (!PathRemoveFileSpecW(workingDirParent)) + { WriteStatusFile(REMOVE_FILE_SPEC_ERROR); LOG(("Error calling PathRemoveFileSpecW: %d", GetLastError())); LogFinish(); return 1; } - if (_wcsnicmp(workingDirParent, gInstallDirPath, MAX_PATH) != 0) { + if (_wcsnicmp(workingDirParent, gInstallDirPath, MAX_PATH) != 0) + { WriteStatusFile(INVALID_APPLYTO_DIR_STAGED_ERROR); LOG(("The apply-to directory must be the same as or " - "a child of the installation directory! Exiting.")); + "a child of the installation directory! Exiting.")); LogFinish(); return 1; } @@ -2791,12 +3035,14 @@ int NS_main(int argc, NS_tchar **argv) #ifdef _WIN32 - if (pid > 0) { + if (pid > 0) + { HANDLE parent = OpenProcess(SYNCHRONIZE, false, (DWORD) pid); // May return nullptr if the parent process has already gone away. // Otherwise, wait for the parent process to exit before starting the // update. - if (parent) { + if (parent) + { DWORD waitTime = PARENT_WAIT; DWORD result = WaitForSingleObject(parent, waitTime); CloseHandle(parent); @@ -2826,15 +3072,19 @@ int NS_main(int argc, NS_tchar **argv) HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE; NS_tchar elevatedLockFilePath[MAXPATHLEN] = {NS_T('\0')}; if (!sUsingService && - (argc > callbackIndex || sStagedUpdate || sReplaceRequest)) { + (argc > callbackIndex || sStagedUpdate || sReplaceRequest)) + { NS_tchar updateLockFilePath[MAXPATHLEN]; - if (sStagedUpdate) { + if (sStagedUpdate) + { // When staging an update, the lock file is: // <install_dir>\updated.update_in_progress.lock NS_tsnprintf(updateLockFilePath, - sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]), - NS_T("%s/updated.update_in_progress.lock"), gInstallDirPath); - } else if (sReplaceRequest) { + sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]), + NS_T("%s/updated.update_in_progress.lock"), gInstallDirPath); + } + else if (sReplaceRequest) + { // When processing a replace request, the lock file is: // <install_dir>\..\moz_update_in_progress.lock NS_tchar installDir[MAXPATHLEN]; @@ -2842,24 +3092,28 @@ int NS_main(int argc, NS_tchar **argv) NS_tchar *slash = (NS_tchar *) NS_tstrrchr(installDir, NS_SLASH); *slash = NS_T('\0'); NS_tsnprintf(updateLockFilePath, - sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]), - NS_T("%s\\moz_update_in_progress.lock"), installDir); - } else { + sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]), + NS_T("%s\\moz_update_in_progress.lock"), installDir); + } + else + { // In the non-staging update case, the lock file is: // <install_dir>\<app_name>.exe.update_in_progress.lock NS_tsnprintf(updateLockFilePath, - sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]), - NS_T("%s.update_in_progress.lock"), argv[callbackIndex]); + sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]), + NS_T("%s.update_in_progress.lock"), argv[callbackIndex]); } // The update_in_progress.lock file should only exist during an update. In // case it exists attempt to remove it and exit if that fails to prevent // simultaneous updates occurring. if (!_waccess(updateLockFilePath, F_OK) && - NS_tremove(updateLockFilePath) != 0) { + NS_tremove(updateLockFilePath) != 0) + { // Try to fall back to the old way of doing updates if a staged // update fails. - if (sStagedUpdate || sReplaceRequest) { + if (sStagedUpdate || sReplaceRequest) + { // Note that this could fail, but if it does, there isn't too much we // can do in order to recover anyways. WriteStatusFile("pending"); @@ -2869,16 +3123,16 @@ int NS_main(int argc, NS_tchar **argv) } updateLockFileHandle = CreateFileW(updateLockFilePath, - GENERIC_READ | GENERIC_WRITE, - 0, - nullptr, - OPEN_ALWAYS, - FILE_FLAG_DELETE_ON_CLOSE, - nullptr); + GENERIC_READ | GENERIC_WRITE, + 0, + nullptr, + OPEN_ALWAYS, + FILE_FLAG_DELETE_ON_CLOSE, + nullptr); NS_tsnprintf(elevatedLockFilePath, - sizeof(elevatedLockFilePath)/sizeof(elevatedLockFilePath[0]), - NS_T("%s/update_elevated.lock"), gPatchDirPath); + sizeof(elevatedLockFilePath)/sizeof(elevatedLockFilePath[0]), + NS_T("%s/update_elevated.lock"), gPatchDirPath); // Even if a file has no sharing access, you can still get its attributes bool startedFromUnelevatedUpdater = @@ -2890,36 +3144,41 @@ int NS_main(int argc, NS_tchar **argv) // updater, then we drop the permissions here. We do not drop the // permissions on the originally called updater because we use its token // to start the callback application. - if (startedFromUnelevatedUpdater) { + if (startedFromUnelevatedUpdater) + { // Disable every privilege we don't need. Processes started using // CreateProcess will use the same token as this process. UACHelper::DisablePrivileges(nullptr); } if (updateLockFileHandle == INVALID_HANDLE_VALUE || - (useService && testOnlyFallbackKeyExists && noServiceFallback)) { + (useService && testOnlyFallbackKeyExists && noServiceFallback)) + { if (!_waccess(elevatedLockFilePath, F_OK) && - NS_tremove(elevatedLockFilePath) != 0) { + NS_tremove(elevatedLockFilePath) != 0) + { fprintf(stderr, "Unable to create elevated lock file! Exiting\n"); return 1; } HANDLE elevatedFileHandle; elevatedFileHandle = CreateFileW(elevatedLockFilePath, - GENERIC_READ | GENERIC_WRITE, - 0, - nullptr, - OPEN_ALWAYS, - FILE_FLAG_DELETE_ON_CLOSE, - nullptr); - - if (elevatedFileHandle == INVALID_HANDLE_VALUE) { + GENERIC_READ | GENERIC_WRITE, + 0, + nullptr, + OPEN_ALWAYS, + FILE_FLAG_DELETE_ON_CLOSE, + nullptr); + + if (elevatedFileHandle == INVALID_HANDLE_VALUE) + { LOG(("Unable to create elevated lock file! Exiting")); return 1; } wchar_t *cmdLine = MakeCommandLine(argc - 1, argv + 1); - if (!cmdLine) { + if (!cmdLine) + { CloseHandle(elevatedFileHandle); return 1; } @@ -2927,7 +3186,8 @@ int NS_main(int argc, NS_tchar **argv) // Make sure the path to the updater to use for the update is on local. // We do this check to make sure that file locking is available for // race condition security checks. - if (useService) { + if (useService) + { BOOL isLocal = FALSE; useService = IsLocalFile(argv[0], isLocal) && isLocal; } @@ -2938,36 +3198,46 @@ int NS_main(int argc, NS_tchar **argv) // Windows 8 provides a user interface so users can configure this // behavior and it can be configured in the registry in all Windows // versions that support UAC. - if (useService) { + if (useService) + { BOOL unpromptedElevation; - if (IsUnpromptedElevation(unpromptedElevation)) { + if (IsUnpromptedElevation(unpromptedElevation)) + { useService = !unpromptedElevation; } } // Make sure the service registry entries for the installation path // are available. If not don't use the service. - if (useService) { + if (useService) + { WCHAR maintenanceServiceKey[MAX_PATH + 1]; // TODO: moggi: needs adaption for LibreOffice // Most likely the registry part is not correct yet if (CalculateRegistryPathFromFilePath(gInstallDirPath, - maintenanceServiceKey)) { + maintenanceServiceKey)) + { HKEY baseKey = nullptr; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - maintenanceServiceKey, 0, - KEY_READ | KEY_WOW64_64KEY, - &baseKey) == ERROR_SUCCESS) { + maintenanceServiceKey, 0, + KEY_READ | KEY_WOW64_64KEY, + &baseKey) == ERROR_SUCCESS) + { RegCloseKey(baseKey); - } else { + } + else + { #ifdef TEST_UPDATER useService = testOnlyFallbackKeyExists; #endif - if (!useService) { + if (!useService) + { lastFallbackError = FALLBACKKEY_NOKEY_ERROR; } } - } else { + } + else + { useService = false; lastFallbackError = FALLBACKKEY_REGPATH_ERROR; } @@ -2981,16 +3251,19 @@ int NS_main(int argc, NS_tchar **argv) // If we still want to use the service try to launch the service // comamnd for the update. - if (useService) { + if (useService) + { // If the update couldn't be started, then set useService to false so // we do the update the old way. DWORD ret = LaunchServiceSoftwareUpdateCommand(argc, (LPCWSTR *)argv); useService = (ret == ERROR_SUCCESS); // If the command was launched then wait for the service to be done. - if (useService) { + if (useService) + { bool showProgressUI = false; // Never show the progress UI when staging updates. - if (!sStagedUpdate) { + if (!sStagedUpdate) + { // We need to call this separately instead of allowing ShowProgressUI // to initialize the strings because the service will move the // ini file out of the way when running updater. @@ -3000,22 +3273,27 @@ int NS_main(int argc, NS_tchar **argv) // Wait for the service to stop for 5 seconds. If the service // has still not stopped then show an indeterminate progress bar. DWORD lastState = WaitForServiceStop(SVC_NAME, 5); - if (lastState != SERVICE_STOPPED) { + if (lastState != SERVICE_STOPPED) + { std::thread waitThread(WaitForServiceFinishThread, nullptr); - if (showProgressUI) { + if (showProgressUI) + { ShowProgressUI(true, false); } waitThread.join(); } lastState = WaitForServiceStop(SVC_NAME, 1); - if (lastState != SERVICE_STOPPED) { + if (lastState != SERVICE_STOPPED) + { // If the service doesn't stop after 10 minutes there is // something seriously wrong. lastFallbackError = FALLBACKKEY_SERVICE_NO_STOP_ERROR; useService = false; } - } else { + } + else + { lastFallbackError = FALLBACKKEY_LAUNCH_ERROR; } } @@ -3023,8 +3301,10 @@ int NS_main(int argc, NS_tchar **argv) // If the service can't be used when staging and update, make sure that // the UAC prompt is not shown! In this case, just set the status to // pending and the update will be applied during the next startup. - if (!useService && sStagedUpdate) { - if (updateLockFileHandle != INVALID_HANDLE_VALUE) { + if (!useService && sStagedUpdate) + { + if (updateLockFileHandle != INVALID_HANDLE_VALUE) + { CloseHandle(updateLockFileHandle); } WriteStatusFile("pending"); @@ -3038,11 +3318,14 @@ int NS_main(int argc, NS_tchar **argv) // current process is running as. // Note that we don't need to do this if we're just staging the update, // as the PostUpdate step runs when performing the replacing in that case. - if (useService && !sStagedUpdate) { + if (useService && !sStagedUpdate) + { bool updateStatusSucceeded = false; if (IsUpdateStatusSucceeded(updateStatusSucceeded) && - updateStatusSucceeded) { - if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) { + updateStatusSucceeded) + { + if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) + { fprintf(stderr, "The post update process which runs as the user" " for service update could not be launched."); } @@ -3056,13 +3339,14 @@ int NS_main(int argc, NS_tchar **argv) // write access all along because in that case the only reason we're // using the service is because we are testing. if (!useService && !noServiceFallback && - updateLockFileHandle == INVALID_HANDLE_VALUE) { + updateLockFileHandle == INVALID_HANDLE_VALUE) + { SHELLEXECUTEINFO sinfo; memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO)); sinfo.cbSize = sizeof(SHELLEXECUTEINFO); sinfo.fMask = SEE_MASK_FLAG_NO_UI | - SEE_MASK_FLAG_DDEWAIT | - SEE_MASK_NOCLOSEPROCESS; + SEE_MASK_FLAG_DDEWAIT | + SEE_MASK_NOCLOSEPROCESS; sinfo.hwnd = nullptr; sinfo.lpFile = argv[0]; sinfo.lpParameters = cmdLine; @@ -3072,35 +3356,45 @@ int NS_main(int argc, NS_tchar **argv) bool result = ShellExecuteEx(&sinfo); free(cmdLine); - if (result) { + if (result) + { WaitForSingleObject(sinfo.hProcess, INFINITE); CloseHandle(sinfo.hProcess); - } else { + } + else + { WriteStatusFile(ELEVATION_CANCELED); } } - if (argc > callbackIndex) { + if (argc > callbackIndex) + { LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, sUsingService); + argv + callbackIndex, sUsingService); } CloseHandle(elevatedFileHandle); if (!useService && !noServiceFallback && - INVALID_HANDLE_VALUE == updateLockFileHandle) { + INVALID_HANDLE_VALUE == updateLockFileHandle) + { // We didn't use the service and we did run the elevated updater.exe. // The elevated updater.exe is responsible for writing out the // update.status file. return 0; - } else if (useService) { + } + else if (useService) + { // The service command was launched. The service is responsible for // writing out the update.status file. - if (updateLockFileHandle != INVALID_HANDLE_VALUE) { + if (updateLockFileHandle != INVALID_HANDLE_VALUE) + { CloseHandle(updateLockFileHandle); } return 0; - } else { + } + else + { // Otherwise the service command was not launched at all. // We are only reaching this code path because we had write access // all along to the directory and a fallback key existed, and we @@ -3114,17 +3408,21 @@ int NS_main(int argc, NS_tchar **argv) } #endif - if (sStagedUpdate) { + if (sStagedUpdate) + { // When staging updates, blow away the old installation directory and create // it from scratch. ensure_remove_recursive(gWorkingDirPath); } - if (!sReplaceRequest) { + if (!sReplaceRequest) + { // Try to create the destination directory if it doesn't exist int rv = NS_tmkdir(gWorkingDirPath, 0755); - if (rv != OK && errno != EEXIST) { + if (rv != OK && errno != EEXIST) + { #ifdef MACOSX - if (isElevated) { + if (isElevated) + { freeArguments(argc, argv); CleanupElevatedMacUpdate(true); } @@ -3136,7 +3434,8 @@ int NS_main(int argc, NS_tchar **argv) #ifdef _WIN32 // For replace requests, we don't need to do any real updates, so this is not // necessary. - if (!sReplaceRequest) { + if (!sReplaceRequest) + { // Allocate enough space for the length of the path an optional additional // trailing slash and null termination. NS_tchar *destpath = (NS_tchar *) malloc((NS_tstrlen(gWorkingDirPath) + 2) * sizeof(NS_tchar)); @@ -3147,7 +3446,8 @@ int NS_main(int argc, NS_tchar **argv) NS_tstrcpy(c, gWorkingDirPath); c += NS_tstrlen(gWorkingDirPath); if (gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('/') && - gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('\\')) { + gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('\\')) + { NS_tstrcat(c, NS_T("/")); c += NS_tstrlen(NS_T("/")); } @@ -3159,20 +3459,23 @@ int NS_main(int argc, NS_tchar **argv) NS_tchar applyDirLongPath[MAXPATHLEN]; if (!GetLongPathNameW(gWorkingDirPath, applyDirLongPath, - sizeof(applyDirLongPath)/sizeof(applyDirLongPath[0]))) { + sizeof(applyDirLongPath)/sizeof(applyDirLongPath[0]))) + { LOG(("NS_main: unable to find apply to dir: " LOG_S, gWorkingDirPath)); LogFinish(); WriteStatusFile(WRITE_ERROR_APPLY_DIR_PATH); EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); - if (argc > callbackIndex) { + if (argc > callbackIndex) + { LaunchCallbackApp(argv[5], argc - callbackIndex, - argv + callbackIndex, sUsingService); + argv + callbackIndex, sUsingService); } return 1; } HANDLE callbackFile = INVALID_HANDLE_VALUE; - if (argc > callbackIndex) { + if (argc > callbackIndex) + { // If the callback executable is specified it must exist for a successful // update. It is important we null out the whole buffer here because later // we make the assumption that the callback application is inside the @@ -3183,12 +3486,13 @@ int NS_main(int argc, NS_tchar **argv) NS_tchar *targetPath = argv[callbackIndex]; NS_tchar buffer[MAXPATHLEN * 2] = { NS_T('\0') }; size_t bufferLeft = MAXPATHLEN * 2; - if (sReplaceRequest) { + if (sReplaceRequest) + { // In case of replace requests, we should look for the callback file in // the destination directory. size_t commonPrefixLength = PathCommonPrefixW(argv[callbackIndex], - gInstallDirPath, - nullptr); + gInstallDirPath, + nullptr); NS_tchar *p = buffer; NS_tstrncpy(p, argv[callbackIndex], commonPrefixLength); p += commonPrefixLength; @@ -3205,29 +3509,32 @@ int NS_main(int argc, NS_tchar **argv) NS_tchar installDir[MAXPATHLEN]; NS_tstrcpy(installDir, gInstallDirPath); size_t callbackPrefixLength = PathCommonPrefixW(argv[callbackIndex], - installDir, - nullptr); + installDir, + nullptr); NS_tstrncpy(p, argv[callbackIndex] + std::max(callbackPrefixLength, commonPrefixLength), bufferLeft); targetPath = buffer; } if (!GetLongPathNameW(targetPath, callbackLongPath, - sizeof(callbackLongPath)/sizeof(callbackLongPath[0]))) { + sizeof(callbackLongPath)/sizeof(callbackLongPath[0]))) + { LOG(("NS_main: unable to find callback file: " LOG_S, targetPath)); LogFinish(); WriteStatusFile(WRITE_ERROR_CALLBACK_PATH); EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); - if (argc > callbackIndex) { + if (argc > callbackIndex) + { LaunchCallbackApp(argv[5], - argc - callbackIndex, - argv + callbackIndex, - sUsingService); + argc - callbackIndex, + argv + callbackIndex, + sUsingService); } return 1; } // Doing this is only necessary when we're actually applying a patch. - if (!sReplaceRequest) { + if (!sReplaceRequest) + { int len = NS_tstrlen(applyDirLongPath); NS_tchar *s = callbackLongPath; NS_tchar *d = gCallbackRelPath; @@ -3239,160 +3546,182 @@ int NS_main(int argc, NS_tchar **argv) // Copy the string and replace backslashes with forward slashes along the // way. - do { + do + { if (*s == NS_T('\\')) *d = NS_T('/'); else *d = *s; ++s; ++d; - } while (*s); + } + while (*s); *d = NS_T('\0'); ++d; // Make a copy of the callback executable so it can be read when patching. NS_tsnprintf(gCallbackBackupPath, - sizeof(gCallbackBackupPath)/sizeof(gCallbackBackupPath[0]), - NS_T("%s" CALLBACK_BACKUP_EXT), argv[callbackIndex]); + sizeof(gCallbackBackupPath)/sizeof(gCallbackBackupPath[0]), + NS_T("%s" CALLBACK_BACKUP_EXT), argv[callbackIndex]); NS_tremove(gCallbackBackupPath); - if(!CopyFileW(argv[callbackIndex], gCallbackBackupPath, true)) { + if (!CopyFileW(argv[callbackIndex], gCallbackBackupPath, true)) + { DWORD copyFileError = GetLastError(); LOG(("NS_main: failed to copy callback file " LOG_S - " into place at " LOG_S, argv[callbackIndex], gCallbackBackupPath)); + " into place at " LOG_S, argv[callbackIndex], gCallbackBackupPath)); LogFinish(); - if (copyFileError == ERROR_ACCESS_DENIED) { + if (copyFileError == ERROR_ACCESS_DENIED) + { WriteStatusFile(WRITE_ERROR_ACCESS_DENIED); - } else { + } + else + { + WriteStatusFile(WRITE_ERROR_CALLBACK_APP); + } + + EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); + LaunchCallbackApp(argv[callbackIndex], + argc - callbackIndex, + argv + callbackIndex, + sUsingService); + return 1; + } + + // Since the process may be signaled as exited by WaitForSingleObject before + // the release of the executable image try to lock the main executable file + // multiple times before giving up. If we end up giving up, we won't + // fail the update. + const int max_retries = 10; + int retries = 1; + DWORD lastWriteError = 0; + do + { + // By opening a file handle wihout FILE_SHARE_READ to the callback + // executable, the OS will prevent launching the process while it is + // being updated. + callbackFile = CreateFileW(targetPath, + DELETE | GENERIC_WRITE, + // allow delete, rename, and write + FILE_SHARE_DELETE | FILE_SHARE_WRITE, + nullptr, OPEN_EXISTING, 0, nullptr); + if (callbackFile != INVALID_HANDLE_VALUE) + break; + + lastWriteError = GetLastError(); + LOG(("NS_main: callback app file open attempt %d failed. " \ + "File: " LOG_S ". Last error: %d", retries, + targetPath, lastWriteError)); + + Sleep(100); + } + while (++retries <= max_retries); + + // CreateFileW will fail if the callback executable is already in use. + if (callbackFile == INVALID_HANDLE_VALUE) + { + // Only fail the update if the last error was not a sharing violation. + if (lastWriteError != ERROR_SHARING_VIOLATION) + { + LOG(("NS_main: callback app file in use, failed to exclusively open " \ + "executable file: " LOG_S, argv[callbackIndex])); + LogFinish(); + if (lastWriteError == ERROR_ACCESS_DENIED) + { + WriteStatusFile(WRITE_ERROR_ACCESS_DENIED); + } + else + { WriteStatusFile(WRITE_ERROR_CALLBACK_APP); } + NS_tremove(gCallbackBackupPath); EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); - LaunchCallbackApp(argv[callbackIndex], - argc - callbackIndex, - argv + callbackIndex, - sUsingService); + LaunchCallbackApp(argv[5], + argc - callbackIndex, + argv + callbackIndex, + sUsingService); return 1; } - - // Since the process may be signaled as exited by WaitForSingleObject before - // the release of the executable image try to lock the main executable file - // multiple times before giving up. If we end up giving up, we won't - // fail the update. - const int max_retries = 10; - int retries = 1; - DWORD lastWriteError = 0; - do { - // By opening a file handle wihout FILE_SHARE_READ to the callback - // executable, the OS will prevent launching the process while it is - // being updated. - callbackFile = CreateFileW(targetPath, - DELETE | GENERIC_WRITE, - // allow delete, rename, and write - FILE_SHARE_DELETE | FILE_SHARE_WRITE, - nullptr, OPEN_EXISTING, 0, nullptr); - if (callbackFile != INVALID_HANDLE_VALUE) - break; - - lastWriteError = GetLastError(); - LOG(("NS_main: callback app file open attempt %d failed. " \ - "File: " LOG_S ". Last error: %d", retries, - targetPath, lastWriteError)); - - Sleep(100); - } while (++retries <= max_retries); - - // CreateFileW will fail if the callback executable is already in use. - if (callbackFile == INVALID_HANDLE_VALUE) { - // Only fail the update if the last error was not a sharing violation. - if (lastWriteError != ERROR_SHARING_VIOLATION) { - LOG(("NS_main: callback app file in use, failed to exclusively open " \ - "executable file: " LOG_S, argv[callbackIndex])); - LogFinish(); - if (lastWriteError == ERROR_ACCESS_DENIED) { - WriteStatusFile(WRITE_ERROR_ACCESS_DENIED); - } else { - WriteStatusFile(WRITE_ERROR_CALLBACK_APP); - } - - NS_tremove(gCallbackBackupPath); - EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1); - LaunchCallbackApp(argv[5], - argc - callbackIndex, - argv + callbackIndex, - sUsingService); - return 1; - } - LOG(("NS_main: callback app file in use, continuing without " \ - "exclusive access for executable file: " LOG_S, - argv[callbackIndex])); - } + LOG(("NS_main: callback app file in use, continuing without " \ + "exclusive access for executable file: " LOG_S, + argv[callbackIndex])); } } + } - // DELETE_DIR is not required when performing a staged update or replace - // request; it can be used during a replace request but then it doesn't - // use gDeleteDirPath. - if (!sStagedUpdate && !sReplaceRequest) { - // The directory to move files that are in use to on Windows. This directory - // will be deleted after the update is finished, on OS reboot using - // MoveFileEx if it contains files that are in use, or by the post update - // process after the update finishes. On Windows when performing a normal - // update (e.g. the update is not a staged update and is not a replace - // request) gWorkingDirPath is the same as gInstallDirPath and - // gWorkingDirPath is used because it is the destination directory. - NS_tsnprintf(gDeleteDirPath, - sizeof(gDeleteDirPath) / sizeof(gDeleteDirPath[0]), - NS_T("%s/%s"), gWorkingDirPath, DELETE_DIR); - - if (NS_taccess(gDeleteDirPath, F_OK)) { - NS_tmkdir(gDeleteDirPath, 0755); - } + // DELETE_DIR is not required when performing a staged update or replace + // request; it can be used during a replace request but then it doesn't + // use gDeleteDirPath. + if (!sStagedUpdate && !sReplaceRequest) + { + // The directory to move files that are in use to on Windows. This directory + // will be deleted after the update is finished, on OS reboot using + // MoveFileEx if it contains files that are in use, or by the post update + // process after the update finishes. On Windows when performing a normal + // update (e.g. the update is not a staged update and is not a replace + // request) gWorkingDirPath is the same as gInstallDirPath and + // gWorkingDirPath is used because it is the destination directory. + NS_tsnprintf(gDeleteDirPath, + sizeof(gDeleteDirPath) / sizeof(gDeleteDirPath[0]), + NS_T("%s/%s"), gWorkingDirPath, DELETE_DIR); + + if (NS_taccess(gDeleteDirPath, F_OK)) + { + NS_tmkdir(gDeleteDirPath, 0755); } + } #endif /* _WIN32 */ - // Run update process on a background thread. ShowProgressUI may return - // before QuitProgressUI has been called, so wait for UpdateThreadFunc to - // terminate. Avoid showing the progress UI when staging an update, or if this - // is an elevated process on OSX. - std::thread t(UpdateThreadFunc, nullptr); - if (!sStagedUpdate && !sReplaceRequest + // Run update process on a background thread. ShowProgressUI may return + // before QuitProgressUI has been called, so wait for UpdateThreadFunc to + // terminate. Avoid showing the progress UI when staging an update, or if this + // is an elevated process on OSX. + std::thread t(UpdateThreadFunc, nullptr); + if (!sStagedUpdate && !sReplaceRequest #ifdef XP_MACOSX - && !isElevated + && !isElevated #endif - ) { - ShowProgressUI(); - } - t.join(); + ) + { + ShowProgressUI(); + } + t.join(); #ifdef _WIN32 - if (argc > callbackIndex && !sReplaceRequest) { - if (callbackFile != INVALID_HANDLE_VALUE) { - CloseHandle(callbackFile); - } - // Remove the copy of the callback executable. - NS_tremove(gCallbackBackupPath); + if (argc > callbackIndex && !sReplaceRequest) + { + if (callbackFile != INVALID_HANDLE_VALUE) + { + CloseHandle(callbackFile); } + // Remove the copy of the callback executable. + NS_tremove(gCallbackBackupPath); + } - if (!sStagedUpdate && !sReplaceRequest && _wrmdir(gDeleteDirPath)) { - LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d", - DELETE_DIR, errno)); - // The directory probably couldn't be removed due to it containing files - // that are in use and will be removed on OS reboot. The call to remove the - // directory on OS reboot is done after the calls to remove the files so the - // files are removed first on OS reboot since the directory must be empty - // for the directory removal to be successful. The MoveFileEx call to remove - // the directory on OS reboot will fail if the process doesn't have write - // access to the HKEY_LOCAL_MACHINE registry key but this is ok since the - // installer / uninstaller will delete the directory along with its contents - // after an update is applied, on reinstall, and on uninstall. - if (MoveFileEx(gDeleteDirPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) { - LOG(("NS_main: directory will be removed on OS reboot: " LOG_S, - DELETE_DIR)); - } else { - LOG(("NS_main: failed to schedule OS reboot removal of " \ - "directory: " LOG_S, DELETE_DIR)); - } + if (!sStagedUpdate && !sReplaceRequest && _wrmdir(gDeleteDirPath)) + { + LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d", + DELETE_DIR, errno)); + // The directory probably couldn't be removed due to it containing files + // that are in use and will be removed on OS reboot. The call to remove the + // directory on OS reboot is done after the calls to remove the files so the + // files are removed first on OS reboot since the directory must be empty + // for the directory removal to be successful. The MoveFileEx call to remove + // the directory on OS reboot will fail if the process doesn't have write + // access to the HKEY_LOCAL_MACHINE registry key but this is ok since the + // installer / uninstaller will delete the directory along with its contents + // after an update is applied, on reinstall, and on uninstall. + if (MoveFileEx(gDeleteDirPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) + { + LOG(("NS_main: directory will be removed on OS reboot: " LOG_S, + DELETE_DIR)); } + else + { + LOG(("NS_main: failed to schedule OS reboot removal of " \ + "directory: " LOG_S, DELETE_DIR)); + } + } #endif /* WNT */ @@ -3401,45 +3730,55 @@ int NS_main(int argc, NS_tchar **argv) // the application bundle and move the distribution directory from // Contents/MacOS to Contents/Resources and if both exist delete the // directory under Contents/MacOS (see Bug 1068439). - if (gSucceeded && !sStagedUpdate) { + if (gSucceeded && !sStagedUpdate) + { NS_tchar oldPrecomplete[MAXPATHLEN]; NS_tsnprintf(oldPrecomplete, sizeof(oldPrecomplete)/sizeof(oldPrecomplete[0]), - NS_T("%s/precomplete"), gInstallDirPath); + NS_T("%s/precomplete"), gInstallDirPath); NS_tremove(oldPrecomplete); NS_tchar oldDistDir[MAXPATHLEN]; NS_tsnprintf(oldDistDir, sizeof(oldDistDir)/sizeof(oldDistDir[0]), - NS_T("%s/Contents/MacOS/distribution"), gInstallDirPath); + NS_T("%s/Contents/MacOS/distribution"), gInstallDirPath); int rv = NS_taccess(oldDistDir, F_OK); - if (!rv) { + if (!rv) + { NS_tchar newDistDir[MAXPATHLEN]; NS_tsnprintf(newDistDir, sizeof(newDistDir)/sizeof(newDistDir[0]), - NS_T("%s/Contents/Resources/distribution"), gInstallDirPath); + NS_T("%s/Contents/Resources/distribution"), gInstallDirPath); rv = NS_taccess(newDistDir, F_OK); - if (!rv) { + if (!rv) + { LOG(("New distribution directory already exists... removing old " \ - "distribution directory: " LOG_S, oldDistDir)); + "distribution directory: " LOG_S, oldDistDir)); rv = ensure_remove_recursive(oldDistDir); - if (rv) { + if (rv) + { LOG(("Removing old distribution directory failed - err: %d", rv)); } - } else { + } + else + { LOG(("Moving old distribution directory to new location. src: " LOG_S \ - ", dst:" LOG_S, oldDistDir, newDistDir)); + ", dst:" LOG_S, oldDistDir, newDistDir)); rv = rename_file(oldDistDir, newDistDir, true); - if (rv) { + if (rv) + { LOG(("Moving old distribution directory to new location failed - " \ - "err: %d", rv)); + "err: %d", rv)); } } } } - if (isElevated) { + if (isElevated) + { SetGroupOwnershipAndPermissions(gInstallDirPath); freeArguments(argc, argv); CleanupElevatedMacUpdate(false); - } else if (IsOwnedByGroupAdmin(gInstallDirPath)) { + } + else if (IsOwnedByGroupAdmin(gInstallDirPath)) + { // If the group ownership of the Firefox .app bundle was set to the "admin" // group during a previous elevated update, we need to ensure that all files // in the bundle have group ownership of "admin" as well as write permission @@ -3452,12 +3791,12 @@ int NS_main(int argc, NS_tchar **argv) int retVal = LaunchCallbackAndPostProcessApps(argc, argv, callbackIndex #ifdef _WIN32 - , elevatedLockFilePath - , updateLockFileHandle + , elevatedLockFilePath + , updateLockFileHandle #elif defined(MACOSX) - , isElevated + , isElevated #endif - ); + ); return retVal ? retVal : (gSucceeded ? 0 : 1); } @@ -3482,7 +3821,8 @@ private: ActionList::~ActionList() { Action* a = mFirst; - while (a) { + while (a) + { Action *b = a; a = a->mNext; delete b; @@ -3507,14 +3847,16 @@ ActionList::Prepare() // If the action list is empty then we should fail in order to signal that // something has gone wrong. Otherwise we report success when nothing is // actually done. See bug 327140. - if (mCount == 0) { + if (mCount == 0) + { LOG(("empty action list")); return MAR_ERROR_EMPTY_ACTION_LIST; } Action *a = mFirst; int i = 0; - while (a) { + while (a) + { int rv = a->Prepare(); if (rv) return rv; @@ -3533,15 +3875,18 @@ ActionList::Execute() { int currentProgress = 0, maxProgress = 0; Action *a = mFirst; - while (a) { + while (a) + { maxProgress += a->mProgressCost; a = a->mNext; } a = mFirst; - while (a) { + while (a) + { int rv = a->Execute(); - if (rv) { + if (rv) + { LOG(("### execution failed")); return rv; } @@ -3549,7 +3894,7 @@ ActionList::Execute() currentProgress += a->mProgressCost; float percent = float(currentProgress) / float(maxProgress); UpdateProgressUI(PROGRESS_PREPARE_SIZE + - PROGRESS_EXECUTE_SIZE * percent); + PROGRESS_EXECUTE_SIZE * percent); a = a->mNext; } @@ -3562,13 +3907,14 @@ ActionList::Finish(int status) { Action *a = mFirst; int i = 0; - while (a) { + while (a) + { a->Finish(status); float percent = float(++i) / float(mCount); UpdateProgressUI(PROGRESS_PREPARE_SIZE + - PROGRESS_EXECUTE_SIZE + - PROGRESS_FINISH_SIZE * percent); + PROGRESS_EXECUTE_SIZE + + PROGRESS_FINISH_SIZE * percent); a = a->mNext; } @@ -3588,29 +3934,35 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) NS_tchar foundpath[MAXPATHLEN]; NS_tsnprintf(searchspec, sizeof(searchspec)/sizeof(searchspec[0]), - NS_T("%s*"), dirpath); + NS_T("%s*"), dirpath); std::unique_ptr<const NS_tchar> pszSpec(get_full_path(searchspec)); hFindFile = FindFirstFileW(pszSpec.get(), &finddata); - if (hFindFile != INVALID_HANDLE_VALUE) { - do { + if (hFindFile != INVALID_HANDLE_VALUE) + { + do + { // Don't process the current or parent directory. if (NS_tstrcmp(finddata.cFileName, NS_T(".")) == 0 || NS_tstrcmp(finddata.cFileName, NS_T("..")) == 0) continue; NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]), - NS_T("%s%s"), dirpath, finddata.cFileName); - if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + NS_T("%s%s"), dirpath, finddata.cFileName); + if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]), - NS_T("%s/"), foundpath); + NS_T("%s/"), foundpath); // Recurse into the directory. rv = add_dir_entries(foundpath, list); - if (rv) { + if (rv) + { LOG(("add_dir_entries error: " LOG_S ", err: %d", foundpath, rv)); return rv; } - } else { + } + else + { // Add the file to be removed to the ActionList. NS_tchar *quotedpath = get_quoted_path(foundpath); if (!quotedpath) @@ -3618,16 +3970,18 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) Action *action = new RemoveFile(); rv = action->Parse(quotedpath); - if (rv) { + if (rv) + { LOG(("add_dir_entries Parse error on recurse: " LOG_S ", err: %d", - quotedpath, rv)); + quotedpath, rv)); return rv; } free(quotedpath); list->Append(action); } - } while (FindNextFileW(hFindFile, &finddata) != 0); + } + while (FindNextFileW(hFindFile, &finddata) != 0); FindClose(hFindFile); { @@ -3640,7 +3994,7 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) rv = action->Parse(quotedpath); if (rv) LOG(("add_dir_entries Parse error on close: " LOG_S ", err: %d", - quotedpath, rv)); + quotedpath, rv)); else list->Append(action); free(quotedpath); @@ -3655,7 +4009,8 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) { int rv = OK; NS_tchar foundpath[MAXPATHLEN]; - struct { + struct + { dirent dent_buffer; char chars[MAXNAMLEN]; } ent_buf; @@ -3663,48 +4018,57 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) std::unique_ptr<NS_tchar> searchpath(get_full_path(dirpath)); DIR* dir = opendir(searchpath.get()); - if (!dir) { + if (!dir) + { LOG(("add_dir_entries error on opendir: " LOG_S ", err: %d", searchpath.get(), - errno)); + errno)); return UNEXPECTED_FILE_OPERATION_ERROR; } - while (readdir_r(dir, (dirent *)&ent_buf, &ent) == 0 && ent) { + while (readdir_r(dir, (dirent *)&ent_buf, &ent) == 0 && ent) + { if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) continue; NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]), - NS_T("%s%s"), searchpath.get(), ent->d_name); + NS_T("%s%s"), searchpath.get(), ent->d_name); struct stat64 st_buf; int test = stat64(foundpath, &st_buf); - if (test) { + if (test) + { closedir(dir); return UNEXPECTED_FILE_OPERATION_ERROR; } - if (S_ISDIR(st_buf.st_mode)) { + if (S_ISDIR(st_buf.st_mode)) + { NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]), - NS_T("%s/"), foundpath); + NS_T("%s/"), foundpath); // Recurse into the directory. rv = add_dir_entries(foundpath, list); - if (rv) { + if (rv) + { LOG(("add_dir_entries error: " LOG_S ", err: %d", foundpath, rv)); closedir(dir); return rv; } - } else { + } + else + { // Add the file to be removed to the ActionList. NS_tchar *quotedpath = get_quoted_path(get_relative_path(foundpath)); - if (!quotedpath) { + if (!quotedpath) + { closedir(dir); return PARSE_ERROR; } Action *action = new RemoveFile(); rv = action->Parse(quotedpath); - if (rv) { + if (rv) + { LOG(("add_dir_entries Parse error on recurse: " LOG_S ", err: %d", - quotedpath, rv)); + quotedpath, rv)); closedir(dir); return rv; } @@ -3721,11 +4085,13 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) Action *action = new RemoveDir(); rv = action->Parse(quotedpath); - if (rv) { + if (rv) + { LOG(("add_dir_entries Parse error on close: " LOG_S ", err: %d", - quotedpath, rv)); + quotedpath, rv)); } - else { + else + { list->Append(action); } @@ -3749,32 +4115,35 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) // FTS_NOCHDIR is used so relative paths from the destination directory are // returned. if (!(ftsdir = fts_open(pathargv, - FTS_PHYSICAL | FTS_NOSTAT | FTS_XDEV | FTS_NOCHDIR, - nullptr))) + FTS_PHYSICAL | FTS_NOSTAT | FTS_XDEV | FTS_NOCHDIR, + nullptr))) return UNEXPECTED_FILE_OPERATION_ERROR; - while ((ftsdirEntry = fts_read(ftsdir)) != nullptr) { + while ((ftsdirEntry = fts_read(ftsdir)) != nullptr) + { NS_tchar foundpath[MAXPATHLEN]; NS_tchar *quotedpath = nullptr; Action *action = nullptr; - switch (ftsdirEntry->fts_info) { + switch (ftsdirEntry->fts_info) + { // Filesystem objects that shouldn't be in the application's directories case FTS_SL: case FTS_SLNONE: case FTS_DEFAULT: LOG(("add_dir_entries: found a non-standard file: " LOG_S, - ftsdirEntry->fts_path)); - // Fall through and try to remove as a file + ftsdirEntry->fts_path)); + // Fall through and try to remove as a file - // Files + // Files case FTS_F: case FTS_NSOK: // Add the file to be removed to the ActionList. NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]), - NS_T("%s"), ftsdirEntry->fts_accpath); + NS_T("%s"), ftsdirEntry->fts_accpath); quotedpath = get_quoted_path(get_relative_path(foundpath)); - if (!quotedpath) { + if (!quotedpath) + { rv = UPDATER_QUOTED_PATH_MEM_ERROR; break; } @@ -3783,16 +4152,17 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) free(quotedpath); if (!rv) list->Append(action); - break; + break; // Directories case FTS_DP: rv = OK; // Add the directory to be removed to the ActionList. NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]), - NS_T("%s/"), ftsdirEntry->fts_accpath); + NS_T("%s/"), ftsdirEntry->fts_accpath); quotedpath = get_quoted_path(get_relative_path(foundpath)); - if (!quotedpath) { + if (!quotedpath) + { rv = UPDATER_QUOTED_PATH_MEM_ERROR; break; } @@ -3802,7 +4172,7 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) free(quotedpath); if (!rv) list->Append(action); - break; + break; // Errors case FTS_DNR: @@ -3810,28 +4180,29 @@ int add_dir_entries(const NS_tchar *dirpath, ActionList *list) // ENOENT is an acceptable error for FTS_DNR and FTS_NS and means that // we're racing with ourselves. Though strange, the entry will be // removed anyway. - if (ENOENT == ftsdirEntry->fts_errno) { + if (ENOENT == ftsdirEntry->fts_errno) + { rv = OK; break; } - // Fall through + // Fall through case FTS_ERR: rv = UNEXPECTED_FILE_OPERATION_ERROR; LOG(("add_dir_entries: fts_read() error: " LOG_S ", err: %d", - ftsdirEntry->fts_path, ftsdirEntry->fts_errno)); - break; + ftsdirEntry->fts_path, ftsdirEntry->fts_errno)); + break; case FTS_DC: rv = UNEXPECTED_FILE_OPERATION_ERROR; LOG(("add_dir_entries: fts_read() returned FT_DC: " LOG_S, - ftsdirEntry->fts_path)); - break; + ftsdirEntry->fts_path)); + break; default: // FTS_D is ignored and FTS_DP is used instead (post-order). rv = OK; - break; + break; } if (rv != OK) @@ -3848,14 +4219,16 @@ static NS_tchar* GetManifestContents(const NS_tchar *manifest) { AutoFile mfile(NS_tfopen(manifest, NS_T("rb"))); - if (mfile == nullptr) { + if (mfile == nullptr) + { LOG(("GetManifestContents: error opening manifest file: " LOG_S, manifest)); return nullptr; } struct stat ms; int rv = fstat(fileno((FILE *)mfile), &ms); - if (rv) { + if (rv) + { LOG(("GetManifestContents: error stating manifest file: " LOG_S, manifest)); return nullptr; } @@ -3866,10 +4239,12 @@ GetManifestContents(const NS_tchar *manifest) size_t r = ms.st_size; char *rb = mbuf; - while (r) { + while (r) + { const size_t count = std::min<size_t>(SSIZE_MAX, r); size_t c = fread(rb, 1, count, mfile); - if (c != count) { + if (c != count) + { LOG(("GetManifestContents: error reading manifest file: " LOG_S, manifest)); free(mbuf); return nullptr; @@ -3885,13 +4260,15 @@ GetManifestContents(const NS_tchar *manifest) return rb; #else NS_tchar *wrb = (NS_tchar *) malloc((ms.st_size + 1) * sizeof(NS_tchar)); - if (!wrb) { + if (!wrb) + { free(mbuf); return nullptr; } if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, rb, -1, wrb, - ms.st_size + 1)) { + ms.st_size + 1)) + { LOG(("GetManifestContents: error converting utf8 to utf16le: %d", GetLastError())); free(mbuf); free(wrb); @@ -3907,16 +4284,17 @@ int AddPreCompleteActions(ActionList *list) { #ifdef MACOSX std::unique_ptr<NS_tchar> manifestPath(get_full_path( - NS_T("Contents/Resources/precomplete"))); + NS_T("Contents/Resources/precomplete"))); #else std::unique_ptr<NS_tchar> manifestPath(get_full_path( - NS_T("precomplete"))); + NS_T("precomplete"))); #endif NS_tchar *rb = GetManifestContents(manifestPath.get()); - if (rb == nullptr) { + if (rb == nullptr) + { LOG(("AddPreCompleteActions: error getting contents of precomplete " \ - "manifest")); + "manifest")); // Applications aren't required to have a precomplete manifest. The mar // generation scripts enforce the presence of a precomplete manifest. return OK; @@ -3924,28 +4302,34 @@ int AddPreCompleteActions(ActionList *list) int rv; NS_tchar *line; - while((line = mstrtok(kNL, &rb)) != 0) { + while ((line = mstrtok(kNL, &rb)) != 0) + { // skip comments if (*line == NS_T('#')) continue; NS_tchar *token = mstrtok(kWhitespace, &line); - if (!token) { + if (!token) + { LOG(("AddPreCompleteActions: token not found in manifest")); return PARSE_ERROR; } Action *action = nullptr; - if (NS_tstrcmp(token, NS_T("remove")) == 0) { // rm file + if (NS_tstrcmp(token, NS_T("remove")) == 0) // rm file + { action = new RemoveFile(); } - else if (NS_tstrcmp(token, NS_T("remove-cc")) == 0) { // no longer supported + else if (NS_tstrcmp(token, NS_T("remove-cc")) == 0) // no longer supported + { continue; } - else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) { // rmdir if empty + else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) // rmdir if empty + { action = new RemoveDir(); } - else { + else + { LOG(("AddPreCompleteActions: unknown token: " LOG_S, token)); return PARSE_ERROR; } @@ -3967,16 +4351,18 @@ int DoUpdate() { NS_tchar manifest[MAXPATHLEN]; NS_tsnprintf(manifest, sizeof(manifest)/sizeof(manifest[0]), - NS_T("%s/updating/update.manifest"), gWorkingDirPath); + NS_T("%s/updating/update.manifest"), gWorkingDirPath); ensure_parent_dir(manifest); // extract the manifest // TODO: moggi: needs adaption for LibreOffice // Why would we need the manifest? Even if we need it why would we need 2? int rv = gArchiveReader.ExtractFile("updatev3.manifest", manifest); - if (rv) { + if (rv) + { rv = gArchiveReader.ExtractFile("updatev2.manifest", manifest); - if (rv) { + if (rv) + { LOG(("DoUpdate: error extracting manifest file")); return rv; } @@ -3984,7 +4370,8 @@ int DoUpdate() NS_tchar *rb = GetManifestContents(manifest); NS_tremove(manifest); - if (rb == nullptr) { + if (rb == nullptr) + { LOG(("DoUpdate: error opening manifest file: " LOG_S, manifest)); return READ_ERROR; } @@ -3994,25 +4381,30 @@ int DoUpdate() NS_tchar *line; bool isFirstAction = true; - while((line = mstrtok(kNL, &rb)) != 0) { + while ((line = mstrtok(kNL, &rb)) != 0) + { // skip comments if (*line == NS_T('#')) continue; NS_tchar *token = mstrtok(kWhitespace, &line); - if (!token) { + if (!token) + { LOG(("DoUpdate: token not found in manifest")); return PARSE_ERROR; } - if (isFirstAction) { + if (isFirstAction) + { isFirstAction = false; // The update manifest isn't required to have a type declaration. The mar // generation scripts enforce the presence of the type declaration. - if (NS_tstrcmp(token, NS_T("type")) == 0) { + if (NS_tstrcmp(token, NS_T("type")) == 0) + { const NS_tchar *type = mstrtok(kQuote, &line); LOG(("UPDATE TYPE " LOG_S, type)); - if (NS_tstrcmp(type, NS_T("complete")) == 0) { + if (NS_tstrcmp(type, NS_T("complete")) == 0) + { rv = AddPreCompleteActions(&list); if (rv) return rv; @@ -4022,13 +4414,16 @@ int DoUpdate() } Action *action = nullptr; - if (NS_tstrcmp(token, NS_T("remove")) == 0) { // rm file + if (NS_tstrcmp(token, NS_T("remove")) == 0) // rm file + { action = new RemoveFile(); } - else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) { // rmdir if empty + else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) // rmdir if empty + { action = new RemoveDir(); } - else if (NS_tstrcmp(token, NS_T("rmrfdir")) == 0) { // rmdir recursive + else if (NS_tstrcmp(token, NS_T("rmrfdir")) == 0) // rmdir recursive + { const NS_tchar *reldirpath = mstrtok(kQuote, &line); if (!reldirpath) return PARSE_ERROR; @@ -4042,22 +4437,28 @@ int DoUpdate() continue; } - else if (NS_tstrcmp(token, NS_T("add")) == 0) { + else if (NS_tstrcmp(token, NS_T("add")) == 0) + { action = new AddFile(); } - else if (NS_tstrcmp(token, NS_T("patch")) == 0) { + else if (NS_tstrcmp(token, NS_T("patch")) == 0) + { action = new PatchFile(); } - else if (NS_tstrcmp(token, NS_T("add-if")) == 0) { // Add if exists + else if (NS_tstrcmp(token, NS_T("add-if")) == 0) // Add if exists + { action = new AddIfFile(); } - else if (NS_tstrcmp(token, NS_T("add-if-not")) == 0) { // Add if not exists + else if (NS_tstrcmp(token, NS_T("add-if-not")) == 0) // Add if not exists + { action = new AddIfNotFile(); } - else if (NS_tstrcmp(token, NS_T("patch-if")) == 0) { // Patch if exists + else if (NS_tstrcmp(token, NS_T("patch-if")) == 0) // Patch if exists + { action = new PatchIfFile(); } - else { + else + { LOG(("DoUpdate: unknown token: " LOG_S, token)); return PARSE_ERROR; } diff --git a/onlineupdate/source/update/updater/win_dirent.cxx b/onlineupdate/source/update/updater/win_dirent.cxx index d7bf872194f6..2368613ee42b 100644 --- a/onlineupdate/source/update/updater/win_dirent.cxx +++ b/onlineupdate/source/update/updater/win_dirent.cxx @@ -16,64 +16,74 @@ static dirent gDirEnt; DIR::DIR(const WCHAR* path) - : findHandle(INVALID_HANDLE_VALUE) + : findHandle(INVALID_HANDLE_VALUE) { - memset(name, 0, sizeof(name)); - wcsncpy(name, path, sizeof(name)/sizeof(name[0])); - wcsncat(name, L"\\*", sizeof(name)/sizeof(name[0]) - wcslen(name) - 1); + memset(name, 0, sizeof(name)); + wcsncpy(name, path, sizeof(name)/sizeof(name[0])); + wcsncat(name, L"\\*", sizeof(name)/sizeof(name[0]) - wcslen(name) - 1); } DIR::~DIR() { - if (findHandle != INVALID_HANDLE_VALUE) { - FindClose(findHandle); - } + if (findHandle != INVALID_HANDLE_VALUE) + { + FindClose(findHandle); + } } dirent::dirent() { - d_name[0] = L'\0'; + d_name[0] = L'\0'; } DIR* opendir(const WCHAR* path) { - return new DIR(path); + return new DIR(path); } int closedir(DIR* dir) { - delete dir; - return 0; + delete dir; + return 0; } dirent* readdir(DIR* dir) { - WIN32_FIND_DATAW data; - if (dir->findHandle != INVALID_HANDLE_VALUE) { - BOOL result = FindNextFileW(dir->findHandle, &data); - if (!result) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) { - errno = ENOENT; - } - return 0; + WIN32_FIND_DATAW data; + if (dir->findHandle != INVALID_HANDLE_VALUE) + { + BOOL result = FindNextFileW(dir->findHandle, &data); + if (!result) + { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + { + errno = ENOENT; + } + return 0; + } } - } else { - // Reading the first directory entry - dir->findHandle = FindFirstFileW(dir->name, &data); - if (dir->findHandle == INVALID_HANDLE_VALUE) { - if (GetLastError() == ERROR_FILE_NOT_FOUND) { - errno = ENOENT; - } else { - errno = EBADF; - } - return 0; + else + { + // Reading the first directory entry + dir->findHandle = FindFirstFileW(dir->name, &data); + if (dir->findHandle == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + { + errno = ENOENT; + } + else + { + errno = EBADF; + } + return 0; + } } - } - memset(gDirEnt.d_name, 0, sizeof(gDirEnt.d_name)); - wcsncpy(gDirEnt.d_name, data.cFileName, - sizeof(gDirEnt.d_name)/sizeof(gDirEnt.d_name[0])); - return &gDirEnt; + memset(gDirEnt.d_name, 0, sizeof(gDirEnt.d_name)); + wcsncpy(gDirEnt.d_name, data.cFileName, + sizeof(gDirEnt.d_name)/sizeof(gDirEnt.d_name[0])); + return &gDirEnt; } #endif diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx index a543aed09915..33c058982caf 100644 --- a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx +++ b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx @@ -20,33 +20,33 @@ template <class T> inline const T& XPCOM_MIN(const T& aA, const T& aB) { - return aB < aA ? aB : aA; + return aB < aA ? aB : aA; } #endif struct VersionPart { - int32_t numA; + int32_t numA; - const char* strB; // NOT null-terminated, can be a null pointer - uint32_t strBlen; + const char* strB; // NOT null-terminated, can be a null pointer + uint32_t strBlen; - int32_t numC; + int32_t numC; - char* extraD; // null-terminated + char* extraD; // null-terminated }; #ifdef _WIN32 struct VersionPartW { - int32_t numA; + int32_t numA; - wchar_t* strB; // NOT null-terminated, can be a null pointer - uint32_t strBlen; + wchar_t* strB; // NOT null-terminated, can be a null pointer + uint32_t strBlen; - int32_t numC; + int32_t numC; - wchar_t* extraD; // null-terminated + wchar_t* extraD; // null-terminated }; #endif @@ -59,64 +59,81 @@ struct VersionPartW static char* ParseVP(char* aPart, VersionPart& aResult) { - char* dot; - - aResult.numA = 0; - aResult.strB = nullptr; - aResult.strBlen = 0; - aResult.numC = 0; - aResult.extraD = nullptr; - - if (!aPart) { - return aPart; - } - - dot = strchr(aPart, '.'); - if (dot) { - *dot = '\0'; - } - - if (aPart[0] == '*' && aPart[1] == '\0') { - aResult.numA = INT32_MAX; - aResult.strB = ""; - } else { - aResult.numA = strtol(aPart, const_cast<char**>(&aResult.strB), 10); - } - - if (!*aResult.strB) { + char* dot; + + aResult.numA = 0; aResult.strB = nullptr; aResult.strBlen = 0; - } else { - if (aResult.strB[0] == '+') { - static const char kPre[] = "pre"; - - ++aResult.numA; - aResult.strB = kPre; - aResult.strBlen = sizeof(kPre) - 1; - } else { - const char* numstart = strpbrk(aResult.strB, "0123456789+-"); - if (!numstart) { - aResult.strBlen = strlen(aResult.strB); - } else { - aResult.strBlen = numstart - aResult.strB; - - aResult.numC = strtol(numstart, &aResult.extraD, 10); - if (!*aResult.extraD) { - aResult.extraD = nullptr; + aResult.numC = 0; + aResult.extraD = nullptr; + + if (!aPart) + { + return aPart; + } + + dot = strchr(aPart, '.'); + if (dot) + { + *dot = '\0'; + } + + if (aPart[0] == '*' && aPart[1] == '\0') + { + aResult.numA = INT32_MAX; + aResult.strB = ""; + } + else + { + aResult.numA = strtol(aPart, const_cast<char**>(&aResult.strB), 10); + } + + if (!*aResult.strB) + { + aResult.strB = nullptr; + aResult.strBlen = 0; + } + else + { + if (aResult.strB[0] == '+') + { + static const char kPre[] = "pre"; + + ++aResult.numA; + aResult.strB = kPre; + aResult.strBlen = sizeof(kPre) - 1; + } + else + { + const char* numstart = strpbrk(aResult.strB, "0123456789+-"); + if (!numstart) + { + aResult.strBlen = strlen(aResult.strB); + } + else + { + aResult.strBlen = numstart - aResult.strB; + + aResult.numC = strtol(numstart, &aResult.extraD, 10); + if (!*aResult.extraD) + { + aResult.extraD = nullptr; + } + } } - } } - } - if (dot) { - ++dot; + if (dot) + { + ++dot; - if (!*dot) { - dot = nullptr; + if (!*dot) + { + dot = nullptr; + } } - } - return dot; + return dot; } @@ -130,64 +147,81 @@ static wchar_t* ParseVP(wchar_t* aPart, VersionPartW& aResult) { - wchar_t* dot; + wchar_t* dot; - aResult.numA = 0; - aResult.strB = nullptr; - aResult.strBlen = 0; - aResult.numC = 0; - aResult.extraD = nullptr; + aResult.numA = 0; + aResult.strB = nullptr; + aResult.strBlen = 0; + aResult.numC = 0; + aResult.extraD = nullptr; - if (!aPart) { - return aPart; - } + if (!aPart) + { + return aPart; + } - dot = wcschr(aPart, '.'); - if (dot) { - *dot = '\0'; - } + dot = wcschr(aPart, '.'); + if (dot) + { + *dot = '\0'; + } - if (aPart[0] == '*' && aPart[1] == '\0') { - aResult.numA = INT32_MAX; - aResult.strB = L""; - } else { - aResult.numA = wcstol(aPart, const_cast<wchar_t**>(&aResult.strB), 10); - } + if (aPart[0] == '*' && aPart[1] == '\0') + { + aResult.numA = INT32_MAX; + aResult.strB = L""; + } + else + { + aResult.numA = wcstol(aPart, const_cast<wchar_t**>(&aResult.strB), 10); + } - if (!*aResult.strB) { - aResult.strB = nullptr; - aResult.strBlen = 0; - } else { - if (aResult.strB[0] == '+') { - static wchar_t kPre[] = L"pre"; - - ++aResult.numA; - aResult.strB = kPre; - aResult.strBlen = sizeof(kPre) - 1; - } else { - const wchar_t* numstart = wcspbrk(aResult.strB, L"0123456789+-"); - if (!numstart) { - aResult.strBlen = wcslen(aResult.strB); - } else { - aResult.strBlen = numstart - aResult.strB; - - aResult.numC = wcstol(numstart, &aResult.extraD, 10); - if (!*aResult.extraD) { - aResult.extraD = nullptr; + if (!*aResult.strB) + { + aResult.strB = nullptr; + aResult.strBlen = 0; + } + else + { + if (aResult.strB[0] == '+') + { + static wchar_t kPre[] = L"pre"; + + ++aResult.numA; + aResult.strB = kPre; + aResult.strBlen = sizeof(kPre) - 1; + } + else + { + const wchar_t* numstart = wcspbrk(aResult.strB, L"0123456789+-"); + if (!numstart) + { + aResult.strBlen = wcslen(aResult.strB); + } + else + { + aResult.strBlen = numstart - aResult.strB; + + aResult.numC = wcstol(numstart, &aResult.extraD, 10); + if (!*aResult.extraD) + { + aResult.extraD = nullptr; + } + } } - } } - } - if (dot) { - ++dot; + if (dot) + { + ++dot; - if (!*dot) { - dot = nullptr; + if (!*dot) + { + dot = nullptr; + } } - } - return dot; + return dot; } #endif @@ -195,16 +229,18 @@ ParseVP(wchar_t* aPart, VersionPartW& aResult) static int32_t ns_strcmp(const char* aStr1, const char* aStr2) { - // any string is *before* no string - if (!aStr1) { - return aStr2 != 0; - } + // any string is *before* no string + if (!aStr1) + { + return aStr2 != 0; + } - if (!aStr2) { - return -1; - } + if (!aStr2) + { + return -1; + } - return strcmp(aStr1, aStr2); + return strcmp(aStr1, aStr2); } // compare two length-specified string, which may be null pointers @@ -212,41 +248,48 @@ static int32_t ns_strnncmp(const char* aStr1, uint32_t aLen1, const char* aStr2, uint32_t aLen2) { - // any string is *before* no string - if (!aStr1) { - return aStr2 != 0; - } - - if (!aStr2) { - return -1; - } + // any string is *before* no string + if (!aStr1) + { + return aStr2 != 0; + } - for (; aLen1 && aLen2; --aLen1, --aLen2, ++aStr1, ++aStr2) { - if (*aStr1 < *aStr2) { - return -1; + if (!aStr2) + { + return -1; } - if (*aStr1 > *aStr2) { - return 1; + for (; aLen1 && aLen2; --aLen1, --aLen2, ++aStr1, ++aStr2) + { + if (*aStr1 < *aStr2) + { + return -1; + } + + if (*aStr1 > *aStr2) + { + return 1; + } } - } - if (aLen1 == 0) { - return aLen2 == 0 ? 0 : -1; - } + if (aLen1 == 0) + { + return aLen2 == 0 ? 0 : -1; + } - return 1; + return 1; } // compare two int32_t static int32_t ns_cmp(int32_t aNum1, int32_t aNum2) { - if (aNum1 < aNum2) { - return -1; - } + if (aNum1 < aNum2) + { + return -1; + } - return aNum1 != aNum2; + return aNum1 != aNum2; } /** @@ -255,22 +298,25 @@ ns_cmp(int32_t aNum1, int32_t aNum2) static int32_t CompareVP(VersionPart& aVer1, VersionPart& aVer2) { - int32_t r = ns_cmp(aVer1.numA, aVer2.numA); - if (r) { - return r; - } - - r = ns_strnncmp(aVer1.strB, aVer1.strBlen, aVer2.strB, aVer2.strBlen); - if (r) { - return r; - } - - r = ns_cmp(aVer1.numC, aVer2.numC); - if (r) { - return r; - } - - return ns_strcmp(aVer1.extraD, aVer2.extraD); + int32_t r = ns_cmp(aVer1.numA, aVer2.numA); + if (r) + { + return r; + } + + r = ns_strnncmp(aVer1.strB, aVer1.strBlen, aVer2.strB, aVer2.strBlen); + if (r) + { + return r; + } + + r = ns_cmp(aVer1.numC, aVer2.numC); + if (r) + { + return r; + } + + return ns_strcmp(aVer1.extraD, aVer2.extraD); } /** @@ -280,30 +326,35 @@ CompareVP(VersionPart& aVer1, VersionPart& aVer2) static int32_t CompareVP(VersionPartW& aVer1, VersionPartW& aVer2) { - int32_t r = ns_cmp(aVer1.numA, aVer2.numA); - if (r) { - return r; - } - - r = wcsncmp(aVer1.strB, aVer2.strB, XPCOM_MIN(aVer1.strBlen, aVer2.strBlen)); - if (r) { - return r; - } - - r = ns_cmp(aVer1.numC, aVer2.numC); - if (r) { - return r; - } - - if (!aVer1.extraD) { - return aVer2.extraD != 0; - } - - if (!aVer2.extraD) { - return -1; - } - - return wcscmp(aVer1.extraD, aVer2.extraD); + int32_t r = ns_cmp(aVer1.numA, aVer2.numA); + if (r) + { + return r; + } + + r = wcsncmp(aVer1.strB, aVer2.strB, XPCOM_MIN(aVer1.strBlen, aVer2.strBlen)); + if (r) + { + return r; + } + + r = ns_cmp(aVer1.numC, aVer2.numC); + if (r) + { + return r; + } + + if (!aVer1.extraD) + { + return aVer2.extraD != 0; + } + + if (!aVer2.extraD) + { + return -1; + } + + return wcscmp(aVer1.extraD, aVer2.extraD); } #endif @@ -313,76 +364,86 @@ namespace mozilla { int32_t CompareVersions(const wchar_t* aStrA, const wchar_t* aStrB) { - wchar_t* A2 = wcsdup(aStrA); - if (!A2) { - return 1; - } + wchar_t* A2 = wcsdup(aStrA); + if (!A2) + { + return 1; + } - wchar_t* B2 = wcsdup(aStrB); - if (!B2) { - free(A2); - return 1; - } + wchar_t* B2 = wcsdup(aStrB); + if (!B2) + { + free(A2); + return 1; + } - int32_t result; - wchar_t* a = A2; - wchar_t* b = B2; + int32_t result; + wchar_t* a = A2; + wchar_t* b = B2; - do { - VersionPartW va, vb; + do + { + VersionPartW va, vb; - a = ParseVP(a, va); - b = ParseVP(b, vb); + a = ParseVP(a, va); + b = ParseVP(b, vb); - result = CompareVP(va, vb); - if (result) { - break; - } + result = CompareVP(va, vb); + if (result) + { + break; + } - } while (a || b); + } + while (a || b); - free(A2); - free(B2); + free(A2); + free(B2); - return result; + return result; } #endif int32_t CompareVersions(const char* aStrA, const char* aStrB) { - char* A2 = strdup(aStrA); - if (!A2) { - return 1; - } + char* A2 = strdup(aStrA); + if (!A2) + { + return 1; + } - char* B2 = strdup(aStrB); - if (!B2) { - free(A2); - return 1; - } + char* B2 = strdup(aStrB); + if (!B2) + { + free(A2); + return 1; + } - int32_t result; - char* a = A2; - char* b = B2; + int32_t result; + char* a = A2; + char* b = B2; - do { - VersionPart va, vb; + do + { + VersionPart va, vb; - a = ParseVP(a, va); - b = ParseVP(b, vb); + a = ParseVP(a, va); + b = ParseVP(b, vb); - result = CompareVP(va, vb); - if (result) { - break; - } + result = CompareVP(va, vb); + if (result) + { + break; + } - } while (a || b); + } + while (a || b); - free(A2); - free(B2); + free(A2); + free(B2); - return result; + return result; } } // namespace mozilla diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h index 0d4d7bb54b87..d793e345eb86 100644 --- a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h +++ b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h @@ -51,120 +51,120 @@ int32_t CompareVersions(const wchar_t* aStrA, const wchar_t* aStrB); struct Version { - explicit Version(const char* aVersionString) - { - versionContent = strdup(aVersionString); - } - - const char* ReadContent() const - { - return versionContent; - } - - ~Version() - { - free(versionContent); - } - - bool operator<(const Version& aRhs) const - { - return CompareVersions(versionContent, aRhs.ReadContent()) == -1; - } - bool operator<=(const Version& aRhs) const - { - return CompareVersions(versionContent, aRhs.ReadContent()) < 1; - } - bool operator>(const Version& aRhs) const - { - return CompareVersions(versionContent, aRhs.ReadContent()) == 1; - } - bool operator>=(const Version& aRhs) const - { - return CompareVersions(versionContent, aRhs.ReadContent()) > -1; - } - bool operator==(const Version& aRhs) const - { - return CompareVersions(versionContent, aRhs.ReadContent()) == 0; - } - bool operator!=(const Version& aRhs) const - { - return CompareVersions(versionContent, aRhs.ReadContent()) != 0; - } - bool operator<(const char* aRhs) const - { - return CompareVersions(versionContent, aRhs) == -1; - } - bool operator<=(const char* aRhs) const - { - return CompareVersions(versionContent, aRhs) < 1; - } - bool operator>(const char* aRhs) const - { - return CompareVersions(versionContent, aRhs) == 1; - } - bool operator>=(const char* aRhs) const - { - return CompareVersions(versionContent, aRhs) > -1; - } - bool operator==(const char* aRhs) const - { - return CompareVersions(versionContent, aRhs) == 0; - } - bool operator!=(const char* aRhs) const - { - return CompareVersions(versionContent, aRhs) != 0; - } + explicit Version(const char* aVersionString) + { + versionContent = strdup(aVersionString); + } + + const char* ReadContent() const + { + return versionContent; + } + + ~Version() + { + free(versionContent); + } + + bool operator<(const Version& aRhs) const + { + return CompareVersions(versionContent, aRhs.ReadContent()) == -1; + } + bool operator<=(const Version& aRhs) const + { + return CompareVersions(versionContent, aRhs.ReadContent()) < 1; + } + bool operator>(const Version& aRhs) const + { + return CompareVersions(versionContent, aRhs.ReadContent()) == 1; + } + bool operator>=(const Version& aRhs) const + { + return CompareVersions(versionContent, aRhs.ReadContent()) > -1; + } + bool operator==(const Version& aRhs) const + { + return CompareVersions(versionContent, aRhs.ReadContent()) == 0; + } + bool operator!=(const Version& aRhs) const + { + return CompareVersions(versionContent, aRhs.ReadContent()) != 0; + } + bool operator<(const char* aRhs) const + { + return CompareVersions(versionContent, aRhs) == -1; + } + bool operator<=(const char* aRhs) const + { + return CompareVersions(versionContent, aRhs) < 1; + } + bool operator>(const char* aRhs) const + { + return CompareVersions(versionContent, aRhs) == 1; + } + bool operator>=(const char* aRhs) const + { + return CompareVersions(versionContent, aRhs) > -1; + } + bool operator==(const char* aRhs) const + { + return CompareVersions(versionContent, aRhs) == 0; + } + bool operator!=(const char* aRhs) const + { + return CompareVersions(versionContent, aRhs) != 0; + } private: - char* versionContent; + char* versionContent; }; #ifdef _WIN32 struct VersionW { - explicit VersionW(const wchar_t* aVersionStringW) - { - versionContentW = - reinterpret_cast<wchar_t*>(wcsdup(aVersionStringW)); - } - - const wchar_t* ReadContentW() const - { - return versionContentW; - } - - ~VersionW() - { - free(versionContentW); - } - - bool operator<(const VersionW& aRhs) const - { - return CompareVersions(versionContentW, aRhs.ReadContentW()) == -1; - } - bool operator<=(const VersionW& aRhs) const - { - return CompareVersions(versionContentW, aRhs.ReadContentW()) < 1; - } - bool operator>(const VersionW& aRhs) const - { - return CompareVersions(versionContentW, aRhs.ReadContentW()) == 1; - } - bool operator>=(const VersionW& aRhs) const - { - return CompareVersions(versionContentW, aRhs.ReadContentW()) > -1; - } - bool operator==(const VersionW& aRhs) const - { - return CompareVersions(versionContentW, aRhs.ReadContentW()) == 0; - } - bool operator!=(const VersionW& aRhs) const - { - return CompareVersions(versionContentW, aRhs.ReadContentW()) != 0; - } + explicit VersionW(const wchar_t* aVersionStringW) + { + versionContentW = + reinterpret_cast<wchar_t*>(wcsdup(aVersionStringW)); + } + + const wchar_t* ReadContentW() const + { + return versionContentW; + } + + ~VersionW() + { + free(versionContentW); + } + + bool operator<(const VersionW& aRhs) const + { + return CompareVersions(versionContentW, aRhs.ReadContentW()) == -1; + } + bool operator<=(const VersionW& aRhs) const + { + return CompareVersions(versionContentW, aRhs.ReadContentW()) < 1; + } + bool operator>(const VersionW& aRhs) const + { + return CompareVersions(versionContentW, aRhs.ReadContentW()) == 1; + } + bool operator>=(const VersionW& aRhs) const + { + return CompareVersions(versionContentW, aRhs.ReadContentW()) > -1; + } + bool operator==(const VersionW& aRhs) const + { + return CompareVersions(versionContentW, aRhs.ReadContentW()) == 0; + } + bool operator!=(const VersionW& aRhs) const + { + return CompareVersions(versionContentW, aRhs.ReadContentW()) != 0; + } private: - wchar_t* versionContentW; + wchar_t* versionContentW; }; #endif diff --git a/onlineupdate/source/winhelper/windowsStart.cxx b/onlineupdate/source/winhelper/windowsStart.cxx index 7237e06da58b..1c782d7a289f 100644 --- a/onlineupdate/source/winhelper/windowsStart.cxx +++ b/onlineupdate/source/winhelper/windowsStart.cxx @@ -19,34 +19,41 @@ */ static int ArgStrLen(const wchar_t *s) { - int backslashes = 0; - int i = wcslen(s); - BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr; - // Only add doublequotes if the string contains a space or a tab - BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr; - - if (addDoubleQuotes) { - i += 2; // initial and final duoblequote - } - - if (hasDoubleQuote) { - while (*s) { - if (*s == '\\') { - ++backslashes; - } else { - if (*s == '"') { - // Escape the doublequote and all backslashes preceding the doublequote - i += backslashes + 1; - } - - backslashes = 0; - } + int backslashes = 0; + int i = wcslen(s); + BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr; + // Only add doublequotes if the string contains a space or a tab + BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr; + + if (addDoubleQuotes) + { + i += 2; // initial and final duoblequote + } - ++s; + if (hasDoubleQuote) + { + while (*s) + { + if (*s == '\\') + { + ++backslashes; + } + else + { + if (*s == '"') + { + // Escape the doublequote and all backslashes preceding the doublequote + i += backslashes + 1; + } + + backslashes = 0; + } + + ++s; + } } - } - return i; + return i; } /** @@ -60,47 +67,59 @@ static int ArgStrLen(const wchar_t *s) */ static wchar_t* ArgToString(wchar_t *d, const wchar_t *s) { - int backslashes = 0; - BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr; - // Only add doublequotes if the string contains a space or a tab - BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr; - - if (addDoubleQuotes) { - *d = '"'; // initial doublequote - ++d; - } + int backslashes = 0; + BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr; + // Only add doublequotes if the string contains a space or a tab + BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr; + + if (addDoubleQuotes) + { + *d = '"'; // initial doublequote + ++d; + } - if (hasDoubleQuote) { - int i; - while (*s) { - if (*s == '\\') { - ++backslashes; - } else { - if (*s == '"') { - // Escape the doublequote and all backslashes preceding the doublequote - for (i = 0; i <= backslashes; ++i) { - *d = '\\'; + if (hasDoubleQuote) + { + int i; + while (*s) + { + if (*s == '\\') + { + ++backslashes; + } + else + { + if (*s == '"') + { + // Escape the doublequote and all backslashes preceding the doublequote + for (i = 0; i <= backslashes; ++i) + { + *d = '\\'; + ++d; + } + } + + backslashes = 0; + } + + *d = *s; ++d; - } + ++s; } - - backslashes = 0; - } - - *d = *s; - ++d; ++s; } - } else { - wcscpy(d, s); - d += wcslen(s); - } + else + { + wcscpy(d, s); + d += wcslen(s); + } - if (addDoubleQuotes) { - *d = '"'; // final doublequote - ++d; - } + if (addDoubleQuotes) + { + *d = '"'; // final doublequote + ++d; + } - return d; + return d; } /** @@ -112,33 +131,35 @@ static wchar_t* ArgToString(wchar_t *d, const wchar_t *s) wchar_t* MakeCommandLine(int argc, wchar_t **argv) { - int i; - int len = 0; - - // The + 1 of the last argument handles the allocation for null termination - for (i = 0; i < argc; ++i) - len += ArgStrLen(argv[i]) + 1; - - // Protect against callers that pass 0 arguments - if (len == 0) - len = 1; - - wchar_t *s = (wchar_t*) malloc(len * sizeof(wchar_t)); - if (!s) - return nullptr; - - wchar_t *c = s; - for (i = 0; i < argc; ++i) { - c = ArgToString(c, argv[i]); - if (i + 1 != argc) { - *c = ' '; - ++c; + int i; + int len = 0; + + // The + 1 of the last argument handles the allocation for null termination + for (i = 0; i < argc; ++i) + len += ArgStrLen(argv[i]) + 1; + + // Protect against callers that pass 0 arguments + if (len == 0) + len = 1; + + wchar_t *s = (wchar_t*) malloc(len * sizeof(wchar_t)); + if (!s) + return nullptr; + + wchar_t *c = s; + for (i = 0; i < argc; ++i) + { + c = ArgToString(c, argv[i]); + if (i + 1 != argc) + { + *c = ' '; + ++c; + } } - } - *c = '\0'; + *c = '\0'; - return s; + return s; } /** @@ -159,79 +180,91 @@ WinLaunchChild(const wchar_t *exePath, HANDLE userToken, HANDLE *hProcess) { - wchar_t *cl; - BOOL ok; - - cl = MakeCommandLine(argc, argv); - if (!cl) { - return FALSE; - } - - STARTUPINFOW si = {0}; - si.cb = sizeof(STARTUPINFOW); - si.lpDesktop = L"winsta0\\Default"; - PROCESS_INFORMATION pi = {0}; - - if (userToken == nullptr) { - ok = CreateProcessW(exePath, - cl, - nullptr, // no special security attributes - nullptr, // no special thread attributes - FALSE, // don't inherit filehandles - 0, // creation flags - nullptr, // inherit my environment - nullptr, // use my current directory - &si, - &pi); - } else { - // Create an environment block for the process we're about to start using - // the user's token. - LPVOID environmentBlock = nullptr; - if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE)) { - environmentBlock = nullptr; + wchar_t *cl; + BOOL ok; + + cl = MakeCommandLine(argc, argv); + if (!cl) + { + return FALSE; } - ok = CreateProcessAsUserW(userToken, - exePath, - cl, - nullptr, // no special security attributes - nullptr, // no special thread attributes - FALSE, // don't inherit filehandles - 0, // creation flags - environmentBlock, - nullptr, // use my current directory - &si, - &pi); - - if (environmentBlock) { - DestroyEnvironmentBlock(environmentBlock); + STARTUPINFOW si = {0}; + si.cb = sizeof(STARTUPINFOW); + si.lpDesktop = L"winsta0\\Default"; + PROCESS_INFORMATION pi = {0}; + + if (userToken == nullptr) + { + ok = CreateProcessW(exePath, + cl, + nullptr, // no special security attributes + nullptr, // no special thread attributes + FALSE, // don't inherit filehandles + 0, // creation flags + nullptr, // inherit my environment + nullptr, // use my current directory + &si, + &pi); } - } + else + { + // Create an environment block for the process we're about to start using + // the user's token. + LPVOID environmentBlock = nullptr; + if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE)) + { + environmentBlock = nullptr; + } - if (ok) { - if (hProcess) { - *hProcess = pi.hProcess; // the caller now owns the HANDLE - } else { - CloseHandle(pi.hProcess); + ok = CreateProcessAsUserW(userToken, + exePath, + cl, + nullptr, // no special security attributes + nullptr, // no special thread attributes + FALSE, // don't inherit filehandles + 0, // creation flags + environmentBlock, + nullptr, // use my current directory + &si, + &pi); + + if (environmentBlock) + { + DestroyEnvironmentBlock(environmentBlock); + } } - CloseHandle(pi.hThread); - } else { - LPVOID lpMsgBuf = nullptr; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, - nullptr); - wprintf(L"Error restarting: %s\n", lpMsgBuf ? lpMsgBuf : L"(null)"); - if (lpMsgBuf) - LocalFree(lpMsgBuf); - } - - free(cl); - - return ok; + + if (ok) + { + if (hProcess) + { + *hProcess = pi.hProcess; // the caller now owns the HANDLE + } + else + { + CloseHandle(pi.hProcess); + } + CloseHandle(pi.hThread); + } + else + { + LPVOID lpMsgBuf = nullptr; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + nullptr); + wprintf(L"Error restarting: %s\n", lpMsgBuf ? lpMsgBuf : L"(null)"); + if (lpMsgBuf) + LocalFree(lpMsgBuf); + } + + free(cl); + + return ok; } |