C++ _tWinMain run more than one times? - c++

Im using DuiLib and Cef.
and I fond that my _tWinMain called 2 times.
1:When I open app,main() was called;
2 When I Create a Window, main() was called 2nd.
here is some code:
vector<wstring> StartArgs;
map<wstring, wstring> argsMaps;
void GetArgMap() {
for (int i = 1; i < StartArgs.size(); ++i) {
wstring argStr = StartArgs[i];
vector<wstring> argVec;
split(argStr, L':', argVec);
if (argVec.size() >= 2) {
wstring k = argVec[0];
wstring v = argVec[1];
argsMaps.insert(map<wstring, wstring>::value_type(k,v));
}
}
}
wstring GetArgForKey(wstring key) {
wstring ret = argsMaps[key];
if (lstrcmpW(ret.c_str(), L"")) {
return ret;
}
else {
return L"null";
}
}
bool CheckParamAvialble(wstring param) {
if (lstrcmpW(param.c_str(), L"null")) {
return true;
}
else {
return false;
}
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,
int nCmdShow)
{
ShowMessageBox(L"this is test alert!", L"WARNING");
int argCount = 0;
LPWSTR cmdline = GetCommandLine();
//cmdline is [m:1 h:0 a:500000 n:xxx c:xxx u:usera o:TOKEN]
LPWSTR* szArgList = CommandLineToArgvW(cmdline, &argCount);
for (int i = 0; i < argCount; ++i) {
wstring a = szArgList[i];
StartArgs.push_back(a);
}
if (argCount >= 7) {
wstring mString = GetArgForKey(L"m");
if (!CheckParamAvialble(mString))
{
ShowMessageBox(L"arg m is wrong!", L"Error");
return 0;
}
/*
do something with other args
*/
CPaintManagerUI::SetInstance(hInstance);
InitResource();
HRESULT Hr = ::CoInitialize(NULL);
if (FAILED(Hr)) return 0;
CefMainArgs args(hInstance);
CefRefPtr<SimpleApp> app(new SimpleApp);
int exitCode = CefExecuteProcess(args, app, NULL);
if (exitCode >= 0)
{
return exitCode;
}
CefSettings settings;
CefInitialize(args, settings, app.get(), NULL);
CefRefPtr<CefCommandLine> command_line;
command_line = CefCommandLine::CreateCommandLine();
command_line->AppendSwitch("no-proxy-server");
MainForm *pFrame = new MainForm(_T("Forms\\MA_MainForm.xml"));
if (pFrame == NULL) return 0;
pFrame->Create(NULL, _T("MainForm"), UI_WNDSTYLE_FRAME, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 0, 0, 600, 800);//when progrom go here,i got 2nd MessageBox[this is test alert!]
pFrame->CenterWindow();
CefRunMessageLoop();
CefShutdown();
return 0;
}
else
{
ShowMessageBox(L"something wrong and exit", L"Error");
return 0;
}
}
and the strange thing is
2nd call main() wont trigger my break point, it just show messagebox[this is test alert!] again.
and if i show another window, it will show 3rd messagebox[this is test alert!]
just show the messagebox multiple times,no break,no exception.
thanks a lot.

Have you read over how the Chromium Embedded Framework works? It will create multiple processes, normally by spawning additional copies of the main executable. When that happens, you'll get a different process displaying your "this is a test alert" dialog. Since this is a different process, your breakpoints will not be hit unless you have your debugger configured to debug any spawned child processes.
The result is that what you see is the expected behavior.

Related

C++ Win API - FindWindow() or EnumWindows() to retrieve specific windows

I have the following problem with retrieving the window handle from a specific window (title and class name are known):
There are two identical windows with different handles under two different processes, but FindWindow() can find the handle only from the newest window spawned, never from the first one.
What can be used instead? Can EnumWindows() be used to retrieve a list of windows with the same characteristics?
Use the Win32 API EnumWindows , and then check which process each window belongs to by using the Win32 API GetWindowThreadProcessId.
Here is a sample:
#include <iostream>
#include <Windows.h>
using namespace std;
BOOL CALLBACK enumProc(HWND hwnd, LPARAM) {
TCHAR buf[1024]{};
GetClassName(hwnd, buf, 100);
if (!lstrcmp(buf, L"Notepad"))
{
GetWindowText(hwnd, buf, 100);
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
wcout << buf << " " << pid << endl;
}
return TRUE;
}
int main() {
EnumWindows(&enumProc, 0);
}
If you need to check the window of each process, you can refer to this answer.
typedef struct
{
const char *name;
const char *class;
HWND handles[10];
int handlesFound;
} SearchWindowInfo;
SearchWindowInfo wi;
wi.handlesFound = 0;
wi.title = "WindowName";
wi.class = "ClassName";
BOOL CALLBACK searchWindowCallback(HWND hwnd, LPARAM lParam)
{
SearchWindoInfo *wi = (SearchWindoInfo *)lParam;
char buffer[256];
if (wi->handlesFound == 10)
return FALSE;
buffer[255] = 0;
if (wi->name)
{
int rc = GetWindowText(hwnd, buffer, sizeof(buffer)-1);
if(rc)
{
if (strcmp(wi->name, buffer) == 0)
{
wi->handles[wi->handlesFound++] = hwnd;
return TRUE;
}
}
}
if (wi->class)
{
int rc = GetClassName (hwnd, buffer, sizeof(buffer)-1);
if(rc)
{
if (strcmp(wi->class, buffer) == 0)
{
wi->handles[wi->handlesFound++] = hwnd;
return TRUE;
}
}
}
return TRUE;
}
EnumWindows(searchWindowCallback, (LPARAM)&wi);
for(int i = 0; i < wi.handlesFound; i++)
{
// yeah...
}

Memory leak when using IShellItem2.GetString()

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

C++ GetModuleFileName does not return correct strings

Sometimes GetModuleFileName returns the correct string, however 99% of the time currently with current code I am using the string returns as ÀÙáøÛáws\system32\HID.DLL instead of E:\Windows\system32\HID.DLL that should be the correct value. With this in mind I can't compare the string with an list of all modules that should be loaded to see if that string is in the list, if not someone injected that DLL.
This code below might not be the best, however it is the code I attempted to use for this. I did try all sorts of code changes to try to figure it out like not using TCHAR and investigating the returns from EnumProcessModules.
void _scan_dll_data(VBTrpSetup_t &setup, VBTrp_DetectData_t &_ret, VBTrp_InjectData_t &_dlllists) {
bool _detected_injected_dll = false;
std::vector<std::string> _ModuleContainer;
std::string _ModuleName;
HMODULE hMods[1024]; /* Hopefully enough for this. */
DWORD cbNeeded;
if (EnumProcessModules(setup.GameProcHandle, hMods, sizeof(hMods), &cbNeeded)) {
for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) {
char szModName[MAX_PATH];
if (GetModuleFileName(hMods[i], szModName, sizeof(szModName) / sizeof(char))) {
_ModuleName = szModName;
for (unsigned int i = 0; i < _dlllists.ModuleExcludeList.size(); i++) {
// item must not be in the ModuleExcludeList!!!
if (!_dlllists.ModuleExcludeList[i].compare(_ModuleName)) {
_ModuleContainer.push_back(_ModuleName);
}
}
}
}
}
if (_dlllists.ModuleList != _ModuleContainer) {
_detected_injected_dll = true;
_ret.DLLName = reinterpret_cast<LPCSTR>(_ModuleName.c_str());
}
if (_detected_injected_dll) {
_ret.value = TRUE;
}
else {
_ret.value = FALSE;
}
if (_ret.value == TRUE) {
_ret.int_value = -1;
} else {
_ret.int_value = NULL;
}
}
Hopefully the answer is something simple that I must have missed. I did do some parts of this according to MSDN examples. Maybe those examples was wrong. I am not so sure.
Does anyone know how to fix this string issue it returns?
The fix was to definately use the Unicode versions and to make the whole function use wide unicode strings. And the reason for this is because of a struct (related to PEB) that is internal and undocumented to ntdll.dll.
So, basically changing everything to the GetModuleBaseNameW function because of the fact I was going to basename them anyway later, the wstring, noticing a second loop using i causing an overwrite of the i on the outer for loop and removing it, and adding checks on GetLastError for when the Handle is invalidated and toreturn the error code to the end user to handle cleanup.
The result is then this code:
void _scan_dll_data(VBTrpSetup_t &setup, VBTrp_DetectData_t &_ret, VBTrp_InjectData_t &_dlllists) {
BOOL _detected_injected_dll = FALSE;
std::vector<std::wstring> _ModuleContainer;
HANDLE hProcess;
std::vector<HMODULE> hMods;
DWORD cbNeeded;
hProcess = GetCurrentProcess();
_ret.int_value = 0;
if (EnumProcessModulesEx(hProcess, hMods.data(), setup.NumOfModules, &cbNeeded, LIST_MODULES_ALL)) {
for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
wchar_t *szModName = L'\x0';
std::wstring _ModuleName;
if (GetModuleBaseNameW(hProcess, hMods[i], reinterpret_cast<LPWSTR>(szModName), MAX_PATH)) {
_ModuleName = szModName;
// item must not be in the ModuleExcludeList!!!
if (!_dlllists.ModuleExcludeList[i].compare(_ModuleName)) {
_ModuleContainer.push_back(_ModuleName);
}
} else {
_ret.error_code = GetLastError();
}
}
} else {
_ret.error_code = GetLastError();
}
if (_ret.error_code != ERROR_INVALID_HANDLE) {
for (unsigned int j = 0; j < _dlllists.ModuleList.size(); j++) {
if (_dlllists.ModuleList[j] != _ModuleContainer[j]) {
_detected_injected_dll = TRUE;
_ret.int_value = -1;
_ret.DLLName = (LPWSTR)_ModuleContainer[j].c_str();
// to avoid overwriting the first one.
break;
}
}
_ret.value = _detected_injected_dll;
}
}

C++, Get handle to open process

I'm trying to get a handle to my open processes, this is what I've got:
#include "stdafx.h"
#include <Psapi.h>
using namespace std;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int iCmdShow)
{
bool _result;
DWORD *pProcessIds = new DWORD[1000];
DWORD cb;
DWORD *pBytesReturned= new DWORD[1000];
_result = EnumProcesses(pProcessIds, 1000,pBytesReturned);
HANDLE _Proccess = new HANDLE;
for (int i = 0;i<=1000; i++)
{
_Proccess = OpenProcess(READ_CONTROL, false, *pProcessIds);
DWORD error;
error = GetLastError();
CloseHandle(_Proccess);
pProcessIds ++;
}
return 0;
}
1- I am constanly getting error "87".
2- _Proccess isn't being assigned anything either. On every itertaion its being set at "0x00000000".
3- EnumProcess is working correctly because pBytesReturned returns a number.
Any Ideas?
Make sure you run as administrator
for (int i = 0;i<=1000; i++)
is wrong because you are missing the last iteration, change <= to <
DWORD *pBytesReturned= new DWORD[1000];
This can just be DWORD bytesToReturn instead of this dynamic array because you only need an integer return.
EnumProcesses(pProcessIds, 1000,pBytesReturned);
Instead of hardcoding 1000, use sizeof(array)
MSDN has a tutorial on how to do this properly.
I modified the code to do what you want it to do and tested it working:
int main(void)
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
{
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
for (i = 0; i < cProcesses; i++)
{
if (aProcesses[i] != 0)
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, aProcesses[i]);
CloseHandle(hProc);
}
}
return 0;
}

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.