Esempio n. 1
0
/********************************************************************
StrAnsiAllocFormattedArgs - allocates or reuses dynamic ANSI string memory
and formats it with the passed in args

NOTE: caller is responsible for freeing ppsz even if function fails
********************************************************************/
extern "C" HRESULT DAPI StrAnsiAllocFormattedArgs(
	__inout LPSTR* ppsz,
	__in LPCSTR szFormat,
	__in va_list args
	)
{
	Assert(ppsz && szFormat && *szFormat);

	HRESULT hr = S_OK;
	DWORD_PTR cch = *ppsz ? MemSize(*ppsz) / sizeof(CHAR) : 0;
	LPSTR pszOriginal = NULL;
	DWORD cchOriginal = 0;

	if (*ppsz)
	{
		cch = MemSize(*ppsz);  // 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(CHAR);  //convert the count in bytes to count in characters

		cchOriginal = lstrlenA(*ppsz);
	}

	if (0 == cch)   // if there is no space in the string buffer
	{
		cch = 256;
		hr = StrAnsiAlloc(ppsz, cch);
		ExitOnFailure1(hr, "failed to allocate string to format: %s", szFormat);
	}

	// format the message (grow until it fits or there is a failure)
	do
	{
		hr = StringCchVPrintfA(*ppsz, cch, szFormat, args);
		if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
		{
			if (!pszOriginal)
			{
				// this allows you to pass the original string as a formatting argument and not crash
				// save the original string and free it after the printf is complete
				pszOriginal = *ppsz;
				*ppsz = NULL;
				// StringCchVPrintfW starts writing to the string...
				// NOTE: this hack only works with sprintf(&pwz, "%s ...", pwz, ...);
				pszOriginal[cchOriginal] = 0;
			}
			cch *= 2;
			hr = StrAnsiAlloc(ppsz, cch);
			ExitOnFailure1(hr, "failed to allocate string to format: %S", szFormat);
			hr = S_FALSE;
		}
	} while (S_FALSE == hr);
	ExitOnFailure(hr, "failed to format string");

LExit:
	ReleaseStr((void*) pszOriginal);
	return hr;
}
Esempio n. 2
0
/********************************************************************
 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;
}