2025-11-28 00:35:46 +09:00

369 lines
9.4 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "stdafx.h"
#include "ComSpyCtl.h"
#include <comsvcs.h>
#include "SysLCESub.h"
#include "ComSpyAudit.h"
#include "CComSpy.h"
#include "MethodSub.h"
#include <strsafe.h>
extern LONGLONG PerformanceFrequency;
STDMETHODIMP CMethodSub::OnMethodCall(COMSVCSEVENTINFO * pInfo, ULONG64 oid,REFCLSID guidCid, REFIID guidRid, ULONG iMeth)
{
TimeStack * pStack = m_map[oid];
if (!pStack)
{
pStack = new TimeStack;
m_map[oid] = pStack;
}
_ASSERTE(pStack);
pStack->push_front(pInfo->perfCount);
m_pSpy->AddEventToList(pInfo->perfCount, L"OnMethodCall", GuidToBstr(pInfo->guidApp));
WCHAR id[32];
StringCchPrintfW(id,ARRAYSIZE(id),L"%#016I64X", oid);
m_pSpy->AddParamValueToList(L"ObjectID", id);
CComBSTR bstrCLSID = GuidToBstr(guidCid);
CComBSTR bstrIID = GuidToBstr(guidRid);
m_pSpy->AddParamValueToList(L"CLSID", bstrCLSID);
m_pSpy->AddParamValueToList(L"riid", bstrIID);
LPWSTR pwszGuidName = NULL;
HRESULT hr;
hr = GetMethodName(guidRid, iMeth, &pwszGuidName) ;
if(hr == S_OK)
{
m_pSpy->AddParamValueToList(L"Method Name", pwszGuidName);
}
else
{
static const size_t cchIndexMax = 8 + 1;
pwszGuidName = new WCHAR[cchIndexMax] ;
StringCchPrintf(pwszGuidName, cchIndexMax, L"%X", iMeth) ;
m_pSpy->AddParamValueToList(L"v-table index", pwszGuidName);
}
IF_AUDIT_DO(OnMethodCall)(pInfo->perfCount,
GuidToBstr(pInfo->guidApp),
id,
bstrCLSID,
bstrIID,
pwszGuidName);
delete [] pwszGuidName ;
pwszGuidName = NULL ;
return S_OK;
}
STDMETHODIMP CMethodSub::OnMethodReturn(COMSVCSEVENTINFO * pInfo,
ULONG64 oid,
REFCLSID guidCid,
REFIID guidRid,
ULONG iMeth,
HRESULT hrRet)
{
m_pSpy->AddEventToList(pInfo->perfCount, L"OnMethodReturn", GuidToBstr(pInfo->guidApp));
WCHAR id[32];
StringCchPrintfW(id,ARRAYSIZE(id),L"%#016I64X", oid);
m_pSpy->AddParamValueToList(L"ObjectID", id);
CComBSTR bstrCLSID = GuidToBstr(guidCid);
CComBSTR bstrIID = GuidToBstr(guidRid);
m_pSpy->AddParamValueToList(L"CLSID", bstrCLSID);
m_pSpy->AddParamValueToList(L"riid", bstrIID);
LPWSTR pwszGuidName = NULL ;
HRESULT hr;
hr = GetMethodName(guidRid, iMeth, &pwszGuidName) ;
if(hr != S_OK)
{
static const size_t cchIndexMax = 8 + 1;
pwszGuidName = new WCHAR[cchIndexMax] ;
StringCchPrintf(pwszGuidName, cchIndexMax,L"%X", iMeth) ;
m_pSpy->AddParamValueToList(L"v-table index", pwszGuidName);
}
else
{
m_pSpy->AddParamValueToList(L"Method Name", pwszGuidName);
}
WCHAR wcRet[16];
StringCchPrintfW(wcRet, ARRAYSIZE(wcRet), L"%#08X", hrRet);
m_pSpy->AddParamValueToList(L"Return Value", wcRet);
WCHAR sTime[16];
TimeStack * pStack = m_map[oid];
if (pStack)
{
LONGLONG oldTime = pStack->front();
pStack->pop_front();
_ASSERTE(oldTime);
DWORD timeDiff = (DWORD)((1000*(pInfo->perfCount-oldTime))/PerformanceFrequency);
StringCchPrintf(sTime, ARRAYSIZE(sTime),L"%d", timeDiff);
m_pSpy->AddParamValueToList(L"Call time (ms)", sTime);
}
IF_AUDIT_DO(OnMethodReturn)(pInfo->perfCount,
GuidToBstr(pInfo->guidApp),
id,
bstrCLSID,
bstrIID,
pwszGuidName,
hrRet,
sTime);
delete [] pwszGuidName ;
pwszGuidName = NULL ;
if (pStack && pStack->empty())
{
delete pStack;
m_map.erase(oid);
}
return S_OK;
}
STDMETHODIMP CMethodSub::OnMethodException(COMSVCSEVENTINFO * pInfo, ULONG64 oid,REFCLSID guidCid, REFIID guidRid, ULONG iMeth)
{
m_pSpy->AddEventToList(pInfo->perfCount, L"OnMethodException", GuidToBstr(pInfo->guidApp));
WCHAR id[32];
StringCchPrintfW(id, ARRAYSIZE(id), L"%#016I64X", oid);
m_pSpy->AddParamValueToList(L"ObjectID", id);
CComBSTR bstrCLSID = GuidToBstr(guidCid);
CComBSTR bstrIID = GuidToBstr(guidRid);
m_pSpy->AddParamValueToList(L"CLSID", bstrCLSID);
m_pSpy->AddParamValueToList(L"riid", bstrIID);
LPWSTR pwszGuidName = NULL ;
HRESULT hr;
hr = GetMethodName(guidRid, iMeth, &pwszGuidName) ;
if(hr != S_OK)
{
pwszGuidName = new WCHAR[64] ;
StringCchCopy(pwszGuidName, 64, L"Unknown (no TypeLibrary)");
}
m_pSpy->AddParamValueToList(L"Method Name", pwszGuidName);
IF_AUDIT_DO(OnMethodException)(pInfo->perfCount,
GuidToBstr(pInfo->guidApp),
id,
bstrCLSID,
bstrIID,
pwszGuidName);
delete [] pwszGuidName ;
pwszGuidName = NULL ;
return S_OK;
}
HRESULT CMethodSub::GetClsidOfTypeLib2 (IID * piid, UUID * puuidClsid)
{
LPWSTR pwszBuffIID = NULL;
HRESULT hr = S_OK;
WCHAR rgBufferIid [40];
WCHAR szBufferClsid[40];
RPC_STATUS RpcStatus;
WCHAR rgBufferKey [256];
long lRetVal;
HKEY hkey;
//-------------------------------------------------------------------------
//Convert the iid to it's string form
RpcStatus = UuidToString ( piid,(unsigned short **)&pwszBuffIID);
StringCchCopy(rgBufferIid, ARRAYSIZE(rgBufferIid), pwszBuffIID);
RpcStringFree ((unsigned short **)&pwszBuffIID);
//-------------------------------------------------------------------------
//Create the Registry key to do the lookup with
StringCchCopy(rgBufferKey, ARRAYSIZE(rgBufferKey), L"Interface\\{");
StringCchCat(rgBufferKey, ARRAYSIZE(rgBufferKey), rgBufferIid);
StringCchCat(rgBufferKey, ARRAYSIZE(rgBufferKey), L"}\\TypeLib");
//UNDONE -- gaganc Perhaps should handle the \interface\<iid1>\forward\<iid2|
//case also.
//-------------------------------------------------------------------------
//Open the appropriate registry key
//HKEY_CLASSES_ROOT\Interface\{<...interface iid ...>}\Typelib
lRetVal = RegOpenKey (
HKEY_CLASSES_ROOT,
rgBufferKey,
&hkey
);
if (lRetVal != ERROR_SUCCESS)
{
return E_FAIL;
}
//-------------------------------------------------------------------------
//Obain the clsid from the open key
DWORD cbBufferClsid = sizeof(szBufferClsid);
lRetVal = RegQueryValueEx (
hkey,
NULL,
NULL,
NULL,
(LPBYTE)szBufferClsid,
&cbBufferClsid
);
if(lRetVal != ERROR_SUCCESS)
{
RegCloseKey(hkey) ;
return E_FAIL ;
}
//-------------------------------------------------------------------------
//Get rid of the braces in the begining and the end.
//Remove the trailing brace
szBufferClsid[37] = '\0';
//convert the string form of the clsid to a binary form. Plus 1 will
//remove the first brace.
lRetVal = UuidFromString ((RPC_WSTR)(szBufferClsid + 1), puuidClsid);
if(lRetVal != ERROR_SUCCESS)
{
RegCloseKey(hkey) ;
return E_UNEXPECTED ;
}
//-------------------------------------------------------------------------
//Prepare to return
lRetVal = RegCloseKey (hkey);
return hr;
} //end GetClsidOfTypeLib
//----------------------------------------------------------------------------
// Function: GetMethodName (INTERNAL FUNCTION)
// Description: Takes an IID and a method index returns the corresponding
// method name.
//
// Exceptions: n/a
// Process:
// Notes: ppwszMethodName should be freed by the client using standard
// C++ delete. If hr != S_OK, ppwszMethodName will be set to
// NULL.
//----------------------------------------------------------------------------
HRESULT CMethodSub::GetMethodName (REFIID riid, int iMeth, LPWSTR* ppwszMethodName)
{
HRESULT hr;
UUID uuidClsid;
LCID lcid = 0x0;
ITypeLib * pITypeLib = NULL;
ITypeInfo * pITypeInfo = NULL;
FUNCDESC * pFuncDesc = 0x0;
LPWSTR pwszMethod = NULL;
BSTR bstrName ;
UINT lcNames = 0 ;
IID * piid = (IID *) &riid;
//Obtain the clsid of the typelib for this interface
hr = GetClsidOfTypeLib2 (piid, &uuidClsid);
if (hr != S_OK) goto errExit ;
//-------------------------------------------------------------------------
//Obtain the ITypeLib interface on the typelib
hr = LoadRegTypeLib (
uuidClsid, //CLSID
1, //Major version number
0, //Minor version number
0, //the locale id
&pITypeLib
);
// if the default system lcid (0) doesn't work, we try
// LCID 9 (standard english) and if that doesn't work, we failfast
if(FAILED(hr))
{
hr = LoadRegTypeLib (uuidClsid, 1,0,9,&pITypeLib);
}
if(FAILED(hr)) goto errExit ;
hr = pITypeLib->GetTypeInfoOfGuid (*piid, &pITypeInfo);
if(FAILED(hr)) goto errExit ;
hr = pITypeInfo->GetFuncDesc(iMeth, &pFuncDesc) ;
if(FAILED(hr)) goto errExit ;
hr = pITypeInfo->GetNames(pFuncDesc->memid, &bstrName, 1, &lcNames) ;
if(FAILED(hr)) goto errExit ;
pwszMethod = new WCHAR[lstrlen(bstrName)+1] ;
if(! pwszMethod)
{
hr = E_OUTOFMEMORY ;
goto errExit ;
}
StringCchCopy(pwszMethod, lstrlen(bstrName)+1, bstrName) ;
SysFreeString(bstrName) ;
errExit:
if (pFuncDesc)
{
pITypeInfo->ReleaseFuncDesc(pFuncDesc) ;
}
if (pITypeInfo)
{
pITypeInfo->Release();
}
if (pITypeLib)
{
pITypeLib->Release() ;
}
*ppwszMethodName = pwszMethod ;
return hr ;
}