Example #1
0
extern "C" HRESULT DAPI LocLoadFromResource(
    __in HMODULE hModule,
    __in_z LPCSTR szResource,
    __out WIX_LOCALIZATION** ppWixLoc
    )
{
    HRESULT hr = S_OK;
    LPVOID pvResource = NULL;
    DWORD cbResource = 0;
    LPWSTR sczXml = NULL;
    IXMLDOMDocument* pixd = NULL;

    hr = ResReadData(hModule, szResource, &pvResource, &cbResource);
    ExitOnFailure(hr, "Failed to read theme from resource.");

    hr = StrAllocStringAnsi(&sczXml, reinterpret_cast<LPCSTR>(pvResource), cbResource, CP_UTF8);
    ExitOnFailure(hr, "Failed to convert XML document data from UTF-8 to unicode string.");

    hr = XmlLoadDocument(sczXml, &pixd);
    ExitOnFailure(hr, "Failed to load theme resource as XML document.");

    hr = ParseWxl(pixd, ppWixLoc);
    ExitOnFailure(hr, "Failed to parse WXL.");

LExit:
    ReleaseObject(pixd);
    ReleaseStr(sczXml);

    return hr;
}
Example #2
0
DAPIV_(HRESULT) BalLog(
    __in BOOTSTRAPPER_LOG_LEVEL level,
    __in_z __format_string LPCSTR szFormat,
    ...
    )
{
    HRESULT hr = S_OK;
    va_list args;
    LPSTR sczFormattedAnsi = NULL;
    LPWSTR sczMessage = NULL;

    if (!vpEngine)
    {
        hr = E_POINTER;
        ExitOnRootFailure(hr, "BalInitialize() must be called first.");
    }

    va_start(args, szFormat);
    hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args);
    va_end(args);
    ExitOnFailure(hr, "Failed to format log string.");

    hr = StrAllocStringAnsi(&sczMessage, sczFormattedAnsi, 0, CP_UTF8);
    ExitOnFailure(hr, "Failed to convert log string to Unicode.");

    hr = vpEngine->Log(level, sczMessage);

LExit:
    ReleaseStr(sczMessage);
    ReleaseStr(sczFormattedAnsi);
    return hr;
}
Example #3
0
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;
}
Example #4
0
/********************************************************************
 WcaCaScriptCreateKey() - creates a unique script key for this
                          CustomAction.

********************************************************************/
extern "C" HRESULT WIXAPI WcaCaScriptCreateKey(
    __out LPWSTR* ppwzScriptKey
    )
{
    AssertSz(WcaIsInitialized(), "WcaInitialize() should have been called before calling this function.");
    HRESULT hr = S_OK;

    hr = StrAllocStringAnsi(ppwzScriptKey, WcaGetLogName(), 0, CP_ACP);
    ExitOnFailure(hr, "Failed to create script key.");

LExit:
    return hr;
}
Example #5
0
HRESULT ScaSqlStrsReadScripts(
    __inout SCA_SQLSTR** ppsssList,
    __in SCA_ACTION saAction
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;
    PMSIHANDLE hViewBinary, hRecBinary;
    PMSIHANDLE hViewUser, hRecUser;

    LPWSTR pwzComponent = NULL;
    LPWSTR pwzData = NULL;

    BYTE* pbScript = NULL;
    DWORD cbRead = 0;
    DWORD cbScript = 0;
    DWORD cchScript = 0;

    LPWSTR pwzScriptBuffer = NULL;
    WCHAR* pwzScript = NULL;
    WCHAR* pwz;
    DWORD cch = 0;

    SCA_SQLSTR sss;
    SCA_SQLSTR* psss = NULL;

    if (S_OK != WcaTableExists(L"SqlScript") || S_OK != WcaTableExists(L"SqlDatabase") || S_OK != WcaTableExists(L"Binary"))
    {
        WcaLog(LOGMSG_VERBOSE, "Skipping ScaSqlStrsReadScripts() - SqlScripts and/or SqlDatabase table not present");
        ExitFunction1(hr = S_FALSE);
    }

    // open a view on the binary table
    hr = WcaOpenView(vcsSqlBinaryScriptQuery, &hViewBinary);
    ExitOnFailure(hr, "Failed to open view on Binary table for SqlScripts");

    // loop through all the sql scripts
    hr = WcaOpenExecuteView(vcsSqlScriptQuery, &hView);
    ExitOnFailure(hr, "Failed to open view on SqlScript table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
        INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;

        hr = WcaGetRecordString(hRec, sscrqComponent, &pwzComponent);
        ExitOnFailure(hr, "Failed to get Component for SQL Script.");

        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction);
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure1(hr, "Failed to get state for component: %ls", pwzComponent);

        // If we're doing install but the Component is not being installed or we're doing
        // uninstall but the Component is not being uninstalled, skip it.
        if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) ||
            (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction))
        {
            continue;
        }

        ::ZeroMemory(&sss, sizeof(sss));

        sss.isInstalled = isInstalled;
        sss.isAction = isAction;

        hr = WcaGetRecordString(hRec, sscrqSqlScript, &pwzData);
        ExitOnFailure(hr, "Failed to get SqlScript.Script");
        hr = ::StringCchCopyW(sss.wzKey, countof(sss.wzKey), pwzData);
        ExitOnFailure1(hr, "Failed to copy SqlScript.Script: %ls", pwzData);

        // find the database information for this string
        hr = WcaGetRecordString(hRec, sscrqSqlDb, &pwzData);
        ExitOnFailure1(hr, "Failed to get SqlScript.SqlDb_ for SqlScript '%ls'", sss.wzKey);
        hr = ::StringCchCopyW(sss.wzSqlDb, countof(sss.wzSqlDb), pwzData);
        ExitOnFailure1(hr, "Failed to copy SqlScritp.SqlDbb: %ls", pwzData);

        hr = WcaGetRecordInteger(hRec, sscrqAttributes, &sss.iAttributes);
        ExitOnFailure1(hr, "Failed to get SqlScript.Attributes for SqlScript '%ls'", sss.wzKey);

        hr = WcaGetRecordInteger(hRec, sscrqSequence, &sss.iSequence);
        ExitOnFailure1(hr, "Failed to get SqlScript.Sequence for SqlScript '%ls'", sss.wzKey);

        // get the sql script out of the binary stream
        hr = WcaExecuteView(hViewBinary, hRec);
        ExitOnFailure1(hr, "Failed to open SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey);
        hr = WcaFetchSingleRecord(hViewBinary, &hRecBinary);
        ExitOnFailure1(hr, "Failed to fetch SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey);

        // Note: We need to allocate an extra character on the stream to NULL terminate the SQL script.
        //       The WcaGetRecordStream() function won't let us add extra space on the end of the stream
        //       so we'll read the stream "the old fashioned way".
        //hr = WcaGetRecordStream(hRecBinary, ssbsqData, (BYTE**)&pbScript, &cbScript);
        //ExitOnFailure1(hr, "Failed to read SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey);
        er = ::MsiRecordReadStream(hRecBinary, ssbsqData, NULL, &cbRead);
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure(hr, "failed to get size of stream");

        cbScript = cbRead + sizeof(WCHAR); // we may have an ANSI SQL script but leave enough to even NULL terminate a WCHAR string
        hr = WcaAllocStream(&pbScript, cbScript); // this will allocate a fully zeroed out buffer so our string will be NULL terminated
        ExitOnFailure(hr, "failed to allocate data for stream");

        er = ::MsiRecordReadStream(hRecBinary, ssbsqData, reinterpret_cast<char*>(pbScript), &cbRead); //read the buffer but leave the space for the NULL terminator
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure(hr, "failed to read from stream");

        Assert(cbRead + sizeof(WCHAR) == cbScript);

        // Check for the UNICODE BOM file marker.
        if ((0xFF == *pbScript) && (0xFE == *(pbScript + 1)))
        {
            // Copy the UNICODE string after the BOM marker (subtract one because we'll skip the BOM marker).
            cchScript = (cbScript / sizeof(WCHAR)) - 1;

            hr = StrAllocString(&pwzScriptBuffer, reinterpret_cast<LPWSTR>(pbScript) + 1, 0);
            ExitOnFailure1(hr, "Failed to allocate WCHAR string of size '%d'", cchScript);
        }
        else
        {
            // We have an ANSI string so convert it to UNICODE.
            cchScript = cbScript;

            hr = StrAllocStringAnsi(&pwzScriptBuffer, reinterpret_cast<LPCSTR>(pbScript), 0, CP_ACP);
            ExitOnFailure1(hr, "Failed to allocate WCHAR string of size '%d'", cchScript);
        }

        // Free the byte buffer since it has been converted to a new UNICODE string, one way or another.
        if (pbScript)
        {
            WcaFreeStream(pbScript);
            pbScript = NULL;
        }

        // Process the SQL script stripping out unnecessary stuff (like comments) and looking for "GO" statements.
        pwzScript = pwzScriptBuffer;
        while (cchScript && pwzScript && *pwzScript)
        {
            // strip off leading whitespace
            while (cchScript && *pwzScript && iswspace(*pwzScript))
            {
                ++pwzScript;
                --cchScript;
            }

            Assert(0 <= cchScript);

            // if there is a SQL comment remove it
            while (cchScript && L'/' == *pwzScript && L'*' == *(pwzScript + 1))
            {
                // go until end of comment
                while (cchScript && *pwzScript && *(pwzScript + 1) && !(L'*' == *pwzScript && L'/' == *(pwzScript + 1)))
                {
                    ++pwzScript;
                    --cchScript;
                }

                Assert(2 <= cchScript);

                if (2 <= cchScript)
                {
                    // to account for */ at end
                    pwzScript+=2;
                    cchScript-=2;
                }

                Assert(0 <= cchScript);

                // strip off any new leading whitespace
                while (cchScript && *pwzScript && iswspace(*pwzScript))
                {
                    ++pwzScript;
                    --cchScript;
                }
            }

            while (cchScript && L'-' == *pwzScript && L'-' == *(pwzScript + 1))
            {
                // go past the new line character
                while (cchScript && *pwzScript && L'\n' != *pwzScript)
                {
                    ++pwzScript;
                    --cchScript;
                }

                Assert(0 <= cchScript);

                if (cchScript && L'\n' == *pwzScript)
                {
                    ++pwzScript;
                    --cchScript;
                }

                Assert(0 <= cchScript);

                // strip off any new leading whitespace
                while (cchScript && *pwzScript && iswspace(*pwzScript))
                {
                    ++pwzScript;
                    --cchScript;
                }
            }

            Assert(0 <= cchScript);

            // try to isolate a "GO" keyword and count the characters in the SQL string
            pwz = pwzScript;
            cch = 0;
            while (cchScript && *pwz)
            {
                //skip past comment lines that might have "go" in them
                //note that these comments are "in the middle" of our function,
                //or possibly at the end of a line
                if (cchScript && L'-' == *pwz && L'-' == *(pwz + 1))
                {
                    // skip past chars until the new line character
                    while (cchScript && *pwz && (L'\n' != *pwz))
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }
                }

                //skip past comment lines of form /* to */ that might have "go" in them
                //note that these comments are "in the middle" of our function,
                //or possibly at the end of a line
                if (cchScript && L'/' == *pwz && L'*' == *(pwz + 1))
                {
                    // skip past chars until the new line character
                    while (cchScript && *pwz && *(pwz + 1) && !((L'*' == *pwz) && (L'/' == *(pwz + 1))))
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }

                    if (2 <= cchScript)
                    {
                        // to account for */ at end
                        pwz+=2;
                        cch+=2;
                        cchScript-=2;
                    }
                }

                // Skip past strings that may be part of the SQL statement that might have a "go" in them
                if ( cchScript && L'\'' == *pwz )
                {
                    ++pwz;
                    ++cch;
                    --cchScript;

                    // Skip past chars until the end of the string
                    while ( cchScript && *pwz && !(L'\'' == *pwz) )
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }
                }

                // Skip past strings that may be part of the SQL statement that might have a "go" in them
                if ( cchScript && L'\"' == *pwz )
                {
                    ++pwz;
                    ++cch;
                    --cchScript;

                    // Skip past chars until the end of the string
                    while ( cchScript && *pwz && !(L'\"' == *pwz) )
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }
                }

                // if "GO" is isolated
                if ((pwzScript == pwz || iswspace(*(pwz - 1))) && 
                    (L'G' == *pwz || L'g' == *pwz) && 
                    (L'O' == *(pwz + 1) || L'o' == *(pwz + 1)) &&
                    (0 == *(pwz + 2) || iswspace(*(pwz + 2))))
                {
                    *pwz = 0; // null terminate the SQL string on the "G"
                    pwz += 2;
                    cchScript -= 2;
                    break;   // found "GO" now add SQL string to list
                }

                ++pwz;
                ++cch;
                --cchScript;
            }

            Assert(0 <= cchScript);

            if (0 < cch) //don't process if there's nothing to process
            {
                // replace tabs with spaces
                for (LPWSTR pwzTab = wcsstr(pwzScript, L"\t"); pwzTab; pwzTab = wcsstr(pwzTab, L"\t"))
                    *pwzTab = ' ';

                // strip off whitespace at the end of the script string
                for (LPWSTR pwzErase = pwzScript + cch - 1; pwzScript < pwzErase && iswspace(*pwzErase); pwzErase--)
                {
                    *(pwzErase) = 0;
                    cch--;
                }
            }

            if (0 < cch)
            {
                hr = NewSqlStr(&psss);
                ExitOnFailure(hr, "failed to allocate new sql string element");

                // copy everything over
                hr = ::StringCchCopyW(psss->wzKey, countof(psss->wzKey), sss.wzKey);
                ExitOnFailure(hr, "Failed to copy key string to sqlstr object");
                hr = ::StringCchCopyW(psss->wzSqlDb, countof(psss->wzSqlDb), sss.wzSqlDb);
                ExitOnFailure(hr, "Failed to copy DB string to sqlstr object");
                hr = ::StringCchCopyW(psss->wzComponent, countof(psss->wzComponent), sss.wzComponent);
                ExitOnFailure(hr, "Failed to copy component string to sqlstr object");
                psss->isInstalled = sss.isInstalled;
                psss->isAction = sss.isAction;
                psss->iAttributes = sss.iAttributes;
                psss->iSequence = sss.iSequence;

                // cchRequired includes the NULL terminating char
                hr = StrAllocString(&psss->pwzSql, pwzScript, 0);
                ExitOnFailure1(hr, "Failed to allocate string for SQL script: '%ls'", psss->wzKey);

                *ppsssList = AddSqlStrToList(*ppsssList, psss);
                psss = NULL; // set the db NULL so it doesn't accidentally get freed below
            }

            pwzScript = pwz;
        }
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while reading SqlString table");

LExit:
    // if anything was left over after an error clean it all up
    if (psss)
    {
        ScaSqlStrsFreeList(psss);
    }

    if (pbScript)
    {
        WcaFreeStream(pbScript);
    }

    ReleaseStr(pwzScriptBuffer);
    ReleaseStr(pwzData);
    ReleaseStr(pwzComponent);

    return hr;
}
Example #6
0
static HRESULT HandleOutput(
    __in BOOL fLogOutput,
    __in HANDLE hRead
    )
{
    BYTE *pBuffer = NULL;
    LPWSTR szLog = NULL;
    LPWSTR szTemp = NULL;
    LPWSTR pEnd = NULL;
    LPWSTR pNext = NULL;
    LPWSTR sczEscaped = NULL;
    LPSTR szWrite = NULL;
    DWORD dwBytes = OUTPUT_BUFFER;
    BOOL bFirst = TRUE;
    BOOL bUnicode = TRUE;
    HRESULT hr = S_OK;

    // Get buffer for output
    pBuffer = static_cast<BYTE *>(MemAlloc(OUTPUT_BUFFER, FALSE));
    ExitOnNull(pBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer for output.");

    while (0 != dwBytes)
    {
        ::ZeroMemory(pBuffer, OUTPUT_BUFFER);
        if (!::ReadFile(hRead, pBuffer, OUTPUT_BUFFER - 1, &dwBytes, NULL) && GetLastError() != ERROR_BROKEN_PIPE)
        {
            ExitOnLastError(hr, "Failed to read from handle.");
        }

        if (fLogOutput)
        {
            // Check for UNICODE or ANSI output
            if (bFirst)
            {
                if ((isgraph(pBuffer[0]) && isgraph(pBuffer[1])) ||
                    (isgraph(pBuffer[0]) && isspace(pBuffer[1])) ||
                    (isspace(pBuffer[0]) && isgraph(pBuffer[1])) ||
                    (isspace(pBuffer[0]) && isspace(pBuffer[1])))
                {
                    bUnicode = FALSE;
                }

                bFirst = FALSE;
            }

            // Keep track of output
            if (bUnicode)
            {
                hr = StrAllocConcat(&szLog, (LPCWSTR)pBuffer, 0);
                ExitOnFailure(hr, "Failed to concatenate output strings");
            }
            else
            {
                hr = StrAllocStringAnsi(&szTemp, (LPCSTR)pBuffer, 0, CP_OEMCP);
                ExitOnFailure(hr, "Failed to allocate output string");
                hr = StrAllocConcat(&szLog, szTemp, 0);
                ExitOnFailure(hr, "Failed to concatenate output strings");
            }

            // Log each line of the output
            pNext = szLog;
            pEnd = wcschr(szLog, L'\r');
            if (NULL == pEnd)
            {
                pEnd = wcschr(szLog, L'\n');
            }
            while (pEnd && *pEnd)
            {
                // Find beginning of next line
                pEnd[0] = 0;
                ++pEnd;
                if ((pEnd[0] == L'\r') || (pEnd[0] == L'\n'))
                {
                    ++pEnd;
                }

                // Log output
                hr = StrAllocString(&sczEscaped, pNext, 0);
                ExitOnFailure(hr, "Failed to allocate copy of string");

                hr = StrReplaceStringAll(&sczEscaped, L"%", L"%%");
                ExitOnFailure(hr, "Failed to escape percent signs in string");

                hr = StrAnsiAllocString(&szWrite, sczEscaped, 0, CP_OEMCP);
                ExitOnFailure(hr, "Failed to convert output to ANSI");
                WcaLog(LOGMSG_STANDARD, szWrite);

                // Next line
                pNext = pEnd;
                pEnd = wcschr(pNext, L'\r');
                if (NULL == pEnd)
                {
                    pEnd = wcschr(pNext, L'\n');
                }
            }

            hr = StrAllocString(&szTemp, pNext, 0);
            ExitOnFailure(hr, "Failed to allocate string");

            hr = StrAllocString(&szLog, szTemp, 0);
            ExitOnFailure(hr, "Failed to allocate string");
        }
    }

    // Print any text that didn't end with a new line
    if (szLog && *szLog)
    {
        hr = StrReplaceStringAll(&szLog, L"%", L"%%");
        ExitOnFailure(hr, "Failed to escape percent signs in string");

        hr = StrAnsiAllocString(&szWrite, szLog, 0, CP_OEMCP);
        ExitOnFailure(hr, "Failed to convert output to ANSI");

        WcaLog(LOGMSG_VERBOSE, szWrite);
    }

LExit:
    ReleaseMem(pBuffer);

    ReleaseStr(szLog);
    ReleaseStr(szTemp);
    ReleaseStr(szWrite);
    ReleaseStr(sczEscaped);

    return hr;
}