// Expectations for Enumerations void CfgTest::ExpectDatabaseInEnum(CFG_ENUMERATION_HANDLE cehHandle, LPCWSTR wzExpectedFriendlyName, BOOL fExpectedSyncByDefault, LPCWSTR wzExpectedPath) { HRESULT hr = S_OK; DWORD dwCount = 0; LPCWSTR wzFriendlyName = NULL; BOOL fSyncByDefault = FALSE; LPCWSTR wzPath = NULL; hr = CfgEnumReadDword(cehHandle, 0, ENUM_DATA_COUNT, &dwCount); ExitOnFailure(hr, "Failed to get count of items in database list enumeration"); for (DWORD i = 0; i < dwCount; ++i) { hr = CfgEnumReadString(cehHandle, i, ENUM_DATA_FRIENDLY_NAME, &wzFriendlyName); ExitOnFailure1(hr, "Failed to read friendly name from database list enum at index %u", i); hr = CfgEnumReadBool(cehHandle, i, ENUM_DATA_SYNC_BY_DEFAULT, &fSyncByDefault); ExitOnFailure1(hr, "Failed to read path from database list enum at index %u", i); hr = CfgEnumReadString(cehHandle, i, ENUM_DATA_PATH, &wzPath); ExitOnFailure1(hr, "Failed to read path from database list enum at index %u", i); // If it isn't the right friendly name, skip to the next database in the enumeration if (0 != lstrcmpW(wzExpectedFriendlyName, wzFriendlyName)) { continue; } if (0 != lstrcmpW(wzExpectedPath, wzPath)) { hr = E_FAIL; ExitOnFailure3(hr, "Database list friendly name '%ls' has incorrect path (expected '%ls', found '%ls')", wzExpectedFriendlyName, wzExpectedPath, wzPath); } if (fSyncByDefault != fExpectedSyncByDefault) { hr = E_FAIL; ExitOnFailure3(hr, "Database list friendly name '%ls' has incorrect 'sync by default' flag (expected %u, found %u)", wzExpectedFriendlyName, fExpectedSyncByDefault, fSyncByDefault); } // We found the right one, so return successfully now return; } hr = E_FAIL; ExitOnFailure2(hr, "Expected to find database in list, but didn't find it: %ls, %ls", wzFriendlyName, wzPath); LExit: return; }
void CfgTest::CheckCfgAndFile(CFGDB_HANDLE cdhDb, LPCWSTR wzFileName, LPCWSTR wzFilePath, BYTE *pbBuffer, SIZE_T cbBuffer) { HRESULT hr = S_OK; BYTE *pbDataReadFromFile = NULL; DWORD cbDataReadFromFile = 0; ExpectFile(cdhDb, wzFileName, pbBuffer, cbBuffer); hr = FileRead(&pbDataReadFromFile, &cbDataReadFromFile, wzFilePath); ExitOnFailure1(hr, "Failed to read file: %ls", wzFilePath); if (cbBuffer != cbDataReadFromFile) { hr = E_FAIL; ExitOnFailure3(hr, "File %ls should be size %u, but was size %u instead", wzFilePath, cbBuffer, cbDataReadFromFile); } if (0 != memcmp(pbBuffer, pbDataReadFromFile, cbBuffer)) { hr = E_FAIL; ExitOnFailure1(hr, "File contents don't match for file of name: %ls", wzFilePath); } LExit: ReleaseMem(pbDataReadFromFile); }
void CfgTest::ExpectIniValue(INI_HANDLE iniHandle, LPCWSTR wzValueName, LPCWSTR wzExpectedValue) { HRESULT hr = S_OK; INI_VALUE* rgivValues = NULL; DWORD civValues = 0; hr = IniGetValueList(iniHandle, &rgivValues, &civValues); ExitOnFailure(hr, "Failed to get value list from INI handle"); for (DWORD i = 0; i < civValues; ++i) { if (0 == wcscmp(rgivValues[i].wzName, wzValueName)) { if (0 == wcscmp(rgivValues[i].wzValue, wzExpectedValue)) { return; } else { hr = E_FAIL; ExitOnFailure3(hr, "Found ini value %ls, but we expected to find value %ls, and found value %ls instead", wzValueName, wzExpectedValue, rgivValues[i].wzValue); } } } hr = E_NOTFOUND; ExitOnFailure1(hr, "Failed to find value %ls in INI", wzValueName); LExit: return; }
void CfgTest::ExpectAdminProductUnregistered(CFGDB_HANDLE cdhAdminDb, LPCWSTR wzProductName, LPCWSTR wzVersion, LPCWSTR wzPublicKey) { HRESULT hr = S_OK; BOOL fRegistered = FALSE; hr = CfgAdminIsProductRegistered(cdhAdminDb, wzProductName, wzVersion, wzPublicKey, &fRegistered); ExitOnFailure3(hr, "Failed to check if product is registered (per-machine): %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey); if (fRegistered) { hr = E_FAIL; ExitOnFailure3(hr, "Product shouldn't be registered (per-machine), but it is!: %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey); } LExit: return; }
void CfgTest::ExpectProductRegistered(CFGDB_HANDLE cdhUserDb, LPCWSTR wzProductName, LPCWSTR wzVersion, LPCWSTR wzPublicKey) { HRESULT hr = S_OK; BOOL fRegistered = FALSE; hr = CfgIsProductRegistered(cdhUserDb, wzProductName, wzVersion, wzPublicKey, &fRegistered); ExitOnFailure3(hr, "Failed to check if product is registered (per-user): %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey); if (!fRegistered) { hr = E_FAIL; ExitOnFailure3(hr, "Product should be registered (per-user), but it isn't!: %ls, %ls, %ls", wzProductName, wzVersion, wzPublicKey); } LExit: return; }
void CfgTest::CheckCfgAndRegValueFlag(CFGDB_HANDLE cdhDb, HKEY hk, LPCWSTR wzCfgName, LPCWSTR wzName, BOOL fExpectedValue, DWORD dwOffset) { HRESULT hr = S_OK; BYTE *pbBytes; DWORD cbBytes; BOOL fRegFoundValue = FALSE; BOOL fCfgFoundValue = FALSE; hr = RegReadBinary(hk, wzName, &pbBytes, &cbBytes); ExitOnFailure1(hr, "Failed to read binary value from registry named %ls", wzName); if (dwOffset >= cbBytes * 8) { hr = E_INVALIDARG; ExitOnFailure2(hr, "Not enough bytes found in registry value %ls to check offset %u", wzName, dwOffset); } fRegFoundValue = (pbBytes[dwOffset / 8] & (0x1 << (dwOffset % 8))) == 0 ? FALSE : TRUE; if (fRegFoundValue != fExpectedValue) { hr = E_FAIL; ExitOnFailure3(hr, "Boolean flag value in registry didn't match expected! RegName: %ls, Offset: %ls, Expected: %ls", wzName, dwOffset, fExpectedValue ? L"TRUE" : L"FALSE"); } hr = CfgGetBool(cdhDb, wzCfgName, &fCfgFoundValue); ExitOnFailure1(hr, "Failed to read boolean from cfg db named %ls", wzCfgName); if (fCfgFoundValue != fExpectedValue) { hr = E_FAIL; ExitOnFailure2(hr, "Boolean flag value in cfg db didn't match expected! CfgName: %ls, Expected: %ls", wzCfgName, fExpectedValue ? L"TRUE" : L"FALSE"); } LExit: ReleaseMem(pbBytes); }
/****************************************************************** CaExecSecureObjects - entry point for SecureObjects Custom Action called as Type 1025 CustomAction (deferred binary DLL) NOTE: deferred CustomAction since it modifies the machine NOTE: CustomActionData == wzObject\twzTable\twzDomain\twzUser\tdwPermissions\twzObject\t... ******************************************************************/ extern "C" UINT __stdcall ExecSecureObjects( __in MSIHANDLE hInstall ) { // AssertSz(FALSE, "debug ExecSecureObjects"); HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; LPWSTR pwz = NULL; LPWSTR pwzData = NULL; LPWSTR pwzObject = NULL; LPWSTR pwzTable = NULL; LPWSTR pwzDomain = NULL; DWORD dwRevision = 0; LPWSTR pwzUser = NULL; DWORD dwPermissions = 0; LPWSTR pwzAccount = NULL; PSID psid = NULL; EXPLICIT_ACCESSW ea = {0}; SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE; PSECURITY_DESCRIPTOR psd = NULL; SECURITY_DESCRIPTOR_CONTROL sdc = {0}; SECURITY_INFORMATION si = {0}; PACL pAclExisting = NULL; // doesn't get freed PACL pAclNew = NULL; PMSIHANDLE hActionRec = ::MsiCreateRecord(1); // // initialize // hr = WcaInitialize(hInstall, "ExecSecureObjects"); ExitOnFailure(hr, "failed to initialize"); hr = WcaGetProperty(L"CustomActionData", &pwzData); ExitOnFailure(hr, "failed to get CustomActionData"); WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %S", pwzData); pwz = pwzData; // // loop through all the passed in data // while (pwz && *pwz) { hr = WcaReadStringFromCaData(&pwz, &pwzObject); ExitOnFailure(hr, "failed to process CustomActionData"); hr = WcaReadStringFromCaData(&pwz, &pwzTable); ExitOnFailure(hr, "failed to process CustomActionData"); hr = WcaReadStringFromCaData(&pwz, &pwzDomain); ExitOnFailure(hr, "failed to process CustomActionData"); hr = WcaReadStringFromCaData(&pwz, &pwzUser); ExitOnFailure(hr, "failed to process CustomActionData"); hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwPermissions)); ExitOnFailure(hr, "failed to processCustomActionData"); WcaLog(LOGMSG_VERBOSE, "Securing Object: %S Type: %S User: %S", pwzObject, pwzTable, pwzUser); // // create the appropriate SID // // figure out the right user to put into the access block if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Everyone")) { hr = AclGetWellKnownSid(WinWorldSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Administrators")) { hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalSystem")) { hr = AclGetWellKnownSid(WinLocalSystemSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalService")) { hr = AclGetWellKnownSid(WinLocalServiceSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"NetworkService")) { hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"AuthenticatedUser")) { hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Guests")) { hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid); } else if(!*pwzDomain && 0 == lstrcmpW(pwzUser, L"CREATOR OWNER")) { hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid); } else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"INTERACTIVE")) { hr = AclGetWellKnownSid(WinInteractiveSid, &psid); } else if(!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Users")) { hr = AclGetWellKnownSid(WinBuiltinUsersSid, &psid); } else { hr = StrAllocFormatted(&pwzAccount, L"%s\\%s", *pwzDomain ? pwzDomain : L".", pwzUser); ExitOnFailure(hr, "failed to build domain user name"); hr = AclGetAccountSid(NULL, pwzAccount, &psid); } ExitOnFailure3(hr, "failed to get sid for account: %S%S%S", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser); // // build up the explicit access // ea.grfAccessPermissions = dwPermissions; ea.grfAccessMode = SET_ACCESS; if (0 == lstrcmpW(L"CreateFolder", pwzTable)) { ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; } else { ea.grfInheritance = NO_INHERITANCE; } ::BuildTrusteeWithSidW(&ea.Trustee, psid); if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) { objectType = SE_SERVICE; // always add these permissions for services // these are basic permissions that are often forgotten dwPermissions |= SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE; } else if (0 == lstrcmpW(L"CreateFolder", pwzTable) || 0 == lstrcmpW(L"File", pwzTable)) { objectType = SE_FILE_OBJECT; } else if (0 == lstrcmpW(L"Registry", pwzTable)) { objectType = SE_REGISTRY_KEY; } if (SE_UNKNOWN_OBJECT_TYPE != objectType) { er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pAclExisting, NULL, &psd); ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get security info for object: %S", pwzObject); //Need to see if DACL is protected so getting Descriptor information if(!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) { ExitOnLastError1(hr, "failed to get security descriptor control for object: %S", pwzObject); } er = ::SetEntriesInAclW(1, &ea, pAclExisting, &pAclNew); ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to add ACLs for object: %S", pwzObject); if (sdc & SE_DACL_PROTECTED) { si = DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION; } else { si = DACL_SECURITY_INFORMATION; } er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pAclNew, NULL); MessageExitOnFailure1(hr = HRESULT_FROM_WIN32(er), msierrSecureObjectsFailedSet, "failed to set security info for object: %S", pwzObject); } else { MessageExitOnFailure1(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %S", pwzTable); } hr = WcaProgressMessage(COST_SECUREOBJECT, FALSE); ExitOnFailure(hr, "failed to send progress message"); objectType = SE_UNKNOWN_OBJECT_TYPE; } LExit: ReleaseStr(pwzUser); ReleaseStr(pwzDomain); ReleaseStr(pwzTable); ReleaseStr(pwzObject); ReleaseStr(pwzData); ReleaseStr(pwzAccount); if (pAclNew) ::LocalFree(pAclNew); if (psd) ::LocalFree(psd); if (psid) AclFreeSid(psid); if (FAILED(hr)) er = ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
/****************************************************************** ExecFirewallExceptions - deferred custom action entry point to register and remove firewall exceptions. ********************************************************************/ extern "C" UINT __stdcall ExecFirewallExceptions( __in MSIHANDLE hInstall ) { HRESULT hr = S_OK; BOOL fSupportProfiles = FALSE; LPWSTR pwz = NULL; LPWSTR pwzCustomActionData = NULL; int iTodo = WCA_TODO_UNKNOWN; LPWSTR pwzName = NULL; LPWSTR pwzRemoteAddresses = NULL; int iAttributes = 0; int iTarget = fetUnknown; LPWSTR pwzFile = NULL; LPWSTR pwzPort = NULL; LPWSTR pwzDescription = NULL; int iProtocol = 0; int iProfile = 0; // initialize hr = WcaInitialize(hInstall, "ExecFirewallExceptions"); ExitOnFailure(hr, "failed to initialize"); hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); ExitOnFailure(hr, "failed to get CustomActionData"); WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); hr = ::CoInitialize(NULL); ExitOnFailure(hr, "failed to initialize COM"); // Find out if we support profiles (only on Vista or later) fSupportProfiles = FSupportProfiles(); // loop through all the passed in data pwz = pwzCustomActionData; while (pwz && *pwz) { // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL hr = WcaReadIntegerFromCaData(&pwz, &iTodo); ExitOnFailure(hr, "failed to read todo from custom action data"); if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK)) { if (WCA_TODO_INSTALL == iTodo) { iTodo = WCA_TODO_UNINSTALL; } else if (WCA_TODO_UNINSTALL == iTodo) { iTodo = WCA_TODO_INSTALL; } } hr = WcaReadStringFromCaData(&pwz, &pwzName); ExitOnFailure(hr, "failed to read name from custom action data"); hr = WcaReadIntegerFromCaData(&pwz, &iProfile); ExitOnFailure(hr, "failed to read profile from custom action data"); hr = WcaReadStringFromCaData(&pwz, &pwzRemoteAddresses); ExitOnFailure(hr, "failed to read remote addresses from custom action data"); hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); ExitOnFailure(hr, "failed to read attributes from custom action data"); BOOL fIgnoreFailures = feaIgnoreFailures == (iAttributes & feaIgnoreFailures); hr = WcaReadIntegerFromCaData(&pwz, &iTarget); ExitOnFailure(hr, "failed to read target from custom action data"); if (iTarget == fetApplication) { hr = WcaReadStringFromCaData(&pwz, &pwzFile); ExitOnFailure(hr, "failed to read file path from custom action data"); } hr = WcaReadStringFromCaData(&pwz, &pwzPort); ExitOnFailure(hr, "failed to read port from custom action data"); hr = WcaReadIntegerFromCaData(&pwz, &iProtocol); ExitOnFailure(hr, "failed to read protocol from custom action data"); hr = WcaReadStringFromCaData(&pwz, &pwzDescription); ExitOnFailure(hr, "failed to read protocol from custom action data"); switch (iTarget) { case fetPort: switch (iTodo) { case WCA_TODO_INSTALL: case WCA_TODO_REINSTALL: WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription); ExitOnFailure3(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); break; case WCA_TODO_UNINSTALL: WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); hr = RemovePortException(fSupportProfiles, pwzName, pwzPort, iProtocol, fIgnoreFailures); ExitOnFailure3(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); break; } break; case fetApplication: switch (iTodo) { case WCA_TODO_INSTALL: case WCA_TODO_REINSTALL: WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile); hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription); ExitOnFailure2(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile); break; case WCA_TODO_UNINSTALL: WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile); hr = RemoveApplicationException(fSupportProfiles, pwzName, pwzFile, fIgnoreFailures, pwzPort, iProtocol); ExitOnFailure2(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile); break; } break; } } LExit: ReleaseStr(pwzCustomActionData); ReleaseStr(pwzName); ReleaseStr(pwzRemoteAddresses); ReleaseStr(pwzFile); ReleaseStr(pwzPort); ReleaseStr(pwzDescription); ::CoUninitialize(); return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS); }