Hmm,
  I can't believe this would make it through some basic testing but here 
goes... I am attempting to detect the state of a product (VC 2005 Runtime) 
using the following snippet.

    <util:ProductSearch Id="SearchForVC2005SP1REDIST" 
Guid="837B34E3-7C30-493C-8F6A-2B0F04E2912C" Variable="VC2005SP1Installed" 
Result="version"/>
    <util:ProductSearch Id="SearchForVC2005SP1MFCLOCREDIST" 
Guid="710F4C1C-CC18-4C49-8CBF-51240C89A1A2" Variable="VC2005SP1MFCLOCInstalled" 
Result="state"/>

When I use a result other than state, then the search functions as expected, 
however if I use state it fails and the log file shows:

[2DB4:40F8][2012-06-14T12:57:17]: Error 0x80070648: Failed to get product info.
[2DB4:40F8][2012-06-14T12:57:17]: MsiProductSearch failed: ID 
'SearchForVC2005SP1MFCLOCREDIST', HRESULT 0x80070648

Looking at code for Burn, I see the following:
search.cpp

static HRESULT MsiProductSearch(
    __in BURN_SEARCH* pSearch,
    __in BURN_VARIABLES* pVariables
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczProductCode = NULL;
    LPCWSTR wzProperty = NULL;
    BURN_VARIANT_TYPE type = BURN_VARIANT_TYPE_NONE;
    BURN_VARIANT value = { };

    switch (pSearch->MsiProductSearch.Type)
    {
    case BURN_MSI_PRODUCT_SEARCH_TYPE_VERSION:
        wzProperty = INSTALLPROPERTY_VERSIONSTRING;
        break;
    case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE:
        wzProperty = INSTALLPROPERTY_LANGUAGE;
        break;
    case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE:
        wzProperty = INSTALLPROPERTY_PRODUCTSTATE; <!-This would happen -->
        break;
    case BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT:
        wzProperty = INSTALLPROPERTY_ASSIGNMENTTYPE;
        break;
    }

    // format product code string
    hr = VariableFormatString(pVariables, 
pSearch->MsiProductSearch.sczProductCode, &sczProductCode, NULL);
    ExitOnFailure(hr, "Failed to format product code string.");

    // get product info
    value.Type = BURN_VARIANT_TYPE_STRING;
    hr = WiuGetProductInfo(sczProductCode, wzProperty, &value.sczValue);
    if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr)
    {
        LogStringLine(REPORT_STANDARD, "Product not found: %ls", 
sczProductCode);

        // set value to indicate absent
        switch (pSearch->MsiProductSearch.Type)
        {
        case BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT: __fallthrough;
        case BURN_MSI_PRODUCT_SEARCH_TYPE_VERSION:
            value.Type = BURN_VARIANT_TYPE_NUMERIC;
            value.llValue = 0;
            break;
        case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE:
            // is supposed to remain empty
            break;
        case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE:
            value.Type = BURN_VARIANT_TYPE_NUMERIC;
            value.llValue = INSTALLSTATE_ABSENT;
            break;
        }

        hr = S_OK;
    }
    ExitOnFailure(hr, "Failed to get product info.");

    // change value type
    switch (pSearch->MsiProductSearch.Type)
    {
    case BURN_MSI_PRODUCT_SEARCH_TYPE_VERSION:
        type = BURN_VARIANT_TYPE_VERSION;
        break;
    case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE:
        type = BURN_VARIANT_TYPE_STRING;
        break;
    case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE: __fallthrough;
    case BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT:
        type = BURN_VARIANT_TYPE_NUMERIC;
        break;
    }
    hr = BVariantChangeType(&value, type);
    ExitOnFailure(hr, "Failed to change value type.");

    // set variable
    hr = VariableSetVariant(pVariables, pSearch->sczVariable, &value, FALSE);
    ExitOnFailure(hr, "Failed to set variable.");

LExit:
    if (FAILED(hr))
    {
        LogStringLine(REPORT_STANDARD, "MsiProductSearch failed: ID '%ls', 
HRESULT 0x%x", pSearch->sczKey, hr);
    }

    ReleaseStr(sczProductCode);
    BVariantUninitialize(&value);

    return hr;
}

wiutil.cpp

extern "C" HRESULT DAPI WiuGetProductInfo(
    __in_z LPCWSTR wzProductCode,
    __in_z LPCWSTR wzProperty,
    __out LPWSTR* psczValue
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    DWORD cch = WIU_GOOD_ENOUGH_PROPERTY_LENGTH;

    hr = StrAlloc(psczValue, cch);
    ExitOnFailure(hr, "Failed to allocate string for product info.");

    er = vpfnMsiGetProductInfoW(wzProductCode, wzProperty, *psczValue, &cch);
    if (ERROR_MORE_DATA == er)
    {
        ++cch;
        hr = StrAlloc(psczValue, cch);
        ExitOnFailure(hr, "Failed to reallocate string for product info.");

        er = vpfnMsiGetProductInfoW(wzProductCode, wzProperty, *psczValue, 
&cch);
    }
    hr = HRESULT_FROM_WIN32(er);
    ExitOnFailure(hr, "Failed to get product info.");

LExit:
    return hr;
}


  When looking at the relevant documentation MsiGetProductInfo 
(http://msdn.microsoft.com/en-us/library/windows/desktop/aa370130(v=vs.85).aspx)
 and MsiGetProductInfoEx 
(http://msdn.microsoft.com/en-us/library/windows/desktop/aa370131(v=vs.85).aspx)
 , It seems to me that INSTALLPROPERTY_PRODUCTSTATE is only applicable when 
calling MsiGetProductInfoEx which the wrapper WiuGetProductInfo does not do. Is 
this a bug in Burn, or is Result="state" just not documented properly for its 
shortcomings on the burn side?

If it is intended to work, then is anyone aware of a current bug or feature 
request logged for it? (If not I can log one.)  I understand it would be a bit 
convoluted, as we would have to test for per user/machine contexts.

Thanks,
Jacob
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
WiX-users mailing list
WiX-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wix-users

Reply via email to