I'm trying to edit memory with my custom function in the luaC api but for example when i do like 3 lua_tonumber(LS, -1) it just gets mixed up? Please try to review my code and tell me how to fix this..
lua_State *L;
using namespace std;
DWORD MyGetProcessId(LPCTSTR ProcessName)
{
PROCESSENTRY32 pt;
HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pt.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hsnap, &pt)) {
do {
if (!lstrcmpi(pt.szExeFile, ProcessName)) {
CloseHandle(hsnap);
return pt.th32ProcessID;
}
} while (Process32Next(hsnap, &pt));
}
CloseHandle(hsnap);
return 0;
}
int CustomGetProcessByName(lua_State* Ls) {
DWORD dieman = MyGetProcessId(lua_tostring(Ls, -1));
lua_pushvalue(Ls, dieman);
return 1;
}
int CustomWriteMemInt(lua_State* Ls) {
HANDLE ProcHand = OpenProcess(PROCESS_ALL_ACCESS, FALSE, lua_tonumber(Ls, -1));
int Value = lua_tonumber(Ls, -3);
WriteProcessMemory(ProcHand, (LPVOID)lua_topointer(Ls, -2), &Value, sizeof(Value), 0);
return 1;
}
void Load() {
L = luaL_newstate();
lua_register(L, "GetProcByName", CustomGetProcessByName);
lua_register(L, "WriteMemInt", CustomWriteMemInt);
}
int main() {
Load();
luaL_dostring(L, "a = GetProcByName('ac_client.exe')");
luaL_dostring(L, "WriteMemInt(a, 0x0293AA60, 9999)");
system("Pause");
}
I know the writing memory function works because I did it without this..
lua_topointer returns a pointer to a lua object. You just want to use lua_tonumber instead.
Note that a number is normally a double so will not be able to hold 64-bit addresses, in your example it should work though as the address appears to be 32-bit.
Related
I'm trying to make a program that deletes a list of files one by one, using system().
The reason I'm using system() instead of remove() is because remove() doesn't support environment variables.
I've tried checking the return value, but my code seems to just always output that it's been deleted, even when it hasn't.
Code:
void fileLoop() {
std::vector<std::string> fileList = { "\"%userprofile%\\test.txt\"" };
while (!inter) {
for (int count = 0; count <= 0; count++) {
std::string moddedstring = "del /F " + fileList[count];
DWORD checker = GetFileAttributes((LPCWSTR)fileList[count].c_str());
if (checker == INVALID_FILE_ATTRIBUTES) {
goto next;
}
else {
system(moddedstring.c_str());
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
}
next:
std::cout << "\n";
}
Sleep(500);
}
}
I thought there is some easy way to find this out. I haven't found a way like that yet.
I will be adding more paths later.
Update:
I've tried using OpenProcessToken() with ExpandEnvironmentStringsForUserW() to add ENVs
But it complains that my buffer is of type LPCSTR* even when I set it to LPCSTR
Thanks!
A better way to get the user's profile path is to simply ask the OS directly, via SHGetFolderPath(CSIDL_PROFILE) or SHGetKnownFolderPath(FOLDERID_Profile).
Also, you should use DeleteFileA() instead of system("del"). There is no need to spawn an external console process when you can do the deletion directly. Also, because you are interested in error checking, which is much easier if you use the Win32 API directly.
Also, (LPCWSTR)fileList[count].c_str() will not work like you think. You can't convert a const char* to a const wchar_t* using a simple typecast. Drop the typecast and use GetFileAttributesA() instead.
Or, simply don't bother checking attributes at all. You can call DeleteFileA() unconditionally and let it tell you if it actually succeeded or failed.
With that said, try something more like this:
#include <shlobj.h>
std::string getUserProfilePath() {
CHAR szPath[MAX_PATH];
if (FAILED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, szPath))) {
// error handling...
throw ...;
}
int len = lstrlenA(szPath);
szPath[len] = '\\';
return std::string(szPath, len + 1);
/*
PWSTR pszPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pszPath))) {
// error handling...
throw ...;
}
int wlen = lstrlenW(pszPath);
int len = WideCharToMultiByte(0, 0, pszPath, wlen, NULL, 0, NULL, NULL);
if (len == 0) {
// error handling...
throw ...;
}
std::vector<CHAR> buffer(len + 1);
len = WideCharToMultiByte(CP_ACP, 0, pszPath, wlen, buffer.data(), len, NULL, NULL);
if (len == 0) {
// error handling...
throw ...;
}
buffer[len] = '\\';
CoTaskMemFree(pszPath);
return std::wstring(buffer.data(), buffer.size());
*/
}
void fileLoop() {
std::vector<std::string> fileList = { getUserProfilePath() + "test.txt" };
while (!inter) {
for (size_t count = 0; count < fileList.size(); ++count) {
if (DeleteFileA(fileList[count].c_str())) {
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
} else {
// error handling...
}
std::cout << "\n";
}
Sleep(500);
}
}
Alternatively, using Unicode strings instead (which you really should use when interacting with the filesystem):
#include <shlobj.h>
std::wstring getUserProfilePath() {
WCHAR szPath[MAX_PATH];
if (FAILED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, szPath))) {
// error handling...
throw ...;
}
int len = lstrlenW(szPath);
szPath[len] = '\\';
return std::wstring(szPath, len + 1);
/*
PWSTR pszPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pszPath))) {
// error handling...
throw ...;
}
int len = lstrlenW(pszPath);
std::wstring sPath(len + 1, '\0');
std::copy(pszPath, pszPath + len, sPath.begin());
sPath[len] = '\\';
CoTaskMemFree(pszPath);
return sPath;
*/
}
void fileLoop() {
std::vector<std::wstring> fileList = { getUserProfilePath() + L"test.txt" };
while (!inter) {
for (size_t count = 0; count < fileList.size(); ++count) {
if (DeleteFileW(fileList[count].c_str())) {
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
} else {
// error handling...
}
std::cout << "\n";
}
Sleep(500);
}
}
Even better, if you are using C++17 or later, consider using the <filesystem> library instead:
#include <shlobj.h>
#include <filesystem>
using fs = std::filesystem;
fs::path getUserProfilePath() {
WCHAR szPath[MAX_PATH];
if (FAILED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, szPath))) {
// error handling...
throw ...;
}
return szPath;
/*
PWSTR pszPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pszPath))) {
// error handling...
throw ...;
}
fs::path pth(pszPath);
CoTaskMemFree(pszPath);
return pth;
*/
}
void fileLoop() {
std::vector<fs::path> fileList = { getUserProfilePath() / L"test.txt" };
while (!inter) {
for (auto &pth : fileList) {
std::error_code ec;
if (fs::remove(pth, ec)) {
MessageBoxW(NULL, L"File found, successfully deleted", L"File Deleted", MB_OK | MB_ICONWARNING);
} else {
// error handling...
}
std::cout << "\n";
}
Sleep(500);
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 months ago.
Improve this question
there is warnings in c++ i can't solve it
i have Visual Studio 2019
first i got error with #include "pch.h"
and 3 warnings
-using uninitialized memory : in processesSnapshot
`
while (Process32Next(processesSnapshot, &processInfo))
`
-argument conversion from 'unsigned __int64' to 'unsigned long', possible loss of data
-argument conversion from 'unsigned __int64' to 'DWORD', possible loss of data
`
MODULEENTRY32 module = GetModule("ac_client.exe", pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
`
`
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
DWORD GetPID(const char* ProcessName) {
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE)
return 0;
Process32First(processesSnapshot, &processInfo);
if (!strcmp(processInfo.szExeFile, ProcessName))
{
CloseHandle(processesSnapshot);
}
while (Process32Next(processesSnapshot, &processInfo))
{
if (!strcmp(processInfo.szExeFile, ProcessName))
{
CloseHandle(processesSnapshot);
}
}
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
MODULEENTRY32 GetModule(const char* moduleName, unsigned long ProcessID)
{
MODULEENTRY32 modEntry = { 0 };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, ProcessID);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 curr = { 0 };
curr.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hSnapshot, &curr))
{
do
{
if (!strcmp(curr.szModule, moduleName))
{
modEntry = curr;
break;
}
} while (Module32Next(hSnapshot, &curr));
}
CloseHandle(hSnapshot);
}
return modEntry;
}
int main()
{
std::cout << "Hello World!\n";
unsigned long long pid = GetPID("ac_client.exe");
MODULEENTRY32 module = GetModule("ac_client.exe", pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
unsigned long long result;
int ammodesiredvalue = 999999;
ReadProcessMemory(phandle, (void*)((unsigned long long)module.modBaseAddr + 0x0010B1E0), &result, sizeof(result), 0);
ReadProcessMemory(phandle, (void*)((unsigned long long)result + 0x54), &result, sizeof(result), 0);
ReadProcessMemory(phandle, (void*)((unsigned long long)result + 0x14), &result, sizeof(result), 0);
//ReadProcessMemory(phandle, (void*)((unsigned long long)result + 0x14), &result, sizeof(result), 0);
WriteProcessMemory(phandle, (void*)((unsigned long long)result + 0x14), &ammodesiredvalue, sizeof(ammodesiredvalue), 0);
std::cout << "Your ammo value is " << result << std::endl;
system("pause");
}
`
i looking for fix this error and warnings
Your code has a number of problems. I'm going to look at one small section, and point out what look to me like obvious problems. Not sure if they're the source of the symptoms you're seeing, but ...
Process32First(processesSnapshot, &processInfo);
if (!strcmp(processInfo.szExeFile, ProcessName))
{
CloseHandle(processesSnapshot);
}
So here if we found the right process, we close the process snapshot, but then:
while (Process32Next(processesSnapshot, &processInfo))
{
...we try to continue using the process snapshot, even if it's already been closed. Then:
if (!strcmp(processInfo.szExeFile, ProcessName))
{
CloseHandle(processesSnapshot);
}
...we check whether we have the right process, and (again) close the snapshot if we found it. But we don't break out of the loop--so again, we try to continue using the snapshot, even if we've closed it. Then:
}
CloseHandle(processesSnapshot);
...when we exit the loop, we close the snapshot yet again. At this point, we've potentially closed our snapshot three times, and continued using it after it was closed in a couple of different places.
My personal inclination is that any time I see something that needs to be opened and later closed (or something along those lines) I think of using RAII/SBRM to deal with it. That means I'd create a class to manage the process snapshot. I'd create the snapshot in the class' constructor, and close it in the class' destructor, and add other member functions to obtain the contents of the current item, advance to the next item, and so on.
Given that this iterates things, it also makes sense (in my opinion) to have this class act as an actual iterator.
// warning: untested code.
class ProcessIterator {
HANDLE snapshot;
bool valid;
PROCESSENTRY32 processInfo;
public:
using iterator_category = std::input_iterator_tag;
using difference_type = std::ptrdiff_t; // not really, but it'll probably do for now.
using value_type = PROCESSENTRY32;
using pointer = PROCESSENTRY32 *;
using reference = PROCESSENTRY32 &;
ProcessIterator(DWORD ID) : snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, ID))
{
if (!snapshot)
throw std::runtime_error("Unable to open process snapshot");
valid = Process32First(snapshot, &processInfo);
}
ProcessIterator() : valid(false) {}
ProcessIterator operator++() {
valid = Process32Next(snapshot, &processInfo);
return *this;
}
PROCESSENTRY32 operator*() const { return processInfo; }
bool operator==(ProcessIterator other) {
// only invalid iterators are equal:
return (!valid) && (!other.valid);
}
~ProcessIterator() { CloseHandle(snapshot); }
};
Since this is a normal iterator, we can use it for normal iterator "stuff", such as finding an entry using std::find_if:
DWORD getPid(char const *filename) {
auto p = std::find_if(ProcessIterator(0), ProcessIterator(),
[&](PROCESSENTRY32 const &p) { return !std::strcmp(filename, p.szExeFile); });
return p->th32ProcessID;
}
So I was checking csgo scripting with C++ and everything was going smoothly but when I finished the Bhop code I found out that "string1" is "const char" and "string2" is wchar. I tried fixing, i searched redit, youtube literally everything but i couldn't fix it.
#include "memory.h"
#include <TlHelp32.h>
Memory :: Memory(const char* processName)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
const auto snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
while (Process32Next(snapShot, &entry))
{
if (!strcmp(processName, entry.szExeFile))
{
this->id = entry.th32ProcessID;
this->process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, this->id);
break;
}
}
if (snapShot)
CloseHandle(this->process);
}
Memory :: ~Memory()
{
if (this->process)
CloseHandle(this->process);
}
DWORD Memory :: GetProcessId()
{
return this->id;
}
HANDLE Memory :: GetProcessHandle()
{
return this->process;
}
uintptr_t Memory :: GetModuleAdress(const char* moduleName)
{
MODULEENTRY32 entry;
entry.dwSize = sizeof(MODULEENTRY32);
const auto snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, this->id);
uintptr_t result = 0;
while (Module32Next(snapShot, &entry))
{
if (!strcmp(moduleName, entry.szModule))
{
result = reinterpret_cast<uintptr_t>(entry.modBaseAddr);
break;
}
}
if (snapShot)
CloseHandle(snapShot);
return result;
}
The error comes up on if (!strcmp(processName, entry.szExeFile)) where processName is "const char" and entry.szExeFile is "wchar". Please tell how to fix my problem
because i got no clue.
You are using TCHAR-based Win32 API macros, and you are compiling your project with UNICODE defined, so the macros are resolving to the wchar_t version of the APIs. But you are using char data in the rest of your code, so you need to use the ANSI (char) version of the APIs explicitly instead.
Also, there are other bugs in your code. Namely, ignoring the 1st entry in the process and modules lists. And your constructor is closing the wrong HANDLE.
Try this:
Memory :: Memory(const char* processName)
{
PROCESSENTRY32A entry;
entry.dwSize = sizeof(entry);
const auto snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32FirstA(snapShot, &entry))
{
do
{
if (strcmp(processName, entry.szExeFile) == 0)
{
this->id = entry.th32ProcessID;
this->process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, this->id);
break;
}
}
while (Process32NextA(snapShot, &entry));
}
if (snapShot)
CloseHandle(snapShot);
}
uintptr_t Memory :: GetModuleAdress(const char* moduleName)
{
MODULEENTRY32A entry;
entry.dwSize = sizeof(entry);
const auto snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, this->id);
uintptr_t result = 0;
if (Module32FirstA(snapShot, &entry))
{
do
{
if (strcmp(moduleName, entry.szModule) == 0)
{
result = reinterpret_cast<uintptr_t>(entry.modBaseAddr);
break;
}
}
while (Module32NextA(snapShot, &entry));
}
if (snapShot)
CloseHandle(snapShot);
return result;
}
I'm using the following code to enumerate the contents of the Recyclebin Shell folder and get the file type of each item.
The code gives the expected results but if I call the function in a loop it looks like there's some memory leak when using the IshellItem2 GetString function (see attached screenshot at the end).
Am I cleaning up everything properly?
Am I misinterpreting the results?
void Test1()
{
// Get recyclebin ishellitem
IShellItem* psiRecycleBin;
if (SUCCEEDED(SHGetKnownFolderItem(FOLDERID_RecycleBinFolder, KF_FLAG_DEFAULT,
NULL, IID_PPV_ARGS(&psiRecycleBin))))
{
// Get ishellitem contents enumerator
IEnumShellItems* pesi;
if (SUCCEEDED(psiRecycleBin->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&pesi))))
{
IShellItem* psi;
while (pesi->Next(1, &psi, NULL) == S_OK)
{
// Get ishellitem2 from ishellitem
IShellItem2* psi2;
if (SUCCEEDED(psi->QueryInterface(IID_PPV_ARGS(&psi2))))
{
// Get the item file type string
LPWSTR fileType = NULL;
if (SUCCEEDED(psi2->GetString(PKEY_ItemTypeText, &fileType)))
{
CoTaskMemFree(fileType);
}
psi2->Release();
}
psi->Release();
}
pesi->Release();
}
psiRecycleBin->Release();
}
}
And I'm calling it in loop like this:
#define STRICT_TYPED_ITEMIDS
#include <shlobj.h>
#include <propkey.h>
#include <iostream>
void Test1();
int main()
{
(void)CoInitialize(NULL);
std::cout << "Enumerating recyclebin items..\n";
for (int ii = 0; ii < 5000; ii++)
{
Test1();
}
CoUninitialize();
return 0;
}
When debugging this console program in VS in the memory diagnostics window this is what I get:
Thanks for the help
yes, here really exist memory leak, related to HIDDENRECYCLEBINDATAV2 structure from shell32.dll
partial definition of it:
struct HIDDENRECYCLEBINDATAV2
{
//... some mebers
FILETIME time;
PWSTR pszLocationBeforeDelete = 0; // !!! not released
PWSTR pszLocationInRecycleBin = 0; // !!! not released
HRESULT Serialize(PBYTE *, PUSHORT);
static HRESULT Deserialize(
_In_reads_bytes_opt_(cbStream) const BYTE *pbStream ,
_In_ USHORT cbStream,
_Out_ HIDDENRECYCLEBINDATAV2 ** pphrbd);
static HRESULT Initialize(HIDDENRECYCLEBINDATAV1 const *, HIDDENRECYCLEBINDATAV2**);
};
this structure hold 2 strings - file path from where it deleted ( pszLocationBeforeDelete - this is my name, i don't know original) and current file path in Recycle Bin ( pszLocationInRecycleBin - again my name)
this names allocated inside Deserialize method, by call IStream_ReadStrLong and must be freed with CoTaskMemFree. but how i found - CoTaskMemFree never called for this two strings.
pseudo code for Deserialize :
static HRESULT HIDDENRECYCLEBINDATAV2::Deserialize(
_In_reads_bytes_opt_(cbInit) const BYTE *pbStream ,
_In_ USHORT cbStream,
_Out_ HIDDENRECYCLEBINDATAV2 ** pphrbd)
{
HRESULT hr = E_FAIL;
if (HIDDENRECYCLEBINDATAV2 *phrbd = new HIDDENRECYCLEBINDATAV2)
{
if (IStream *pStream = SHCreateMemStream(pbStream, cbStream))
{
if (0 <= (hr = IStream_ReadStrLong(pStream, &phrbd->pszLocationBeforeDelete)) &&
0 <= (hr = IStream_ReadStrLong(pStream, &phrbd->pszLocationInRecycleBin)))
{
*pphrbd = phrbd, phrbd = 0;
}
pStream->Release();
}
CoTaskMemFree(phrbd); // !! error, need delete phrbd
}
return hr;
}
and it called from CBitBucket::_ValidateItem :
HRESULT InitDeletedItem(PCWSTR pszLocationBeforeDelete, PCWSTR pszLocationBeforeDelete, DELETEDITEM *);
static HRESULT CBitBucket::_ValidateItem(_ITEMIDLIST_RELATIVE const *, DELETEDITEM ** ppdi)
{
HIDDENRECYCLEBINDATAV2 * phrbd;
if (0 <= HIDDENRECYCLEBINDATAV2::Deserialize(pbStream, cbStream, &phrbd))
{
if (DELETEDITEM * pdi = new DELETEDITEM)
{
if (0 <= InitDeletedItem( phrbd->pszLocationBeforeDelete,
phrbd->pszLocationInRecycleBin, pdi))
{
*ppdi = pdi, pdi = 0;
}
if (pdi) delete pdi;
}
CoTaskMemFree(phrbd); // !! error, need delete phrbd
}
}
in both functions - memory for HIDDENRECYCLEBINDATAV2 simply released with CoTaskMemFree api, but memory for strings inside this structure not released. i think need add
HIDDENRECYCLEBINDATAV2::~HIDDENRECYCLEBINDATAV2()
{
CoTaskMemFree(pszLocationInRecycleBin);
CoTaskMemFree(pszLocationBeforeDelete);
}
to this structure and call delete instead CoTaskMemFree
how possible found this ? i hook RtlAllocateHeap and RtlFreeHeap before second call to Test1() (important do this not on first call, because during first call may be additional libs load, some differed initialization, etc.. - all this can distort the real result)and log all alloc/free calls in current thread. also i replace while (pesi->Next..) to if (pesi->Next..) (usually one iteration is enough ). and i found that count of alloc on 2 more than count of free. so i easy found from where this 2 allocations- inside IStream_ReadStrLong. then i set breakpoint here and easy view from where this called :
CBitBucket::_ValidateItem
HIDDENRECYCLEBINDATAV2::Deserialize
IStream_ReadStrLong
CoTaskMemAlloc
partial demo code for log:
struct AI
{
PVOID BaseAddress;
PVOID From;
ULONG Size;
ULONG Flags;
};
struct TID
{
AI *pi;
ULONG nAlloc, nFree, nCells, MaxAllocDelta;
BOOL bNotLog;
TID()
{
RtlZeroMemory(this, sizeof(*this));
}
};
BOOLEAN NTAPI hook_RtlFreeHeap(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress )
{
TID* p = RTL_FRAME<TID>::get();
if (!p || p->bNotLog)
{
return RtlFreeHeap(HeapHandle, Flags, BaseAddress) != 0;
}
p->bNotLog = TRUE;
if (!RtlFreeHeap(HeapHandle, Flags, BaseAddress))
{
__debugbreak();
}
if (BaseAddress)
{
AI* pi = p->pi;
ULONG n = p->nCells;
do
{
if (pi->BaseAddress == BaseAddress)
{
pi->BaseAddress = 0;
p->nFree++;
break;
}
} while (pi++, --n);
if (!n)
{
__debugbreak();
}
}
p->bNotLog = FALSE;
return TRUE;
}
PVOID NTAPI hook_RtlAllocateHeap( PVOID HeapHandle, ULONG Flags, SIZE_T Size )
{
TID* p = RTL_FRAME<TID>::get();
if (!p || p->bNotLog)
{
return RtlAllocateHeap(HeapHandle, Flags, Size);
}
p->bNotLog = TRUE;
if (PVOID BaseAddress = RtlAllocateHeap(HeapHandle, Flags, Size))
{
AI* pi = p->pi;
ULONG n = p->nCells;
do
{
if (!pi->BaseAddress)
{
pi->BaseAddress = BaseAddress;
pi->From = _ReturnAddress();
pi->Size = (ULONG)Size;
pi->Flags = Flags;
p->nAlloc++;
ULONG k = p->nAlloc - p->nFree;
if (k > p->MaxAllocDelta)
{
p->MaxAllocDelta = k;
}
break;
}
} while (pi++, --n);
if (!n)
{
__debugbreak();
}
p->bNotLog = FALSE;
return BaseAddress;
}
return 0;
}
void TestEx()
{
enum { cell_count = 0x1000 };
if (AI* pi = new AI[cell_count])
{
Test1();// first call
// hook RtlAllocateHeap + RtlFreeHeap
{
RtlZeroMemory(pi, cell_count * sizeof(AI));
RTL_FRAME<TID> f;
f.pi = pi;
f.nCells = cell_count;
Test1();// second call
DbgPrint("%x(%x) %x\n", f.nAlloc, f.nFree, f.MaxAllocDelta);
if (f.nAlloc - f.nFree)
{
ULONG n = cell_count;
AI* qi = pi;
do
{
if (qi->BaseAddress)
{
DbgPrint("%p> %x %x\n", qi->From, qi->Size, qi->Flags);
}
} while (qi++, --n);
}
}
delete [] pi;
}
}
As far as I can see, a pointer to structure can be used. But I am wondering, is there any more efficient or elegant way to do that? At least when a structure is being used, it is not easy to see what are the parameters used by the function.
Thanks for any insightful answer.
Here's a small example, that uses WIN32 API:
#include <windows.h>
#include <stdio.h>
struct PARAMS
{
int i;
char* msg;
};
DWORD WINAPI myThread(void* parameter)
{
PARAMS* params = (PARAMS*)parameter;
printf("Received parameters: i = %d, msg = '%s'\n", params->i, params->msg);
return 0;
}
int main(int argc, char* argv[])
{
char msg[] = "Hi there.";
PARAMS params;
params.i = 1;
params.msg = msg;
HANDLE threadHandle = CreateThread(NULL, 0, myThread, ¶ms, 0, NULL);
WaitForSingleObject(threadHandle, INFINITE);
return 0;
}
You say, that "it is not easy to see what are the parameters used by the function". Well it depends on situation. If you don't consider it "elegant" enough, you should leave some helpful comment there at least... if you are using good naming and trying to write code, that is self-documenting, then using of structure will be just fine.
Here's an example of wrapping CreateThread so that programmer that uses your code doesn't have to know that you are using some structure:
#include <windows.h>
#include <stdio.h>
class MyWrapper
{
private:
struct PARAMS
{
int i;
char* msg;
};
static DWORD WINAPI myThread(void* parameter)
{
PARAMS* params = (PARAMS*)parameter;
printf("Received parameters: i = %d, msg = '%s'\n", params->i, params->msg);
delete params;
return 0;
}
public:
HANDLE createThread(int i, char* msg)
{
PARAMS* params = new PARAMS;
params->i = i;
params->msg = msg;
return CreateThread(NULL, 0, MyWrapper::myThread, params, 0, NULL);
}
};
int main(int argc, char* argv[])
{
MyWrapper mw;
char msg[] = "Hi there.";
HANDLE threadHandle = mw.createThread(1, msg);
WaitForSingleObject(threadHandle, INFINITE);
return 0;
}
Here is a small example if you want to pass a single parameter to a thread function in Win32 API
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
DWORD WINAPI funHello(void *x)
{
int c = (int*)x;
printf("\n Thread No: %d\n",c);
// Do some work , call some function, etc.
return 0;
}
int main()
{
HANDLE myhandle;
DWORD threadId;
int c = 1;
myhandle = CreateThread(NULL, 0, funHello, (void *)c, 0, &threadId);
if (myhandle == NULL)
{
printf("Create Thread Failed. Error no: %d\n", GetLastError);
}
WaitForSingleObject(myhandle, INFINITE);
printf("\n Main Hello...\n");
CloseHandle(myhandle);
return 0;
}