Working with threads in c++ - c++

I need to create two threads, one of which will return even numbers and the other will return odd numbers. What am I doing wrong?
int _tmain(int argc, _TCHAR* argv[])
{
DWORD ID1 = 1, ID2 = 100;
DWORD arr[] = {ID1, ID2};
HANDLE h[1];
for (int i = 0; i < 2; ++i)
{
h[0] = CreateThread(NULL, 0, &f1, arr, 0, &arr[0]);
if (h[0] == NULL)
_tprintf(_T("%d"), GetLastError());
h[1] = CreateThread(NULL, 0, &f2, arr, 0, &arr[1]);
if (h[1] == NULL)
_tprintf(_T("%d"), GetLastError());
}
WaitForMultipleObjects(2, h, TRUE, INFINITE);
for (int i = 0; i < 2; ++i)
CloseHandle(h[i]);
return 0;
}

Change this
HANDLE h[1];
for (int i = 0; i < 2; ++i)
{
h[0] = CreateThread(NULL, 0, &f1, arr, 0, &arr[0]);
if (h[0] == NULL)
_tprintf(_T("%d"), GetLastError());
h[1] = CreateThread(NULL, 0, &f2, arr, 0, &arr[1]);
if (h[1] == NULL)
_tprintf(_T("%d"), GetLastError());
}
To this
HANDLE h[2];
h[0] = CreateThread(NULL, 0, &f1, arr, 0, &arr[0]);
if (h[0] == NULL)
_tprintf(_T("%d"), GetLastError());
h[1] = CreateThread(NULL, 0, &f2, arr, 0, &arr[1]);
if (h[1] == NULL)
_tprintf(_T("%d"), GetLastError());
You are creating 2 threads within the body of a for loop which executes twice (AKA 4 threads when you really meant for 2).
You are attempting to save the handles to these threads into a HANDLE array which can only hold one element.
On the second execution of the loop, you have overwritten the elements of h[] again, so when you later wait for them to finish and attempt to close the handles, you are not even closing the same handle.
You need the HANDLE array to be size 2, and you need to remove the first for loop (you are passing the function pointers separately, so there is no way to do this in a loop unless you put the function pointers into an array of the same length as h[]).

Related

Converting char to wchar_t

I'm trying to modify this function https://stackoverflow.com/a/35658917/19324589
from CStringA (i have no idea what data type is it) to std::wstring
char buf[1024] to wstring buf
'original' function:
char buf[1024];
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!::ReadFile(hPipeRead, buf, min(sizeof(buf) - 1, dwAvail), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
buf[dwRead] = 0;
strResult += buf;
my attempt:
when i modify buf from char to wstring, it stores only garbage after the ReadFile line.
std::wstring strResult;
// ...
std::wstring buf(1024, '\0');
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!::ReadFile(hPipeRead, buf.data(), min((buf.size() * sizeof(wchar_t)), dwAvail), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
strResult += buf;
I end up doing:
bool bProcessEnded = false;
std::string result;
for (; !bProcessEnded;)
{
// Give some timeslice (50 ms), so we won't waste 100% CPU.
bProcessEnded = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;
// Even if process exited - we continue reading, if
// there is some data available over pipe.
for (;;)
{
char buf[1024];
DWORD dwRead = 0;
DWORD dwAvail = 0;
if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!::ReadFile(hPipeRead, buf, min((sizeof(buf) - 1), dwAvail), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
buf[dwRead] = 0;
result += buf;
}
} //for
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return to_wstring(result);
In my use case buf is returning a data like already connected to 127.0.0.1:5555
I would like to understand what i'm doing wrong?

Multithreading programing in Win32

I use mutex to sync file writing and reading. I create some threads to read file and some threads to write file. But writing Thread sometimes block in WaitForSingleObject(hMutexRW,INFINITE). I'm new to Win32 Threads programming and I don't know what the problem is. I think the mutex is the problem, and I want to know how to solve this problem.
const int nThreadWriting = 5;
const int nThreadReading = 5;
const int nBufSize = 100;
const int maxWritten = 10;
const int timeRange = 3;
HANDLE hMutexRW, hMutexW, hMutexR, hMutexN;
int currentSemaphoreR = 0;
int numberWritten = 0;
unsigned __stdcall ThreadReading(void *pV)
{
HANDLE hFile;
int waitTime, lastTime;
char buf[nBufSize];
int* ptr = (int*)pV;
srand(*ptr);
while (1)
{
WaitForSingleObject(hMutexN, INFINITE);
if (numberWritten >= maxWritten)
{
ReleaseMutex(hMutexN);
return 0;
}
ReleaseMutex(hMutexN);
waitTime = rand() % timeRange+1;
lastTime = rand() % timeRange+1;
WaitForSingleObject(hMutexW, INFINITE);
WaitForSingleObject(hMutexR, INFINITE);
if (currentSemaphoreR == 0)
{
WaitForSingleObject(hMutexRW, INFINITE);
sprintf_s(buf, nBufSize, "%d R GET MUTEX_RW\n", GetCurrentThreadId());
std::cout << buf << std::endl;
}
currentSemaphoreR++;
ReleaseMutex(hMutexR);
ReleaseMutex(hMutexW);
hFile = CreateFile(TEXT("nice.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "cannot open file" << std::endl;
}
sprintf_s(buf, nBufSize, "%d R %d %d\n", GetCurrentThreadId(), waitTime, lastTime);
std::cout << buf <<std::endl;
CloseHandle(hFile);
WaitForSingleObject(hMutexR, INFINITE);
currentSemaphoreR--;
if (currentSemaphoreR == 0)
ReleaseMutex(hMutexRW);
ReleaseMutex(hMutexR);
}
return 0;
}
unsigned __stdcall ThreadWriting(void *pV)
{
int waitTime, lastTime;
char buf[nBufSize];
int* ptr = (int*)pV;
srand(*ptr);
HANDLE hFile;
while (1)
{
WaitForSingleObject(hMutexN, INFINITE);
if (numberWritten >= maxWritten)
{
ReleaseMutex(hMutexN);
return 0;
}
numberWritten++;
ReleaseMutex(hMutexN);
WaitForSingleObject(hMutexW, INFINITE);
WaitForSingleObject(hMutexRW, INFINITE);
hFile = CreateFile(TEXT("nice.txt"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "cannot open file" << std::endl;
return 1;
}
SetFilePointer(hFile, 0, NULL, FILE_END);
sprintf_s(buf, nBufSize, "%d W %d %d\n", GetCurrentThreadId(), waitTime, lastTime);
WriteFile(hFile, buf, strlen(buf), NULL, NULL);
CloseHandle(hFile);
ReleaseMutex(hMutexRW);
ReleaseMutex(hMutexW);
}
return 0;
}
int main()
{
HANDLE hFile;
hFile = CreateFile(TEXT("nice.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(hFile);
DWORD IDThread[nThreadWriting+ nThreadReading];
HANDLE hThread[nThreadWriting + nThreadReading];
int num[nThreadWriting + nThreadReading];
for (int i = 0; i < nThreadWriting + nThreadReading; i++)
num[i] = i;
hMutexRW = CreateMutex(NULL, FALSE, NULL);
hMutexR = CreateMutex(NULL, FALSE, NULL);
hMutexW = CreateMutex(NULL, FALSE, NULL);
hMutexN = CreateMutex(NULL, FALSE, NULL);
if (!hMutexRW || !hMutexW || !hMutexR)
return 1;
for (int i = 0; i < nThreadReading; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadReading, num + i, 0, (unsigned int*)&IDThread[i]);
if (!hThread[i])
ExitProcess(3);
}
for (int i = nThreadReading; i < nThreadWriting + nThreadReading; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadWriting, num + i, 0, (unsigned int*)&IDThread[i]);
if (!hThread[i])
ExitProcess(3);
}
WaitForMultipleObjects(nThreadWriting + nThreadReading, hThread, TRUE, INFINITE);
for (int i = 0; i < nThreadWriting + nThreadReading; i++)
CloseHandle(hThread[i]);
CloseHandle(hMutexRW);
CloseHandle(hMutexR);
CloseHandle(hMutexW);
CloseHandle(hMutexN);
return 0;
}

How can I read a vector of structures in a mapped-file?

I have 2 programs, one gets all processes information using Windows API and stores them in a vector of structure like this:
struct Info{
int pid,ppid;
char exeName[256];
}
I keep back_pushing structure in vector when i populate a structure with data.
Now, I've tried to use memcpy() to memorize data in mapped-file but I can't read it properly in the second program. Can you help me to figure out how to read data properly?
Code program 1:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include <vector>
struct InfoProces {
DWORD pid;
DWORD ppid;
char exeName[256];
};
int main(){
HANDLE hProcesses;
PROCESSENTRY32 pe32;
hProcesses = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if (hProcesses == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot failed. err = %d", GetLastError());
return -1;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcesses, &pe32)) {
printf("Process32First failed. err = %d", GetLastError());
CloseHandle(hProcesses);
return -1;
}
HANDLE hdata = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024 * 1024, "data");
if (hdata == NULL) {
printf("Can't create a file mapping. err = %d", GetLastError());
return -1;
}
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_WRITE, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapping file. err = %d", GetLastError());
return -1;
}
do {
InfoProces pi;
pi.pid = pe32.th32ProcessID;
pi.ppid = pe32.th32ParentProcessID;
strcpy(pi.exeName, pe32.szExeFile);
} while (Process32Next(hProcesses, &pe32));
getchar();
CloseHandle(hProcesses);
return 0;
Code program 2:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <vector>
#include <stdio.h>
struct InfoProces {
DWORD pid;
DWORD ppid;
char exeName[256];
};
int main()
{
HANDLE hdata = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "data");
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_READ, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapped file. err = %d", GetLastError());
return -1;
}
std::vector<InfoProces>processes;
memcpy(&processes,pdata,sizeof(data));
for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
printf("Process[%d](parinte[%d]): %s\n", i->pid, i->ppid, i->exeName);
return 0;
}
As the comment pointed out, you have got the starting address of the mapped view(pdata), You can only use the pdata for memory sharing, but not any stack address of the process.
Try to copy the memory of InfoProces to the pdata in program 1:
memcpy(pdata, &pi, sizeof(InfoProces));
In addition, in program 2, you did not set the size for the vector, and you should replace &processes with processes.data(). You also need to know the size of the array you added in program 1:
std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(), pdata, sizeof(InfoProces)*count);
Following code works for me.
Program 1:(Record the count of InfoProces and save it to a DWORD in the beginning of pdata)
...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_WRITE, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapping file. err = %d", GetLastError());
return -1;
}
unsigned char* begin = pdata;
//offset a size of DWORD;
DWORD count = 0;
pdata += sizeof(DWORD);
do {
InfoProces pi;
pi.pid = pe32.th32ProcessID;
pi.ppid = pe32.th32ParentProcessID;
strcpy(pi.exeName, pe32.szExeFile);
memcpy(pdata, &pi, sizeof(InfoProces));
pdata += sizeof(InfoProces);
count++;
} while (Process32Next(hProcesses, &pe32));
memcpy(begin, &count, sizeof(DWORD));
getchar();
UnmapViewOfFile(begin);
CloseHandle(hdata);
CloseHandle(hProcesses);
...
Program 2:
...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_READ, 0, 0, 0);
if (pdata == NULL) {
printf("cant get pointer to mapped file. err = %d", GetLastError());
return -1;
}
unsigned char* begin = pdata;
DWORD count = 0;
memcpy(&count, pdata, sizeof(DWORD));
pdata += sizeof(DWORD);
std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(), pdata, sizeof(InfoProces)*count);
for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
printf("Process[%d](parinte[%d]): %s\n", i->pid, i->ppid, i->exeName);
UnmapViewOfFile(begin);
CloseHandle(hdata);
...
Finally, do not forget to close the handle and unmap address.

How to get files on the whole drive

I have written a code to iterate over the drive to find the file of specific extension and if the file is fount it'll be added to the list box but the code fails its iteration when it finds a directory. The iteration stops with the files not the directories. I want my program to search the file with a given extension even in the directories and sub-directories what shall I do?
here is my code
The variable buffer seen in my code is nothing but the drive string e.g H:\
count = 0;
int Class::countOfDocuments(wchar_t buffer[10])
{
wchar_t driveString[MAX_PATH + 1] = { 0 };
wcsncat_s(driveString,260,buffer,260);
wcsncat_s(driveString, 260, L"*doc", 260);
WIN32_FIND_DATA documents;
HANDLE hFind; bool var = true;
hFind = FindFirstFile(driveString, &documents);
if (INVALID_HANDLE_VALUE == hFind)
{
wchar_t* no = L"No documents found";
SendMessage(list1, LB_ADDSTRING, NULL, (LPARAM)no);
for (int i = 0; i <= 10; i++)
{
SendMessage(cprogress, PBM_SETRANGE, 0, i);
SendMessage(cprogress, PBM_SETSTEP, (WPARAM)1, 0);
SendMessage(cprogress, PBM_STEPIT, 0, 1);
}
return count = -1;
}
else
{
wchar_t* Yes = L"Document found";
perform = true;
SendMessage(list1, LB_ADDSTRING, NULL, (LPARAM)Yes);
while (var = FindNextFile(hFind, &documents) == TRUE)
{
count++;
}
for (int i = 0; i <= count; i++)
{
SendMessage(cprogress, PBM_SETRANGE, 0, i);
SendMessage(cprogress, PBM_SETSTEP, (WPARAM)1, 0);
SendMessage(cprogress, PBM_STEPIT, 0, 1);
wchar_t* doc = L"Document found";
SendMessage(list1, LB_ADDSTRING, NULL, (LPARAM)doc);
}
wchar_t* z = L"search complete";
SendMessage(list1, LB_ADDSTRING, NULL, (LPARAM)z);
}
return count;
}

Getting md5 hash code for dll file in c++

Hi guys i am trying to get dll md5 hash but it is returning same value all the time, what i did wrong?
this dll is already loaded when i am trying to getHash
i am getting hash with getHash() method and calculating it with CalcHash
thnks in advanced.
#define BUFSIZE 1024
#define MD5LEN 16
int CalcHash(HANDLE hFile, char *md5sum)
{
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigits[] = "0123456789abcdef";
char byt[3];
int rc, err;
rc = CryptAcquireContext(&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
if(!rc)
{
err = GetLastError();
if(err==0x80090016)
{
//first time using crypto API, need to create a new keyset
rc=CryptAcquireContext(&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!rc)
{
err=GetLastError();
return 0;
}
}
}
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
while(bResult = ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
CryptHashData(hHash, rgbFile, cbRead, 0);
}
cbHash = MD5LEN;
CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0);
md5sum[0] = 0;
for (DWORD i = 0; i < cbHash; i++)
{
sprintf(byt, "%c%c", rgbDigits[rgbHash[i] >> 4], rgbDigits[rgbHash[i] & 0xf]);
strcat(md5sum, byt);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return 1;
}
char *getHash()
{
CalcHash(L"dsetup.dll", md5sum);
Logger(md5sum);
return md5sum;
}