Beispiel #1
0
/********************************************************************
 RegValueEnum - enumerates a registry value.

*********************************************************************/
HRESULT DAPI RegValueEnum(
    __in HKEY hk,
    __in DWORD dwIndex,
    __deref_out_z LPWSTR* psczName,
    __out_opt DWORD *pdwType
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    DWORD cbValueName = 0;

    er = vpfnRegQueryInfoKeyW(hk, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cbValueName, NULL, NULL, NULL);
    ExitOnWin32Error(er, hr, "Failed to get max size of value name under registry key.");

    // Add one for null terminator
    ++cbValueName;

    hr = StrAlloc(psczName, cbValueName);
    ExitOnFailure(hr, "Failed to allocate array for registry value name");

    er = vpfnRegEnumValueW(hk, dwIndex, *psczName, &cbValueName, NULL, pdwType, NULL, NULL);
    if (ERROR_NO_MORE_ITEMS == er)
    {
        ExitFunction1(hr = E_NOMOREITEMS);
    }
    ExitOnWin32Error(er, hr, "Failed to enumerate registry value");

LExit:
    return hr;
}
Beispiel #2
0
/********************************************************************
 RegKeyEnum - enumerates a registry key.

*********************************************************************/
extern "C" HRESULT DAPI RegKeyEnum(
    __in HKEY hk,
    __in DWORD dwIndex,
    __deref_out_z LPWSTR* psczKey
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    DWORD cch = 0;

    if (psczKey && *psczKey)
    {
        hr = StrMaxLength(*psczKey, reinterpret_cast<DWORD_PTR*>(&cch));
        ExitOnFailure(hr, "Failed to determine length of string.");
    }

    if (2 > cch)
    {
        cch = 2;

        hr = StrAlloc(psczKey, cch);
        ExitOnFailure(hr, "Failed to allocate string to minimum size.");
    }

    er = vpfnRegEnumKeyExW(hk, dwIndex, *psczKey, &cch, NULL, NULL, NULL, NULL);
    if (ERROR_MORE_DATA == er)
    {
        er = vpfnRegQueryInfoKeyW(hk, NULL, NULL, NULL, NULL, &cch, NULL, NULL, NULL, NULL, NULL, NULL);
        ExitOnWin32Error(er, hr, "Failed to get max size of subkey name under registry key.");

        ++cch; // add one because RegQueryInfoKeyW() returns the length of the subkeys without the null terminator.
        hr = StrAlloc(psczKey, cch);
        ExitOnFailure(hr, "Failed to allocate string bigger for enum registry key.");

        er = vpfnRegEnumKeyExW(hk, dwIndex, *psczKey, &cch, NULL, NULL, NULL, NULL);
    }
    else if (ERROR_NO_MORE_ITEMS == er)
    {
        ExitFunction1(hr = E_NOMOREITEMS);
    }
    ExitOnWin32Error(er, hr, "Failed to enum registry key.");

    // Always ensure the registry key name is null terminated.
#pragma prefast(push)
#pragma prefast(disable:26018)
    (*psczKey)[cch] = L'\0'; // note that cch will always be one less than the size of the buffer because that's how RegEnumKeyExW() works.
#pragma prefast(pop)

LExit:
    return hr;
}
Beispiel #3
0
/******************************************************************
 PromptToContinue - displays the prompt if the application is still
  running.

******************************************************************/
static HRESULT PromptToContinue(
    __in_z LPCWSTR wzApplication,
    __in_z LPCWSTR wzPrompt
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    PMSIHANDLE hRecMessage = NULL;
    DWORD *prgProcessIds = NULL;
    DWORD cProcessIds = 0;

    hRecMessage = ::MsiCreateRecord(1);
    ExitOnNull(hRecMessage, hr, E_OUTOFMEMORY, "Failed to create record for prompt.");

    er = ::MsiRecordSetStringW(hRecMessage, 0, wzPrompt);
    ExitOnWin32Error(er, hr, "Failed to set prompt record field string");

    do
    {
        hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds);
        if (SUCCEEDED(hr) && 0 < cProcessIds)
        {
            er = WcaProcessMessage(static_cast<INSTALLMESSAGE>(INSTALLMESSAGE_WARNING | MB_ABORTRETRYIGNORE | MB_DEFBUTTON3 | MB_ICONWARNING), hRecMessage);
            if (IDABORT == er)
            {
                hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
            }
            else if (IDRETRY == er)
            {
                hr = S_FALSE;
            }
            else if (IDIGNORE == er)
            {
                hr = S_OK;
            }
            else
            {
                ExitOnWin32Error(er, hr, "Unexpected return value from prompt to continue.");
            }
        }

        ReleaseNullMem(prgProcessIds);
        cProcessIds = 0;
    } while (S_FALSE == hr);

LExit:
    ReleaseMem(prgProcessIds);
    return hr;
}
Beispiel #4
0
DAPI_(HRESULT) SrpCreateRestorePoint(
    __in_z LPCWSTR wzApplicationName,
    __in SRP_ACTION action
    )
{
    HRESULT hr = S_OK;
    RESTOREPOINTINFOW restorePoint = { };
    STATEMGRSTATUS status = { };

    if (!vpfnSRSetRestorePointW)
    {
        ExitFunction1(hr = E_NOTIMPL);
    }

    restorePoint.dwEventType = BEGIN_SYSTEM_CHANGE;
    restorePoint.dwRestorePtType = (SRP_ACTION_INSTALL == action) ? APPLICATION_INSTALL : (SRP_ACTION_UNINSTALL == action) ? APPLICATION_UNINSTALL : MODIFY_SETTINGS;
    ::StringCbCopyW(restorePoint.szDescription, sizeof(restorePoint.szDescription), wzApplicationName);

    if (!vpfnSRSetRestorePointW(&restorePoint, &status))
    {
        ExitOnWin32Error(status.nStatus, hr, "Failed to create system restore point.");
    }

LExit:
    return hr;
}
Beispiel #5
0
/********************************************************************
RmuRegisterResources - Registers resources for the Restart Manager.

This should be called rarely because it is expensive to run. Call
functions like RmuAddFile for multiple resources then commit them
as a batch of updates to RmuRegisterResources.

Duplicate resources appear to be handled by Restart Manager.
Only one WM_QUERYENDSESSION is being sent for each top-level window.

********************************************************************/
extern "C" HRESULT DAPI RmuRegisterResources(
    __in PRMU_SESSION pSession
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    HMODULE hModule = NULL;
    PFNRMREGISTERRESOURCES pfnRmRegisterResources = NULL;

    AssertSz(vcRmuInitialized, "Restart Manager was not properly initialized.");

    ::EnterCriticalSection(&pSession->cs);

    er = vpfnRmRegisterResources(
        pSession->dwSessionHandle,
        pSession->cFilenames,
        pSession->rgsczFilenames,
        pSession->cApplications,
        pSession->rgApplications,
        pSession->cServiceNames,
        pSession->rgsczServiceNames
        );
    ExitOnWin32Error(er, hr, "Failed to register the resources with the Restart Manager session.");

    // Empty the arrays if registered in case additional resources are added later.
    ReleaseNullStrArray(pSession->rgsczFilenames, pSession->cFilenames);
    ReleaseNullApplicationArray(pSession->rgApplications, pSession->cApplications);
    ReleaseNullStrArray(pSession->rgsczServiceNames, pSession->cServiceNames);

LExit:
    ::LeaveCriticalSection(&pSession->cs);
    return hr;
}
Beispiel #6
0
/********************************************************************
RmuEndSession - Ends the session.

If the session was joined by RmuJoinSession, any remaining resources
are registered before the session is ended (left).

********************************************************************/
extern "C" HRESULT DAPI RmuEndSession(
    __in PRMU_SESSION pSession
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;

    AssertSz(vcRmuInitialized, "Restart Manager was not properly initialized.");

    // Make sure all resources are registered if we joined the session.
    if (!pSession->fStartedSessionHandle)
    {
        hr = RmuRegisterResources(pSession);
        ExitOnFailure(hr, "Failed to register remaining resources.");
    }

    er = vpfnRmEndSession(pSession->dwSessionHandle);
    ExitOnWin32Error(er, hr, "Failed to end the Restart Manager session.");

LExit:
    if (pSession->fInitialized)
    {
        ::DeleteCriticalSection(&pSession->cs);
    }

    ReleaseNullStrArray(pSession->rgsczFilenames, pSession->cFilenames);
    ReleaseNullApplicationArray(pSession->rgApplications, pSession->cApplications);
    ReleaseNullStrArray(pSession->rgsczServiceNames, pSession->cServiceNames);
    ReleaseNullMem(pSession);

    RmuUninitialize();

    return hr;
}
Beispiel #7
0
/********************************************************************
 RegCreate - creates a registry key with extra options.

*********************************************************************/
HRESULT DAPI RegCreateEx(
    __in HKEY hkRoot,
    __in_z LPCWSTR wzSubKey,
    __in DWORD dwAccess,
    __in BOOL fVolatile,
    __in_opt SECURITY_ATTRIBUTES* pSecurityAttributes,
    __out HKEY* phk,
    __out_opt BOOL* pfCreated
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    DWORD dwDisposition;

    er = vpfnRegCreateKeyExW(hkRoot, wzSubKey, 0, NULL, fVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE, dwAccess, pSecurityAttributes, phk, &dwDisposition);
    ExitOnWin32Error(er, hr, "Failed to create registry key.");

    if (pfCreated)
    {
        *pfCreated = (REG_CREATED_NEW_KEY == dwDisposition);
    }

LExit:
    return hr;
}
Beispiel #8
0
/********************************************************************
WcaOpenExecuteView() - opens and executes a view on the installing database

********************************************************************/
extern "C" HRESULT WIXAPI WcaOpenExecuteView(
    __in_z LPCWSTR wzSql,
    __out MSIHANDLE* phView
    )
{
    if (!wzSql || !*wzSql|| !phView)
    {
        return E_INVALIDARG;
    }

    HRESULT hr = S_OK;
    UINT er = ::MsiDatabaseOpenViewW(WcaGetDatabaseHandle(), wzSql, phView);
    ExitOnWin32Error(er, hr, "failed to open view on database");

    er = ::MsiViewExecute(*phView, NULL);
    ExitOnWin32Error(er, hr, "failed to execute view");

LExit:
    return hr;
}
Beispiel #9
0
/********************************************************************
WcaGetRecordFormattedString() - gets formatted string filed from record

********************************************************************/
extern "C" HRESULT WIXAPI WcaGetRecordFormattedString(
    __in MSIHANDLE hRec,
    __in UINT uiField,
    __inout LPWSTR* ppwzData
    )
{
    if (!hRec || !ppwzData)
    {
        return E_INVALIDARG;
    }

    HRESULT hr = S_OK;
    UINT er;
    DWORD_PTR cch = 0;
    PMSIHANDLE hRecFormat;

    // get the format string
    hr = WcaGetRecordString(hRec, uiField, ppwzData);
    ExitOnFailure(hr, "failed to get string from record");

    if (!**ppwzData)
    {
        ExitFunction();
    }

    // hide the nulls '[~]' so we can get them back after formatting
    HideNulls(*ppwzData);

    // set up the format record
    hRecFormat = ::MsiCreateRecord(1);
    ExitOnNull(hRecFormat, hr, E_UNEXPECTED, "Failed to create record to format string");
    hr = WcaSetRecordString(hRecFormat, 0, *ppwzData);
    ExitOnFailure(hr, "failed to set string to format record");

    // format the string
    hr = StrMaxLength(*ppwzData, &cch);
    ExitOnFailure(hr, "failed to get max length of string");

    er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecFormat, *ppwzData, (DWORD*)&cch);
    if (ERROR_MORE_DATA == er)
    {
        hr = StrAlloc(ppwzData, ++cch);
        ExitOnFailure(hr, "Failed to allocate memory for record string");

        er = ::MsiFormatRecordW(WcaGetInstallHandle(), hRecFormat, *ppwzData, (DWORD*)&cch);
    }
    ExitOnWin32Error(er, hr, "Failed to format string");

    // put the nulls back
    RevealNulls(*ppwzData);

LExit:
    return hr;
}
Beispiel #10
0
/********************************************************************
 RegCreate - creates a registry key.

*********************************************************************/
extern "C" HRESULT DAPI RegCreate(
    __in HKEY hkRoot,
    __in_z LPCWSTR wzSubKey,
    __in DWORD dwAccess,
    __out HKEY* phk
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;

    er = vpfnRegCreateKeyExW(hkRoot, wzSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, phk, NULL);
    ExitOnWin32Error(er, hr, "Failed to create registry key.");

LExit:
    return hr;
}
Beispiel #11
0
/********************************************************************
WcaGetRecordString() - gets a string field out of a record

********************************************************************/
extern "C" HRESULT WIXAPI WcaGetRecordString(
    __in MSIHANDLE hRec,
    __in UINT uiField,
    __inout LPWSTR* ppwzData
    )
{
    if (!hRec || !ppwzData)
        return E_INVALIDARG;

    HRESULT hr = S_OK;
    UINT er;
    DWORD_PTR cch = 0;

    if (!*ppwzData)
    {
        WCHAR szEmpty[1] = L"";
        er = ::MsiRecordGetStringW(hRec, uiField, szEmpty, (DWORD*)&cch);
        if (ERROR_MORE_DATA == er || ERROR_SUCCESS == er)
        {
            hr = StrAlloc(ppwzData, ++cch);
        }
        else
        {
            hr = HRESULT_FROM_WIN32(er);
        }
        ExitOnFailure(hr, "Failed to allocate memory for record string");
    }
    else
    {
        hr = StrMaxLength(*ppwzData, &cch);
        ExitOnFailure(hr, "Failed to get previous size of string");
    }

    er = ::MsiRecordGetStringW(hRec, uiField, *ppwzData, (DWORD*)&cch);
    if (ERROR_MORE_DATA == er)
    {
        hr = StrAlloc(ppwzData, ++cch);
        ExitOnFailure(hr, "Failed to allocate memory for record string");

        er = ::MsiRecordGetStringW(hRec, uiField, *ppwzData, (DWORD*)&cch);
    }
    ExitOnWin32Error(er, hr, "Failed to get string from record");

LExit:
    return hr;
}
Beispiel #12
0
/********************************************************************
WcaExecuteView() - executes a parameterized open view on the installing database

********************************************************************/
extern "C" HRESULT WIXAPI WcaExecuteView(
    __in MSIHANDLE hView,
    __in MSIHANDLE hRec
    )
{
    if (!hView)
    {
        return E_INVALIDARG;
    }
    AssertSz(hRec, "Use WcaOpenExecuteView() if you don't need to pass in a record");

    HRESULT hr = S_OK;
    UINT er = ::MsiViewExecute(hView, hRec);
    ExitOnWin32Error(er, hr, "failed to execute view");

LExit:
    return hr;
}
Beispiel #13
0
/********************************************************************
 RegOpen - opens a registry key.

*********************************************************************/
extern "C" HRESULT DAPI RegOpen(
    __in HKEY hkRoot,
    __in_z LPCWSTR wzSubKey,
    __in DWORD dwAccess,
    __out HKEY* phk
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;

    er = vpfnRegOpenKeyExW(hkRoot, wzSubKey, 0, dwAccess, phk);
    if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er))
    {
        ExitFunction1(hr = E_FILENOTFOUND);
    }
    ExitOnWin32Error(er, hr, "Failed to open registry key.");

LExit:
    return hr;
}
Beispiel #14
0
static HRESULT InitializeComSecurity()
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    SECURITY_DESCRIPTOR sd = {0};
    EXPLICIT_ACCESS ea[5] = {0};
    ACL* pAcl = NULL;
    ULONGLONG rgSidBA[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
    ULONGLONG rgSidLS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
    ULONGLONG rgSidNS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
    ULONGLONG rgSidPS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
    ULONGLONG rgSidSY[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
    DWORD cbSid = 0;

    // Create the security descriptor explicitly as follows because
    // CoInitializeSecurity() will not accept the relative security descriptors
    // returned by ConvertStringSecurityDescriptorToSecurityDescriptor().
    //
    // The result is a security descriptor that is equivalent to the following 
    // security descriptor definition language (SDDL) string:
    //
    //   O:BAG:BAD:(A;;0x1;;;LS)(A;;0x1;;;NS)(A;;0x1;;;PS)(A;;0x1;;;SY)(A;;0x1;;;BA)
    //
 
    // Initialize the security descriptor.
    if (!::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
    {
        ExitWithLastError(hr, "Failed to initialize security descriptor for system restore.");
    }

    // Create an administrator group security identifier (SID).
    cbSid = sizeof(rgSidBA);
    if (!::CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, rgSidBA, &cbSid))
    {
        ExitWithLastError(hr, "Failed to create administrator SID for system restore.");
    }

    // Create a local service security identifier (SID).
    cbSid = sizeof(rgSidLS);
    if (!::CreateWellKnownSid(WinLocalServiceSid, NULL, rgSidLS, &cbSid))
    {
        ExitWithLastError(hr, "Failed to create local service SID for system restore.");
    }

    // Create a network service security identifier (SID).
    cbSid = sizeof(rgSidNS);
    if (!::CreateWellKnownSid(WinNetworkServiceSid, NULL, rgSidNS, &cbSid))
    {
        ExitWithLastError(hr, "Failed to create network service SID for system restore.");
    }

    // Create a personal account security identifier (SID).
    cbSid = sizeof(rgSidPS);
    if (!::CreateWellKnownSid(WinSelfSid, NULL, rgSidPS, &cbSid))
    {
        ExitWithLastError(hr, "Failed to create self SID for system restore.");
    }

    // Create a local service security identifier (SID).
    cbSid = sizeof(rgSidSY);
    if (!::CreateWellKnownSid(WinLocalSystemSid, NULL, rgSidSY, &cbSid))
    {
        ExitWithLastError(hr, "Failed to create local system SID for system restore.");
    }

    // Setup the access control entries (ACE) for COM. COM_RIGHTS_EXECUTE and
    // COM_RIGHTS_EXECUTE_LOCAL are the minimum access rights required.
    ea[0].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance = NO_INHERITANCE;
    ea[0].Trustee.pMultipleTrustee = NULL;
    ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[0].Trustee.ptstrName = (LPTSTR)rgSidBA;

    ea[1].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
    ea[1].grfAccessMode = SET_ACCESS;
    ea[1].grfInheritance = NO_INHERITANCE;
    ea[1].Trustee.pMultipleTrustee = NULL;
    ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName = (LPTSTR)rgSidLS;

    ea[2].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
    ea[2].grfAccessMode = SET_ACCESS;
    ea[2].grfInheritance = NO_INHERITANCE;
    ea[2].Trustee.pMultipleTrustee = NULL;
    ea[2].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
    ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[2].Trustee.ptstrName = (LPTSTR)rgSidNS;

    ea[3].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
    ea[3].grfAccessMode = SET_ACCESS;
    ea[3].grfInheritance = NO_INHERITANCE;
    ea[3].Trustee.pMultipleTrustee = NULL;
    ea[3].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
    ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[3].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[3].Trustee.ptstrName = (LPTSTR)rgSidPS;

    ea[4].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
    ea[4].grfAccessMode = SET_ACCESS;
    ea[4].grfInheritance = NO_INHERITANCE;
    ea[4].Trustee.pMultipleTrustee = NULL;
    ea[4].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
    ea[4].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[4].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[4].Trustee.ptstrName = (LPTSTR)rgSidSY;

    // Create an access control list (ACL) using this ACE list.
    er = ::SetEntriesInAcl(countof(ea), ea, NULL, &pAcl);
    ExitOnWin32Error(er, hr, "Failed to create ACL for system restore.");

    // Set the security descriptor owner to Administrators.
    if (!::SetSecurityDescriptorOwner(&sd, rgSidBA, FALSE))
    {
        ExitWithLastError(hr, "Failed to set administrators owner for system restore.");
    }

    // Set the security descriptor group to Administrators.
    if (!::SetSecurityDescriptorGroup(&sd, rgSidBA, FALSE))
    {
        ExitWithLastError(hr, "Failed to set administrators group access for system restore.");
    }

    // Set the discretionary access control list (DACL) to the ACL.
    if (!::SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE))
    {
        ExitWithLastError(hr, "Failed to set DACL for system restore.");
    }

    // Note that an explicit security descriptor is being passed in.
    hr= ::CoInitializeSecurity(&sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, NULL);
    ExitOnFailure(hr, "Failed to initialize COM security for system restore.");

LExit:
    if (pAcl)
    {
        ::LocalFree(pAcl);
    }

    return hr;
}
Beispiel #15
0
/******************************************************************
WixWaitForEvent - entry point for WixWaitForEvent custom action
    which waits for either the WixWaitForEventFail or
    WixWaitForEventSucceed named auto reset events. Signaling the
    WixWaitForEventFail event will return ERROR_INSTALL_FAILURE or
    signaling the WixWaitForEventSucceed event will return
    ERROR_SUCCESS. Both events are declared in the Global\ namespace.
********************************************************************/
extern "C" UINT __stdcall WixWaitForEvent(
    __in MSIHANDLE hInstall
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    HWND hMessageWindow = NULL;
    LPCWSTR wzSDDL = L"D:(A;;GA;;;WD)";
    OS_VERSION version = OS_VERSION_UNKNOWN;
    DWORD dwServicePack = 0;
    PSECURITY_DESCRIPTOR pSD = NULL;
    SECURITY_ATTRIBUTES sa = { };
    HANDLE rghEvents[2];

    hr = WcaInitialize(hInstall, "WixWaitForEvent");
    ExitOnFailure(hr, "Failed to initialize.");

    // Create a window to prevent shutdown requests.
    hr = CreateMessageWindow(&hMessageWindow);
    ExitOnFailure(hr, "Failed to create message window.");

    // If running on Vista/2008 or newer use integrity enhancements.
    OsGetVersion(&version, &dwServicePack);
    if (OS_VERSION_VISTA <= version)
    {
        // Add SACL to allow Everyone to signal from a medium integrity level.
        wzSDDL = L"D:(A;;GA;;;WD)S:(ML;;NW;;;ME)";
    }

    // Create the security descriptor and attributes for the events.
    if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSDDL, SDDL_REVISION_1, &pSD, NULL))
    {
        ExitWithLastError(hr, "Failed to create the security descriptor for the events.");
    }

    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;

    rghEvents[0] = ::CreateEventW(&sa, FALSE, FALSE, L"Global\\WixWaitForEventFail");
    ExitOnNullWithLastError(rghEvents[0], hr, "Failed to create the Global\\WixWaitForEventFail event.");

    rghEvents[1] = ::CreateEventW(&sa, FALSE, FALSE, L"Global\\WixWaitForEventSucceed");
    ExitOnNullWithLastError(rghEvents[1], hr, "Failed to create the Global\\WixWaitForEventSucceed event.");

    // Wait for either of the events to be signaled and handle accordingly.
    er = ::WaitForMultipleObjects(countof(rghEvents), rghEvents, FALSE, INFINITE);
    switch (er)
    {
    case WAIT_OBJECT_0 + 0:
        er = ERROR_INSTALL_FAILURE;
        break;
    case WAIT_OBJECT_0 + 1:
        er = ERROR_SUCCESS;
        break;
    default:
        ExitOnWin32Error(er, hr, "Unexpected failure.");
    }

LExit:
    ReleaseHandle(rghEvents[1]);
    ReleaseHandle(rghEvents[0]);

    if (pSD)
    {
        ::LocalFree(pSD);
    }

    if (hMessageWindow)
    {
        CloseMessageWindow(hMessageWindow);
    }

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }

    return WcaFinalize(er);
}
Beispiel #16
0
/********************************************************************
 RegDelete - deletes a registry key (and optionally it's whole tree).

*********************************************************************/
extern "C" HRESULT DAPI RegDelete(
    __in HKEY hkRoot,
    __in_z LPCWSTR wzSubKey,
    __in REG_KEY_BITNESS kbKeyBitness,
    __in BOOL fDeleteTree
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    LPWSTR pszEnumeratedSubKey = NULL;
    LPWSTR pszRecursiveSubKey = NULL;
    HKEY hkKey = NULL;
    REGSAM samDesired = 0;

    if (fDeleteTree)
    {
        hr = RegOpen(hkRoot, wzSubKey, KEY_READ, &hkKey);
        if (E_FILENOTFOUND == hr)
        {
            ExitFunction1(hr = S_OK);
        }
        ExitOnFailure1(hr, "Failed to open this key for enumerating subkeys", wzSubKey);

        // Yes, keep enumerating the 0th item, because we're deleting it every time
        while (E_NOMOREITEMS != (hr = RegKeyEnum(hkKey, 0, &pszEnumeratedSubKey)))
        {
            ExitOnFailure(hr, "Failed to enumerate key 0");
            
            hr = PathConcat(wzSubKey, pszEnumeratedSubKey, &pszRecursiveSubKey);
            ExitOnFailure2(hr, "Failed to concatenate paths while recursively deleting subkeys. Path1: %ls, Path2: %ls", wzSubKey, pszEnumeratedSubKey);

            hr = RegDelete(hkRoot, pszRecursiveSubKey, kbKeyBitness, fDeleteTree);
            ExitOnFailure1(hr, "Failed to recursively delete subkey: %ls", pszRecursiveSubKey);
        }

        hr = S_OK;
    }

    if (!vfRegInitialized && REG_KEY_DEFAULT != kbKeyBitness)
    {
        hr = E_INVALIDARG;
        ExitOnFailure(hr, "RegInitialize must be called first in order to RegDelete() a key with non-default bit attributes!");
    }

    switch (kbKeyBitness)
    {
    case REG_KEY_32BIT:
        samDesired = KEY_WOW64_32KEY;
        break;
    case REG_KEY_64BIT:
        samDesired = KEY_WOW64_64KEY;
        break;
    case REG_KEY_DEFAULT:
        // Nothing to do
        break;
    }

    if (NULL != vpfnRegDeleteKeyExW)
    {
        er = vpfnRegDeleteKeyExW(hkRoot, wzSubKey, samDesired, 0);
        if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er))
        {
            ExitFunction1(hr = E_FILENOTFOUND);
        }
        ExitOnWin32Error(er, hr, "Failed to delete registry key (ex).");
    }
    else
    {
        er = vpfnRegDeleteKeyW(hkRoot, wzSubKey);
        if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er))
        {
            ExitFunction1(hr = E_FILENOTFOUND);
        }
        ExitOnWin32Error(er, hr, "Failed to delete registry key.");
    }

LExit:
    ReleaseRegKey(hkKey);
    ReleaseStr(pszEnumeratedSubKey);
    ReleaseStr(pszRecursiveSubKey);

    return hr;
}
Beispiel #17
0
HRESULT WIXAPI QuietExecEx(
    __inout_z LPWSTR wzCommand,
    __in DWORD dwTimeout,
    __in BOOL fLogCommand,
    __in BOOL fLogOutput
    )
{
    HRESULT hr = S_OK;
    PROCESS_INFORMATION oProcInfo;
    STARTUPINFOW oStartInfo;
    DWORD dwExitCode = ERROR_SUCCESS;
    HANDLE hOutRead = INVALID_HANDLE_VALUE;
    HANDLE hOutWrite = INVALID_HANDLE_VALUE;
    HANDLE hErrWrite = INVALID_HANDLE_VALUE;
    HANDLE hInRead = INVALID_HANDLE_VALUE;
    HANDLE hInWrite = INVALID_HANDLE_VALUE;

    memset(&oProcInfo, 0, sizeof(oProcInfo));
    memset(&oStartInfo, 0, sizeof(oStartInfo));

    // Create output redirect pipes
    hr = CreatePipes(&hOutRead, &hOutWrite, &hErrWrite, &hInRead, &hInWrite);
    ExitOnFailure(hr, "Failed to create output pipes");

    // Set up startup structure
    oStartInfo.cb = sizeof(STARTUPINFOW);
    oStartInfo.dwFlags = STARTF_USESTDHANDLES;
    oStartInfo.hStdInput = hInRead;
    oStartInfo.hStdOutput = hOutWrite;
    oStartInfo.hStdError = hErrWrite;

    // Log command if we were asked to do so
    if (fLogCommand)
    {
        WcaLog(LOGMSG_VERBOSE, "%ls", wzCommand);
    }

#pragma prefast(suppress:25028)
    if (::CreateProcessW(NULL,
        wzCommand, // command line
        NULL, // security info
        NULL, // thread info
        TRUE, // inherit handles
        ::GetPriorityClass(::GetCurrentProcess()) | CREATE_NO_WINDOW, // creation flags
        NULL, // environment
        NULL, // cur dir
        &oStartInfo,
        &oProcInfo))
    {
        ReleaseFile(oProcInfo.hThread);

        // Close child output/input handles so it doesn't hang
        ReleaseFile(hOutWrite);
        ReleaseFile(hErrWrite);
        ReleaseFile(hInRead);

        // Log output if we were asked to do so; otherwise just read the output handle
        HandleOutput(fLogOutput, hOutRead);

        // Wait for everything to finish
        ::WaitForSingleObject(oProcInfo.hProcess, dwTimeout);
        if (!::GetExitCodeProcess(oProcInfo.hProcess, &dwExitCode))
        {
            dwExitCode = ERROR_SEM_IS_SET;
        }

        ReleaseFile(hOutRead);
        ReleaseFile(hInWrite);
        ReleaseFile(oProcInfo.hProcess);
    }
    else
    {
        ExitOnLastError(hr, "Command failed to execute.");
    }

    ExitOnWin32Error(dwExitCode, hr, "Command line returned an error.");

LExit:
    return hr;
}
Beispiel #18
0
/********************************************************************
RmuAddProcessById - Adds the process ID to the Restart Manager sesion.

You should call this multiple times as necessary before calling
RmuRegisterResources.

********************************************************************/
extern "C" HRESULT DAPI RmuAddProcessById(
    __in PRMU_SESSION pSession,
    __in DWORD dwProcessId
    )
{
    HRESULT hr = S_OK;
    HANDLE hProcess = NULL;
    FILETIME CreationTime = {};
    FILETIME ExitTime = {};
    FILETIME KernelTime = {};
    FILETIME UserTime = {};
    BOOL fLocked = FALSE;

    HANDLE hToken = NULL;
    TOKEN_PRIVILEGES priv = { 0 };
    TOKEN_PRIVILEGES* pPrevPriv = NULL;
    DWORD cbPrevPriv = 0;
    DWORD er = ERROR_SUCCESS;
    BOOL fAdjustedPrivileges = FALSE;
    BOOL fElevated = FALSE;
    ProcElevated(::GetCurrentProcess(), &fElevated);

    // Must be elevated to adjust process privileges
    if (fElevated) {
        // Adding SeDebugPrivilege in the event that the process targeted by ::OpenProcess() is in a another user context.
        if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
        {
            ExitWithLastError(hr, "Failed to get process token.");
        }

        priv.PrivilegeCount = 1;
        priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        if (!::LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &priv.Privileges[0].Luid))
        {
            ExitWithLastError(hr, "Failed to get debug privilege LUID.");
        }

        cbPrevPriv = sizeof(TOKEN_PRIVILEGES);
        pPrevPriv = static_cast<TOKEN_PRIVILEGES*>(MemAlloc(cbPrevPriv, TRUE));
        ExitOnNull(pPrevPriv, hr, E_OUTOFMEMORY, "Failed to allocate memory for empty previous privileges.");

        if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, cbPrevPriv, pPrevPriv, &cbPrevPriv))
        {
            LPVOID pv = MemReAlloc(pPrevPriv, cbPrevPriv, TRUE);
            ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for previous privileges.");
            pPrevPriv = static_cast<TOKEN_PRIVILEGES*>(pv);

            if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, cbPrevPriv, pPrevPriv, &cbPrevPriv))
            {
                ExitWithLastError(hr, "Failed to get debug privilege LUID.");
            }
        }

        fAdjustedPrivileges = TRUE;
    }

    hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
    if (hProcess)
    {
        if (!::GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime))
        {
            ExitWithLastError(hr, "Failed to get the process times for process ID %d.", dwProcessId);
        }

        ::EnterCriticalSection(&pSession->cs);
        fLocked = TRUE;
        hr = RmuApplicationArrayAlloc(&pSession->rgApplications, &pSession->cApplications, dwProcessId, CreationTime);
        ExitOnFailure(hr, "Failed to add the application to the array.");
    }
    else
    {
        er = ::GetLastError();
        if (ERROR_ACCESS_DENIED == er)
        {
            // OpenProcess will fail when not elevated and the target process is in another user context. Let the caller log and continue.
            hr = E_NOTFOUND;
        }
        else
        {
            ExitOnWin32Error(er, hr, "Failed to open the process ID %d.", dwProcessId);
        }
    }

LExit:
    if (hProcess)
    {
        ::CloseHandle(hProcess);
    }

    if (fAdjustedPrivileges)
    {
        ::AdjustTokenPrivileges(hToken, FALSE, pPrevPriv, 0, NULL, NULL);
    }

    ReleaseMem(pPrevPriv);
    ReleaseHandle(hToken);

    if (fLocked)
    {
        ::LeaveCriticalSection(&pSession->cs);
    }

    return hr;
}