(.Net )API Hooking: Why my implemented IEnumWbemClassObject->Next() hang at original Next - hook

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();
}

Related

How to use openssl to do a anonymous DH connection

Hi I am new to working with openssl, i am trying to implement anonymous Diffie Hellman connection using openssl.
The code server code looks some thing like this:
#include "openssl/err.h"
#include "openssl/ssl.h"
#include "openssl/dh.h"
#include <arpa/inet.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <resolv.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define FAIL -1
// Create the SSL socket and intialize the socket address structure
int OpenListener(int port) {
int sd;
struct sockaddr_in addr;
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port");
abort();
}
if (listen(sd, 10) != 0) {
perror("Can't configure listening port");
abort();
}
return sd;
}
int isRoot() {
if (getuid() != 0) {
return 0;
} else {
return 1;
}
}
SSL_CTX *InitServerCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
DH *dh_;
int codes = 0;
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
method = TLSv1_2_server_method(); /* create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
abort();
}
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA256") != 1) {
ERR_print_errors_fp(stderr);
abort();
}
dh_ = DH_new();
if (dh_ == NULL) {
printf ("Alloc for dh failed\n");
ERR_print_errors_fp(stderr);
abort();
}
// Generate Parameters.
if (!DH_generate_parameters_ex (dh_, 1024, DH_GENERATOR_5, NULL)) {
printf ("Generate Parameters failed!!\n");
ERR_print_errors_fp(stderr);
abort();
ERR_print_errors_fp(stderr);
}
// Check if p and g parameters are safe to use.
if (!DH_check (dh_, &codes)) {
printf ("Cannot perform DH check\n");
ERR_print_errors_fp(stderr);
abort();
}
if (codes) {
printf ("DH codes: %x\n", codes);
ERR_print_errors_fp(stderr);
abort();
}
if (!DH_generate_key (dh_)) {
printf ("Failure in DH Generate key\n");
ERR_print_errors_fp(stderr);
abort();
}
SSL_CTX_set_tmp_dh(ctx, dh_);
DH_free(dh_);
return ctx;
}
void Servlet(SSL *ssl) /* Serve the connection -- threadable */
{
char buf[1024] = {0};
int sd, bytes;
const char *ServerResponse = "<\Body>\
<Name>aticleworld.com</Name>\
<year>1.5</year>\
<BlogType>Embedede and c\c++<\BlogType>\
<Author>amlendra<Author>\
<\Body>";
const char *cpValidMessage = "<Body>\
<UserName>aticle<UserName>\
<Password>123<Password>\
<\Body>";
if (SSL_accept(ssl) == FAIL) /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
else {
//ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
buf[bytes] = '\0';
printf("Client msg: \"%s\"\n", buf);
if (bytes > 0) {
if (strcmp(cpValidMessage, buf) == 0) {
SSL_write(ssl, ServerResponse, strlen(ServerResponse)); /* send reply */
} else {
SSL_write(ssl, "Invalid Message",
strlen("Invalid Message")); /* send reply */
}
} else {
ERR_print_errors_fp(stderr);
}
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
int main(int count, char *Argc[]) {
SSL_CTX *ctx;
int server;
char *portnum;
// Only root user have the permsion to run the server
if (!isRoot()) {
printf("This program must be run as root/sudo user!!");
exit(0);
}
if (count != 2) {
printf("Usage: %s <portnum>\n", Argc[0]);
exit(0);
}
// Initialize the SSL library
SSL_library_init();
portnum = Argc[1];
ctx = InitServerCTX(); /* initialize SSL */
server = OpenListener(atoi(portnum)); /* create server socket */
while (1) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
int client = accept(server, (struct sockaddr *)&addr,
&len); /* accept connection as usual */
printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
Servlet(ssl); /* service connection */
}
close(server); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}
The client program looks like this:
#include <errno.h>
#include <malloc.h>
#include <netdb.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/dh.h>
#include <resolv.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define FAIL -1
int OpenConnection(const char *hostname, int port) {
int sd;
struct hostent *host;
struct sockaddr_in addr;
if ((host = gethostbyname(hostname)) == NULL) {
perror(hostname);
abort();
}
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long *)(host->h_addr);
printf ("Connecting....\n");
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
close(sd);
perror(hostname);
abort();
} else {
printf ("Connected...\n");
}
return sd;
}
SSL_CTX *InitCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
DH *dh_;
int codes = 0;
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */
method = TLSv1_2_client_method(); /* Create new client-method instance */
ctx = SSL_CTX_new(method); /* Create new context */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
abort();
}
if (SSL_CTX_set_cipher_list(ctx, "ADH-AES256-SHA256") != 1) {
printf("SSL_CTX_set_cipher_list failed\n");
SSL_CTX_free (ctx);
ctx = NULL;
ERR_print_errors_fp(stderr);
abort();
}
dh_ = DH_new();
if (dh_ == NULL) {
printf ("Alloc for dh failed\n");
}
// Generate Parameters.
if (!DH_generate_parameters_ex (dh_, 1024, DH_GENERATOR_5, NULL)) {
printf ("Generate Parameters failed!!\n");
}
// Check if p and g parameters are safe to use.
if (!DH_check (dh_, &codes)) {
printf ("Cannot perform DH check\n");
}
if (codes) {
printf ("DH codes: %x\n", codes);
}
if (!DH_generate_key (dh_)) {
printf ("Failure in DH Generate key\n");
//retVal = false;
//break;
}
SSL_CTX_set_tmp_dh(ctx, dh_);
DH_free(dh_);
return ctx;
}
void ShowCerts(SSL *ssl) {
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if (cert != NULL) {
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line); /* free the malloc'ed string */
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line); /* free the malloc'ed string */
X509_free(cert); /* free the malloc'ed certificate copy */
} else
printf("Info: No client certificates configured.\n");
}
int main(int count, char *strings[]) {
SSL_CTX *ctx;
int server;
SSL *ssl;
char buf[1024];
char acClientRequest[1024] = {0};
int bytes;
char *hostname, *portnum;
if (count != 3) {
printf("usage: %s <hostname> <portnum>\n", strings[0]);
exit(0);
}
SSL_library_init();
hostname = strings[1];
portnum = strings[2];
ctx = InitCTX();
server = OpenConnection(hostname, atoi(portnum));
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
printf ("Before connect\n");
if (SSL_connect(ssl) == FAIL) /* perform the connection */
ERR_print_errors_fp(stderr);
else {
char acUsername[16] = {0};
char acPassword[16] = {0};
const char *cpRequestMessage = "<Body>\
<UserName>%s<UserName>\
<Password>%s<Password>\
<\Body>";
printf("Enter the User Name : ");
scanf("%s", acUsername);
printf("\n\nEnter the Password : ");
scanf("%s", acPassword);
sprintf(acClientRequest, cpRequestMessage, acUsername,
acPassword); /* construct reply */
printf("\n\nConnected with %s encryption\n", SSL_get_cipher(ssl));
ShowCerts(ssl); /* get any certs */
SSL_write(ssl, acClientRequest,
strlen(acClientRequest)); /* encrypt & send message */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
buf[bytes] = 0;
printf("Received: \"%s\"\n", buf);
SSL_free(ssl); /* release connection state */
}
close(server); /* close socket */
SSL_CTX_free(ctx); /* release context */
return 0;
}
When i compile and execute this code i get the following error:
server side:
140093403805344:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure:s3_pkt.c:996:
client side error:
140134052299200:error:141640B5:SSL routines:tls_construct_client_hello:no ciphers available:../ssl/statem/statem_clnt.c:800:
Can any help me out on how to establish a connection with Anonymous DH?

WCHAR* not compatible with "LPSTR" parameter. In wsprintf C++

Can't compile the following code in C++ with Visual Studio 2017 (Got it from: Source Code):
#include <Wincodec.h> // we use WIC for saving images
#include <d3d9.h> // DirectX 9 header
#pragma comment(lib, "d3d9.lib") // link to DirectX 9 library
#include <stdio.h>
#include <Windows.h>
#include <wchar.h>
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFILE__ WIDEN(__FILE__)
#define HRCHECK(__expr) {hr=(__expr);if(FAILED(hr)){wprintf(L"FAILURE 0x%08X (%i)\n\tline: %u file: '%s'\n\texpr: '" WIDEN(#__expr) L"'\n",hr, hr, __LINE__,__WFILE__);goto cleanup;}}
#define RELEASE(__p) {if(__p!=nullptr){__p->Release();__p=nullptr;}}
HRESULT SavePixelsToFile32bppPBGRA(UINT width, UINT height, UINT stride, LPBYTE pixels, LPWSTR filePath, const GUID &format)
{
if (!filePath || !pixels)
return E_INVALIDARG;
HRESULT hr = S_OK;
IWICImagingFactory *factory = nullptr;
IWICBitmapEncoder *encoder = nullptr;
IWICBitmapFrameEncode *frame = nullptr;
IWICStream *stream = nullptr;
GUID pf = GUID_WICPixelFormat32bppPBGRA;
BOOL coInit = CoInitialize(nullptr);
HRCHECK(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)));
HRCHECK(factory->CreateStream(&stream));
HRCHECK(stream->InitializeFromFilename(filePath, GENERIC_WRITE));
HRCHECK(factory->CreateEncoder(format, nullptr, &encoder));
HRCHECK(encoder->Initialize(stream, WICBitmapEncoderNoCache));
HRCHECK(encoder->CreateNewFrame(&frame, nullptr)); // we don't use options here
HRCHECK(frame->Initialize(nullptr)); // we dont' use any options here
HRCHECK(frame->SetSize(width, height));
HRCHECK(frame->SetPixelFormat(&pf));
HRCHECK(frame->WritePixels(height, stride, stride * height, pixels));
HRCHECK(frame->Commit());
HRCHECK(encoder->Commit());
cleanup:
RELEASE(stream);
RELEASE(frame);
RELEASE(encoder);
RELEASE(factory);
if (coInit) CoUninitialize();
return hr;
}
HRESULT Direct3D9TakeScreenshots(UINT adapter, UINT count)
{
HRESULT hr = S_OK;
IDirect3D9 *d3d = nullptr;
IDirect3DDevice9 *device = nullptr;
IDirect3DSurface9 *surface = nullptr;
D3DPRESENT_PARAMETERS parameters = { 0 };
D3DDISPLAYMODE mode;
D3DLOCKED_RECT rc;
UINT pitch;
SYSTEMTIME st;
LPBYTE *shots = nullptr;
// init D3D and get screen size
d3d = Direct3DCreate9(D3D_SDK_VERSION);
HRCHECK(d3d->GetAdapterDisplayMode(adapter, &mode));
parameters.Windowed = TRUE;
parameters.BackBufferCount = 1;
parameters.BackBufferHeight = mode.Height;
parameters.BackBufferWidth = mode.Width;
parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
parameters.hDeviceWindow = NULL;
// create device & capture surface
HRCHECK(d3d->CreateDevice(adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &parameters, &device));
HRCHECK(device->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, nullptr));
// compute the required buffer size
HRCHECK(surface->LockRect(&rc, NULL, 0));
pitch = rc.Pitch;
HRCHECK(surface->UnlockRect());
// allocate screenshots buffers
shots = new LPBYTE[count];
for (UINT i = 0; i < count; i++)
{
shots[i] = new BYTE[pitch * mode.Height];
}
GetSystemTime(&st); // measure the time we spend doing <count> captures
wprintf(L"%i:%i:%i.%i\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
for (UINT i = 0; i < count; i++)
{
// get the data
HRCHECK(device->GetFrontBufferData(0, surface));
// copy it into our buffers
HRCHECK(surface->LockRect(&rc, NULL, 0));
CopyMemory(shots[i], rc.pBits, rc.Pitch * mode.Height);
HRCHECK(surface->UnlockRect());
}
GetSystemTime(&st);
wprintf(L"%i:%i:%i.%i\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
// save all screenshots
for (UINT i = 0; i < count; i++)
{
WCHAR file[100];
wsprintf(file, L"cap%i.png", i);
HRCHECK(SavePixelsToFile32bppPBGRA(mode.Width, mode.Height, pitch, shots[i], file, GUID_ContainerFormatPng));
}
cleanup:
if (shots != nullptr)
{
for (UINT i = 0; i < count; i++)
{
delete shots[i];
}
delete[] shots;
}
RELEASE(surface);
RELEASE(device);
RELEASE(d3d);
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = Direct3D9TakeScreenshots(D3DADAPTER_DEFAULT, 10);
return 0;
}
Gives error at:
// save all screenshots
for (UINT i = 0; i < count; i++)
{
WCHAR file[100];
wsprintf(file, L"cap%i.png", i);
HRCHECK(SavePixelsToFile32bppPBGRA(mode.Width, mode.Height, pitch, shots[i], file, GUID_ContainerFormatPng));
}
Where:
"WCHAR file[100]" is not compatible with "LSPTR" on wsprintf.
L"cap%i.png" (const wchar_t) is not compatible with LPCSTR on wsprintf.
And in:
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = Direct3D9TakeScreenshots(D3DADAPTER_DEFAULT, 10);
return 0;
}
Where _TCHAR is not defined.
¡I'm new to C++ so please give me some hints!

work with parallel port interrupt

I am working on parallel port driver. Now i had seen the methods to get interrupt from parallel port.
by one of them,
First make 4th pin of control reg 1(IRQ).
then make nACK low.
so i make a switch in between data pin 8 and nACK. so, if i write some data which has msb 1 then it will be interrupted, if that switch is on. Now i have a problem. If i disconnected that switch and again connect then it will not give me interrupt.
So, how can i do that thing by which i got interrupt by means of switch is connect or not.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/parport.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <asm/irq.h>
#include <linux/kthread.h>
#define DEVICE_NAME "parlelport"
struct pardevice *pdev;
static int dummy;
int ret;
static irqreturn_t recv_handler(int irq, void *dev_id)
{
printk("we inside if isr");
return 0;
}
int led_open(struct inode *inode, struct file *file)
{
printk("1\n");
printk("Device File Opened\n");
char byte1;
byte1=inb(0x37A);
printk("%d \n",byte1);
return 0;
}
ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
printk("2\n");
char byte=inb(0x37A);
printk("%d",byte);
byte = byte | 0x10; // 0x10= 00010000, 4th pin of CTRL reg
outb(byte, 0x37A); //which enable IRQ
char kbuf;
copy_from_user(&kbuf, buf, 1);
parport_claim_or_block(pdev); /* Claim the port */
parport_write_data(pdev->port, kbuf); /* Write to the device */
//parport_release (pdev);
return count;
}
int led_release(struct inode *inode, struct file *file)
{
printk("3\n");
printk("Device File Released\n");
char byte;
byte=inb(0x37A);
printk("%d", byte);
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int led_preempt(void *handle)
{
printk("4\n");
return 1;
}
static void led_attach(struct parport *port)
{
printk("5\n");
pdev = parport_register_device(port, DEVICE_NAME, led_preempt, NULL, NULL, 0, NULL);
printk("Port attached\n");
char byte1;
byte1=inb(0x37A);
printk("%d \n",byte1);
}
static void led_detach(struct parport *port)
{
printk("6\n");
parport_unregister_device (pdev);
printk("Port Deattached\n");
}
static struct parport_driver led_driver = {
.name= "led",
.attach = led_attach,
.detach = led_detach,
};
int __init led_init(void)
{
printk("7\n");
if (register_chrdev(89, DEVICE_NAME, &led_fops))
{
printk("Can't register device\n");
return -1;
}
char byte=inb(0x37A);
printk("%d",byte);
byte = byte | 0x10;
outb(byte, 0x37A);
char byte1;
byte1=inb(0x37A);
printk("%d %d \n",byte,byte1);
parport_register_driver(&led_driver);
ret= request_irq(7, recv_handler, IRQF_SHARED, "parlelport", &dummy);
printk("%d",ret);
return 0;
}
void __exit led_cleanup(void)
{
printk("8\n");
unregister_chrdev(89, DEVICE_NAME);
if(!ret)
free_irq(7, &dummy);
parport_unregister_driver(&led_driver);
printk("LED Driver unregistered.\n");
return;
}
module_init(led_init);
module_exit(led_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vikrant Patel");
Test.c file
int main()
{
int fd=open("/dev/parlelport",O_RDWR);
char byte;
printf("Enter Value to send on parallel port");
scanf("%c",&byte);
printf("Byte value is %c\n",byte);
if(write(fd,&byte,sizeof(char)))
{
printf("\nSuccessfully written on port");
}
getchar();
getchar();
close(fd);
}
I got it.
First make a thread
put the Enable IRQ code in that thread
so it will continuously execute it
whenever i connect pins at my hardware then it will be interrupted.
check this code for your ref.
#include <linux/module.h>
#include <linux/parport.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#define DEVICE_NAME "parlelport"
#define DATA 0x378
#define STATUS 0x379
#define CONTROL 0x37A
struct pardevice *pdev;
struct task_struct *ts1, *ts2;
int dummy;
char buf1='1',buf2='2';
char byte='0';
int thread1(void *data)
{
while(1)
{
outb(byte, CONTROL); /* 0x30 = 0011 0000 , makes IRQ pin(5th bit) enable */
printk("Thread1\n");
parport_claim_or_block(pdev); /* Claim the port */
parport_write_data(pdev->port, buf1); /* Write to the device */
parport_release(pdev); /* Release the port */
msleep(4000);
if (kthread_should_stop())
break;
}
return 0;
}
int thread2(void *data)
{
while(1)
{
outb(byte,CONTROL); /* 0x30 = 0011 0000 , makes IRQ pin(5th bit) enable */
printk("Thread2\n");
parport_claim_or_block(pdev); /* Claim the port */
parport_write_data(pdev->port, buf2); /* Write to the device */
parport_release(pdev); /* Release the port */
msleep(4000);
if (kthread_should_stop())
break;
}
return 0;
}
int led_open(struct inode *inode, struct file *file)
{
printk("Device File Opened\n");
ts1=kthread_run(thread1,NULL,"kthread"); /* Initiation of thread 1 */
msleep(2000);
ts2=kthread_run(thread2,NULL,"kthread"); /* Initiation of thread 2 */
return 0;
}
ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
return count;
}
int led_release(struct inode *inode, struct file *file)
{
printk("Device File Released\n");
kthread_stop(ts1);
kthread_stop(ts2);
buf1='1';
buf2='2';
outb_p(0x00,DATA);
return 0;
}
static irqreturn_t recv_handler(int irq, void *unused)
{
printk("we inside of isr");
buf1= buf1 ^ 0x7F;
buf2= buf2 ^ 0x7F;
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int led_preempt(void *handle)
{
return 1;
}
static void led_attach(struct parport *port)
{
pdev = parport_register_device(port, DEVICE_NAME, led_preempt, NULL, NULL, 0, NULL);
printk("Port attached\n");
}
static void led_detach(struct parport *port)
{
parport_unregister_device (pdev);
printk("Port Deattached\n");
}
static struct parport_driver led_driver = {
.name= "led",
.attach = led_attach,
.detach = led_detach,
};
int __init led_init(void)
{
/*Register our ISR with the kernel for PARALLEL_IRQ */
if (request_irq(7, recv_handler, IRQF_SHARED, DEVICE_NAME ,&dummy))
{
printk("Registering ISR failed\n");
return -ENODEV;
}
/*Register Character Device Driver at 89 Major number*/
if (register_chrdev(89, DEVICE_NAME, &led_fops))
{
printk("Can't register device\n");
return -1;
}
/*Register parallel port driver with parport structure led_driver*/
parport_register_driver(&led_driver);
return 0;
}
void __exit led_cleanup(void)
{
unregister_chrdev(89, DEVICE_NAME); /* Unregister char driver */
free_irq(7, &dummy); /* Free the ISR from IRQ7 */
parport_unregister_driver(&led_driver); /* Unregister the parallel port driver */
printk("LED Driver unregistered.\n");
return;
}
module_init(led_init);
module_exit(led_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vikrant Patel");

Using callback function in a directshow filter cause memory leaks

I am using third party API which I get streams from a callback function
int OnNewImage(BYTE *pData, int nLen)
When I run a simple C++ sample program from console
int continue = 1;
int OnNewImage(BYTE *pData, int nLen)
{
std::cout << "On new image is called" << std::endl;
return continue;
}
int main()
{
// This will block
int result = DownloadStream(/*params*/...,OnNewImage /*callbackfunction*/);
return 0;
}
I get no memory leaks.[ memory does not increase ]
But When I use this callback function in a directshow filter, it
produce memory leaks.[ memory increase regularly]
What may cause this? And how can I fix it? Any ideas?
UPDATE: My DirectShow Filter structure
What I do:
Basically
I get streams at "unsigned __stdcall DVRStreamThread(LPVOID
pvParam)" function which call back OnNewImage
Then i insert frames into my queue inside that callback[OnNewImage]
Finally At FillBuffer I consume frames from queue.
It is am h264 stream. I can able to set simple graph like this
MySourceFilter ---> H264 Decoder ---> Video Renderer
Here is my FilterSourceCode:
Well I have a simple queue which i insert incoming frames then consume:
SynchronisedQueue
template <typename T>
class SynchronisedQueue
{
public:
void Enqueue(const T& data)
{
boost::unique_lock<boost::mutex> lock(queueMutex);
dataQueue.push(data);
conditionVariable.notify_one();
}
T Dequeue()
{
boost::unique_lock<boost::mutex> lock(queueMutex);
while (dataQueue.size()==0)
{
conditionVariable.wait(lock);
}
T result=dataQueue.front(); dataQueue.pop();
return result;
}
int Size()
{
boost::unique_lock<boost::mutex> lock(queueMutex);
int size = dataQueue.size();
return size;
}
private:
std::queue<T> dataQueue;
boost::mutex queueMutex;
boost::condition_variable conditionVariable;
};
Then My Filter:
DvrSourceFilter [ header]
#define DVRSourceFilterName L"DVRDirectShowFilter"
#include <streams.h>
#include <process.h>
#include <MyDvrApi.h>
#include "SynchronisedQueue.h"
// {F89A85DA-F77C-4d44-893B-CCA43A49E7EF}
DEFINE_GUID(CLSID_DVRSourceFilter,
0xf89a85da, 0xf77c, 0x4d44, 0x89, 0x3b, 0xcc, 0xa4, 0x3a, 0x49, 0xe7, 0xef);
class DECLSPEC_UUID("34363248-0000-0010-8000-00AA00389B71") Subtype_H264;
class DVRSourceFilter;
using namespace std;
/*
* **********************
* DVRPin
* **********************
*/
class DVRPin : public CSourceStream
{
public:
DVRPin(HRESULT *phr, DVRSourceFilter *pFilter);
~DVRPin();
// Override the version that offers exactly one media type
HRESULT GetMediaType(CMediaType *pMediaType);
HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest);
HRESULT FillBuffer(IMediaSample *pSample);
static int OnNewImage(void *pUser, BYTE *pData, int nLen, int nCh, int tMts, int nType, void *returnHandle);
// Setters
void SetDvrIp(char* dvrIp);
void SetDvrPort( int dvrPort);
void SetDvrUserName( char * userName);
void SetDvrPassword(char* password);
void SetStartTime(int startTime);
void SetMilliSecond(int milliSecond);
void SetChannelNumber(int channelNumber);
void SetSize(int width, int height);
// Getters
char* GetDvrIp();
int GetDvrPort();
char* GetDvrUserName();
char* GetDvrPassword();
int GetStartTime();
int GetMilliSecond();
int GetChannelNumber();
int GetMode();
public:
char* dvrIp;
int dvrPort;
char* userName;
char* password;
int startTime;
int milliSecond;
int channelNumber;
BITMAPINFOHEADER m_bmpInfo;
BYTE* m_RGB24Buffer;
DWORD m_RGB24BufferSize;
bool streamCompleted;
int hDecHandle;
HANDLE m_hDVRStreamThreadHandle;
unsigned int m_dwThreadID;
SynchronisedQueue<std::vector<BYTE>> IncomingFramesQueue;
protected:
virtual HRESULT OnThreadCreate();
virtual HRESULT OnThreadDestroy();
virtual HRESULT DoBufferProcessingLoop();
};
/*
* **********************
* DVRSourceFilter
* *********************
*
*/
class DVRSourceFilter : public CSource
{
public:
DECLARE_IUNKNOWN;
static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
void SetDVRLiveParameters(char* dvrIP, int dvrPort, char* userName, char* password, int channelNumber, int width, int height);
private:
DVRSourceFilter(IUnknown *pUnk, HRESULT *phr);
~DVRSourceFilter();
private:
DVRPin *m_pPin;
};
DvrSourceFilter [implementation]
#include "DvrSourceFilter.h"
unsigned __stdcall DVRStreamThread(LPVOID pvParam)
{
DVRPin* streamReader = (DVRPin*)pvParam;
int channelBits = 1 << (streamReader->channelNumber - 1);
streamReader->m_RGB24BufferSize = streamReader->m_bmpInfo.biWidth * streamReader->m_bmpInfo.biHeight * 3;
streamReader->m_RGB24Buffer = (BYTE*)malloc(streamReader->m_RGB24BufferSize);
DownloadStream((LPCTSTR)streamReader->dvrIp,
streamReader->dvrPort , (LPCTSTR)streamReader->userName ,
(LPCTSTR)streamReader->password , channelBits, channelBits,
streamReader->startTime, streamReader->milliSecond,
streamReader->OnNewImage, (void*)streamReader);
streamReader->startTime = -2; // End Of Stream
return 0;
}
/*
* ******************
* DVRPin Class
* ******************
*/
DVRPin::DVRPin(HRESULT *phr, DVRSourceFilter *pFilter)
: CSourceStream(NAME("DVR Source Bitmap"), phr, pFilter, L"Out")
{
m_bmpInfo.biSize = sizeof(BITMAPINFOHEADER);
m_bmpInfo.biCompression = BI_RGB;
m_bmpInfo.biBitCount = 24;
m_bmpInfo.biPlanes = 1;
m_bmpInfo.biClrImportant = 0;
m_bmpInfo.biClrUsed = 0;
m_bmpInfo.biXPelsPerMeter = 0;
m_bmpInfo.biYPelsPerMeter = 0;
hDecHandle = 0;
m_RGB24Buffer = NULL;
m_RGB24BufferSize = 0;
streamCompleted = false;
startTime = -1; // Live Stream
*phr = S_OK;
}
DVRPin::~DVRPin()
{
}
int DVRPin::OnNewImage(void *pUser, BYTE *pData, int nLen, int nCh, int tMts, int nType, void *returnHandle)
{
DVRPin* reader = (DVRPin*)pUser;
if(reader->streamCompleted)
{
return false;
}
if(pData)
{
std::vector<BYTE> vecFrame(pData, pData + nLen/sizeof(pData[0]));
reader->IncomingFramesQueue.Enqueue(vecFrame);
}
return !reader->streamCompleted;
}
HRESULT DVRPin::OnThreadCreate()
{
m_hDVRStreamThreadHandle =
(HANDLE)_beginthreadex(NULL, 0, &DVRStreamThread, (void*)this, 0, &m_dwThreadID);
return S_OK;
}
HRESULT DVRPin::OnThreadDestroy() {
streamCompleted = true;
_endthreadex(0);
CloseHandle(m_hDVRStreamThreadHandle);
return S_OK;
}
HRESULT DVRPin::GetMediaType(CMediaType *pMediaType)
{
CAutoLock cAutoLock(m_pFilter->pStateLock());
CheckPointer(pMediaType, E_POINTER);
VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
if (pvi == 0)
return(E_OUTOFMEMORY);
ZeroMemory(pvi, pMediaType->cbFormat);
pvi->bmiHeader = m_bmpInfo;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
SetRectEmpty(&(pvi->rcSource));
SetRectEmpty(&(pvi->rcTarget));
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);
// Work out the GUID for the subtype from the header info.
const GUID SubTypeGUID = __uuidof(Subtype_H264);//GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);
return S_OK;
}
HRESULT DVRPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)
{
HRESULT hr;
CAutoLock cAutoLock(m_pFilter->pStateLock());
CheckPointer(pAlloc, E_POINTER);
CheckPointer(pRequest, E_POINTER);
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*) m_mt.Format();
if (pRequest->cBuffers == 0)
{
pRequest->cBuffers = 2;
}
pRequest->cbBuffer = pvi->bmiHeader.biSizeImage;
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pRequest, &Actual);
if (FAILED(hr))
{
return hr;
}
if (Actual.cbBuffer < pRequest->cbBuffer)
{
return E_FAIL;
}
return S_OK;
}
HRESULT DVRPin::FillBuffer(IMediaSample *pSample)
{
if(!streamCompleted)
{
CAutoLock cAutoLock(m_pLock);
HRESULT hr;
BYTE* pData = NULL;
hr = pSample->GetPointer(&pData);
if(FAILED(hr))
{
pSample->Release();
return hr;
}
if(IncomingFramesQueue.Size() <= 0) {
return S_OK;
}
vector<BYTE> data = IncomingFramesQueue.Dequeue();
int dataSize = (int)data.size();
if(dataSize <= 0 || dataSize > 1000000)
{
return S_OK;
}
memcpy(pData, &data[0], dataSize);
hr = pSample->SetActualDataLength(dataSize);
if(FAILED(hr))
{
pSample->Release();
return hr;
}
hr = pSample->SetSyncPoint(TRUE);
if(FAILED(hr))
{
pSample->Release();
return hr;
}
pSample->Release();
}
return S_OK;
}
HRESULT DVRPin::DoBufferProcessingLoop() {
Command com;
REFERENCE_TIME rtNow = 0L;
REFERENCE_TIME rtAdvise = 0L;
OnThreadStartPlay();
do {
while (!streamCompleted && !CheckRequest(&com)) {
IncomingFramesQueue.WaitUntilHaveElements();
IMediaSample *pSample;
HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,FALSE);
if (FAILED(hr)) {
continue; // go round again. Perhaps the error will go away
// or the allocator is decommited & we will be asked to
// exit soon.
}
hr = FillBuffer(pSample);
if (hr == S_OK) {
Deliver(pSample);
} else if (hr == S_FALSE) {
pSample->Release();
DeliverEndOfStream();
return S_FALSE;
} else {
// Log Error
}
pSample->Release();
}
if (com == CMD_RUN || com == CMD_PAUSE)
com = GetRequest(); // throw command away
else if (com != CMD_STOP)
{
// Log Error
}
} while (!streamCompleted && com != CMD_STOP);
return S_OK;
}
void DVRPin::SetDvrIp( char* dvrIp )
{
this->dvrIp = dvrIp;
}
void DVRPin::SetDvrPort( int dvrPort )
{
this->dvrPort = dvrPort;
}
void DVRPin::SetDvrUserName( char * userName )
{
this->userName = userName;
}
void DVRPin::SetDvrPassword( char* password )
{
this->password = password;
}
void DVRPin::SetStartTime( int startTime )
{
this->startTime = startTime;
}
void DVRPin::SetMilliSecond( int milliSecond )
{
this->milliSecond = milliSecond;
}
void DVRPin::SetSize(int width, int height) {
m_bmpInfo.biWidth = width;
m_bmpInfo.biHeight = height;
m_bmpInfo.biSizeImage = GetBitmapSize(&m_bmpInfo);
}
char* DVRPin::GetDvrIp()
{
return dvrIp;
}
int DVRPin::GetDvrPort()
{
return dvrPort;
}
char* DVRPin::GetDvrUserName()
{
return userName;
}
char* DVRPin::GetDvrPassword()
{
return password;
}
int DVRPin::GetStartTime()
{
return startTime;
}
int DVRPin::GetMilliSecond()
{
return milliSecond;
}
void DVRPin::SetChannelNumber( int channelNumber )
{
this->channelNumber = channelNumber;
}
int DVRPin::GetChannelNumber()
{
return channelNumber;
}
/*
* ****************************
* DVRSourceFilter Class
* ***************************
*/
DVRSourceFilter::DVRSourceFilter(IUnknown *pUnk, HRESULT *phr)
: CSource(NAME("DVRSourceBitmap"), pUnk, CLSID_DVRSourceFilter)
{
// The pin magically adds itself to our pin array.
m_pPin = new DVRPin(phr, this);
// Just for test at graph studio
SetDVRLiveParameters("192.168.3.151", 7000, "admin", "000000", 3, 352, 288);
if (phr)
{
if (m_pPin == NULL)
*phr = E_OUTOFMEMORY;
else
*phr = S_OK;
}
}
DVRSourceFilter::~DVRSourceFilter()
{
delete m_pPin;
}
CUnknown * WINAPI DVRSourceFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr)
{
DVRSourceFilter *pNewFilter = new DVRSourceFilter(pUnk, phr);
if (phr)
{
if (pNewFilter == NULL)
*phr = E_OUTOFMEMORY;
else
*phr = S_OK;
}
return pNewFilter;
}
STDMETHODIMP DVRSourceFilter::NonDelegatingQueryInterface( REFIID riid, void **ppv )
{
return CSource::NonDelegatingQueryInterface(riid, ppv);
}
void DVRSourceFilter::SetDVRLiveParameters( char* dvrIP, int dvrPort, char* userName, char* password, int channelNumber, int width, int height )
{
m_pPin->SetDvrIp(dvrIP);
m_pPin->SetDvrPort(dvrPort);
m_pPin->SetDvrUserName(userName);
m_pPin->SetDvrPassword(password);
m_pPin->SetChannelNumber(channelNumber);
m_pPin->SetStartTime(-1);// Live Stream
m_pPin->SetMilliSecond(0);
m_pPin->SetSize(width, height);
}
...
To make directshow Filter simple [ to understand memory leak source], just implement OnNewImage function and FillBufferFunction as "dummy", but still has memory leak:
int DVRPin::OnNewImage(void *pUser, BYTE *pData, int nLen, int nCh, int tMts, int nType, void *returnHandle)
{
return 1; // for not to end call back
}
HRESULT DVRPin::FillBuffer(IMediaSample *pSample)
{
pSample->Release();
return S_OK;
}
In DVRStreamThread, you have:
streamReader->m_RGB24Buffer = (BYTE*)malloc(streamReader->m_RGB24BufferSize);
But I don't see a matching call to free() anywhere. When your DVRPin object is deleted, you will have to explicitly free the data pointed to by its m_RGB24Buffer member.
First thing I see, is that your destructors are not virtual. This might be a cause of leaks when release is not taking place when inheritance is used. See related article about the necessity of virtual destructors.

My Own Personal MFC

I can't seem to find this on msdn been searching for a bit (described below).
Please forgive the amount of code posted, I will paste in order. You can really skip most of it. But I just want to put it all out there so my request is clear.
Lets say I wanted to make a really simple MFC. So I have the following abstract and concrete classes (pasted below) that I want in my really crappy framework.
I am also assuming (though not implemented yet) that WinMain will call a users defined main function (like Qt). What do I need to do so I can reuse my code in every other small crappy Win32 program I try to write. To be more clear, I am wondering if I compile it into a DLL, or a Library. If so how do I go about doing this? How do you include a WinMain function in a DLL?
#ifndef IAPPLICATION_H_
#define IAPPLICATION_H_
#include <Windows.h>
namespace nApplication
{
class IController;
class IWindow;
class IApplication
{
public:
virtual int Run( ) = 0;
virtual HINSTANCE gethInstance( ) = 0;
virtual int getnCmdShow( ) = 0;
virtual IController* getMainControl( ) = 0;
protected:
IWindow *main_window;
IController *main_control;
private:
virtual int MessageLoop() = 0;
};
}
#endif /* IAPPLICATION */
-
#ifndef APPLICATION_H_
#define APPLICATION_H_
#include <Windows.h>
#include "IApplication.h"
#include "IWindow.h"
#include "IController.h"
#include "Controller.h"
namespace nApplication
{
class Application : public IApplication
{
public:
Application( HINSTANCE hInstance, int nCmdShow );
virtual ~Application( );
virtual int Run( );
virtual int getnCmdShow( ) { return mnCmdShow; }
virtual HINSTANCE gethInstance( ) { return mhInstance; }
virtual IController* getMainControl( ) { return main_control; }
private:
int mnCmdShow;
HINSTANCE mhInstance;
int MessageLoop();
Application( Application &app );
Application& operator= ( const Application &app );
};
}
#endif /* IAPPLICATION */
-
#include "Application.h"
#include "MainWindow.h"
namespace nApplication
{
Application::Application( HINSTANCE hInstance, int nCmdShow )
: mhInstance( hInstance ), mnCmdShow( nCmdShow )
{
}
Application::~Application( )
{
}
int Application::Run( )
{
main_window = new MainWindow( this );
main_control = new Controller( this );
main_window->Init( );
main_window->Display( );
MessageLoop( );
delete main_window;
return 0;
}
int Application::MessageLoop()
{
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
}
-
#ifndef IWINDOW_H_
#define IWINDOW_H_
#include <Windows.h>
#include "IController.h"
namespace nApplication
{
class IWindow
{
public:
virtual void Init() = 0;
virtual void Display( ) = 0;
private:
};
}
#endif /* IWINDOW_H_ */
-
#ifndef MAINWINDOW_H_
#define MAINWINDOW_H_
#include <windows.h>
#include "IWindow.h"
#include "IController.h"
#include "IApplication.h"
namespace nApplication
{
class MainWindow : public IWindow
{
public:
MainWindow( IApplication *iApp);
~MainWindow();
void Init();
void Display( );
private:
WNDCLASSEX wc;
HWND hWnd;
IApplication *iApp;
};
}
#endif //MAINWINDOW_H_
-
#include "MainWindow.h"
namespace nApplication
{
namespace
{
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static IController *cntrl;
cntrl = (IController*)::GetWindowLongPtr(hWnd, GWL_USERDATA);
if(uMsg == WM_NCCREATE)
{
cntrl = (IController*)(((CREATESTRUCT*)lParam)->lpCreateParams);
::SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)cntrl);
cntrl->CheckStatus();
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
switch(uMsg)
{
case WM_CREATE:
{
}
case WM_PAINT:
{
hDC = BeginPaint( hWnd, &ps );
TextOut( hDC, 10, 10, TEXT("Hello, Windows!"), 15 );
EndPaint( hWnd, &ps );
return 0;
}
case WM_DESTROY:
{
PostQuitMessage( 0 );
return 0;
}
default:
{
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
}
}
}
MainWindow::MainWindow( IApplication* iApp ) : iApp( iApp )
{
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = iApp->gethInstance( );
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = TEXT( "GenericAppMenu");
wc.lpszClassName = TEXT( "myWindowClass" );
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
}
MainWindow::~MainWindow()
{
}
void MainWindow::Init()
{
if( !RegisterClassEx(&wc) )
{
MessageBox(NULL, TEXT( "Window Registration Failed!" ), TEXT( "Error!" ), MB_ICONEXCLAMATION | MB_OK);
exit(0);
}
}
void MainWindow::Display( )
{
hWnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("myWindowClass"),
TEXT("The title of my window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
240, 120, NULL, NULL, iApp->gethInstance( ), iApp->getMainControl( ) );
if(hWnd == NULL)
{
::MessageBox( NULL, TEXT( "Window Creation Failed!" ),
TEXT( "Error!" ), MB_ICONEXCLAMATION | MB_OK );
exit(0);
}
::ShowWindow( hWnd, iApp->getnCmdShow( ) );
::UpdateWindow(hWnd);
}
}
-
#ifndef ICONTROLLER_H_
#define ICONTROLLER_H_
#include <windows.h>
namespace nApplication
{
class IController
{
public:
virtual int CheckStatus() = 0;
};
}
#endif ICONTROLLER_H_
-
#ifndef CONTROLLER_H_
#define CONTROLLER_H_
#include <windows.h>
#include "IController.h"
#include "IApplication.h"
namespace nApplication
{
class Controller : public IController
{
public:
Controller( IApplication *iApp );
virtual ~Controller();
virtual int CheckStatus();
private:
Controller( Controller &c );
Controller& operator= ( Controller &c );
IApplication *iApp;
};
}
#endif //CONTROLLER_H_
-
#include "Controller.h"
namespace nApplication
{
Controller::Controller( IApplication *iApp ) : iApp( iApp )
{
}
Controller::~Controller()
{
}
int Controller::CheckStatus()
{
return 0;
}
}
-
#include <windows.h>
#include "Application.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
nApplication::Application app( hInstance, nCmdShow );
return app.Run( );
}
-
main.exe : main.cpp
cl /EHsc main.cpp Application.cpp Controller.cpp MainWindow.cpp user32.lib gdi32.lib
del *.obj
#/link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup
If you are making a library, you don't have a WinMain, you have a DllMain for dynamic libraries, or nothing for static libraries.
In your case, you'd need to export all the classes functionality from your dll, then in any apps that use your library, you'd include the headers of your project and link to the .lib of the library, then have this in your app where you need the GUI functionality:
nApplication::Application app( hInstance, nCmdShow );
return app.Run( );
Of course this ignores all the side details like registering event callbacks and setup along those lines, however Qt is free and open source, you you might want to look into that before reinventing the wheel, or to help make your own wheel a little rounder.

Resources