示例#1
0
extern "C" HRESULT CatalogElevatedUpdateCatalogFile(
    __in BURN_CATALOGS* pCatalogs,
    __in_z LPCWSTR wzId,
    __in_z LPCWSTR wzPath
    )
{
    HRESULT hr = S_OK;
    BURN_CATALOG* pCatalog = NULL;

    // Find the catalog
    hr = CatalogFindById(pCatalogs, wzId, &pCatalog);
    ExitOnFailure(hr, "Failed to locate catalog information.");

    if (NULL == pCatalog->sczLocalFilePath)
    {
        hr = StrAllocString(&pCatalog->sczLocalFilePath, wzPath, 0);
        ExitOnFailure(hr, "Failed to allocated catalog path.");

        // Get a handle to the file
        pCatalog->hFile = ::CreateFileW(pCatalog->sczLocalFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
        if (INVALID_HANDLE_VALUE == pCatalog->hFile)
        {
            ExitWithLastError1(hr, "Failed to open catalog in working path: %ls", pCatalog->sczLocalFilePath);
        }
    }

LExit:
    return hr;
}
示例#2
0
文件: cabutil.cpp 项目: BMurri/wix3
static __callback long FAR DIAMONDAPI CabExtractSeek(__in INT_PTR hf, __in long dist, __in int seektype)
{
    HRESULT hr = S_OK;
    DWORD dwMoveMethod;
    LONG lMove = 0;

    switch (seektype)
    {
    case 0:   // SEEK_SET
        dwMoveMethod = FILE_BEGIN;
        dist += static_cast<long>(vdw64EmbeddedOffset);
        break;
    case 1:   /// SEEK_CUR
        dwMoveMethod = FILE_CURRENT;
        break;
    case 2:   // SEEK_END
        dwMoveMethod = FILE_END;
        break;
    default :
        dwMoveMethod = 0;
        hr = E_UNEXPECTED;
        ExitOnFailure1(hr, "unexpected seektype in FDISeek(): %d", seektype);
    }

    // SetFilePointer returns -1 if it fails (this will cause FDI to quit with an FDIERROR_USER_ABORT error. 
    // (Unless this happens while working on a cabinet, in which case FDI returns FDIERROR_CORRUPT_CABINET)
    lMove = ::SetFilePointer(reinterpret_cast<HANDLE>(hf), dist, NULL, dwMoveMethod);
    if (0xFFFFFFFF == lMove)
    {
        ExitWithLastError1(hr, "failed to move file pointer %d bytes", dist);
    }

LExit:
    return FAILED(hr) ? -1 : lMove - static_cast<long>(vdw64EmbeddedOffset);
}
示例#3
0
HRESULT LaunchTarget(
    __in LPWSTR wzCommandline,
    __in LPWSTR wzCurrentDirectory,
    __out HANDLE * phProcess
    )
{
    HRESULT hr = S_OK;
    STARTUPINFOW startupInfo = {0};
    PROCESS_INFORMATION procInfo = {0};

    if (!::CreateProcessW(NULL, wzCommandline, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, wzCurrentDirectory, &startupInfo, &procInfo))
    {
        ExitWithLastError1(hr, "Failed to execute %S.", wzCommandline);
    }

LExit:
    if (procInfo.hThread)
    {
        ::CloseHandle(procInfo.hThread);
    }

    if (procInfo.hProcess)
    {
        *phProcess = procInfo.hProcess;
    }

    return hr;
}
示例#4
0
文件: cabutil.cpp 项目: BMurri/wix3
static __callback INT_PTR FAR DIAMONDAPI CabExtractOpen(__in_z PSTR pszFile, __in int oflag, __in int pmode)
{
    HRESULT hr = S_OK;
    INT_PTR pFile = -1;
    LPWSTR sczCabFile = NULL;

    // if FDI asks for some unusual mode (in low memory situation it could ask for a scratch file) fail
    if ((oflag != (/*_O_BINARY*/ 0x8000 | /*_O_RDONLY*/ 0x0000)) || (pmode != (_S_IREAD | _S_IWRITE)))
    {
        hr = E_OUTOFMEMORY;
        ExitOnFailure(hr, "FDI asked for a scratch file to be created, which is unsupported");
    }

    hr = StrAllocStringAnsi(&sczCabFile, pszFile, 0, CP_UTF8);
    ExitOnFailure(hr, "Failed to convert UTF8 cab file name to wide character string");

    pFile = reinterpret_cast<INT_PTR>(::CreateFileW(sczCabFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
    if (INVALID_HANDLE_VALUE == reinterpret_cast<HANDLE>(pFile))
    {
        ExitWithLastError1(hr, "failed to open file: %ls", sczCabFile);
    }

    if (vdw64EmbeddedOffset)
    {
        hr = CabExtractSeek(pFile, 0, 0);
        ExitOnFailure1(hr, "Failed to seek to embedded offset %I64d", vdw64EmbeddedOffset);
    }

LExit:
    ReleaseStr(sczCabFile);

    return FAILED(hr) ? -1 : pFile;
}
示例#5
0
HRESULT SendQwordString(
    __in DWORD dwThreadId,
    __in DWORD dwMessageId,
    __in DWORD dwDatabaseIndex,
    __in DWORD64 qwQword1,
    __in_z LPCWSTR wzString1
    )
{
    HRESULT hr = S_OK;
    QWORD_STRING *pQwordString = NULL;

    pQwordString = static_cast<QWORD_STRING *>(MemAlloc(sizeof(QWORD_STRING), TRUE));

    pQwordString->qwQword1 = qwQword1;
    
    if (NULL != wzString1)
    {
        hr = StrAllocString(&pQwordString->sczString1, wzString1, 0);
        ExitOnFailure1(hr, "Failed to allocate copy of string1: %ls", wzString1);
    }

    if (!::PostThreadMessageW(dwThreadId, dwMessageId, dwDatabaseIndex, reinterpret_cast<LPARAM>(pQwordString)))
    {
        ExitWithLastError1(hr, "Failed to send message %u to worker thread", dwMessageId);
    }

    pQwordString = NULL;

LExit:
    ReleaseQwordString(pQwordString);

    return hr;
}
示例#6
0
static HRESULT InitializeResume(
    __in LPCWSTR wzDestinationPath,
    __out LPWSTR* psczResumePath,
    __out HANDLE* phResumeFile,
    __out DWORD64* pdw64ResumeOffset
    )
{
    HRESULT hr = S_OK;
    HANDLE hResumeFile = INVALID_HANDLE_VALUE;
    DWORD cbTotalReadResumeData = 0;
    DWORD cbReadData = 0;

    *pdw64ResumeOffset = 0;

    hr = CacheGetResumePath(wzDestinationPath, psczResumePath);
    ExitOnFailure1(hr, "Failed to calculate resume path from working path: %ls", wzDestinationPath);

    hResumeFile = ::CreateFileW(*psczResumePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hResumeFile)
    {
        ExitWithLastError1(hr, "Failed to create resume file: %ls", *psczResumePath);
    }

    do
    {
        if (!::ReadFile(hResumeFile, reinterpret_cast<BYTE*>(pdw64ResumeOffset) + cbTotalReadResumeData, sizeof(DWORD64) - cbTotalReadResumeData, &cbReadData, NULL))
        {
            ExitWithLastError1(hr, "Failed to read resume file: %ls", *psczResumePath);
        }
        cbTotalReadResumeData += cbReadData;
    } while (cbReadData && sizeof(DWORD64) > cbTotalReadResumeData);

    // Start over if we couldn't get a resume offset.
    if (cbTotalReadResumeData != sizeof(DWORD64))
    {
        *pdw64ResumeOffset = 0;
    }

    *phResumeFile = hResumeFile;
    hResumeFile = INVALID_HANDLE_VALUE;

LExit:
    ReleaseFileHandle(hResumeFile);
    return hr;
}
示例#7
0
文件: OsInfo.cpp 项目: BMurri/wix3
/********************************************************************
SetPropertyWellKnownSID

 Set a property with the localized name of a well known windows SID
********************************************************************/
static HRESULT SetPropertyWellKnownSID(
    __in WELL_KNOWN_SID_TYPE sidType,
    __in LPCWSTR wzPropertyName,
    __in BOOL fIncludeDomainName
    )
{
    HRESULT hr = S_OK;
    PSID psid = NULL;
    WCHAR wzRefDomain[MAX_PATH] = {0};
    SID_NAME_USE nameUse;
    DWORD refSize = MAX_PATH;
    WCHAR wzName[MAX_PATH] = {0};
    LPWSTR pwzPropertyValue = NULL;
    DWORD size = MAX_PATH;

    hr = AclGetWellKnownSid(sidType, &psid);
    ExitOnFailure1(hr, "Failed to get SID; skipping account %ls", wzPropertyName);

    if (!::LookupAccountSidW(NULL, psid, wzName, &size, wzRefDomain, &refSize, &nameUse))
    {
        ExitWithLastError1(hr, "Failed to look up account for SID; skipping account %ls.", wzPropertyName);
    }

    if (fIncludeDomainName)
    {
        hr = StrAllocFormatted(&pwzPropertyValue, L"%s\\%s", wzRefDomain, wzName);
        ExitOnFailure(hr, "Failed to format property value");

        hr = WcaSetProperty(wzPropertyName, pwzPropertyValue);
        ExitOnFailure(hr, "Failed write domain\\name property");
    }
    else
    {
        hr = WcaSetProperty(wzPropertyName, wzName);
        ExitOnFailure(hr, "Failed write name-only property");
    }
 
LExit:
    if (NULL != psid)
    {
        ::LocalFree(psid);
    }
    ReleaseStr(pwzPropertyValue);
    return hr;
}
示例#8
0
HRESULT SendStringTriplet(
    __in DWORD dwThreadId,
    __in DWORD dwMessageId,
    __in DWORD dwDatabaseIndex,
    __in_z LPCWSTR wzString1,
    __in_z LPCWSTR wzString2,
    __in_z LPCWSTR wzString3
    )
{
    HRESULT hr = S_OK;
    STRING_TRIPLET *pStringTriplet = NULL;

    pStringTriplet = static_cast<STRING_TRIPLET *>(MemAlloc(sizeof(STRING_TRIPLET), TRUE));

    if (NULL != wzString1)
    {
        hr = StrAllocString(&pStringTriplet->sczString1, wzString1, 0);
        ExitOnFailure1(hr, "Failed to allocate copy of string1: %ls", wzString1);
    }

    if (NULL != wzString2)
    {
        hr = StrAllocString(&pStringTriplet->sczString2, wzString2, 0);
        ExitOnFailure1(hr, "Failed to allocate copy of string2: %ls", wzString2);
    }

    if (NULL != wzString3)
    {
        hr = StrAllocString(&pStringTriplet->sczString3, wzString3, 0);
        ExitOnFailure1(hr, "Failed to allocate copy of string3: %ls", wzString3);
    }

    if (!::PostThreadMessageW(dwThreadId, dwMessageId, dwDatabaseIndex, reinterpret_cast<LPARAM>(pStringTriplet)))
    {
        ExitWithLastError1(hr, "Failed to send message %u to worker thread", dwMessageId);
    }

    pStringTriplet = NULL;

LExit:
    ReleaseStringTriplet(pStringTriplet);

    return hr;
}
示例#9
0
文件: wcascript.cpp 项目: aspnet/Home
/********************************************************************
 WcaCaScriptCreate() - creates the appropriate script for this
                       CustomAction Script Key.

********************************************************************/
extern "C" HRESULT WIXAPI WcaCaScriptCreate(
    __in WCA_ACTION action,
    __in WCA_CASCRIPT script,
    __in BOOL fImpersonated,
    __in LPCWSTR wzScriptKey,
    __in BOOL fAppend,
    __in WCA_CASCRIPT_HANDLE* phScript
    )
{
    HRESULT hr = S_OK;
    LPWSTR pwzScriptPath = NULL;
    HANDLE hScriptFile = INVALID_HANDLE_VALUE;

    hr = CaScriptFileName(action, script, fImpersonated, wzScriptKey, &pwzScriptPath);
    ExitOnFailure(hr, "Failed to calculate script file name.");

    hScriptFile = ::CreateFileW(pwzScriptPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, fAppend ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (INVALID_HANDLE_VALUE == hScriptFile)
    {
        ExitWithLastError1(hr, "Failed to open CaScript: %S", pwzScriptPath);
    }

    if (fAppend && INVALID_SET_FILE_POINTER == ::SetFilePointer(hScriptFile, 0, NULL, FILE_END))
    {
        ExitWithLastError(hr, "Failed to seek to end of file.");
    }

    *phScript = reinterpret_cast<WCA_CASCRIPT_HANDLE>(MemAlloc(sizeof(WCA_CASCRIPT_STRUCT), TRUE));
    ExitOnNull(*phScript, hr, E_OUTOFMEMORY, "Failed to allocate space for cascript handle.");

    (*phScript)->pwzScriptPath = pwzScriptPath;
    pwzScriptPath = NULL;
    (*phScript)->hScriptFile = hScriptFile;
    hScriptFile = INVALID_HANDLE_VALUE;

LExit:
    if (INVALID_HANDLE_VALUE != hScriptFile)
    {
        ::CloseHandle(hScriptFile);
    }

    ReleaseStr(pwzScriptPath);
    return hr;
}
示例#10
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;

    hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
    ExitOnNullWithLastError1(hProcess, hr, "Failed to open the process ID %d.", dwProcessId);

    if (!::GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime))
    {
        ExitWithLastError1(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.");

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

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

    return hr;
}
示例#11
0
文件: resrutil.cpp 项目: BMurri/wix3
/********************************************************************
 ResReadStringAnsi

 NOTE: ppszString should be freed with StrFree()
********************************************************************/
extern "C" HRESULT DAPI ResReadStringAnsi(
    __in HINSTANCE hinst,
    __in UINT uID,
    __deref_out_z LPSTR* ppszString
    )
{
    Assert(hinst && ppszString);

    HRESULT hr = S_OK;
    DWORD cch = 64;  // first guess
    DWORD cchReturned = 0;

    do
    {
        hr = StrAnsiAlloc(ppszString, cch);
        ExitOnFailureDebugTrace1(hr, "Failed to allocate string for resource id: %d", uID);

#pragma prefast(push)
#pragma prefast(disable:25068)
        cchReturned = ::LoadStringA(hinst, uID, *ppszString, cch);
#pragma prefast(pop)
        if (0 == cchReturned)
        {
            ExitWithLastError1(hr, "Failed to load string resource id: %d", uID);
        }

        // if the returned string count is one character too small, it's likely we have
        // more data to read
        if (cchReturned + 1 == cch)
        {
            cch *= 2;
            hr = S_FALSE;
        }
    } while (S_FALSE == hr);
    ExitOnFailure1(hr, "failed to load string resource id: %d", uID);

LExit:
    return hr;
}
示例#12
0
文件: shelutil.cpp 项目: BMurri/wix3
/********************************************************************
 ShelExec() - executes a target.

*******************************************************************/
extern "C" HRESULT DAPI ShelExec(
    __in_z LPCWSTR wzTargetPath,
    __in_z_opt LPCWSTR wzParameters,
    __in_z_opt LPCWSTR wzVerb,
    __in_z_opt LPCWSTR wzWorkingDirectory,
    __in int nShowCmd,
    __in_opt HWND hwndParent,
    __out_opt HANDLE* phProcess
    )
{
    HRESULT hr = S_OK;
    SHELLEXECUTEINFOW shExecInfo = {};

    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
    shExecInfo.hwnd = hwndParent;
    shExecInfo.lpVerb = wzVerb;
    shExecInfo.lpFile = wzTargetPath;
    shExecInfo.lpParameters = wzParameters;
    shExecInfo.lpDirectory = wzWorkingDirectory;
    shExecInfo.nShow = nShowCmd;

    if (!vpfnShellExecuteExW(&shExecInfo))
    {
        ExitWithLastError1(hr, "ShellExecEx failed with return code: %d", Dutil_er);
    }

    if (phProcess)
    {
        *phProcess = shExecInfo.hProcess;
        shExecInfo.hProcess = NULL;
    }

LExit:
    ReleaseHandle(shExecInfo.hProcess);

    return hr;
}
示例#13
0
extern "C" HRESULT CatalogLoadFromPayload(
    __in BURN_CATALOGS* pCatalogs,
    __in BURN_PAYLOADS* pPayloads
    )
{
    HRESULT hr = S_OK;
    BURN_CATALOG* pCatalog = NULL;
    BURN_PAYLOAD* pPayload = NULL;

    // go through each catalog file
    for (DWORD i = 0; i < pCatalogs->cCatalogs; i++)
    {
        pCatalog = &pCatalogs->rgCatalogs[i];

        // get the payload for this catalog file
        hr = PayloadFindById(pPayloads, pCatalog->sczPayload, &pPayload);
        ExitOnFailure(hr, "Failed to find payload for catalog file.");

        // Get the local file name
        hr = StrAllocString(&pCatalog->sczLocalFilePath, pPayload->sczLocalFilePath, 0);
        ExitOnFailure(hr, "Failed to get catalog local file path");

        // Get a handle to the file
        pCatalog->hFile = ::CreateFileW(pCatalog->sczLocalFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
        if (INVALID_HANDLE_VALUE == pCatalog->hFile)
        {
            ExitWithLastError1(hr, "Failed to open catalog in working path: %ls", pCatalog->sczLocalFilePath);
        }

        // Verify the catalog file
        hr = CacheVerifyPayloadSignature(pPayload, pCatalog->sczLocalFilePath, pCatalog->hFile);
        ExitOnFailure1(hr, "Failed to verify catalog signature: %ls", pCatalog->sczLocalFilePath);
    }

LExit:
    return hr;
}
示例#14
0
static HRESULT DownloadResource(
    __in BURN_USER_EXPERIENCE* pUX,
    __in_z LPCWSTR wzPackageOrContainerId,
    __in_z LPCWSTR wzPayloadId,
    __in HINTERNET hSession,
    __inout_z LPWSTR* psczUrl,
    __in_z_opt LPCWSTR wzUser,
    __in_z_opt LPCWSTR wzPassword,
    __in_z LPCWSTR wzDestinationPath,
    __in DWORD64 dw64AuthoredResourceLength,
    __in DWORD64 dw64ResourceLength,
    __in DWORD64 dw64ResumeOffset,
    __in HANDLE hResumeFile,
    __in_opt BURN_CACHE_CALLBACK* pCallback
    )
{
    HRESULT hr = S_OK;
    HANDLE hPayloadFile = INVALID_HANDLE_VALUE;
    DWORD cbMaxData = 64 * 1024; // 64 KB
    BYTE* pbData = NULL;
    BOOL fRangeRequestsAccepted = TRUE;
    LPWSTR sczRangeRequestHeader = NULL;
    HINTERNET hConnect = NULL;
    HINTERNET hUrl = NULL;
    LONGLONG llLength = 0;

    hPayloadFile = ::CreateFileW(wzDestinationPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hPayloadFile)
    {
        ExitWithLastError1(hr, "Failed to create download destination file: %ls", wzDestinationPath);
    }

    // Allocate a memory block on a page boundary in case we want to do optimal writing.
    pbData = static_cast<BYTE*>(::VirtualAlloc(NULL, cbMaxData, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
    ExitOnNullWithLastError(pbData, hr, "Failed to allocate buffer to download files into.");

    // Let's try downloading the file assuming that range requests are accepted. If range requests
    // are not supported we'll have to start over and accept the fact that we only get one shot
    // downloading the file however big it is. Hopefully, not more than 2 GB since wininet doesn't
    // like files that big.
    while (fRangeRequestsAccepted && (0 == dw64ResourceLength || dw64ResumeOffset < dw64ResourceLength))
    {
        hr = AllocateRangeRequestHeader(dw64ResumeOffset, 0 == dw64ResourceLength ? dw64AuthoredResourceLength : dw64ResourceLength, &sczRangeRequestHeader);
        ExitOnFailure(hr, "Failed to allocate range request header.");

        ReleaseNullInternet(hConnect);
        ReleaseNullInternet(hUrl);

        hr = MakeRequest(pUX, wzPackageOrContainerId, wzPayloadId, hSession, psczUrl, L"GET", sczRangeRequestHeader, wzUser, wzPassword, &hConnect, &hUrl, &fRangeRequestsAccepted);
        ExitOnFailure1(hr, "Failed to request URL for download: %ls", *psczUrl);

        // If we didn't get the size of the resource from the initial "HEAD" request
        // then let's try to get the size from this "GET" request.
        if (0 == dw64ResourceLength)
        {
            hr = InternetGetSizeByHandle(hUrl, &llLength);
            if (SUCCEEDED(hr))
            {
                dw64ResourceLength = llLength;
            }
            else // server didn't tell us the resource length.
            {
                // Fallback to the authored size of the resource. However, since we
                // don't really know the size on the server, don't try to use
                // range requests either.
                dw64ResourceLength = dw64AuthoredResourceLength;
                fRangeRequestsAccepted = FALSE;
            }
        }

        // If we just tried to do a range request and found out that it isn't supported, start over.
        if (!fRangeRequestsAccepted)
        {
            // TODO: log a message that the server did not accept range requests.
            dw64ResumeOffset = 0;
        }

        hr = WriteToFile(hUrl, hPayloadFile, &dw64ResumeOffset, hResumeFile, dw64ResourceLength, pbData, cbMaxData, pCallback);
        ExitOnFailure1(hr, "Failed while reading from internet and writing to: %ls", wzDestinationPath);
    }

LExit:
    ReleaseInternet(hUrl);
    ReleaseInternet(hConnect);
    ReleaseStr(sczRangeRequestHeader);
    if (pbData)
    {
        ::VirtualFree(pbData, 0, MEM_RELEASE);
    }
    ReleaseFileHandle(hPayloadFile);

    return hr;
}
示例#15
0
文件: cabutil.cpp 项目: BMurri/wix3
static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE iNotification, __inout FDINOTIFICATION *pFDINotify)
{
    Assert(pFDINotify->pv);

    HRESULT hr = S_OK;
    INT_PTR ipResult = 0;   // result to return on success

    CAB_CALLBACK_STRUCT* pccs = static_cast<CAB_CALLBACK_STRUCT*>(pFDINotify->pv);
    LPCSTR sz;
    WCHAR wz[MAX_PATH];
    FILETIME ft;

    switch (iNotification)
    {
    case fdintCOPY_FILE:  // begin extracting a resource from cabinet
        ExitOnNull(pFDINotify->psz1, hr, E_INVALIDARG, "No cabinet file ID given to convert");
        ExitOnNull(pccs, hr, E_INVALIDARG, "Failed to call cabextract callback, because no callback struct was provided");

        if (pccs->fStopExtracting)
        {
            ExitFunction1(hr = S_FALSE);   // no more extracting
        }

        // convert params to useful variables
        sz = static_cast<LPCSTR>(pFDINotify->psz1);
        if (!::MultiByteToWideChar(CP_ACP, 0, sz, -1, wz, countof(wz)))
        {
            ExitWithLastError1(hr, "failed to convert cabinet file id to unicode: %s", sz);
        }

        if (pccs->pfnProgress)
        {
            hr = pccs->pfnProgress(TRUE, wz, pccs->pvContext);
            if (S_OK != hr)
            {
                ExitFunction();
            }
        }

        if (L'*' == *pccs->pwzExtract || 0 == lstrcmpW(pccs->pwzExtract, wz))
        {
            // get the created date for the resource in the cabinet
            FILETIME ftLocal;
            if (!::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ftLocal))
            {
                ExitWithLastError1(hr, "failed to get time for resource: %ls", wz);
            }
            ::LocalFileTimeToFileTime(&ftLocal, &ft);
            

            WCHAR wzPath[MAX_PATH];
            hr = ::StringCchCopyW(wzPath, countof(wzPath), pccs->pwzExtractDir);
            ExitOnFailure2(hr, "failed to copy in extract directory: %ls for file: %ls", pccs->pwzExtractDir, wz);
            hr = ::StringCchCatW(wzPath, countof(wzPath), wz);
            ExitOnFailure2(hr, "failed to concat onto path: %ls file: %ls", wzPath, wz);

            ipResult = reinterpret_cast<INT_PTR>(::CreateFileW(wzPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
            if (INVALID_HANDLE_VALUE == reinterpret_cast<HANDLE>(ipResult))
            {
                ExitWithLastError1(hr, "failed to create file: %s", wzPath);
            }

            ::SetFileTime(reinterpret_cast<HANDLE>(ipResult), &ft, &ft, &ft);   // try to set the file time (who cares if it fails)

            if (::SetFilePointer(reinterpret_cast<HANDLE>(ipResult), pFDINotify->cb, NULL, FILE_BEGIN))   // try to set the end of the file (don't worry if this fails)
            {
                if (::SetEndOfFile(reinterpret_cast<HANDLE>(ipResult)))
                {
                    ::SetFilePointer(reinterpret_cast<HANDLE>(ipResult), 0, NULL, FILE_BEGIN);  // reset the file pointer
                }
            }
        }
        else  // resource wasn't requested, skip it
        {
            hr = S_OK;
            ipResult = 0;
        }

        break;
    case fdintCLOSE_FILE_INFO:  // resource extraction complete
        Assert(pFDINotify->hf && pFDINotify->psz1);
        ExitOnNull(pccs, hr, E_INVALIDARG, "Failed to call cabextract callback, because no callback struct was provided");

        // convert params to useful variables
        sz = static_cast<LPCSTR>(pFDINotify->psz1);
        ExitOnNull(sz, hr, E_INVALIDARG, "Failed to convert cabinet file id, because no cabinet file id was provided");

        if (!::MultiByteToWideChar(CP_ACP, 0, sz, -1, wz, countof(wz)))
        {
            ExitWithLastError1(hr, "failed to convert cabinet file id to unicode: %s", sz);
        }

        if (NULL != pFDINotify->hf)  // just close the file
        {
            ::CloseHandle(reinterpret_cast<HANDLE>(pFDINotify->hf));
        }

        if (pccs->pfnProgress)
        {
            hr = pccs->pfnProgress(FALSE, wz, pccs->pvContext);
        }

        if (S_OK == hr && L'*' == *pccs->pwzExtract)   // if everything is okay and we're extracting all files, keep going
        {
            ipResult = TRUE;
        }
        else   // something went wrong or we only needed to extract one file
        {
            hr = S_OK;
            ipResult = FALSE;
            pccs->fStopExtracting = TRUE;
        }

        break;
    case fdintPARTIAL_FILE: __fallthrough;   // no action needed for these messages, fall through
    case fdintNEXT_CABINET: __fallthrough;
    case fdintENUMERATE: __fallthrough;
    case fdintCABINET_INFO:
        break;
    default:
        AssertSz(FALSE, "CabExtractCallback() - unknown FDI notification command");
    };

LExit:
    return (S_OK == hr) ? ipResult : -1;
}
示例#16
0
DAPI_(HRESULT) PathExpand(
    __out LPWSTR *psczFullPath,
    __in_z LPCWSTR wzRelativePath,
    __in DWORD dwResolveFlags
    )
{
    Assert(wzRelativePath && *wzRelativePath);

    HRESULT hr = S_OK;
    DWORD cch = 0;
    LPWSTR sczExpandedPath = NULL;
    DWORD cchExpandedPath = 0;

    LPWSTR sczFullPath = NULL;

    //
    // First, expand any environment variables.
    //
    if (dwResolveFlags & PATH_EXPAND_ENVIRONMENT)
    {
        cchExpandedPath = PATH_GOOD_ENOUGH;

        hr = StrAlloc(&sczExpandedPath, cchExpandedPath);
        ExitOnFailure(hr, "Failed to allocate space for expanded path.");

        cch = ::ExpandEnvironmentStringsW(wzRelativePath, sczExpandedPath, cchExpandedPath);
        if (0 == cch)
        {
            ExitWithLastError1(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
        }
        else if (cchExpandedPath < cch)
        {
            cchExpandedPath = cch;
            hr = StrAlloc(&sczExpandedPath, cchExpandedPath);
            ExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");

            cch = ::ExpandEnvironmentStringsW(wzRelativePath, sczExpandedPath, cchExpandedPath);
            if (0 == cch)
            {
                ExitWithLastError1(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
            }
            else if (cchExpandedPath < cch)
            {
                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                ExitOnFailure(hr, "Failed to allocate buffer for expanded path.");
            }
        }

        if (MAX_PATH < cch)
        {
            hr = PathPrefix(&sczExpandedPath); // ignore invald arg from path prefix because this may not be a complete path yet
            if (E_INVALIDARG == hr)
            {
                hr = S_OK;
            }
            ExitOnFailure(hr, "Failed to prefix long path after expanding environment variables.");

            hr = StrMaxLength(sczExpandedPath, reinterpret_cast<DWORD_PTR *>(&cchExpandedPath));
            ExitOnFailure(hr, "Failed to get max length of expanded path.");
        }
    }

    //
    // Second, get the full path.
    //
    if (dwResolveFlags & PATH_EXPAND_FULLPATH)
    {
        LPWSTR wzFileName = NULL;
        LPCWSTR wzPath = sczExpandedPath ? sczExpandedPath : wzRelativePath;
        DWORD cchFullPath = PATH_GOOD_ENOUGH < cchExpandedPath ? cchExpandedPath : PATH_GOOD_ENOUGH;

        hr = StrAlloc(&sczFullPath, cchFullPath);
        ExitOnFailure(hr, "Failed to allocate space for full path.");

        cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName);
        if (0 == cch)
        {
            ExitWithLastError1(hr, "Failed to get full path for string: %ls", wzPath);
        }
        else if (cchFullPath < cch)
        {
            cchFullPath = cch < MAX_PATH ? cch : cch + 7; // ensure space for "\\?\UNC" prefix if needed
            hr = StrAlloc(&sczFullPath, cchFullPath);
            ExitOnFailure(hr, "Failed to re-allocate more space for full path.");

            cch = ::GetFullPathNameW(wzPath, cchFullPath, sczFullPath, &wzFileName);
            if (0 == cch)
            {
                ExitWithLastError1(hr, "Failed to get full path for string: %ls", wzPath);
            }
            else if (cchFullPath < cch)
            {
                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                ExitOnFailure(hr, "Failed to allocate buffer for full path.");
            }
        }

        if (MAX_PATH < cch)
        {
            hr = PathPrefix(&sczFullPath);
            ExitOnFailure(hr, "Failed to prefix long path after expanding.");
        }
    }
    else
    {
        sczFullPath = sczExpandedPath;
        sczExpandedPath = NULL;
    }

    hr = StrAllocString(psczFullPath, sczFullPath? sczFullPath : wzRelativePath, 0);
    ExitOnFailure(hr, "Failed to copy relative path into full path.");

LExit:
    ReleaseStr(sczFullPath);
    ReleaseStr(sczExpandedPath);

    return hr;
}
示例#17
0
文件: netfxca.cpp 项目: 925coder/wix3
// Searches subdirectories of the given path for the highest version of ngen.exe available
static HRESULT GetNgenVersion(
    __in LPWSTR pwzParentPath,
    __out LPWSTR* ppwzVersion
    )
{
    Assert(pwzParentPath);

    HRESULT hr = S_OK;
    DWORD dwError = 0;
    DWORD dwNgenFileFlags = 0;

    LPWSTR pwzVersionSearch = NULL;
    LPWSTR pwzNgen = NULL;
    LPWSTR pwzTemp = NULL;
    LPWSTR pwzTempVersion = NULL;
    DWORD dwMaxMajorVersion = 0; // This stores the highest major version we've seen so far
    DWORD dwMaxMinorVersion = 0; // This stores the minor version of the highest major version we've seen so far
    DWORD dwMajorVersion = 0; // This stores the major version of the directory we're currently considering
    DWORD dwMinorVersion = 0; // This stores the minor version of the directory we're currently considering
    BOOL fFound = TRUE;
    WIN32_FIND_DATAW wfdVersionDirectories;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    
    hr = StrAllocFormatted(&pwzVersionSearch, L"%s*", pwzParentPath);
    ExitOnFailure1(hr, "failed to create outer directory search string from string %ls", pwzParentPath);
    hFind = FindFirstFileW(pwzVersionSearch, &wfdVersionDirectories);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        ExitWithLastError1(hr, "failed to call FindFirstFileW with string %ls", pwzVersionSearch);
    }

    while (fFound)
    {
        pwzTempVersion = (LPWSTR)&(wfdVersionDirectories.cFileName);

        // Explicitly exclude v1.1.4322, which isn't backwards compatible and is not supported
        if (wfdVersionDirectories.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            if (0 != lstrcmpW(L"v1.1.4322", pwzTempVersion))
            {
                // A potential candidate directory was found to run ngen from - let's make sure ngen actually exists here
                hr = StrAllocFormatted(&pwzNgen, L"%s%s\\ngen.exe", pwzParentPath, pwzTempVersion);
                ExitOnFailure2(hr, "failed to create inner ngen search string with strings %ls and %ls", pwzParentPath, pwzTempVersion);

                // If Ngen.exe does exist as a file here, then let's check the file version
                if (FileExistsEx(pwzNgen, &dwNgenFileFlags) && (0 == (dwNgenFileFlags & FILE_ATTRIBUTE_DIRECTORY)))
                {
                    hr = FileVersion(pwzNgen, &dwMajorVersion, &dwMinorVersion);

                    if (FAILED(hr))
                    {
                        WcaLog(LOGMSG_VERBOSE, "Failed to get version of %ls - continuing", pwzNgen);
                    }
                    else if (dwMajorVersion > dwMaxMajorVersion || (dwMajorVersion == dwMaxMajorVersion && dwMinorVersion > dwMaxMinorVersion))
                    {
                        // If the version we found is the highest we've seen so far in this search, it will be our new best-so-far candidate
                        hr = StrAllocString(ppwzVersion, pwzTempVersion, 0);
                        ExitOnFailure1(hr, "failed to copy temp version string %ls to version string", pwzTempVersion);
                        // Add one for the backslash after the directory name
                        WcaLog(LOGMSG_VERBOSE, "Found highest-so-far version of ngen.exe (in directory %ls, version %u.%u.%u.%u)", *ppwzVersion, (DWORD)HIWORD(dwMajorVersion), (DWORD)LOWORD(dwMajorVersion), (DWORD)HIWORD(dwMinorVersion), (DWORD)LOWORD(dwMinorVersion));

                        dwMaxMajorVersion = dwMajorVersion;
                        dwMaxMinorVersion = dwMinorVersion;
                    }
                }
                else
                {
                    WcaLog(LOGMSG_VERBOSE, "Ignoring %ls because it doesn't contain the file ngen.exe", pwzTempVersion);
                }
            }
            else
            {
                WcaLog(LOGMSG_VERBOSE, "Ignoring %ls because it is from .NET Framework v1.1, which is not backwards compatible with other versions of the Framework and thus is not supported by this custom action.", pwzTempVersion);
            }
        }
        else
        {
            WcaLog(LOGMSG_VERBOSE, "Ignoring %ls because it isn't a directory", pwzTempVersion);
        }

        fFound = FindNextFileW(hFind, &wfdVersionDirectories);

        if (!fFound)
        {
            dwError = ::GetLastError();
            hr = (ERROR_NO_MORE_FILES == dwError) ? ERROR_SUCCESS : HRESULT_FROM_WIN32(dwError);
            ExitOnFailure1(hr, "Failed to call FindNextFileW() with query %ls", pwzVersionSearch);
        }
    }

    if (NULL == *ppwzVersion)
    {
        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
        ExitOnRootFailure1(hr, "Searched through all subdirectories of %ls, but failed to find any version of ngen.exe", pwzParentPath);
    }
    else
    {
        WcaLog(LOGMSG_VERBOSE, "Using highest version of ngen found, located in this subdirectory: %ls, version %u.%u.%u.%u", *ppwzVersion, (DWORD)HIWORD(dwMajorVersion), (DWORD)LOWORD(dwMajorVersion), (DWORD)HIWORD(dwMinorVersion), (DWORD)LOWORD(dwMinorVersion));
    }

LExit:
    if (hFind != INVALID_HANDLE_VALUE)
    {
        if (0 == FindClose(hFind))
        {
            dwError = ::GetLastError();
            hr = HRESULT_FROM_WIN32(dwError);
            WcaLog(LOGMSG_STANDARD, "Failed to close handle created by outer FindFirstFile with error %x - continuing", hr);
        }
        hFind = INVALID_HANDLE_VALUE;
    }

    ReleaseStr(pwzVersionSearch);
    ReleaseStr(pwzNgen);
    ReleaseStr(pwzTemp);
    // Purposely don't release pwzTempVersion, because it wasn't allocated in this function, it's just a pointer to a string inside wfdVersionDirectories

    return hr;
}
示例#18
0
static HRESULT InstallCertificate(
	__in HCERTSTORE hStore,
	__in BOOL fUserCertificateStore,
	__in LPCWSTR wzName,
	__in_opt BYTE* rgbData,
	__in DWORD cbData,
	__in_opt LPCWSTR wzPFXPassword
	)
{
	HRESULT hr = S_OK;

	HCERTSTORE hPfxCertStore = NULL;
	PCCERT_CONTEXT pCertContext = NULL;
	PCCERT_CONTEXT pCertContextDelete = NULL;
	CERT_BLOB blob = { 0 };
	DWORD dwEncodingType;
	DWORD dwContentType;
	DWORD dwFormatType;

	// Figure out what type of blob (certificate or PFX) we're dealing with here.
	blob.pbData = rgbData;
	blob.cbData = cbData;

	if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext))
	{
		ExitWithLastError1(hr, "Failed to parse the certificate blob: %S", wzName);
	}

	if (!pCertContext)
	{
		// If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
		if (dwContentType & CERT_QUERY_CONTENT_PFX)
		{
			hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET);
			ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");

			// There should be at least one certificate in the PFX.
			pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, NULL);
			ExitOnNullWithLastError(pCertContext, hr, "Failed to read first certificate out of PFX file.");
		}
		else
		{
			hr = E_UNEXPECTED;
			ExitOnFailure(hr, "Unexpected certificate type processed.");
		}
	}


	// Update the friendly name of the certificate to be configured.
	blob.pbData = (BYTE*)wzName;
	blob.cbData = (lstrlenW(wzName) + 1) * sizeof(WCHAR); // including terminating null

	if (!::CertSetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, 0, &blob))
	{
		ExitWithLastError1(hr, "Failed to set the friendly name of the certificate: %S", wzName);
	}

	WcaLog(LOGMSG_STANDARD, "Adding certificate: %S", wzName);
	if (!::CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL))
	{
		MessageExitOnLastError(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
	}

	hr = WcaProgressMessage(COST_CERT_ADD, FALSE);
	ExitOnFailure(hr, "Failed to send install progress message.");

LExit:
	if (pCertContext)
	{
		::CertFreeCertificateContext(pCertContext);
	}

	// Close the stores after the context's are released.
	if (hPfxCertStore)
	{
		::CertCloseStore(hPfxCertStore, 0);
	}

	return hr;
}
示例#19
0
文件: pipe.cpp 项目: firegiant/wix3
/*******************************************************************
 PipeCreatePipes - create the pipes and event to signal child process.

*******************************************************************/
extern "C" HRESULT PipeCreatePipes(
    __in BURN_PIPE_CONNECTION* pConnection,
    __in BOOL fCreateCachePipe,
    __out HANDLE* phEvent
    )
{
    Assert(pConnection->sczName);
    Assert(INVALID_HANDLE_VALUE == pConnection->hPipe);
    Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe);

    HRESULT hr = S_OK;
    PSECURITY_DESCRIPTOR psd = NULL;
    SECURITY_ATTRIBUTES sa = { };
    LPWSTR sczFullPipeName = NULL;
    HANDLE hPipe = INVALID_HANDLE_VALUE;
    HANDLE hCachePipe = INVALID_HANDLE_VALUE;

    // Only the grant special rights when the pipe is being used for "embedded"
    // scenarios (aka: there is no cache pipe).
    if (!fCreateCachePipe)
    {
        // Create the security descriptor that grants read/write/sync access to Everyone.
        // TODO: consider locking down "WD" to LogonIds (logon session)
        LPCWSTR wzSddl = L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGW0x00100000;;;WD)";
        if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSddl, SDDL_REVISION_1, &psd, NULL))
        {
            ExitWithLastError(hr, "Failed to create the security descriptor for the connection event and pipe.");
        }

        sa.nLength = sizeof(sa);
        sa.lpSecurityDescriptor = psd;
        sa.bInheritHandle = FALSE;
    }

    // Create the pipe.
    hr = StrAllocFormatted(&sczFullPipeName, PIPE_NAME_FORMAT_STRING, pConnection->sczName);
    ExitOnFailure1(hr, "Failed to allocate full name of pipe: %ls", pConnection->sczName);

    // TODO: consider using overlapped IO to do waits on the pipe and still be able to cancel and such.
    hPipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, psd ? &sa : NULL);
    if (INVALID_HANDLE_VALUE == hPipe)
    {
        ExitWithLastError1(hr, "Failed to create pipe: %ls", sczFullPipeName);
    }

    if (fCreateCachePipe)
    {
        // Create the cache pipe.
        hr = StrAllocFormatted(&sczFullPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
        ExitOnFailure1(hr, "Failed to allocate full name of cache pipe: %ls", pConnection->sczName);

        hCachePipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, NULL);
        if (INVALID_HANDLE_VALUE == hCachePipe)
        {
            ExitWithLastError1(hr, "Failed to create pipe: %ls", sczFullPipeName);
        }
    }

    pConnection->hCachePipe = hCachePipe;
    hCachePipe = INVALID_HANDLE_VALUE;

    pConnection->hPipe = hPipe;
    hPipe = INVALID_HANDLE_VALUE;

    // TODO: remove the following
    *phEvent = NULL;

LExit:
    ReleaseFileHandle(hCachePipe);
    ReleaseFileHandle(hPipe);
    ReleaseStr(sczFullPipeName);

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

    return hr;
}
示例#20
0
extern "C" UINT __stdcall WixShellExecBinary(
    __in MSIHANDLE hInstall
)
{
    Assert(hInstall);
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    LPWSTR pwzBinary = NULL;
    LPWSTR pwzFilename = NULL;
    BYTE* pbData = NULL;
    DWORD cbData = 0;
    HANDLE hFile = INVALID_HANDLE_VALUE;

#if 0
    ::MessageBoxA(0, "WixShellExecBinary", "-->> ATTACH HERE", MB_OK);
#endif

    hr = WcaInitialize(hInstall, "WixShellExecBinary");
    ExitOnFailure(hr, "failed to initialize");

    hr = WcaGetFormattedProperty(L"WixShellExecBinaryId", &pwzBinary);
    ExitOnFailure(hr, "failed to get WixShellExecBinaryId");

    WcaLog(LOGMSG_VERBOSE, "WixShellExecBinaryId is %ls", pwzBinary);

    if (!pwzBinary || !*pwzBinary)
    {
        hr = E_INVALIDARG;
        ExitOnFailure(hr, "failed to get WixShellExecBinaryId");
    }

    // get temporary path for extracted file
    StrAlloc(&pwzFilename, MAX_PATH);
    ExitOnFailure(hr, "Failed to allocate temporary path");
    ::GetTempPathW(MAX_PATH, pwzFilename);
    hr = ::StringCchCatW(pwzFilename, MAX_PATH, pwzBinary);
    ExitOnFailure(hr, "Failed to append filename.");

    // grab the bits
    hr = ExtractBinary(pwzBinary, &pbData, &cbData);
    ExitOnFailure(hr, "failed to extract binary data");

    // write 'em to the temp file
    hFile = ::CreateFileW(pwzFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hFile)
    {
        ExitWithLastError1(hr, "Failed to open new temp file: %ls", pwzFilename);
    }

    DWORD cbWritten = 0;
    if (!::WriteFile(hFile, pbData, cbData, &cbWritten, NULL))
    {
        ExitWithLastError1(hr, "Failed to write data to new temp file: %ls", pwzFilename);
    }

    // close it
    ::CloseHandle(hFile);
    hFile = INVALID_HANDLE_VALUE;

    // and run it
    hr = ShellExec(pwzFilename);
    ExitOnFailure1(hr, "failed to launch target: %ls", pwzFilename);

LExit:
    ReleaseStr(pwzBinary);
    ReleaseStr(pwzFilename);
    ReleaseMem(pbData);
    if (INVALID_HANDLE_VALUE != hFile)
    {
        ::CloseHandle(hFile);
    }

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
示例#21
0
HRESULT RssUpdateTryLaunchUpdate(
    __in LPCWSTR wzAppId,
    __in DWORD64 dw64AppVersion,
    __out HANDLE* phUpdateProcess,
    __out_opt DWORD64* pdw64NextUpdateTime
    )
{
    HRESULT hr = S_OK;
    DWORD64 dw64NextUpdateTime = 0;
    BOOL fUpdateReady = FALSE;
    DWORD64 dw64UpdateVersion = 0;
    LPWSTR pwzLocalFeedPath = NULL;
    LPWSTR pwzLocalSetupPath = NULL;

    STARTUPINFOW startupInfo = {0};
    PROCESS_INFORMATION procInfo = {0};

    // If an update is available and higher version that the application currently on the local 
    // machine, launch the install.
    hr = RssUpdateGetUpdateInfo(wzAppId, &dw64NextUpdateTime, &fUpdateReady, &dw64UpdateVersion, &pwzLocalFeedPath, &pwzLocalSetupPath);
    if (SUCCEEDED(hr) && fUpdateReady)
    {
        if (dw64AppVersion < dw64UpdateVersion)
        {
            Trace1(REPORT_DEBUG, "Launching a previously downloaded update at %ls.", pwzLocalSetupPath);

            if (!::CreateProcessW(NULL, pwzLocalSetupPath, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &startupInfo, &procInfo))
            {
                ExitWithLastError1(hr, "Failed to execute %S.", pwzLocalSetupPath);
            }

            RssUpdateDeleteUpdateInfo(wzAppId);
            ExitFunction();
        }
        else // update is not newer, ignore it and continue normally
        {
            RssUpdateSetUpdateInfo(wzAppId, dw64NextUpdateTime, 0, NULL, NULL);
        }
    }

    if (pdw64NextUpdateTime)
    {
        *pdw64NextUpdateTime = dw64NextUpdateTime;
    }

    *phUpdateProcess = procInfo.hProcess;
    procInfo.hProcess = NULL;

LExit:
    if (procInfo.hThread)
    {
        ::CloseHandle(procInfo.hThread);
    }

    if (procInfo.hProcess)
    {
        ::CloseHandle(procInfo.hProcess);
    }

    ReleaseStr(pwzLocalSetupPath);
    ReleaseStr(pwzLocalFeedPath);
    return hr;
}
示例#22
0
/*******************************************************************
 EmbeddedLaunchChildProcess - 

*******************************************************************/
extern "C" HRESULT EmbeddedRunBundle(
    __in LPCWSTR wzExecutablePath,
    __in LPCWSTR wzArguments,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out DWORD* pdwExitCode
    )
{
    HRESULT hr = S_OK;
    DWORD dwCurrentProcessId = ::GetCurrentProcessId();
    HANDLE hCreatedPipesEvent = NULL;
    LPWSTR sczCommand = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    BURN_PIPE_RESULT result = { };

    BURN_PIPE_CONNECTION connection = { };
    PipeConnectionInitialize(&connection);

    BURN_EMBEDDED_CALLBACK_CONTEXT context = { };
    context.pfnGenericMessageHandler = pfnGenericMessageHandler;
    context.pvContext = pvContext;

    hr = PipeCreateNameAndSecret(&connection.sczName, &connection.sczSecret);
    ExitOnFailure(hr, "Failed to create embedded pipe name and client token.");

    hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent);
    ExitOnFailure(hr, "Failed to create embedded pipe.");

    hr = StrAllocFormatted(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
    ExitOnFailure(hr, "Failed to allocate embedded command.");

    if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
    {
        ExitWithLastError1(hr, "Failed to create embedded process atpath: %ls", wzExecutablePath);
    }

    connection.dwProcessId = ::GetProcessId(pi.hProcess);
    connection.hProcess = pi.hProcess;
    pi.hProcess = NULL;

    hr = PipeWaitForChildConnect(&connection);
    ExitOnFailure(hr, "Failed to wait for embedded process to connect to pipe.");

    hr = PipePumpMessages(connection.hPipe, ProcessEmbeddedMessages, &context, &result);
    ExitOnFailure(hr, "Failed to process messages from embedded message.");

    // Get the return code from the embedded process.
    hr = ProcWaitForCompletion(connection.hProcess, INFINITE, pdwExitCode);
    ExitOnFailure1(hr, "Failed to wait for embedded executable: %ls", wzExecutablePath);

LExit:
    ReleaseHandle(pi.hThread);
    ReleaseHandle(pi.hProcess);

    ReleaseStr(sczCommand);
    ReleaseHandle(hCreatedPipesEvent);
    PipeConnectionUninitialize(&connection);

    return hr;
}
示例#23
0
extern "C" HRESULT ApprovedExesLaunch(
    __in BURN_VARIABLES* pVariables,
    __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe,
    __out DWORD* pdwProcessId
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczArgumentsFormatted = NULL;
    LPWSTR sczArgumentsObfuscated = NULL;
    LPWSTR sczCommand = NULL;
    LPWSTR sczCommandObfuscated = NULL;
    LPWSTR sczExecutableDirectory = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };

    // build command
    if (pLaunchApprovedExe->sczArguments && *pLaunchApprovedExe->sczArguments)
    {
        hr = VariableFormatString(pVariables, pLaunchApprovedExe->sczArguments, &sczArgumentsFormatted, NULL);
        ExitOnFailure(hr, "Failed to format argument string.");

        hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %s", pLaunchApprovedExe->sczExecutablePath, sczArgumentsFormatted);
        ExitOnFailure(hr, "Failed to create executable command.");

        hr = VariableFormatStringObfuscated(pVariables, pLaunchApprovedExe->sczArguments, &sczArgumentsObfuscated, NULL);
        ExitOnFailure(hr, "Failed to format obfuscated argument string.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", pLaunchApprovedExe->sczExecutablePath, sczArgumentsObfuscated);
    }
    else
    {
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\"", pLaunchApprovedExe->sczExecutablePath);
        ExitOnFailure(hr, "Failed to create executable command.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\"", pLaunchApprovedExe->sczExecutablePath);
    }
    ExitOnFailure(hr, "Failed to create obfuscated executable command.");

    // Try to get the directory of the executable so we can set the current directory of the process to help those executables
    // that expect stuff to be relative to them.  Best effort only.
    hr = PathGetDirectory(pLaunchApprovedExe->sczExecutablePath, &sczExecutableDirectory);
    if (FAILED(hr))
    {
        ReleaseNullStr(sczExecutableDirectory);
    }

    LogId(REPORT_STANDARD, MSG_LAUNCHING_APPROVED_EXE, pLaunchApprovedExe->sczExecutablePath, sczCommandObfuscated);

    si.cb = sizeof(si);
    if (!::CreateProcessW(pLaunchApprovedExe->sczExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP, NULL, sczExecutableDirectory, &si, &pi))
    {
        ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", pLaunchApprovedExe->sczExecutablePath);
    }

    *pdwProcessId = pi.dwProcessId;

    if (pLaunchApprovedExe->dwWaitForInputIdleTimeout)
    {
        ::WaitForInputIdle(pi.hProcess, pLaunchApprovedExe->dwWaitForInputIdleTimeout);
    }

LExit:
    StrSecureZeroFreeString(sczArgumentsFormatted);
    ReleaseStr(sczArgumentsObfuscated);
    StrSecureZeroFreeString(sczCommand);
    ReleaseStr(sczCommandObfuscated);
    ReleaseStr(sczExecutableDirectory);

    ReleaseHandle(pi.hThread);
    ReleaseHandle(pi.hProcess);

    return hr;
}
示例#24
0
extern "C" HRESULT MsuEngineExecutePackage(
    __in BURN_EXECUTE_ACTION* pExecuteAction,
    __in BOOL fRollback,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out BOOTSTRAPPER_APPLY_RESTART* pRestart
    )
{
    HRESULT hr = S_OK;
    int nResult = IDNOACTION;
    LPWSTR sczCachedDirectory = NULL;
    LPWSTR sczMsuPath = NULL;
    LPWSTR sczSystemPath = NULL;
    LPWSTR sczWusaPath = NULL;
    LPWSTR sczCommand = NULL;
    SC_HANDLE schWu = NULL;
    BOOL fWuWasDisabled = FALSE;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    GENERIC_EXECUTE_MESSAGE message = { };
    DWORD dwExitCode = 0;
    BOOL fDoDependency = FALSE;

    // get wusa.exe path
    hr = PathGetKnownFolder(CSIDL_SYSTEM, &sczSystemPath);
    ExitOnFailure(hr, "Failed to find System32 directory.");

    hr = PathConcat(sczSystemPath, L"wusa.exe", &sczWusaPath);
    ExitOnFailure(hr, "Failed to allocate WUSA.exe path.");

    // build command
    switch (pExecuteAction->msuPackage.action)
    {
    case BOOTSTRAPPER_ACTION_STATE_INSTALL:
        // get cached executable path
        hr = CacheGetCompletedPath(TRUE, pExecuteAction->msuPackage.pPackage->sczCacheId, &sczCachedDirectory);
        ExitOnFailure1(hr, "Failed to get cached path for package: %ls", pExecuteAction->msuPackage.pPackage->sczId);

        hr = PathConcat(sczCachedDirectory, pExecuteAction->msuPackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczMsuPath);
        ExitOnFailure(hr, "Failed to build executable path.");

        // format command
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\" \"%ls\" /quiet /norestart", sczWusaPath, sczMsuPath);
        ExitOnFailure(hr, "Failed to format MSU install command.");
        break;

    case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
        // format command
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pExecuteAction->msuPackage.pPackage->Msu.sczKB);
        ExitOnFailure(hr, "Failed to format MSU uninstall command.");
        break;

    default:
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Failed to get action arguments for MSU package.");
    }

    if (pExecuteAction->msuPackage.sczLogPath && *pExecuteAction->msuPackage.sczLogPath)
    {
        hr = StrAllocConcat(&sczCommand, L" /log:", 0);
        ExitOnFailure(hr, "Failed to append log switch to MSU command-line.");

        hr = StrAllocConcat(&sczCommand, pExecuteAction->msuPackage.sczLogPath, 0);
        ExitOnFailure(hr, "Failed to append log path to MSU command-line.");
    }

    LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->msuPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msuPackage.action), sczMsuPath ? sczMsuPath : pExecuteAction->msuPackage.pPackage->Msu.sczKB, sczCommand);

    hr = EnsureWUServiceEnabled(&schWu, &fWuWasDisabled);
    ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package.");

    // create process
    si.cb = sizeof(si);
    if (!::CreateProcessW(sczWusaPath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
    {
        ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", sczWusaPath);
    }

    do
    {
        message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
        message.dwAllowedResults = MB_OKCANCEL;
        message.progress.dwPercentage = 50;
        nResult = pfnGenericMessageHandler(&message, pvContext);
        hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
        ExitOnRootFailure(hr, "Bootstrapper application aborted during MSU progress.");

        // wait for process to terminate
        hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode);
        if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
        {
            ExitOnFailure1(hr, "Failed to wait for executable to complete: %ls", sczWusaPath);
        }
    } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);

    // get process exit code
    if (!::GetExitCodeProcess(pi.hProcess, &dwExitCode))
    {
        ExitWithLastError(hr, "Failed to get process exit code.");
    }

    // We'll normalize the restart required error code from wusa.exe just in case. Most likely
    // that on reboot we'll actually get WU_S_REBOOT_REQUIRED.
    if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) == static_cast<HRESULT>(dwExitCode))
    {
        dwExitCode = ERROR_SUCCESS_REBOOT_REQUIRED;
    }

    // handle exit code
    switch (dwExitCode)
    {
    case S_OK: __fallthrough;
    case WU_S_ALREADY_INSTALLED:
        fDoDependency = TRUE;
        __fallthrough;
    case S_FALSE: __fallthrough;
    case WU_E_NOT_APPLICABLE:
        *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
        hr = S_OK;
        break;

    case ERROR_SUCCESS_REBOOT_REQUIRED: __fallthrough;
    case WU_S_REBOOT_REQUIRED:
        fDoDependency = TRUE;
        *pRestart = BOOTSTRAPPER_APPLY_RESTART_REQUIRED;
        hr = S_OK;
        break;

    default:
        hr = E_UNEXPECTED;
        break;
    }

    if (fDoDependency)
    {
        if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->msuPackage.action)
        {
            hr = DependencyRegisterPackage(pExecuteAction->msuPackage.pPackage);
            ExitOnFailure(hr, "Failed to register the package dependency providers.");
        }
        else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->msuPackage.action)
        {
            hr = DependencyUnregisterPackage(pExecuteAction->msuPackage.pPackage);
            ExitOnFailure(hr, "Failed to unregister the package dependency providers.");
        }
    }

LExit:
    ReleaseStr(sczCachedDirectory);
    ReleaseStr(sczMsuPath);
    ReleaseStr(sczSystemPath);
    ReleaseStr(sczWusaPath);
    ReleaseStr(sczCommand);

    ReleaseHandle(pi.hProcess);
    ReleaseHandle(pi.hThread);

    if (fWuWasDisabled)
    {
        SetServiceStartType(schWu, SERVICE_DISABLED);
    }

    return hr;
}
示例#25
0
extern "C" HRESULT ExeEngineExecutePackage(
    __in BURN_EXECUTE_ACTION* pExecuteAction,
    __in BURN_VARIABLES* pVariables,
    __in BOOL fRollback,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out BOOTSTRAPPER_APPLY_RESTART* pRestart
    )
{
    HRESULT hr = S_OK;
    WCHAR wzCurrentDirectory[MAX_PATH] = { };
    BOOL fChangedCurrentDirectory = FALSE;
    int nResult = IDNOACTION;
    LPCWSTR wzArguments = NULL;
    LPWSTR sczArgumentsFormatted = NULL;
    LPWSTR sczArgumentsObfuscated = NULL;
    LPWSTR sczCachedDirectory = NULL;
    LPWSTR sczExecutablePath = NULL;
    LPWSTR sczCommand = NULL;
    LPWSTR sczCommandObfuscated = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    DWORD dwExitCode = 0;
    GENERIC_EXECUTE_MESSAGE message = { };

    // get cached executable path
    hr = CacheGetCompletedPath(pExecuteAction->exePackage.pPackage->fPerMachine, pExecuteAction->exePackage.pPackage->sczCacheId, &sczCachedDirectory);
    ExitOnFailure1(hr, "Failed to get cached path for package: %ls", pExecuteAction->exePackage.pPackage->sczId);

    // Best effort to set the execute package cache folder variable.
    VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE);

    hr = PathConcat(sczCachedDirectory, pExecuteAction->exePackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczExecutablePath);
    ExitOnFailure(hr, "Failed to build executable path.");

    // pick arguments
    switch (pExecuteAction->exePackage.action)
    {
    case BOOTSTRAPPER_ACTION_STATE_INSTALL:
        wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczInstallArguments;
        break;

    case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
        wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczUninstallArguments;
        break;

    case BOOTSTRAPPER_ACTION_STATE_REPAIR:
        wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczRepairArguments;
        break;

    default:
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Failed to get action arguments for executable package.");
    }

    // build command
    if (wzArguments && *wzArguments)
    {
        hr = VariableFormatString(pVariables, wzArguments, &sczArgumentsFormatted, NULL);
        ExitOnFailure(hr, "Failed to format argument string.");

        hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %s", sczExecutablePath, sczArgumentsFormatted);
        ExitOnFailure(hr, "Failed to create executable command.");

        hr = VariableFormatStringObfuscated(pVariables, wzArguments, &sczArgumentsObfuscated, NULL);
        ExitOnFailure(hr, "Failed to format obfuscated argument string.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", sczExecutablePath, sczArgumentsObfuscated);
    }
    else
    {
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\"", sczExecutablePath);
        ExitOnFailure(hr, "Failed to create executable command.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\"", sczExecutablePath);
    }
    ExitOnFailure(hr, "Failed to create obfuscated executable command.");

    if (BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol)
    {
        // Add the list of dependencies to ignore, if any, to the burn command line.
        if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol)
        {
            hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
            ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");

            hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
            ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the obfuscated command line.");
        }

        // Add the list of ancestors, if any, to the burn command line.
        if (pExecuteAction->exePackage.sczAncestors)
        {
            hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
            ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");

            hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
            ExitOnFailure(hr, "Failed to append the list of ancestors to the obfuscated command line.");
        }
    }

    // Log before we add the secret pipe name and client token for embedded processes.
    LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->exePackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);

    if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol)
    {
        hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
        ExitOnFailure1(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
    }
    else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pExecuteAction->exePackage.pPackage->Exe.protocol)
    {
        hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
        ExitOnFailure1(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
    }
    else // create and wait for the executable process while sending fake progress to allow cancel.
    {
        // Make the cache location of the executable the current directory to help those executables
        // that expect stuff to be relative to them.
        if (::GetCurrentDirectoryW(countof(wzCurrentDirectory), wzCurrentDirectory))
        {
            fChangedCurrentDirectory = ::SetCurrentDirectoryW(sczCachedDirectory);
        }

        si.cb = sizeof(si); // TODO: hookup the stdin/stdout/stderr pipes for logging purposes?
        if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
        {
            ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
        }

        if (pExecuteAction->exePackage.fFireAndForget)
        {
            ::WaitForInputIdle(pi.hProcess, 5000);
            ExitFunction();
        }

        do
        {
            message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
            message.dwAllowedResults = MB_OKCANCEL;
            message.progress.dwPercentage = 50;
            nResult = pfnGenericMessageHandler(&message, pvContext);
            hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
            ExitOnRootFailure(hr, "Bootstrapper application aborted during EXE progress.");

            hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode);
            if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
            {
                ExitOnFailure1(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath);
            }
        } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
    }

    hr = HandleExitCode(pExecuteAction->exePackage.pPackage, dwExitCode, pRestart);
    ExitOnRootFailure1(hr, "Process returned error: 0x%x", dwExitCode);

LExit:
    if (fChangedCurrentDirectory)
    {
        ::SetCurrentDirectoryW(wzCurrentDirectory);
    }

    StrSecureZeroFreeString(sczArgumentsFormatted);
    ReleaseStr(sczArgumentsObfuscated);
    ReleaseStr(sczCachedDirectory);
    ReleaseStr(sczExecutablePath);
    StrSecureZeroFreeString(sczCommand);
    ReleaseStr(sczCommandObfuscated);

    ReleaseHandle(pi.hThread);
    ReleaseHandle(pi.hProcess);

    // Best effort to clear the execute package cache folder variable.
    VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, NULL, TRUE);

    return hr;
}
示例#26
0
文件: load.cpp 项目: 925coder/wix3
static DWORD WINAPI LoadThreadProc(
    __in LPVOID pvContext
    )
{
    HRESULT hr = S_OK;

    LOAD_THREAD_CONTEXT* pContext = static_cast<LOAD_THREAD_CONTEXT*>(pvContext);
    LPWSTR sczThemePath = pContext->sczThemePath;
    HWND hWnd = pContext->hWnd;

    // We can signal the initialization event as soon as we have copied the context
    // values into local variables.
    ::SetEvent(pContext->hInit);

    BOOL fComInitialized = FALSE;
    HANDLE hDirectory = INVALID_HANDLE_VALUE;
    LPWSTR sczDirectory = NULL;
    LPWSTR wzFileName = NULL;

    THEME* pTheme = NULL;
    HANDLE_THEME* pHandle = NULL;

    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "Failed to initialize COM on load thread.");
    fComInitialized = TRUE;

    // Open a handle to the directory so we can put a notification on it.
    hr = PathGetDirectory(sczThemePath, &sczDirectory);
    ExitOnFailure(hr, "Failed to get path directory.");

     wzFileName = PathFile(sczThemePath);

    hDirectory = ::CreateFileW(sczDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (INVALID_HANDLE_VALUE == hDirectory)
    {
        ExitWithLastError1(hr, "Failed to open directory: %ls", sczDirectory);
    }

    BOOL fUpdated = FALSE;
    do
    {
        // Get the last modified time on the file we're loading for verification that the
        // file actually gets changed down below.
        FILETIME ftModified = { };
        FileGetTime(sczThemePath, NULL, NULL, &ftModified);

        // Try to load the theme file.
        hr = ThemeLoadFromFile(sczThemePath, &pTheme);
        if (FAILED(hr))
        {
            ::SendMessageW(hWnd, WM_THMVWR_THEME_LOAD_ERROR, 0, hr);
        }
        else
        {
            hr = AllocHandleTheme(pTheme, &pHandle);
            ExitOnFailure(hr, "Failed to allocate handle to theme");

            ::SendMessageW(hWnd, WM_THMVWR_NEW_THEME, 0, reinterpret_cast<LPARAM>(pHandle));
            pHandle = NULL;
        }

        fUpdated = FALSE;
        do
        {
            DWORD rgbNotifications[1024];
            DWORD cbRead = 0;
            if (!::ReadDirectoryChangesW(hDirectory, rgbNotifications, sizeof(rgbNotifications), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &cbRead, NULL, NULL))
            {
                ExitWithLastError1(hr, "Failed while watching directory: %ls", sczDirectory);
            }

            // Wait for half a second to let all the file handles get closed to minimize access
            // denied errors.
            ::Sleep(500);

            FILE_NOTIFY_INFORMATION* pNotification = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(rgbNotifications);
            while (pNotification)
            {
                // If our file was updated, check to see if the modified time really changed. The notifications
                // are often trigger happy thinking the file changed two or three times in a row. Maybe it's AV
                // software creating the problems but actually checking the modified date works well.
                if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pNotification->FileName, pNotification->FileNameLength / sizeof(WCHAR), wzFileName, -1))
                {
                    FILETIME ft = { };
                    FileGetTime(sczThemePath, NULL, NULL, &ft);

                    fUpdated = (ftModified.dwHighDateTime < ft.dwHighDateTime) || (ftModified.dwHighDateTime == ft.dwHighDateTime && ftModified.dwLowDateTime < ft.dwLowDateTime);
                    break;
                }

                pNotification = pNotification->NextEntryOffset ? reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<BYTE*>(pNotification) + pNotification->NextEntryOffset) : NULL;
            }
        } while (!fUpdated);
    } while(fUpdated);

LExit:
    if (fComInitialized)
    {
        ::CoUninitialize();
    }

    ReleaseFileHandle(hDirectory);
    ReleaseStr(sczDirectory);
    ReleaseStr(sczThemePath);
    return hr;
}
示例#27
0
文件: pipe.cpp 项目: firegiant/wix3
/*******************************************************************
 PipeChildConnect - Called from the child process to connect back
                    to the pipe provided by the parent process.

*******************************************************************/
extern "C" HRESULT PipeChildConnect(
    __in BURN_PIPE_CONNECTION* pConnection,
    __in BOOL fConnectCachePipe
    )
{
    Assert(pConnection->sczName);
    Assert(pConnection->sczSecret);
    Assert(!pConnection->hProcess);
    Assert(INVALID_HANDLE_VALUE == pConnection->hPipe);
    Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe);

    HRESULT hr = S_OK;
    LPWSTR sczPipeName = NULL;

    // Try to connect to the parent.
    hr = StrAllocFormatted(&sczPipeName, PIPE_NAME_FORMAT_STRING, pConnection->sczName);
    ExitOnFailure(hr, "Failed to allocate name of parent pipe.");

    hr = E_UNEXPECTED;
    for (DWORD cRetry = 0; FAILED(hr) && cRetry < PIPE_RETRY_FOR_CONNECTION; ++cRetry)
    {
        pConnection->hPipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (INVALID_HANDLE_VALUE == pConnection->hPipe)
        {
            hr = HRESULT_FROM_WIN32(::GetLastError());
            if (E_FILENOTFOUND == hr) // if the pipe isn't created, call it a timeout waiting on the parent.
            {
                hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
            }

            ::Sleep(PIPE_WAIT_FOR_CONNECTION);
        }
        else // we have a connection, go with it.
        {
            hr = S_OK;
        }
    }
    ExitOnRootFailure1(hr, "Failed to open parent pipe: %ls", sczPipeName)

    // Verify the parent and notify it that the child connected.
    hr = ChildPipeConnected(pConnection->hPipe, pConnection->sczSecret, &pConnection->dwProcessId);
    ExitOnFailure1(hr, "Failed to verify parent pipe: %ls", sczPipeName);

    if (fConnectCachePipe)
    {
        // Connect to the parent for the cache pipe.
        hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
        ExitOnFailure(hr, "Failed to allocate name of parent cache pipe.");

        pConnection->hCachePipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (INVALID_HANDLE_VALUE == pConnection->hCachePipe)
        {
            ExitWithLastError1(hr, "Failed to open parent pipe: %ls", sczPipeName)
        }

        // Verify the parent and notify it that the child connected.
        hr = ChildPipeConnected(pConnection->hCachePipe, pConnection->sczSecret, &pConnection->dwProcessId);
        ExitOnFailure1(hr, "Failed to verify parent pipe: %ls", sczPipeName);
    }

    pConnection->hProcess = ::OpenProcess(SYNCHRONIZE, FALSE, pConnection->dwProcessId);
    ExitOnNullWithLastError1(pConnection->hProcess, hr, "Failed to open companion process with PID: %u", pConnection->dwProcessId);

LExit:
    ReleaseStr(sczPipeName);

    return hr;
}
示例#28
0
static HRESULT InstallCertificatePackage(
    __in HCERTSTORE hStore,
    __in BOOL fUserCertificateStore,
    __in LPCWSTR wzName,
    __in_opt BYTE* rgbData,
    __in DWORD cbData,
    __in_opt LPCWSTR wzPFXPassword
    )
{
    HRESULT hr = S_OK;

    HCERTSTORE hPfxCertStore = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    CERT_BLOB blob = { 0 };
    DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
    DWORD dwEncodingType;
    DWORD dwContentType;
    DWORD dwFormatType;
    LPWSTR pwzUniqueName = NULL;
    int iUniqueId = 0;

    // Figure out what type of blob (certificate or PFX) we're dealing with here.
    blob.pbData = rgbData;
    blob.cbData = cbData;

    if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext))
    {
        ExitWithLastError1(hr, "Failed to parse the certificate blob: %ls", wzName);
    }

    hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
    ExitOnFailure(hr, "Failed to format unique name");

    if (!pCertContext)
    {
        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
        if (dwContentType & CERT_QUERY_CONTENT_PFX)
        {
            ExitOnNull(wzPFXPassword, hr, E_INVALIDARG, "Failed to import PFX blob because no password was provided");

            // If we fail and our password is blank, also try passing in NULL for the password (according to the docs)
            hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset);
            if (NULL == hPfxCertStore && !*wzPFXPassword)
            {
                hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset);
            }
            ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");

            // Install all certificates in the PFX
            for (pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext);
                 pCertContext;
                 pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext))
            {
                WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", pwzUniqueName);
                hr = CertInstallSingleCertificate(hStore, pCertContext, pwzUniqueName);
                MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");

                hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
                ExitOnFailure(hr, "Failed to format unique name");
            }
        }
        else
        {
            hr = E_UNEXPECTED;
            ExitOnFailure(hr, "Unexpected certificate type processed.");
        }
    }
    else
    {
        WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", pwzUniqueName);
        hr = CertInstallSingleCertificate(hStore, pCertContext, pwzUniqueName);
        MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
    }

    hr = WcaProgressMessage(COST_CERT_ADD, FALSE);
    ExitOnFailure(hr, "Failed to send install progress message.");

LExit:
    ReleaseStr(pwzUniqueName);

    if (pCertContext)
    {
        ::CertFreeCertificateContext(pCertContext);
    }

    // Close the stores after the context's are released.
    if (hPfxCertStore)
    {
        if (!::CertCloseStore(hPfxCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
        {
            WcaLog(LOGMSG_VERBOSE, "PFX cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
        }
    }

    return hr;
}
示例#29
0
extern "C" HRESULT NetFxRunChainer(
    __in LPCWSTR wzExecutablePath,
    __in LPCWSTR wzArguments,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out DWORD* pdwExitCode
)
{
    HRESULT hr = S_OK;
    DWORD er = 0;
    UUID guid = { };
    WCHAR wzGuid[39];
    RPC_STATUS rs = RPC_S_OK;
    LPWSTR sczEventName = NULL;
    LPWSTR sczSectionName = NULL;
    LPWSTR sczCommand = NULL;
    NetFxChainer* pNetfxChainer = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    HRESULT hrInternalError = 0;

    // Create the unique name suffix.
    rs = ::UuidCreate(&guid);
    hr = HRESULT_FROM_RPC(rs);
    ExitOnFailure(hr, "Failed to create netfx chainer guid.");

    if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
    {
        hr = E_OUTOFMEMORY;
        ExitOnRootFailure(hr, "Failed to convert netfx chainer guid into string.");
    }

    hr = StrAllocFormatted(&sczSectionName, L"NetFxSection.%ls", wzGuid);
    ExitOnFailure(hr, "Failed to allocate section name.");

    hr = StrAllocFormatted(&sczEventName, L"NetFxEvent.%ls", wzGuid);
    ExitOnFailure(hr, "Failed to allocate event name.");

    hr = CreateNetFxChainer(sczSectionName, sczEventName, &pNetfxChainer);
    ExitOnFailure(hr, "Failed to create netfx chainer.");

    hr = StrAllocFormatted(&sczCommand, L"%ls /pipe %ls", wzArguments, sczSectionName);
    ExitOnFailure(hr, "Failed to allocate netfx chainer arguments.");

    si.cb = sizeof(si);
    if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
    {
        ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
    }

    HANDLE handles[2] = { pi.hProcess, pNetfxChainer->hEventChaineeSend };

    for (;;)
    {
        er = ::WaitForMultipleObjects(2, handles, FALSE, 100);
        if (WAIT_OBJECT_0 == er)
        {
            // Process has exited
            *pdwExitCode = NetFxGetResult(pNetfxChainer, &hrInternalError);
            if (E_PENDING == *pdwExitCode)
            {
                if (!::GetExitCodeProcess(pi.hProcess, pdwExitCode))
                {
                    ExitWithLastError(hr, "Failed to get netfx return code.");
                }
            }
            else if (FAILED(hrInternalError))
            {
                // push internal error message
                OnNetFxError(pNetfxChainer, hrInternalError, pfnGenericMessageHandler, pvContext);
                ExitOnFailure(hr, "Failed to send internal error message from netfx chainer.");
            }

            break;
        }
        else if (WAIT_OBJECT_0 + 1 == er)
        {
            // Chainee has notified us of a change.
            hr = ProcessNetFxMessage(pNetfxChainer, pfnGenericMessageHandler, pvContext);
            ExitOnFailure(hr, "Failed to process netfx chainer message.");
        }
        else if (WAIT_FAILED == er)
        {
            ExitWithLastError(hr, "Failed to wait for netfx chainer process to complete");
        }
    }

LExit:
    ReleaseStr(sczSectionName);
    ReleaseStr(sczEventName);
    ReleaseStr(sczCommand);
    DestroyNetFxChainer(pNetfxChainer);
    ReleaseHandle(pi.hThread);
    ReleaseHandle(pi.hProcess);

    return hr;
}
示例#30
0
/********************************************************************
StrAllocStringAnsi - allocates or reuses dynamic string memory and copies in an existing ANSI string

NOTE: caller is responsible for freeing ppwz even if function fails
NOTE: cchSource must equal the length of wzSource (not including the NULL terminator)
NOTE: if cchSource == 0, length of wzSource is used instead
********************************************************************/
extern "C" HRESULT DAPI StrAllocStringAnsi(
	__inout LPWSTR* ppwz,
	__in LPCSTR szSource,
	__in DWORD_PTR cchSource,
	__in UINT uiCodepage
	)
{
	Assert(ppwz && szSource);

	HRESULT hr = S_OK;
	LPWSTR pwz = NULL;
	DWORD_PTR cch = 0;
	DWORD_PTR cchDest = cchSource;  // at least enough

	if (*ppwz)
	{
		cch = MemSize(*ppwz);  // get the count in bytes so we can check if it failed (returns -1)
		if (-1 == cch)
		{
			ExitOnFailure(hr = E_INVALIDARG, "failed to get size of destination string");
		}
		cch /= sizeof(WCHAR);  //convert the count in bytes to count in characters
	}

	if (0 == cchSource)
	{
		cchDest = ::MultiByteToWideChar(uiCodepage, 0, szSource, -1, NULL, 0);
		if (0 == cchDest)
		{
			ExitWithLastError1(hr, "failed to get required size for conversion to unicode: %s", szSource);
		}

		--cchDest; //subtract one because MultiByteToWideChar includes space for the NULL terminator that we track below
	}
	else if (L'\0' == szSource[cchSource]) // if the source already had a null terminator, don't count that in the character count because we track it below
	{
		cchDest = cchSource - 1;
	}

	if (cch < cchDest + 1)
	{
		cch = cchDest + 1;
		if (cch >= MAXDWORD / sizeof(WCHAR))
		{
			ExitOnFailure1(hr = E_OUTOFMEMORY, "Not enough memory to allocate string of size: %d", cch);
		}

		if (*ppwz)
		{
			pwz = static_cast<LPWSTR>(MemReAlloc(*ppwz, sizeof(WCHAR) * cch, TRUE));
		}
		else
		{
			pwz = static_cast<LPWSTR>(MemAlloc(sizeof(WCHAR) * cch, TRUE));
		}

		ExitOnNull1(pwz, hr, E_OUTOFMEMORY, "failed to allocate string, len: %d", cch);

		*ppwz = pwz;
	}

	if (0 == ::MultiByteToWideChar(uiCodepage, 0, szSource, 0 == cchSource ? -1 : (int)cchSource, *ppwz, (int)cch))
	{
		ExitWithLastError1(hr, "failed to convert to unicode: %s", szSource);
	}
	(*ppwz)[cchDest] = L'\0';

LExit:
	return hr;
}