'(.Net )API Hooking: Why my implemented IEnumWbemClassObject->Next() hang at original Next
I want to hook native code to do some cool things:
var wql=new WqlObjectQuery(queryString);
using(var searcher =new ManagementObjectSearcher(scope,wql))
{
using(var records=searcher.Get())
{
**foreach(var record in records)** //This is where I want to hook
{
//do something
}
}
}
By digging into https://referencesource.microsoft.com/ , I find .Net send WQL string to WMINet_Util.dll ExecQueryWmi() . By using MS-Detours , I succeed in outputing passed-in WQL. To control the enumeration , I implemented my IEnumWbemClassObject & IWbemClassObject.
When ExecQueryWmi() is called , I redirect the pointer to pointer to refer to my IEnumWbemClassObject .
In implementation of IEnumWbemClassObject::Next , I also edirect the pointer to pointer to refer to my IWbemClassObject.
But the reality is ,my implemented IEnumWbemClassObject->Next() hang at original Next() , it never go to next line I can't figure out why . Could anyone help ?
Below is my code ******************************
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <stdio.h>
#include <strsafe.h>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <mutex>>
#include<fstream>
#include <Windows.h>
#include <comdef.h>
#include <WbemIdl.h>
#include <comdef.h>
#include <comutil.h>
#include "detours.h"
#include "ImpIEnumWbemClassObject.h"
#pragma comment(lib, "comsuppw.lib")
using namespace std;
std::mutex g_mutex;
static bool unloaded = false;
static LONG dwSlept = 0;
#pragma region Function Pre-definition
std::string WChar2Ansi(LPCWSTR pwszSrc);
std::wstring StringToWString(const std::string& s);
void WINAPI log(string& _str);
void WINAPI log(const char* log, DWORD _size);
#pragma endregion
#pragma region WMI
//forum.exetools.com/showthread.php?t=14432
//unknowncheats.me/forum/c-and-c/244372-changing-gpu-info-using-ms-detours-3-0-a.html
typedef HRESULT(__stdcall* PWMINet_Util_ExecQueryWmi) ( BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppIEnumWbemClassObject,DWORD authLevel,DWORD impLevel,IWbemServices* pCurrentNamespace,BSTR strUser,BSTR strPassword,BSTR strAuthority);
PWMINet_Util_ExecQueryWmi TrueExecQueryWmi = NULL;
HRESULT(__stdcall MyExecQueryWmi) (BSTR strQueryLanguage, BSTR strQuery, long lFlags,
IWbemContext* pCtx, IEnumWbemClassObject** ppIEnumWbemClassObject, DWORD authLevel,
DWORD impLevel, IWbemServices* pCurrentNamespace, BSTR strUser,
BSTR strPassword, BSTR strAuthority)
{
if (TrueExecQueryWmi==NULL)
{
log("NO TrueExecQueryWmi()",32);
return WBEM_E_FAILED;
}
log((string("\r\n WMI MyExecQueryWmi() is called. language =") + _com_util::ConvertBSTRToString(strQueryLanguage) + " strQuery =" + _com_util::ConvertBSTRToString(strQuery) + "\r\n").c_str(), 256);
HRESULT result=TrueExecQueryWmi(strQueryLanguage,strQuery,lFlags,pCtx,ppIEnumWbemClassObject,authLevel,impLevel,pCurrentNamespace,strUser,strPassword,strAuthority);
if (string(_com_util::ConvertBSTRToString(strQuery)).find("MSFT_PhysicalDisk")!=string::npos)
{
log("\r\MSFT_PhysicalDisk found\r\n",64);
ImpIEnumWbemClassObject* myImpIEnumWbemClassObject=new ImpIEnumWbemClassObject(*ppIEnumWbemClassObject);
(*ppIEnumWbemClassObject) = myImpIEnumWbemClassObject;
log("\r\MSFT_PhysicalDisk redirected\r\n", 64);
}
return result;
}
#pragma endregion
void split(const std::string& s,
std::vector<std::string>& sv,
const char delim = ' ') {
sv.clear();
std::istringstream iss(s);
std::string temp;
while (std::getline(iss, temp, delim)) {
sv.emplace_back(std::move(temp));
}
return;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
LONG error=0;
HMODULE hMod=NULL;
string str;
if (DetourIsHelperProcess()) {
return TRUE;
}
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
str = string("\r\nlast error when DLL_PROCESS_ATTACH starts=") + to_string(GetLastError()) + "\r\n";
log(str.c_str(), str.length());
LoadLibraryA("c:\\windows\\system32\\wbem\\fastprox.dll");
LoadLibraryA("C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\WMINet_Utils.dll");
DetourRestoreAfterWith();
log("simple" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
" Starting.\n",128);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
log("aaaaaaaaaaaaa \n",32);
//DetourAttach(&(PVOID&)TrueSleepEx, TimedSleepEx
if (GetModuleHandleA("fastprox.dll")==NULL)
{
char exe[MAX_PATH];
GetModuleFileNameA(NULL,exe,MAX_PATH);
log((string("NO fastprox.dll loaded by ")+exe).c_str(),MAX_PATH);
}
else
{
if (GetModuleHandleA("WMINet_Utils.dll") == NULL)
{
char exe[MAX_PATH];
GetModuleFileNameA(NULL, exe, MAX_PATH);
log((string("NO WMINet_Utils.dll loaded by ") + exe).c_str(), MAX_PATH);
}
else
{
TrueExecQueryWmi = (PWMINet_Util_ExecQueryWmi)DetourFindFunction("WMINet_Utils.dll", "ExecQueryWmi");
if (TrueExecQueryWmi==NULL)
{
log("NO ExecQueryWmi found in WMINet_Utils.dll",128);
}
else {
DetourAttach(&(PVOID&)TrueExecQueryWmi, (LPBYTE)MyExecQueryWmi);
}
}
//DetourAttach(&(PVOID&)TrueGetTickCount, MyTickCount);
error = DetourTransactionCommit();
log("bbbbbbbbbbbb \n",32);
if (error == NO_ERROR) {
log("simple" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
"Detoured() Succeed.\n",128);
}
else {
string s_err = string("simple") + DETOURS_STRINGIFY(DETOURS_BITS) + ".dll Error with DetourAttach() " + std::to_string(error);
log(s_err);
}
str = string("\r\nDetour attachment is DONE. last error when DLL_PROCESS_ATTACH ends=") + to_string(GetLastError()) + "\r\n";
log(str.c_str(), str.length());
SetLastError(0);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
log("\r\n DLL_PROCESS_DETACH is called ,reason is ",64);
if (lpReserved==NULL)
{
log("loaded unsuccessfully or reference count==0 \r\n",128);
fflush(stdout);
log("loaded unsuccessfully or reference count==0 \r\n",128);
}
else {
log("process is terminating",64);
fflush(stdout);
log("process is terminating",64);
}
if (!unloaded)
{
unloaded = true;
log("DLL_PROCESS_DETACH 1st \r\n",32);
fflush(stdout);
return TRUE;
}
{
log("DLL_PROCESS_DETACH again \r\n",32);
fflush(stdout);
return TRUE;
}
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (TrueExecQueryWmi!=NULL)
{
DetourDetach(&(PVOID&)TrueExecQueryWmi, (LPBYTE)MyExecQueryWmi);
}
error = DetourTransactionCommit();
log("simple" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:"
" Removed SleepEx() (result=%d), slept %d ticks.\r\n", dwSlept);
fflush(stdout);
break;
}
SetLastError(0);
return TRUE;
}
void WINAPI log(string& _str)
{
log(_str.c_str(),_str.length());
}
void WINAPI log(const char* log, DWORD _size)
{
g_mutex.lock();
BOOL bErrorFlag = FALSE;
DWORD dwBytesWritten = 0;
HANDLE hfile = NULL;
ofstream fout;
ifstream fin;
fin.open(logPath);
fout.open(logPath, ios::app);
if (fin.is_open())
fout << log;
fin.close();
fout.close();
g_mutex.unlock();
}
//wstring to string
std::string WChar2Ansi(LPCWSTR pwszSrc)
{
int nLen = WideCharToMultiByte(CP_ACP,0,pwszSrc,-1,NULL,0,NULL,NULL);
if (nLen<=0)
{
log("Fail in WChar2Ansi()",32);
return std::string("");
}
char* pszDst = new char[nLen];
if (NULL==pszDst)
{
log("Fail in WChar2Ansi()", 32);
return std::string("");
}
WideCharToMultiByte(CP_ACP,0,pwszSrc,-1,pszDst,nLen,NULL,NULL);
pszDst[nLen-1] = 0;
std::string strTemp(pszDst);
delete[] pszDst;
return strTemp;
}
//string o wstring
std::wstring StringToWString(const std::string& s)
{
std::wstring wszStr;
int nLength = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, NULL, NULL);
wszStr.resize(nLength);
LPWSTR lpwszStr = new wchar_t[nLength];
MultiByteToWideChar(CP_ACP,0,s.c_str(),-1,lpwszStr,nLength);
wszStr = lpwszStr;
delete[] lpwszStr;
return wszStr;
}
//my implemented IWbemClassObject.cpp
#include "stdafx.h"
#include <stdio.h>
#include <strsafe.h>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include<fstream>
#include <mutex>>
#include <comdef.h>
#include <comutil.h>
#include "ImpIWbemClassObject.h"
using namespace std;
std::mutex g_mutex3;
const WCHAR* logPath3 = L"D:\\practice_demos\\DetourPratice\\x64\\Debug\\logWbemClassObject.txt";
void WINAPI log3(const char* log, DWORD _size);
ImpIWbemClassObject::ImpIWbemClassObject(IWbemClassObject* _realIWbemClassObject)
{
log3("\r\n ImpIWbemClassObject->ImpIWbemClassObject() ", 128);
_pIWbemClassObject = _realIWbemClassObject;
}
ImpIWbemClassObject::~ImpIWbemClassObject()
{
log3("\r\n ~ImpIWbemClassObject() ", 128);
}
#pragma region implementation of IUnkown
ULONG ImpIWbemClassObject::AddRef()
{
log3("\r\n ImpIWbemClassObject->AddRef() ", 128);
return _pIWbemClassObject->AddRef();
}
HRESULT ImpIWbemClassObject::QueryInterface(
REFIID riid,
void** ppvObject
)
{
log3("\r\n ImpIWbemClassObject->QueryInterface() ", 128);
(*ppvObject)=this;
return 1;
}
ULONG ImpIWbemClassObject::Release()
{
log3("\r\n ImpIWbemClassObject->Rlease() ", 128);
return _pIWbemClassObject->Release();
}
#pragma endregion
#pragma region below implementation
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetQualifierSet(
/* [out] */ IWbemQualifierSet** ppQualSet)
{
log3("\r\n ImpIWbemClassObject->GetQualifierSet() ", 128);
return _pIWbemClassObject->GetQualifierSet(ppQualSet);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::Get(
/* [string][in] */ LPCWSTR wszName,
/* [in] */ long lFlags,
/* [unique][in][out] */ VARIANT* pVal,
/* [unique][in][out] */ CIMTYPE* pType,
/* [unique][in][out] */ long* plFlavor)
{
log3("\r\n ImpIWbemClassObject->Get() ", 128);
return _pIWbemClassObject->Get(wszName,lFlags,pVal,pType,plFlavor);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::Put(
/* [string][in] */ LPCWSTR wszName,
/* [in] */ long lFlags,
/* [in] */ VARIANT* pVal,
/* [in] */ CIMTYPE Type)
{
log3("\r\n ImpIWbemClassObject->Put() ", 128);
return _pIWbemClassObject->Put(wszName,lFlags,pVal,Type);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::Delete(
/* [string][in] */ LPCWSTR wszName)
{
log3("\r\n ImpIWbemClassObject->Delete() ", 128);
return _pIWbemClassObject->Delete(wszName);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetNames(
/* [string][in] */ LPCWSTR wszQualifierName,
/* [in] */ long lFlags,
/* [in] */ VARIANT* pQualifierVal,
/* [out] */ SAFEARRAY** pNames)
{
log3("\r\n ImpIWbemClassObject->GetNames() ", 128);
return _pIWbemClassObject->GetNames(wszQualifierName,lFlags,pQualifierVal,pNames);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::BeginEnumeration(
/* [in] */ long lEnumFlags)
{
log3("\r\n ImpIWbemClassObject->BeginEnumeration() ", 128);
return _pIWbemClassObject->BeginEnumeration(lEnumFlags);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::EndEnumeration()
{
log3("\r\n ImpIWbemClassObject->EndEnumeration() ", 128);
return _pIWbemClassObject->EndEnumeration();
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetPropertyQualifierSet(
/* [string][in] */ LPCWSTR wszProperty,
/* [out] */ IWbemQualifierSet** ppQualSet)
{
log3("\r\n ImpIWbemClassObject->GetPropertyQualifierSet() ", 128);
return _pIWbemClassObject->GetPropertyQualifierSet(wszProperty,ppQualSet);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::Clone(
/* [out] */ IWbemClassObject** ppCopy)
{
log3("\r\n ImpIWbemClassObject->Clone() ", 128);
return _pIWbemClassObject->Clone(ppCopy);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetObjectText(
/* [in] */ long lFlags,
/* [out] */ BSTR* pstrObjectText)
{
log3("\r\n ImpIWbemClassObject->GetObjectText() ", 128);
return _pIWbemClassObject->GetObjectText(lFlags,pstrObjectText);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::SpawnDerivedClass(
/* [in] */ long lFlags,
/* [out] */ IWbemClassObject** ppNewClass)
{
log3("\r\n ImpIWbemClassObject->SpawnDerivedClass() ", 128);
return _pIWbemClassObject->SpawnDerivedClass(lFlags, ppNewClass);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::SpawnInstance(
/* [in] */ long lFlags,
/* [out] */ IWbemClassObject** ppNewInstance)
{
log3("\r\n ImpIWbemClassObject->SpawnInstance() ", 128);
return _pIWbemClassObject->SpawnInstance(lFlags,ppNewInstance);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::CompareTo(
/* [in] */ long lFlags,
/* [in] */ IWbemClassObject* pCompareTo)
{
return _pIWbemClassObject->CompareTo(lFlags,pCompareTo);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetPropertyOrigin(
/* [string][in] */ LPCWSTR wszName,
/* [out] */ BSTR* pstrClassName)
{
log3("\r\n ImpIWbemClassObject->GetPropertyOrigin() ", 128);
return _pIWbemClassObject->GetPropertyOrigin(wszName,pstrClassName);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::InheritsFrom(
/* [in] */ LPCWSTR strAncestor)
{
return _pIWbemClassObject->InheritsFrom(strAncestor);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetMethod(
/* [string][in] */ LPCWSTR wszName,
/* [in] */ long lFlags,
/* [out] */ IWbemClassObject** ppInSignature,
/* [out] */ IWbemClassObject** ppOutSignature)
{
log3("\r\n ImpIWbemClassObject->GetMethod() ", 128);
return _pIWbemClassObject->GetMethod(wszName,lFlags,ppInSignature,ppOutSignature) ;
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::PutMethod(
/* [string][in] */ LPCWSTR wszName,
/* [in] */ long lFlags,
/* [in] */ IWbemClassObject* pInSignature,
/* [in] */ IWbemClassObject* pOutSignature)
{
return _pIWbemClassObject->PutMethod(wszName,lFlags,pInSignature,pOutSignature);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::DeleteMethod(
/* [string][in] */ LPCWSTR wszName)
{
return _pIWbemClassObject->DeleteMethod(wszName);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::BeginMethodEnumeration(
/* [in] */ long lEnumFlags)
{
log3("\r\n ImpIWbemClassObject->BeginMethodEnumeration() ", 128);
return _pIWbemClassObject->BeginMethodEnumeration(lEnumFlags);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::Next(
/* [in] */ long lFlags,
/* [unique][in][out] */ BSTR* strName,
/* [unique][in][out] */ VARIANT* pVal,
/* [unique][in][out] */ CIMTYPE* pType,
/* [unique][in][out] */ long* plFlavor)
{
log3("\r\nBefore ImpIWbemClassObject->Next\r\n",64);
HRESULT result = _pIWbemClassObject->Next(lFlags,strName,pVal,pType,plFlavor);
string propertyName = string(_com_util::ConvertBSTRToString(*strName));
if ((*pVal).vt == VT_BSTR)
{
_bstr_t bs_a(*pVal);
log3((string("\r\n ImpIWbemClassObject->Next() , propertyName = ") + propertyName + " value = " + static_cast<const char*>(bs_a) + "\r\n").c_str(), 256);
}
else
{
log3((string("\r\n ImpIWbemClassObject->Next() , propertyName = ") + propertyName).c_str() , 128);
}
log3("\r\nAfter ImpIWbemClassObject->Next\r\n", 64);
return 1;
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::NextMethod(
/* [in] */ long lFlags,
/* [unique][in][out] */ BSTR* pstrName,
/* [unique][in][out] */ IWbemClassObject** ppInSignature,
/* [unique][in][out] */ IWbemClassObject** ppOutSignature)
{
log3("\r\n ImpIWbemClassObject->NextMethod() ", 128);
return _pIWbemClassObject->NextMethod(lFlags,pstrName,ppInSignature,ppOutSignature);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::EndMethodEnumeration(void)
{
return _pIWbemClassObject->EndMethodEnumeration();
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetMethodQualifierSet(
/* [string][in] */ LPCWSTR wszMethod,
/* [out] */ IWbemQualifierSet** ppQualSet)
{
log3("\r\n ImpIWbemClassObject->GetMethodQualifierSet() ", 128);
return _pIWbemClassObject->GetMethodQualifierSet(wszMethod,ppQualSet);
}
HRESULT STDMETHODCALLTYPE ImpIWbemClassObject::GetMethodOrigin(
/* [string][in] */ LPCWSTR wszMethodName,
/* [out] */ BSTR* pstrClassName)
{
log3("\r\n ImpIWbemClassObject->GetMethodOrigin() ", 128);
return _pIWbemClassObject->GetMethodOrigin(wszMethodName,pstrClassName);
}
#pragma endregion
void WINAPI log3(const char* log, DWORD _size)
{
g_mutex3.lock();
BOOL bErrorFlag = FALSE;
DWORD dwBytesWritten = 0;
HANDLE hfile = NULL;
ofstream fout;
ifstream fin;
fin.open(logPath3);
fout.open(logPath3, ios::app);
if (fin.is_open())
fout << log;
fin.close();
fout.close();
g_mutex3.unlock();
}
//my implemented IEnumWbelClassObject.cpp
#include "stdafx.h"
#include <stdio.h>
#include <strsafe.h>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include<fstream>
#include <mutex>>
#include <comdef.h>
#include <comutil.h>
#include "ImpIEnumWbemClassObject.h"
#include "ImpIWbemClassObject.h"
#include <atlconv.h>
using namespace std;
std::mutex g_mutex2;
const WCHAR* logPath2 = L"D:\\practice_demos\\DetourPratice\\x64\\Debug\\logIEnum.txt";
void WINAPI log2(const char* log, DWORD _size);
ImpIEnumWbemClassObject::ImpIEnumWbemClassObject(IEnumWbemClassObject* _realIEnumWbemClassObject)
{
_pIEnumWbemClassObject = _realIEnumWbemClassObject;
}
ImpIEnumWbemClassObject::~ImpIEnumWbemClassObject()
{
log2("\r\nBefore ~ImpIEnumWbemClassObject\r\n", 64);
}
ULONG ImpIEnumWbemClassObject::AddRef()
{
log2("\r\nBefore ImpIEnumWbemClassObject::AddRef\r\n", 64);
return _pIEnumWbemClassObject->AddRef();
}
HRESULT ImpIEnumWbemClassObject::QueryInterface(
REFIID riid,
void** ppvObject
)
{
log2("\r\nBefore ImpIEnumWbemClassObject::QueryInterface\r\n", 64);
LPWSTR pwsz;
HRESULT sfiid = StringFromIID(riid, &pwsz);
if (sfiid==E_OUTOFMEMORY)
{
log2("NO memeory to contain Interface name",128);
}
char riidname[256] = "";
wcstombs(riidname, pwsz,256);
log2((string("ImpIEnumWbemClassObject::QueryInterface() ")+ riidname+"\r\n").c_str(), 256);
if (riid==IID_IUnknown)
{
(*ppvObject) = this;
return 1;
}
(*ppvObject)=this;
return 1;
}
ULONG ImpIEnumWbemClassObject::Release()
{
log2("\r\nBefore ImpIEnumWbemClassObject::Release\r\n", 64);
return _pIEnumWbemClassObject->Release();
}
HRESULT ImpIEnumWbemClassObject::Clone(
IEnumWbemClassObject** ppEnum
)
{
log2("\r\nBefore ImpIEnumWbemClassObject::Clone\r\n", 64);
return _pIEnumWbemClassObject->Clone(ppEnum);
}
HRESULT ImpIEnumWbemClassObject::Next(
long lTimeout,
ULONG uCount,
IWbemClassObject** apObjects,
ULONG* puReturned
)
{
log2("\r\nBefore ImpIEnumWbemClassObject::Next\r\n", 64);
HRESULT result= _pIEnumWbemClassObject->Next(lTimeout,uCount,apObjects,puReturned);
log2("\r\Never go here , hang !!! ImpIEnumWbemClassObject::Next is done\r\n", 64); //**It never go here**
const void* pAddress = static_cast<const void*>((*apObjects));
stringstream ss;
ss << pAddress;
log2((string("\r\n original address is ")+ss.str()+"\r\n").c_str(), 64);
ImpIWbemClassObject* impIWbemClassObject=new ImpIWbemClassObject(*apObjects);
(*apObjects) = impIWbemClassObject;
pAddress = static_cast<const void*>((*apObjects));
stringstream ss2;
ss2 << pAddress;
log2((string("\r\n updated address is ") + ss2.str() + "\r\n").c_str(), 64);
log2("\r\After ImpIEnumWbemClassObject::Next\r\n", 64);
return result;
}
HRESULT ImpIEnumWbemClassObject::NextAsync(
ULONG uCount,
IWbemObjectSink* pSink
)
{
log2("\r\nBefore ImpIEnumWbemClassObject::NextAsync\r\n", 64);
return _pIEnumWbemClassObject->NextAsync(uCount,pSink);
}
HRESULT ImpIEnumWbemClassObject::Reset()
{
return _pIEnumWbemClassObject->Reset();
}
HRESULT ImpIEnumWbemClassObject::Skip(
long lTimeout,
ULONG nCount
)
{
return _pIEnumWbemClassObject->Skip(lTimeout,nCount);
}
void WINAPI log2(const char* log, DWORD _size)
{
g_mutex2.lock();
BOOL bErrorFlag = FALSE;
DWORD dwBytesWritten = 0;
HANDLE hfile = NULL;
ofstream fout;
ifstream fin;
fin.open(logPath2);
fout.open(logPath2, ios::app);
if (fin.is_open())
fout << log;
fin.close();
fout.close();
g_mutex2.unlock();
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|