Exemple #1
0
VOID
ConditionGetValue(
	IN PCONDITION_ENTRY Entry,
	OUT PWCHAR Buffer,
	IN ULONG Length 
	)
{
	switch (Entry->Type) {

		case ConditionDataUlong:
			_ultow_s(Entry->UlongValue, Buffer, Length, 16);
			break;

		case ConditionDataUlong64:
			_ui64tow_s(Entry->UlongValue, Buffer, Length, 16);
			break;

			//
			// N.B. double is encoded as string
			//

		case ConditionDataDouble:
		case ConditionDataString:
			StringCchCopy(Buffer, Length, Entry->StringValue);
			break;

		default:
			StringCchCopy(Buffer, Length, Entry->StringValue);
	}	

}
Exemple #2
0
/****************************
TemporaryManager::GetNextTemporaryName -- gets next temp name (_t1, etc.)
*****************************/
STRING *
TemporaryManager::GetNextTemporaryName
(
    Vtypes TemporaryVtype,
    LifetimeClass Lifetime
)
{
    if (TemporaryVtype >= 0 && TemporaryVtype < _countof(m_CountOfTemporariesOfVtype))
    {
        StringBuffer NameBuffer;
        WCHAR CharacterBuffer[32];  // VS Everett security bug #515087

        NameBuffer.AppendString(VBTemporaryPrefix);

        if (m_ExtraPrefix)
        {
            NameBuffer.AppendString(m_ExtraPrefix);
            NameBuffer.AppendChar(L'$');
        }

        NameBuffer.AppendString(s_wszVOfVtype[TemporaryVtype]);
        NameBuffer.AppendChar(L'$');
        NameBuffer.AppendChar(
            (Lifetime == LifetimeLongLived) ? L'L' : (Lifetime == LifetimeShortLived) ? L'S' : L'N');

        _ultow_s(m_CountOfTemporariesOfVtype[TemporaryVtype]++, CharacterBuffer, _countof(CharacterBuffer), 10);
        NameBuffer.AppendString(CharacterBuffer);

        return m_Compiler->AddString(&NameBuffer);
    }

    return NULL;
}
void CrashHandlerWindows::writeCrashDump(PEXCEPTION_POINTERS pointers) {
	
	WCHAR tick[24];
	if(!GetTempPath(boost::size(m_pCrashInfo->miniDumpTmpFile), m_pCrashInfo->miniDumpTmpFile)
		 || _ultow_s(GetTickCount(), tick, 10) || wcscat_s(m_pCrashInfo->miniDumpTmpFile, tick)
		 || wcscat_s(m_pCrashInfo->miniDumpTmpFile, L"-arx-crash.dmp")) {
		return;
	}
	
	HANDLE file = CreateFileW(m_pCrashInfo->miniDumpTmpFile, GENERIC_READ | GENERIC_WRITE,
	                          0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(file == INVALID_HANDLE_VALUE) {
		return;
	}
	
	MINIDUMP_TYPE miniDumpType = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory
	                                             | MiniDumpScanMemory);
	
	MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
	exceptionInfo.ThreadId = m_pCrashInfo->threadId;
	exceptionInfo.ExceptionPointers = pointers;
	exceptionInfo.ClientPointers = TRUE;

	// Write the minidump
	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file, miniDumpType,
	                  &exceptionInfo, NULL, NULL);
	
	CloseHandle(file);
	
}
Exemple #4
0
std::wstring ConvertCrcValueToString(ULONG crc) {
  wchar_t crc_val[16] = {0};
  _ultow_s(crc, crc_val, 16, 16);

  std::wstring value = crc_val;

  if (value.length() < 8)
    value.insert(0, 8 - value.length(), '0');

  ToUpper(value);

  return value;
}
Exemple #5
0
    void TypeSArray::ToString( std::wstring& str )
    {
        // we're using space for a ulong's digits, but we only need that for a uint
        const int UlongDigits = 20;
        wchar_t numStr[ UlongDigits + 1 ] = L"";
        errno_t err = 0;

        err = _ultow_s( Length, numStr, 10 );
        _ASSERT( err == 0 );

        Next->ToString( str );
        str.append( L"[" );
        str.append( numStr );
        str.append( L"]" );
    }
Exemple #6
0
bool _GetDescription(ISpObjectToken *p_token, WCHAR **r_description)
{
	typedef HRESULT (WINAPI *_RegLoadMUIStringWPtr)(HKEY, LPCWSTR, LPWSTR, DWORD, LPDWORD, DWORD, LPCWSTR);
	static HMODULE s_advapi32 = NULL;
	static _RegLoadMUIStringWPtr s_RegLoadMUIStringW = NULL;

	if (s_advapi32 == NULL)
	{
		// Attempt to load function RegLoadMUIStringW which should be available if we're running on Vista & later
        s_advapi32 = LoadLibraryA("advapi32.dll");
        if(s_advapi32 != NULL)
			s_RegLoadMUIStringW = (_RegLoadMUIStringWPtr)GetProcAddress(s_advapi32, "RegLoadMUIStringW");
	}

	bool t_success = true;

    if (r_description == NULL)
    {
        return false;
    }

	WCHAR *t_description = NULL;

    if(s_RegLoadMUIStringW != NULL)
    {
		WCHAR* t_path = NULL;
		WCHAR* t_reg_key = NULL;
		HKEY   t_hkey = NULL;

        t_success = SUCCEEDED(p_token->GetId(&t_reg_key));

        if (t_success)
        {
			// Split the path & base of the registry key - path is invalid if there is no separator
            t_path = wcschr(t_reg_key, L'\\');
			t_success = t_path != NULL;
		}
        if(t_success)
        {
            *t_path++ = L'\0';

            if (wcscmp(t_reg_key, L"HKEY_LOCAL_MACHINE") == 0)
				t_success = ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, t_path, 0, KEY_QUERY_VALUE, &t_hkey);
            else if (wcscmp(t_reg_key, L"HKEY_CURRENT_USER") == 0)
                t_success = ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, t_path, 0, KEY_QUERY_VALUE, &t_hkey);
            else
				t_success = false;
            
			DWORD t_size = 0;
            if (t_success)
				t_success = ERROR_MORE_DATA == s_RegLoadMUIStringW(t_hkey, L"Description", NULL, 0, &t_size, 0, NULL);
			if (t_success)
				t_success = NULL != (t_description = (WCHAR*) CoTaskMemAlloc(t_size));
			if (t_success)
                t_success = ERROR_SUCCESS == s_RegLoadMUIStringW(t_hkey, L"Description", t_description, t_size, NULL, 0, NULL);
        }

		// Cleanup
        if(t_hkey)
            RegCloseKey(t_hkey);
        if(t_reg_key)
            CoTaskMemFree(t_reg_key);

		if (!t_success && t_description != NULL)
		{
			CoTaskMemFree(t_description);
			t_description = NULL;
		}
    }

    // fetch from the registry - if all else fails, fallback to the default attribute
	if (s_RegLoadMUIStringW == NULL || !t_success)
    {
	    WCHAR t_lang_id[10];

		if (_ultow_s(GetUserDefaultUILanguage(), t_lang_id, 9, 16))
		{
			t_lang_id[0] = L'0';
			t_lang_id[1] = 0;
		}

		HRESULT hr;
        hr = p_token->GetStringValue(t_lang_id, &t_description);
        if (hr == SPERR_NOT_FOUND)
        {
            hr = p_token->GetStringValue(NULL, &t_description);
        }
		t_success = SUCCEEDED(hr);
    }

	if (t_success)
		*r_description = t_description;

    return t_success;
}
bool Cx_CfgRecord::SetUInt16(const wchar_t* pszEntry, WORD nValue)
{
    wchar_t szNum[35];
    _ultow_s(nValue, szNum, _countof(szNum), 10);
    return AddFieldValue(pszEntry, szNum);
}
Exemple #8
0
HRESULT ConfigParser::SetOutputFile(const WCHAR* outputFile, const WCHAR* openMode)
{
    // If present, replace the {PID} token with the process ID
    const WCHAR* pidStr = nullptr;
    WCHAR buffer[_MAX_PATH];
    if ((pidStr = wcsstr(outputFile, L"{PID}")) != nullptr)
    {
        size_t pidStartPosition = pidStr - outputFile;

        WCHAR* pDest = buffer;
        size_t bufferLen = _MAX_PATH;

        // Copy the filename before the {PID} token
        wcsncpy_s(pDest, bufferLen, outputFile, pidStartPosition);
        pDest += pidStartPosition;
        bufferLen = bufferLen - pidStartPosition;

        // Copy the PID
        _ultow_s(GetCurrentProcessId(), pDest, /*bufferSize=*/_MAX_PATH - pidStartPosition, /*radix=*/10);
#pragma prefast(suppress: 26014, "ultow string length is smaller than 256")
        pDest += wcslen(pDest);
        bufferLen = bufferLen - wcslen(pDest);

        // Copy the rest of the string.
#pragma prefast(suppress: 26014, "Overwriting pDset's null terminator is intentional since the string being copied is null terminated")
        wcscpy_s(pDest, bufferLen, outputFile + pidStartPosition + /*length of {PID}*/ 5);

        outputFile = buffer;
    }

    wchar_t fileName[_MAX_PATH];
    wchar_t moduleName[_MAX_PATH];
    GetModuleFileName(0, moduleName, _MAX_PATH);
    _wsplitpath_s(moduleName, nullptr, 0, nullptr, 0, fileName, _MAX_PATH, nullptr, 0);
    if (_wcsicmp(fileName, L"WWAHost") == 0 || _wcsicmp(fileName, L"ByteCodeGenerator") == 0 ||
        _wcsicmp(fileName, L"spartan") == 0 || _wcsicmp(fileName, L"spartan_edge") == 0 ||
        _wcsicmp(fileName, L"MicrosoftEdge") == 0 || _wcsicmp(fileName, L"MicrosoftEdgeCP") == 0)
    {

        // we need to output to %temp% directory in wwa. we don't have permission otherwise.
        if (GetEnvironmentVariable(L"temp", fileName, _MAX_PATH) != 0)
        {
            wcscat_s(fileName, _MAX_PATH, L"\\");
            const wchar_t * fileNameOnly = wcsrchr(outputFile, L'\\');
            // if outputFile is full path we just need filename, discard the path
            wcscat_s(fileName, _MAX_PATH, fileNameOnly == nullptr ? outputFile : fileNameOnly);
        }
        else
        {
            AssertMsg(FALSE, "Get temp environment failed");
        }
        outputFile = fileName;
    }

    FILE *fp;
    if ((fp = _wfsopen(outputFile, openMode, _SH_DENYWR)) != nullptr)
    {
        Output::SetOutputFile(fp);
        return S_OK;
    }

    AssertMsg(false, "Could not open file for logging output.");
    return E_FAIL;
}
Exemple #9
0
//*****************************************************************************
// Function:   ValueToString
// Purpose:    Takes a variant, returns a string representation of that variant
//*****************************************************************************
WCHAR *ValueToString(CIMTYPE dwType, VARIANT *pValue, WCHAR **pbuf, WCHAR *fnHandler(VARIANT *pv))
{
    DWORD iTotBufSize;

    WCHAR *vbuf = NULL;
    WCHAR *buf = NULL;

    WCHAR lbuf[BLOCKSIZE];

    switch (pValue->vt)
    {
        case VT_EMPTY:
        {
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, BLOCKSIZE, L"<empty>");
            }
            break;
        }

        case VT_NULL:
        {
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, BLOCKSIZE, L"<null>");
            }
            break;
        }

        case VT_BOOL:
        {
            VARIANT_BOOL b = pValue->boolVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                if (!b)
                {
                    StringCbCopyW(buf, BLOCKSIZE, L"FALSE");
                }
                else
                {
                    StringCbCopyW(buf, BLOCKSIZE, L"TRUE");
                }
            }
            break;
        }

        case VT_I1:
        {
            char b = pValue->bVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                if (b >= 32)
                {
                    StringCbPrintfW(buf, BLOCKSIZE, L"'%c' (%hd, 0x%hX)", b, (signed char)b, b);
                }
                else
                {
                    StringCbPrintfW(buf, BLOCKSIZE, L"%hd (0x%hX)", (signed char)b, b);
                }
            }
            break;
        }

        case VT_UI1:
        {
            unsigned char b = pValue->bVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                if (b >= 32)
                {
                    StringCbPrintfW(buf, BLOCKSIZE, L"'%c' (%hu, 0x%hX)", b, (unsigned char)b, b);
                }
                else
                {
                    StringCbPrintfW(buf, BLOCKSIZE, L"%hu (0x%hX)", (unsigned char)b, b);
                }
            }
            break;
        }

        case VT_I2:
        {
            SHORT i = pValue->iVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                StringCbPrintfW(buf, BLOCKSIZE, L"%hd (0x%hX)", i, i);
            }
            break;
        }

        case VT_UI2:
        {
            USHORT i = pValue->uiVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                StringCbPrintfW(buf, BLOCKSIZE, L"%hu (0x%hX)", i, i);
            }
            break;
        }

        case VT_I4:
        {
            LONG l = pValue->lVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                StringCbPrintfW(buf, BLOCKSIZE, L"%d (0x%X)", l, l);
            }
            break;
        }

        case VT_UI4:
        {
            ULONG l = pValue->ulVal;
            buf = (WCHAR *)malloc(BLOCKSIZE);
            if (buf)
            {
                StringCbPrintfW(buf, BLOCKSIZE, L"%u (0x%X)", l, l);
            }
            break;
        }

        case VT_R4:
        {
            float f = pValue->fltVal;
            buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR));
            if (buf)
            {
                StringCbPrintfW(buf, BLOCKSIZE,  L"%10.4f", f);
            }
            break;
        }

        case VT_R8:
        {
            double d = pValue->dblVal;
            buf = (WCHAR *)malloc(CVTBUFSIZE * sizeof(WCHAR));
            if (buf)
            {
                StringCbPrintfW(buf, BLOCKSIZE, L"%10.4f", d);
            }
            break;
        }

        case VT_BSTR:
        {
            if (dwType == CIM_SINT64)
            {
                // a little redundant, but it makes me feel better
                LPWSTR pWStr = pValue->bstrVal;
                __int64 l = _wtoi64(pWStr);

                buf = (WCHAR *)malloc(BLOCKSIZE);
                if (buf)
                {
                    StringCbPrintfW(buf, BLOCKSIZE, L"%I64d", l);
                }
            }
            else if (dwType == CIM_UINT64)
            {
                // a little redundant, but it makes me feel better
                LPWSTR pWStr = pValue->bstrVal;
                __int64 l = _wtoi64(pWStr);

                buf = (WCHAR *)malloc(BLOCKSIZE);
                if (buf)
                {
                    StringCbPrintfW(buf, BLOCKSIZE,  L"%I64u", l);
                }
            }
            else // string, datetime, reference
            {
                LPWSTR pWStr = pValue->bstrVal;
                buf = (WCHAR *)malloc((wcslen(pWStr) * sizeof(WCHAR)) + sizeof(WCHAR) + (2 * sizeof(WCHAR)));
                if (buf)
                {
                    StringCbPrintfW(buf, BLOCKSIZE,  L"\"%wS\"", pWStr);
                }
            }
            break;
        }

        case VT_BOOL|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
					StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf, (iUBound - iLBound + 1) * BLOCKSIZE, L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    VARIANT_BOOL v;
                    SafeArrayGetElement(pVec, &i, &v);
                    if (v)
                    {
                        StringCbCatW(buf, (iUBound - iLBound + 1) * BLOCKSIZE, L"TRUE");
                    }
                    else
                    {
                        StringCbCatW(buf, (iUBound - iLBound + 1) * BLOCKSIZE, L"FALSE");
                    }
                }
            }

            break;
        }

        case VT_I1|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
					StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            int bufSize = (iUBound - iLBound + 1) * BLOCKSIZE;
            buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
            if (buf)
            {

                StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");
                WCHAR *pos = buf;
                DWORD len;

                BYTE *pbstr;
                SafeArrayAccessData(pVec, (void HUGEP* FAR*)&pbstr);

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCopyW(pos, bufSize - (pos - buf) * sizeof(WCHAR), L",");
                        pos += 1;
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    char v;
                    //            SafeArrayGetElement(pVec, &i, &v);
                    v = pbstr[i];

                    if (v < 32)
                    {
                        len = StringCbPrintfW(lbuf, sizeof(lbuf), L"%hd (0x%X)", v, v);	
                    }
                    else
                    {
                        len = StringCbPrintfW(lbuf, sizeof(lbuf), L"'%c' %hd (0x%X)", v, v, v);
                    }
                    StringCbCopyW(pos, bufSize - (pos - buf)*sizeof(WCHAR), lbuf);
                    pos += len;
                }
            }

            SafeArrayUnaccessData(pVec);

            break;
        }

        case VT_UI1|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
					StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

			int bufsize = (iUBound - iLBound + 1) * BLOCKSIZE;
            buf = (WCHAR *)malloc(bufsize);
            if (buf)
            {
                StringCbCopyW(buf, bufsize, L"");
                WCHAR *pos = buf;
                DWORD len;

                BYTE *pbstr;
                SafeArrayAccessData(pVec, (void HUGEP* FAR*)&pbstr);

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCopyW(pos, bufsize - ((pos - buf)*sizeof(WCHAR)), L",");
                        pos += 1;
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    unsigned char v;
                    //            SafeArrayGetElement(pVec, &i, &v);
                    v = pbstr[i];

                    if (v < 32)
                    {
                        len = StringCbPrintfW(lbuf, sizeof(lbuf), L"%hu (0x%X)", v, v);
                    }
                    else
                    {
                        len = StringCbPrintfW(lbuf, sizeof(lbuf), L"'%c' %hu (0x%X)", v, v, v);
                    }

                    StringCbCopyW(pos, bufsize - ((pos - buf)*sizeof(WCHAR)), lbuf);
                    pos += len;
                }
            }

            SafeArrayUnaccessData(pVec);

            break;
        }

        case VT_I2|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
					StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    SHORT v;
                    SafeArrayGetElement(pVec, &i, &v);
                    StringCbPrintfW(lbuf, sizeof(lbuf), L"%hd", v);
                    StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), lbuf);
                }
            }

            break;
        }

        case VT_UI2|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
	                StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    USHORT v;
                    SafeArrayGetElement(pVec, &i, &v);
                    StringCbPrintfW(lbuf, sizeof(lbuf), L"%hu", v);
                    StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), lbuf);
                }
            }

            break;
        }

        case VT_I4|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
	                StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf,((iUBound - iLBound + 1) * BLOCKSIZE), L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    LONG v;
                    SafeArrayGetElement(pVec, &i, &v);
                    _ltow_s(v, lbuf, 10);
                    StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), lbuf);
                }
            }

            break;
        }

        case VT_UI4|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
	                StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
            if (buf)
            {
                StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    ULONG v;
                    SafeArrayGetElement(pVec, &i, &v);
                    _ultow_s(v, lbuf, 10);
                    StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), lbuf);
                }
            }

            break;
        }

        case CIM_REAL32|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
	                StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            int bufSize = (iUBound - iLBound + 1) * (CVTBUFSIZE * sizeof(WCHAR));
            buf = (WCHAR *)malloc(bufSize);
            if (buf)
            {
                StringCbCopyW(buf,  bufSize, L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf, bufSize, L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    FLOAT v;
                    SafeArrayGetElement(pVec, &i, &v);
                    StringCbPrintfW(lbuf, sizeof(lbuf), L"%10.4f", v);
                    StringCbCatW(buf, bufSize, lbuf);
                }
            }

            break;
        }

        case CIM_REAL64|VT_ARRAY:
        {
            SAFEARRAY *pVec = pValue->parray;
            long iLBound, iUBound;
            BOOL bFirst = TRUE;

            SafeArrayGetLBound(pVec, 1, &iLBound);
            SafeArrayGetUBound(pVec, 1, &iUBound);
            if ((iUBound - iLBound + 1) == 0)
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
				if (buf)
				{
	                StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
				}
                break;
            }

            int bufSize = (iUBound - iLBound + 1) * (CVTBUFSIZE * sizeof(WCHAR));
            buf = (WCHAR *)malloc(bufSize);
            if (buf)
            {
                StringCbCopyW(buf, bufSize, L"");

                for (long i = iLBound; i <= iUBound; i++)
                {
                    if (!bFirst)
                    {
                        StringCbCatW(buf, bufSize, L",");
                    }
                    else
                    {
                        bFirst = FALSE;
                    }

                    double v;
                    SafeArrayGetElement(pVec, &i, &v);
                    StringCbPrintfW(lbuf, sizeof(lbuf), L"%10.4f", v);
                    StringCbCatW(buf, bufSize, lbuf);
                }
            }

            break;
        }

        case VT_BSTR|VT_ARRAY:
        {
            if (dwType == (CIM_UINT64|VT_ARRAY))
            {
                SAFEARRAY *pVec = pValue->parray;
                long iLBound, iUBound;
                BOOL bFirst = TRUE;

                SafeArrayGetLBound(pVec, 1, &iLBound);
                SafeArrayGetUBound(pVec, 1, &iUBound);
                if ((iUBound - iLBound + 1) == 0)
                {
                    buf = (WCHAR *)malloc(BLOCKSIZE);
					if (buf)
					{
	                    StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
					}
                    break;
                }

                buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
                if (buf)
                {
                    StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                    for (long i = iLBound; i <= iUBound; i++)
                    {
                        if (!bFirst)
                        {
                            StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L",");
                        }
                        else
                        {
                            bFirst = FALSE;
                        }

                        BSTR v = NULL;

                        SafeArrayGetElement(pVec, &i, &v);

                        StringCbPrintfW(lbuf, sizeof(lbuf), L"%I64u", _wtoi64(v));
                        StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), lbuf);
                    }
                }
            }
            else if (dwType == (CIM_SINT64|VT_ARRAY))
            {
                SAFEARRAY *pVec = pValue->parray;
                long iLBound, iUBound;
                BOOL bFirst = TRUE;

                SafeArrayGetLBound(pVec, 1, &iLBound);
                SafeArrayGetUBound(pVec, 1, &iUBound);
                if ((iUBound - iLBound + 1) == 0)
                {
                    buf = (WCHAR *)malloc(BLOCKSIZE);
					if (buf)
					{
	                    StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
					}
                    break;
                }

                buf = (WCHAR *)malloc((iUBound - iLBound + 1) * BLOCKSIZE);
                if (buf)
                {
                    StringCbCopyW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L"");

                    for (long i = iLBound; i <= iUBound; i++)
                    {
                        if (!bFirst)
                        {
                            StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), L",");
                        }
                        else
                        {
                            bFirst = FALSE;
                        }

                        BSTR v = NULL;

                        SafeArrayGetElement(pVec, &i, &v);

                        StringCbPrintfW(lbuf, sizeof(lbuf), L"%I64d", _wtoi64(v));
                        StringCbCatW(buf, ((iUBound - iLBound + 1) * BLOCKSIZE), lbuf);
                    }
                }
            }
            else // string, datetime, reference
            {
                SAFEARRAY *pVec = pValue->parray;
                long iLBound, iUBound;
                DWORD iNeed;
                size_t iVSize;
                DWORD iCurBufSize;

                SafeArrayGetLBound(pVec, 1, &iLBound);
                SafeArrayGetUBound(pVec, 1, &iUBound);
                if ((iUBound - iLBound + 1) == 0)
                {
                    buf = (WCHAR *)malloc(BLOCKSIZE);
					if (buf)
					{
	                    StringCbCopyW(buf, BLOCKSIZE, L"<empty array>");
					}
                    break;
                }

                iTotBufSize = (iUBound - iLBound + 1) * BLOCKSIZE;
                buf = (WCHAR *)malloc(iTotBufSize);
                if (buf)
                {
                   
					buf[0] = L'\0';
                    iCurBufSize = 0;
                    iVSize = BLOCKSIZE;
                    vbuf = (WCHAR *)malloc(BLOCKSIZE);

                    if (vbuf)
                    {
                        size_t iLen;
						WCHAR *Buffer;
						WCHAR *Buff;
                        for (long i = iLBound; i <= iUBound; i++)
                        {
                           	BSTR v = NULL;
                            SafeArrayGetElement(pVec, &i, &v);
                            iLen = (SysStringLen(v) + 1) * sizeof(WCHAR);
                            if (iLen > iVSize)
                            {
                                Buffer = vbuf;
								vbuf = (WCHAR *)realloc(vbuf, iLen + sizeof(WCHAR));								
                                iVSize = iLen;
                            }

                            // String size + (quotes + comma + null)
							if (vbuf)
							{
								iNeed = (StringCbPrintfW(vbuf, iVSize, L"%wS", v) + 4) * sizeof(WCHAR);
								if (iNeed + iCurBufSize > iTotBufSize)
								{
									iTotBufSize += (iNeed * 2);  // Room enough for 2 more entries
									Buff = buf;
									buf = (WCHAR *)realloc(buf, iTotBufSize);									
								}
								if (buf)
								{
									StringCbCatW(buf, iTotBufSize, L"\"");
									StringCbCatW(buf, iTotBufSize, vbuf);
									if (i + 1 <= iUBound)
									{
										StringCbCatW(buf, iTotBufSize, L"\",");
									}
									else
									{
										StringCbCatW(buf, iTotBufSize, L"\"");
									}
									iCurBufSize += iNeed;
								}
								else
								{
									buf = Buff;
								}
							}
							else
							{
								vbuf = Buffer;
							}    
                            SysFreeString(v);
                        }
                        free(vbuf);
                    }
                }
            }

            break;
        }

        default:
        {
            if (fnHandler != NULL)
            {
                buf = fnHandler(pValue);
            }
            else
            {
                buf = (WCHAR *)malloc(BLOCKSIZE);
                if (buf)
                {
                    StringCbCopyW(buf, BLOCKSIZE, L"<conversion error>");
                }
            }
            break;
        }
   }

   if (!buf)
   {
       PrintErrorAndExit("ValueToString() out of memory", S_OK, 0);
   }

   *pbuf = buf;
   return buf;
}
	//add Id array to a document fragment node
	HRESULT AddIdsNode(
		    IXMLDOMDocument* pDOM, 
		    BSTR indentBstr,
		    const wchar_t* wszIdsNodeName, 
		    const wchar_t* wszIdsNodeAttribute,
		    const wchar_t* wszIdNode,
		    const std::vector<int>& ids, 
		    IXMLDOMDocumentFragment* pdf	// Release is completed outside
		)
	{
		VARIANT var;
		BSTR bstr = NULL;
		BSTR bstr_wst = SysAllocString(L"\t");
		IXMLDOMElement* pe = NULL;
		IXMLDOMDocumentFragment* pdfSub = NULL;
		IXMLDOMAttribute *pa = NULL;
		IXMLDOMAttribute *pa1 = NULL;

        HRESULT hr = S_OK;
		do
		{
			//create a Node to hold ids.
			bstr = SysAllocString(wszIdsNodeName);
			HR_SUCCESSCALL( pDOM->createElement(bstr, &pe), hr );
			SAFE_BSTR_RELEASE(bstr);

			//create a attribute for the <wszIdsNodeName> element, and
			//assign the element num as the attribute value.
			
			//get ids num string
			size_t idsNum = ids.size();
			const int radix = 10;
			const size_t sizeOfstr = 30;
			wchar_t wszIdsNumString[sizeOfstr] = {0};
			_ultow_s(static_cast<unsigned long>(idsNum), wszIdsNumString, sizeOfstr, radix);

			//put num string into attribute
			bstr = SysAllocString(wszIdsNodeAttribute);
			VariantInit(&var);
			V_BSTR(&var) = SysAllocString(wszIdsNumString);
			V_VT(&var) = VT_BSTR;

			HR_SUCCESSCALL( pDOM->createAttribute(bstr, &pa), hr );
			HR_SUCCESSCALL( pa->put_value(var), hr );
			HR_SUCCESSCALL( pe->setAttributeNode(pa, &pa1), hr );

			//create a document fragment to hold ids sub-elements.
			HR_SUCCESSCALL( pDOM->createDocumentFragment(&pdfSub), hr );

			//add ids to pdfSub
			for( size_t i=0; i < idsNum; ++i )
			{
				 int id = ids[i];
				 WCHAR wszIdString[sizeOfstr] = {0};
				 _itow_s(id, wszIdString, sizeOfstr, radix);

				 //add white space before <id>
				 HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr );
				 HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr );
				 HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, wszIdNode, wszIdString, pdfSub), hr );
			}

            //test whether it is successful in "add ids to pdfSub"
			HR_SUCCESSCALL( hr, hr );

			//add ids array to document fragment node
			HR_SUCCESSCALL( AppendChildToParent(pdfSub, pe), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pe), hr );
			HR_SUCCESSCALL( AppendChildToParent(pe, pdf), hr );
			
		}while(0);

        //release the com objects
		SAFE_COM_RELEASE(pa1);
		SAFE_COM_RELEASE(pa);
		SAFE_COM_RELEASE(pdfSub);
		SAFE_COM_RELEASE(pe);

		//release the bstr and variant
        SAFE_BSTR_RELEASE(bstr);
        SAFE_BSTR_RELEASE(bstr_wst);
        VariantClear(&var);

		return hr;
	}
int CMediaLibrary::GetExtendedFileInfo(const wchar_t *fn, const wchar_t *Metadata, wchar_t *dest, size_t destlen)
{

	bool FindTag;
	int RetCode;

	::EnterCriticalSection(&CriticalSection);

	if (std::wstring(fn) != FileName)
	{
		FindTag = GetTagInfo(fn);
	}
	else
	{
		FindTag = true;
	}

	if (FindTag) {
		wchar_t	Buff[MAX_MUSICTEXT];
		const char *MetaData = reinterpret_cast<const char*>(Metadata);

		if (_stricmp(MetaData, "length") == 0) {
			_ultow_s(TagDataW.Length, dest, destlen, 10);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "formatinformation") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Format.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "type") == 0) {
			Buff[0] = '0';
			Buff[1] = 0;
			wcsncpy_s(dest, destlen, Buff, _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "family") == 0) {
			wcsncpy_s(dest, destlen, L"The True Audio File", _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "lossless") == 0) {
			Buff[0] = '1';
			wcsncpy_s(dest, destlen, Buff, _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "title") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Title.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "artist") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Artist.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "albumartist") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.AlbumArtist.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "comment") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Comment.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "album") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Album.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "year") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Year.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "genre") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Genre.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "track") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Track.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "composer") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Composer.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "publisher") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Publisher.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "disc") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.Disc.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else if (_stricmp(MetaData, "bpm") == 0) {
			wcsncpy_s(dest, destlen, TagDataW.BPM.c_str(), _TRUNCATE);
			RetCode = 1;
		}
		else {
			RetCode = 0;
		}

	}
	else {
		FileName = L"";
		RetCode = 0;
	}

	::LeaveCriticalSection(&CriticalSection);
	return RetCode;
}