C++ System Call Thread - c++

Hello I am trying to write a program that will create a thread in which it will system call the char buffer. I am new to threads and I am having a hard time to get the thread working.
Most of this stuff I got is from just searching in gooogle and watching videos.
Here is what I have so far.
#define BUFFERSIZE 25
DWORD WINAPI ThreadFunc(LPVOID param);
int main()
{
while (1)
{
char buffer[BUFFERSIZE];
DWORD threadID;
HANDLE ThreadHandle;
fgets(buffer,BUFFERSIZE,stdin);
if (buffer == "dir")
{
ThreadHandle = CreateThread(NULL, 0,ThreadFunc, &buffer, 0, &threadID);
}
else if (buffer == "help")
{
}
else if (buffer == "vol")
{
}
else if (buffer == "path")
{
}
else if (buffer == "tasklist")
{
}
else if (buffer == "notepad")
{
}
else if (buffer == "echo")
{
}
else if (buffer == "color")
{
}
else
{
}
}
}
DWORD WINAPI ThreadFunc(LPVOID param)
{
char* value = (char*)param;
system(value);
return 0;
}

There are few problems with your code:
1. As Daniel pointed out, incorrect parameter to CreateThread (buffer). You use wrong type and scope of the variable.
2. Expressions in your if statements will be always evaluated to false. Types like char * don't have overloaded operators and == will result to pointer comparison.
#define BUFFERSIZE 25
DWORD WINAPI ThreadFunc(LPVOID param);
int main()
{
while (1)
{
char* buffer = new char [BUFFERSIZE];
DWORD threadID;
HANDLE ThreadHandle;
fgets(buffer,BUFFERSIZE,stdin);
if (strcmp(buffer, "dir") == 0)
{
ThreadHandle = CreateThread(NULL, 0,ThreadFunc, buffer, 0, &threadID);
}
else if(...) // next
{
}
else
{
delete[] buffer;
}
}
}
DWORD WINAPI ThreadFunc(LPVOID param)
{
char* value = (char*)param;
system(value);
delete[] value;
return 0;
}

There seems to be two mistakes:
First
ThreadHandle = CreateThread(NULL, 0,ThreadFunc, &buffer, 0, &threadID)
Should be
ThreadHandle = CreateThread(NULL, 0,ThreadFunc, buffer, 0, &threadID)
Notice that the buffer lost it's & since the name of an array is already a pointer to it.
Second
Your main thread exits right after running the second thread.
Sadly, as soon as the main thread exists the process is terminated, so nothing happens. Try adding a sleep in your main thread.

Related

WriteFile with an overlapped occasionally gives me ERROR_INVALID_HANDLE. Am I doing memset correct?

I am using WriteFile to write to a file and I am getting an error of ERROR_INVALID_HANDLE sometimes. I read that this could be because the value of HANDLE in Overlapped is invalid.
But I am just having a hard time figuring this out. I wonder if something is going out of scope. Would appreciate it if someone can take a look. I can always add more code here
const LPOVERLAPPED lpOverlapped = GetOverlapped(true, hFile, ulBufSize, &ullFileOffset,volumeName);
if (lpOverlapped == nullptr)
{
CloseHandle(hFile);
return false;
}
if (!WriteFile(hFile,(const PVOID)(((UINT64) s_pMemoryBuffer[volumeName]) + iBufferOffset),ulBufSize,&dwBytesWritten,lpOverlapped))
{
DWORD errCode = GetLastError(); //Error here
//Why do I get an error code 6 here every now and then
}
Now this is the method that returns the overlapped structure
LPOVERLAPPED foo::GetOverlapped(bool useOverlappedIo, HANDLE hFile, UINT32 ulBufSize, UINT64* ullFileOffset,const std::string& volumeName)
{
if (useOverlappedIo)
{
while (true)
{
int index = 0;
while (index < cMaxOverlappedIOS)
{
if (!OverlappedInUse[volumeName][index])
{
OverlappedInUse[volumeName][index] = true;
LPOVERLAPPED overlapped = &(OverlappedArray[volumeName][index]);
if (overlapped->hEvent == nullptr) // Need Event
{
overlapped->hEvent = CreateEvent(
nullptr,
TRUE,
TRUE,
nullptr);
if (overlapped->hEvent == nullptr)
{
printf("Error creating event (error code: %u)\n", GetLastError());
return nullptr;
}
}
overlapped->Offset = (UINT32)(*ullFileOffset & 0xFFFFFFFF); // Low order 32 bits
overlapped->OffsetHigh = (UINT32)(*ullFileOffset >> 32); // High order 32 bits
*ullFileOffset += ulBufSize; // Update pointer to next record
return overlapped;
}
// Else Keep looking
index++;
}
// None available, wait for at least one to free up
if (WaitForPendingIOs(hFile, FALSE,volumeName) != ERROR_SUCCESS)
{
return nullptr;
}
} // Now start loop over again
}
else
{
return nullptr;
}
}
This is how I am initializing the array before this code gets called
for(auto vol : readVolumes)
{
OVERLAPPED* oarray = new OVERLAPPED[cMaxOverlappedIOS];
memset(oarray, 0, sizeof(oarray));
OverlappedArray[vol] = oarray;
bool* boolinuse = new bool[cMaxOverlappedIOS]{false};
OverlappedInUse[vol] = boolinuse;
s_pMemoryBuffer[vol] = nullptr;
s_uDataBufferSize[vol] = 0;
}
Any suggestions on why I would get that error ?

How to make it run sync?

Hello I want to sync two threads one incrementing a variable and other decrementing it.
The result that I want looks like:
Thread #0 j = 1
Thread #1 j = 0
Thread #0 j = 1
Thread #1 j = 0
And so on.. but my code sometimes works like that in some cases it print really weird values. I supose that I have some undefined behavior in somewhere but I can't figured out what is really happen.
My code consist in a HANDLE ghMutex that containg the handler of my mutex:
My main function:
int main(void)
{
HANDLE aThread[THREADCOUNT];
ghMutex = CreateMutex(NULL, FALSE, NULL);
aThread[0] = (HANDLE)_beginthreadex(NULL, 0, &inc, NULL, CREATE_SUSPENDED, 0);
aThread[1] = (HANDLE)_beginthreadex(NULL, 0, &dec, NULL, CREATE_SUSPENDED, 0);
ResumeThread(aThread[0]);
ResumeThread(aThread[1]);
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
printf("j = %d\n", j);
for (int i = 0; i < THREADCOUNT; i++)
CloseHandle(aThread[i]);
CloseHandle(ghMutex);
return 0;
}
Inc function:
unsigned int __stdcall inc(LPVOID)
{
for (volatile int i = 0; i < MAX; ++i)
{
WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
j++;
printf("Thread %d j = %d\n", GetCurrentThreadId(), j);
ReleaseMutex(ghMutex);
}
_endthread();
return TRUE;
}
Dec function:
unsigned int __stdcall dec(void*)
{
for (volatile int i = 0; i < MAX; ++i)
{
WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
j--;
printf("Thread %d j = %d\n", GetCurrentThreadId(), j);
ReleaseMutex(ghMutex);
}
_endthread();
return TRUE;
}
I need a win api solution in std c++98.
A mutex is not the right tool to synchronize two threads, it is there to protect a resource. You do have a resource j which is protected by your mutex, however the sequence of which thread gets the lock is undefined, so you can have the case where dec gets called several times before inc has the chance to run.
If you want to synchronize the order of the threads you will have to use another synchronization primitive, for example a semaphore. You could, for example, increment the semaphore in inc and decrement it in dec. This would be the classic producer - consumer relationship where the producer will be stalled when the semaphore reaches its maximum value and the consumer will wait for items to consume.
Sorry, no WinAPI C++98 solution from me because that would be silly, but I hope I pointed you to the right direction.
windows mutex object guarantees exclusive ownership, but does not care about the ownership order. so that the same thread can capture several times in a row while others will wait.
for your task you need signal to another thread, when your task is done, and then wait for signal from another thread. for this task can be used event pair for example. thread (i) signal event (1-i) and wait on event (i). for optimize instead 2 calls -
SetEvent(e[1-i]); WaitForSingleObject(e[i], INFINITE);
we can use single call SignalObjectAndWait
SignalObjectAndWait(e[1-i], e[i], INFINITE, FALSE)
of course start and end of loop require special care. for inc
HANDLE hObjectToSignal = _hEvent[1], hObjectToWaitOn = _hEvent[0];
for (;;)
{
_shared_value++;
if (!--n)
{
SetEvent(hObjectToSignal);
break;
}
SignalObjectAndWait(hObjectToSignal, hObjectToWaitOn, INFINITE, FALSE);
}
and for dec
HANDLE hObjectToSignal = _hEvent[0], hObjectToWaitOn = _hEvent[1];
WaitForSingleObject(hObjectToWaitOn, INFINITE);
for (;;)
{
--_shared_value;
if (!--n)
{
break;
}
SignalObjectAndWait(hObjectToSignal, hObjectToWaitOn, INFINITE, FALSE);
}
if write full test, with error checking
struct Task
{
HANDLE _hEvent[4];
ULONG _n;
LONG _iTasks;
LONG _shared_value;
Task()
{
RtlZeroMemory(this, sizeof(*this));
}
~Task()
{
ULONG n = RTL_NUMBER_OF(_hEvent);
do
{
if (HANDLE hEvent = _hEvent[--n]) CloseHandle(hEvent);
} while (n);
}
ULONG WaitTaskEnd()
{
return WaitForSingleObject(_hEvent[2], INFINITE);
}
ULONG WaitTaskReady()
{
return WaitForSingleObject(_hEvent[3], INFINITE);
}
void SetTaskReady()
{
SetEvent(_hEvent[3]);
}
void End()
{
if (!InterlockedDecrement(&_iTasks)) SetEvent(_hEvent[2]);
}
void Begin()
{
InterlockedIncrementNoFence(&_iTasks);
}
static ULONG WINAPI IncThread(PVOID p)
{
return reinterpret_cast<Task*>(p)->Inc(), 0;
}
void Inc()
{
if (WaitTaskReady() == WAIT_OBJECT_0)
{
if (ULONG n = _n)
{
HANDLE hObjectToSignal = _hEvent[1], hObjectToWaitOn = _hEvent[0];
for (;;)
{
if (_shared_value) __debugbreak();
if (n < 17) DbgPrint("Inc(%u)\n", n);
_shared_value++;
if (!--n)
{
SetEvent(hObjectToSignal);
break;
}
if (SignalObjectAndWait(hObjectToSignal, hObjectToWaitOn, INFINITE, FALSE) != WAIT_OBJECT_0)
{
break;
}
}
}
}
End();
}
static ULONG WINAPI DecThread(PVOID p)
{
return reinterpret_cast<Task*>(p)->Dec(), 0;
}
void Dec()
{
if (WaitTaskReady() == WAIT_OBJECT_0)
{
if (ULONG n = _n)
{
HANDLE hObjectToSignal = _hEvent[0], hObjectToWaitOn = _hEvent[1];
if (WaitForSingleObject(hObjectToWaitOn, INFINITE) == WAIT_OBJECT_0)
{
for (;;)
{
--_shared_value;
if (_shared_value) __debugbreak();
if (n < 17) DbgPrint("Dec(%u)\n", n);
if (!--n)
{
break;
}
if (SignalObjectAndWait(hObjectToSignal, hObjectToWaitOn, INFINITE, FALSE) != WAIT_OBJECT_0)
{
break;
}
}
}
}
}
End();
}
ULONG Create()
{
ULONG n = RTL_NUMBER_OF(_hEvent);
do
{
if (HANDLE hEvent = CreateEventW(0, n > 2, 0, 0)) _hEvent[--n] = hEvent;
else return GetLastError();
} while (n);
return NOERROR;
}
ULONG Start()
{
static PTHREAD_START_ROUTINE aa[] = { IncThread, DecThread };
ULONG n = RTL_NUMBER_OF(aa);
do
{
Begin();
if (HANDLE hThread = CreateThread(0, 0, aa[--n], this, 0, 0))
{
CloseHandle(hThread);
}
else
{
n = GetLastError();
End();
return n;
}
} while (n);
return NOERROR;
}
ULONG Start(ULONG n)
{
_iTasks = 1;
ULONG dwError = Start();
_n = dwError ? 0 : n;
SetTaskReady();
End();
return dwError;
}
};
void TaskTest(ULONG n)
{
Task task;
if (task.Create() == NOERROR)
{
task.Start(n);
task.WaitTaskEnd();
}
}
note, that no any sense declare local variable (which will be accessed only from single thread and not accessed by any interrupts, etc) as volatile
also when we write code, like:
// thread #1
write_shared_data();
SetEvent(hEvent);
// thread #2
WaitForSingleObject(hEvent, INFINITE);
read_shared_data();
inside SetEvent(hEvent); was atomic write to event state with release semantic (really stronger of course) and inside wait for event function - atomic read it state with more than acquire semantic. as result all what thread #1 write to memory before SetEvent - will be visible to thread #2 after Wait for event (if wait finished as result of call Set from thread #1)

Synchronize 2 processes using a mutex

I have 2 processes:
The first one creates a memory mapped region, a mutex and spawns
the second process. Then writes some pairs of numbers in the memory mapped region.
The second one opens the memory mapped region, opens the mutex and then reads the numbers written by the process 1.
I intended the first process to write a pair of numbers and the second one to immediately read it.
The process 2 seems to be starving.
What did I do wrong?
Process 1:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD memSize = 400 * sizeof(DWORD);
HANDLE map_file = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, memSize, TEXT("mem1"));
if (map_file == NULL)
{
_tprintf(_T("(Parent) File mapping is null\n"));
return 1;
}
char* map_ptr = (char *) MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
if (map_ptr == NULL)
{
_tprintf(_T("(Parent) PTR is null \n"));
}
HANDLE hMutex = CreateMutex(NULL, TRUE, _T("mt"));
LPTSTR szCmdline = _tcsdup(TEXT("C:\\Users\\cristi\\source\\repos\\process_synchronization_reader\\Debug\\process_synchronization_reader.exe"));
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
_tprintf(_T("Process created\n"));
}
_tprintf(_T("pare ca s-a creat"));
for (int i = 1; i <= 200; ++i)
{
WaitForSingleObject(hMutex, INFINITE);
_tprintf(_T("(Parent %d) writing from the parent\n"), i);
DWORD a, b;
CopyMemory((LPVOID) &a, map_ptr, sizeof(DWORD));
map_ptr += sizeof (DWORD);
CopyMemory((LPVOID) &b, map_ptr, sizeof(DWORD));
map_ptr += sizeof(DWORD);
ReleaseMutex(hMutex);
}
int n;
cin >> n;
CloseHandle(map_file);
return 0;
}
Process 2:
#include "stdafx.h"
#include <windows.h>
int main()
{
HANDLE map_file = OpenFileMapping(FILE_MAP_READ, FALSE, TEXT("mem1"));
if (map_file == NULL)
{
_tprintf(_T("(Child) File mapping is null\n"));
return 1;
}
char* map_ptr = (char *) MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
if (map_ptr == NULL)
{
_tprintf(_T("(Child) PTR is null \n"));
}
_tprintf(_T("(CHILD) BEfore reading the first number\n"));
HANDLE hMutex = OpenMutex(SYNCHRONIZE, TRUE, _T("mt"));
for (int i = 1; i <= 200; i++)
{
WaitForSingleObject(hMutex, INFINITE);
DWORD a = i;
DWORD b = 2 * i;
CopyMemory((LPVOID) map_ptr, &a, sizeof(DWORD));
map_ptr += sizeof(DWORD);
CopyMemory((LPVOID) map_ptr, &b, sizeof(DWORD));
map_ptr += sizeof(DWORD);
_tprintf(_T("[================================================]\n"));
_tprintf(_T("( %d %d )\n"), a, b);
_tprintf(_T("[=================================================]\n"));
ReleaseMutex(hMutex);
}
return 0;
}
for got sequential write/read from shared memory we need 2 events (let name it Low and High).
first thread:
write data
signal Low event
wait on High event or break loop
goto 1
second thread:
wait on Low event
read data
break loop or signal High event
goto 1
unlike this solution mutex can not provide a sequence of reading / writing. mutex guarantee that until one thread will be access shared data (read or write) another thread will be not do this in concurrent. but this can not prevent several times in a row for write or read. really - insert messagebox in begin of process 2 - before he first time try acquire mutex - first process already many time acquire and release mutex. or if one thread will be suspended between release and wait for mutex - meanwhile another thread many time wait and release it. so code can look like:
struct SHARED_DATA
{
ULONG id;
ULONG nLoops;
BOOL bTask;
};
DWORD proc2(SHARED_DATA* p)
{
if (HANDLE hLowEvent = OpenEvent(SYNCHRONIZE, FALSE, L"LowEvent"))
{
if (HANDLE hHighEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, L"hHighEvent"))
{
ULONG id = GetCurrentThreadId();
for(;;)
{
if (WaitForSingleObject(hLowEvent, INFINITE) != WAIT_OBJECT_0)
{
break;
}
// ++ checking for sequence
if (p->id == id)
{
__debugbreak();// must never be
}
p->id = id;
// -- checking for sequence
if (!p->bTask)
{
// no more task
break;
}
// task done
p->bTask = FALSE;
// signal to #1
if (!SetEvent(hHighEvent))
{
break;
}
}
CloseHandle(hHighEvent);
}
CloseHandle(hLowEvent);
}
return 0;
}
DWORD proc1(SHARED_DATA* p)
{
if (HANDLE hLowEvent = CreateEvent(0, FALSE, FALSE, L"LowEvent"))
{
if (HANDLE hHighEvent = CreateEvent(0, FALSE, FALSE, L"hHighEvent"))
{
ULONG id = GetCurrentThreadId();
p->nLoops = 0x1000;
p->id = 0;
p->bTask = FALSE;
// exec proc2 here
goto __1;
do
{
if (WaitForSingleObject(hHighEvent, INFINITE) != WAIT_OBJECT_0)
{
break;
}
if (p->bTask)
{
__debugbreak();
}
// ++ checking for sequence
if (p->id == id)
{
__debugbreak();// must never be
}
__1:
p->id = id;
// -- checking for sequence
p->bTask = 0 < --p->nLoops;
// signal to #2
if (!SetEvent(hLowEvent))
{
break;
}
} while (p->nLoops);
CloseHandle(hHighEvent);
}
CloseHandle(hLowEvent);
}
return 0;
}
You create a mutex as initially owned (the second argument to CreateMutex is TRUE) and then you call a wait-function on it. So even after calling ReleaseMutex, it is still owned by a main thread of the first process.
Either change the argument to FALSE, or skip calling WaitForSingleObject for the first loop iteration.

NetApiBufferFree returns ERROR_INVALID_PARAMETER (Error Code 87)

I have been developing an application that uses winapi to get administrator group members. I used NetLocalGroupGetMembers method for that purpose. My problem is when i try to free buffer's heap space i get ERROR_INVALID_PARAMETER (Error Code 87) from NetApiBufferFree method. I have administrator privileges for the application.
Here is the code:
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <lm.h>
#include <time.h>
#include <assert.h>
#define SLEEP_TIME 2000
#define OS_GROUP_NAME L"administrators"
void createServiceThread();
DWORD WINAPI mainServiceThread( LPVOID lpParam );
char** getUsersByLocalGroup();
void freeNetApiBuffer(LPVOID buffer);
int localGroupUserCount;
int WriteToLog(char* str)
{
printf("%s\n", str);
return 0;
}
int main()
{
createServiceThread();
}
void createServiceThread(){
WriteToLog("Application Started...");
while(TRUE){
mainServiceThread(NULL);
Sleep(SLEEP_TIME);
}
WriteToLog("Application Closed...");
}
//-------------------------------------------
// A function that represents Main Service Thread
//-------------------------------------------
DWORD WINAPI mainServiceThread( LPVOID lpParam )
{
time_t startTime;
time (&startTime);
char startTimeText[30];
sprintf(startTimeText, "Service Loop Started %s", ctime(&startTime));
WriteToLog(startTimeText);
localGroupUserCount = 0;
char** localGroupUsers = getUsersByLocalGroup();
WriteToLog("User not found...");
time_t endTime;
time (&endTime);
char endTimeText[30];
sprintf(endTimeText, "Service Loop Ended %s", ctime(&endTime));
WriteToLog(endTimeText);
}
char** getUsersByLocalGroup(){
WriteToLog("getUsersByLocalGroup started");
LOCALGROUP_MEMBERS_INFO_3 *pBuf;
DWORD dwLevel = 3;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
NET_API_STATUS nStatus;
WriteToLog("Call NetLocalGroupGetMembers");
nStatus = NetLocalGroupGetMembers(
NULL,
OS_GROUP_NAME,
dwLevel,
(LPBYTE *) &pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
NULL
);
// nStatus = ERROR_SUCCESS;
WriteToLog("NetLocalGroupGetMembers called");
//
// If the call succeeds,
//
if (nStatus == ERROR_SUCCESS || nStatus == ERROR_MORE_DATA)
{
DWORD i;
DWORD dwTotalCount = 0;
WriteToLog("Correct Status");
if (pBuf != NULL)
{
//
// Loop through the entries.
//
for (i = 0; (i < dwEntriesRead); i++)
{
assert(pBuf != NULL);
if (pBuf == NULL)
{
char bufError[] = "";
sprintf(bufError, "An access violation has occurred %d", stderr);
WriteToLog(bufError);
break;
}
LPWSTR userNameOnBuffer = pBuf->lgrmi3_domainandname;
pBuf++;
dwTotalCount++;
}
localGroupUserCount = dwTotalCount;
char totalCount[] = "";
sprintf(totalCount, "Entries enumerated: %d", dwTotalCount);
WriteToLog(totalCount);
}
//
// Otherwise, print the system error.
//
else{
char systemError[] = "";
sprintf(systemError, "An system error has occurred %d - %d", stderr, nStatus);
WriteToLog(systemError);
}
}
//
// Free the allocated buffer.
//
if (pBuf != NULL)
{
NET_API_STATUS nBufferFreeStatus = NetApiBufferFree((LPVOID)pBuf);
if(nBufferFreeStatus == NERR_Success){
WriteToLog("Succesfully freed buffer");
}
else{
WriteToLog("Error occured freeing buffer");
}
pBuf = NULL;
}
WriteToLog("getUsersByLocalGroup finished");
return NULL;
}
In your loop you have the line pBuf++;. This modifies pBuf which means that the value you are freeing is not the value that was allocated. Hence the invalid parameter.
Also, these lines
char totalCount[] = "";
sprintf(totalCount, "Entries enumerated: %d", dwTotalCount);
create a stack buffer overflow, which is probably corrupting your pBuf variable. There is another instance of it a few lines later.
In general, here's how you debug it: Set a breakpoint as soon as NetLocalGroupGetMembers returns. Look at the value in pBuf and write it down in a safe place. Set another breakpoint when you are about to call NetApiBufferFree. Look at the value of pBuf you are passing. Is it equal to the value you wrote down earlier? If not, then you have a bug. Use the debugger to find out why you are passing the wrong value.

Create multiple files using multi threading in C++ using Win32 API

I am trying to create files in a pen drive. If the pen drive is not present, threads should suspend. When it is inserted it should resume. Here is the code I tried but it's not working properly. Can any one help me?
#include "stdafx.h"
#include <Windows.h>
#include <Strsafe.h>
#include <WinBase.h>
LPCTSTR Disk=L"E:\";
LPTSTR drive_Name=L"E:\\demo";
CRITICAL_SECTION section;
#define BUFFER_SIZE 1024
#define count 10
HANDLE Write_Handle[10],Open_Handle[10],read_Handle[10] ;
DWORD WINAPI check_Thread(LPVOID lpParameter)
{
int *nThreadNo = (int*)lpParameter;
while(1)
{
if(GetDiskFreeSpaceExW(Disk,NULL,NULL,NULL))
{
ResumeThread(Write_Handle[*nThreadNo]);
ResumeThread(read_Handle[*nThreadNo]);
}
else
{
SuspendThread(Write_Handle[*nThreadNo]);
SuspendThread(read_Handle[*nThreadNo]);
}
}
}
DWORD WINAPI Write_Thread(LPVOID lpParameter)
{
DWORD g_tid = GetCurrentThreadId();
_tprintf(_T(" write thread id %d\n"),g_tid);
LPCWSTR filename=(LPCWSTR)lpParameter;
HANDLE ofile;
EnterCriticalSection(&section);
ofile=CreateFileW(filename,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,NULL, NULL);
int d;
d=GetLastError();
if(ERROR_SUCCESS!=GetLastError())
{
_tprintf(_T("error values in open thread %d \n"),GetLastError());
_tprintf(_T("filename %s \n"),filename);
}
const int filesizeinKB = 1024;
BOOL bError;
DWORD dwBytesWritten=0;
WCHAR ReadBuffer[BUFFER_SIZE] = {0};
int i;
for(i = 0; i <= BUFFER_SIZE; i++)
{
ReadBuffer[i] = (char)(i%26 + 'a');
}
for (i = 0; i <= filesizeinKB; i++)
{
SetLastError(0);
bError= WriteFile(ofile, ReadBuffer-1, BUFFER_SIZE,&dwBytesWritten, NULL);
bError=GetLastError();
if (ERROR_SUCCESS!=GetLastError())
{ _tprintf(_T("error value in write %d\n"),GetLastError());
_tprintf(_T(" Write Error...\n"));
return 1;
}
}
SetLastError(0);
CloseHandle(ofile);
_tprintf(_T("write close error values %d\n"),GetLastError());
LeaveCriticalSection(&section);
return 1;
}
DWORD WINAPI Read_Thread(LPVOID lpParameter)
{
HANDLE ofile;
DWORD g_tid = GetCurrentThreadId();
_tprintf(_T(" write thread id %d\n"),g_tid);
LPCWSTR filename=(LPCWSTR)lpParameter;
EnterCriticalSection(&section);
ofile=CreateFileW(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS,NULL, NULL);
int d;
d=GetLastError();
if(ERROR_SUCCESS!=GetLastError())
{
_tprintf(_T("error values in open thread %d \n"),GetLastError());
_tprintf(_T("filename %s \n"),filename);
}
DWORD dwBytesRead=0;
WCHAR ReadBuffer[BUFFER_SIZE] = {0};
_tprintf(_T(" read thread \n"));
SetLastError(0);
int err;
ReadFile(ofile, ReadBuffer, (BUFFER_SIZE-1), &dwBytesRead, NULL);
err=GetLastError();
_tprintf(_T("read error values %d \n"),GetLastError());
if(ERROR_SUCCESS!=GetLastError())
{
_tprintf(L"reading failed \n");
return 0;
}
SetLastError(0);
CloseHandle(ofile);
err=GetLastError();
_tprintf(_T("close error values %d\n"),GetLastError());
LeaveCriticalSection(&section);
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
unsigned int myCounter = 0;
DWORD WritethreadID,OpenThreadID,ReadthreadID;
HANDLE check_Handle;
DWORD exThread;
TCHAR filename[100];
HANDLE hfile;
INT bsize=100;
int i=0;
InitializeCriticalSection (&section);
CreateDirectory(drive_Name,NULL);
for(i=0;i<5;i++)
{
SetLastError(0);
StringCchPrintf(filename,bsize, TEXT("%s\\file_%d.txt"),drive_Name,i );
hfile=CreateFileW(filename,GENERIC_WRITE|GENERIC_READ,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
_tprintf(_T("invalid handle \n" ));
}
_tprintf(_T("file created %s\n"),filename);
CloseHandle(hfile);
Write_Handle[i] =CreateThread(0, 0, Write_Thread, filename, CREATE_SUSPENDED, &WritethreadID);
SetThreadPriority(Write_Handle[i],2);
_tprintf(_T("write thread id is %d\n"),WritethreadID);
read_Handle[i]=CreateThread(0, 0, Read_Thread, filename, CREATE_SUSPENDED, &ReadthreadID);
SetThreadPriority(read_Handle[i],1);
_tprintf(_T("read thread id is %d\n "),ReadthreadID);
check_Handle =CreateThread(0, 0, check_Thread,(void*)&i ,0,&OpenThreadID);
}
for (i=0; i<count; ++i)
{
WaitForSingleObject(Write_Handle[i],INFINITE);
if ( !GetExitCodeThread(Write_Handle, &exThread) )
{
_tprintf(_T("close thread %08X\n"),GetLastError());
}
SetLastError(0);
CloseHandle(Write_Handle[i]);
_tprintf(_T("close thread %08X\n"),GetLastError());
WaitForSingleObject(read_Handle[i],INFINITE);
if ( !GetExitCodeThread(read_Handle, &exThread) )
{
_tprintf(_T("GetExitCodeThread %08X\n"),GetLastError());
}
SetLastError(0);
CloseHandle(read_Handle[i]);
_tprintf(_T("GetExitCodeThread %08X\n"),GetLastError());
CloseHandle(check_Thread);
}
DeleteCriticalSection(&section);
return 1;
}
If you have open file handles to a USB drive when that drive is removed, those file handles will become invalid. Reinserting the USB drive will not reconstitute those handles in such a way that you can continue after resuming a thread.
You will need to:
detect when the device is removed, and close those now-broken handles
when the device is inserted, open the files again and continue whatever you were doing
Your error handlers are returning without calling LeaveCriticalSection, leaving the CS locked and blocking the other threads indefinitely. From the EnterCriticalSection docs:
If a thread terminates while it has ownership of a critical section,
the state of the critical section is undefined.
Those cases also leave the file handles open.