|
I have the same problem. while debugging some jni code. i have to power down the machine. won't restart. won't let me log off!!
way to go microsoft!!!!
|
|
|
|
|
I've been having this issue as well for the last two months or so, and found it very annoying (I work remotely and sometimes need to reboot the machine - the presence of orphan windows makes it impossible). Guess I'm not adding anything useful to this discussion, but maybe if enough voices of protest are raised, Redmond would do something about it.
|
|
|
|
|
I'm currently working on a rewrite of my most recent article Monitoring and Controlling a Recursing Function in a Worker Thread. I was as happy as someone could be when they've managed to get something that they've been very baffled by to actually do what they wanted it to do when I submitted the original article. Luckily for me, though, someone who is a better programmer than I kindly pointed out the short cuts in it which I was too ignorant to even know I'd made.
So - sixteen months after posting the original article I am currently preparing an update which includes new code employing exclusion techniques which, I hope, satisfies thread safety requirements thereby making the article more useful to people who want to base more complex threaded software on it.
Beyond the thread safety issue, I also looking in to the issue of making the thread function a global (non static) function. This was suggested as a possibility to me. I am not sure why this might be a benefit. The process of re-implementing the function is helping me to attend to the threadsafe issues, though.
I would be very glad to hear of any ideas you have of the benefits of moving the function to a global scope - or possibly keeping it as a member function.
Thanks,
Ben.
|
|
|
|
|
IMO, it's just a matter of style. if your thread func needs to access something that's defined inside the class (typedefs, enums, child classes, etc.) then it makes sense to use a static member function. but if the thread func doesn't need anything like that, i'd use a global static.
|
|
|
|
|
Thanks! That's the impression I've been getting.
|
|
|
|
|
Hi everyone, can anybody help me by answering this question please:
write a program that implements a Phone Number Encrypter. This entity should be capable of reading a telephone number as a string in the form (555) 555-5555. Reading should include validating the format i.e. while (555) 555-5555 would be correct, 5555555555 would be incorrect as also (555) abc-3128, (3m5) 523+3289. It should then extract the area code, the first three digits of the phone number and the last four digits of the phone number. The seven digits of the phone number should then be concatenated into one string. The next step would be to convert the area code and the seven digit phone number strings into ints. Finally, you want to encrypt the number as follows:
• The area code should be converted to the binary notation using the complete number e.g. 555 would be 1000101011. Note that you would need 10 bits to accommodate all possible combinations
• The seven digit phone number should be converted into binary notation where all digits should first be added and the sum be converted into binary notation. In the given example the sum of the digits in 5555555 is 35 and hence the binary notation will be 100011. Six bits should suffice to hold the results
Finally the two encrypted binary representations should be concatenated. This would be a 16 digit binary number.
Implement a class to represent a Phone Number Encrypter. Following good object oriented programming practices, keep the data members private. Accessor functions should be declared to set and get the private data if needed, your overloaded input operator should take care of reading the phone number initially. You are free to use c-strings or objects of string class to store the ISBN as a string, although, the object-oriented string class is recommended. Write a test program to illustrate the use of your class.
I know it a long question but I really need your help...
|
|
|
|
|
I see that you have posted the text of your homework assignment. Unfortunately, you seem to have forgotten to include your actual question about it, or indicate what you have done on it. For more information, please see here[^].
Once you post your question, someone maybe able to help you.Please do not read this signature.
|
|
|
|
|
What have you done so far ? Watched code never compiles.
|
|
|
|
|
zakria81 wrote: I know it a long question
I can't see any question.
|
|
|
|
|
Hi,
My purpose is to help the author of mpatrol to make that program as easy to use than valgrind on Windows. So i tried to look at DLL injection and API hooking.
I have written a program (named valgrind :p) and a DLL to test those 2 technics. More precisely, I have:
- valgrind.exe : the program that will inject the DLL below
- valgrind.dll : the DLL that will be injected in an executable and that will do API hooking
- valgrind_test.exe : a executable that calls a function overloaded in valgrind.dll
I have taken some bits of code here and there in CodeProject. For the DLL injection, I used the VirtualAllocEx() / CreateRemoteThread() technic. For the API hooking, I enumerate all the modules and use ImageDirectoryEntryToData().
Here are the different codes:
valgrind.c
#include <stdio.h>
#include <string.h>
#include <windows.h>
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
typedef HMODULE (*_load_library) (const char *);
typedef BOOL (*_free_library) (HMODULE);
typedef struct _Vg Vg;
struct _Vg
{
_load_library ll;
_free_library fl;
char *dll_fullname;
int dll_length;
struct {
HANDLE process1;
HANDLE thread;
HANDLE process2;
} child;
DWORD exit_code;
};
FARPROC
_vg_symbol_get (const char *module, const char *symbol)
{
HMODULE mod;
FARPROC proc;
printf (" * loading library %s... ", module);
mod = LoadLibrary(module);
if (!mod)
{
printf("failed\n", module);
return NULL;
}
printf ("done\n");
printf (" * retrieving symbol %s... ", symbol);
proc = GetProcAddress(mod, symbol);
if (!proc)
{
printf("failed\n", symbol);
goto free_library;
}
printf ("done\n");
FreeLibrary(mod);
return proc;
free_library:
FreeLibrary(mod);
return NULL;
}
Vg *
vg_new()
{
char buf[MAX_PATH];
Vg *vg;
HMODULE kernel32;
DWORD length;
kernel32 = LoadLibrary("kernel32.dll");
if (!kernel32)
{
printf("no kernel32.dll found\n");
return 0;
}
if (!GetProcAddress(kernel32, "CreateRemoteThread"))
{
printf("no CreateRemoteThread found\n");
goto free_kernel32;
}
vg = (Vg *)calloc (1, sizeof (Vg));
if (!vg)
goto free_kernel32;
vg->ll = (_load_library)_vg_symbol_get("kernel32.dll", "LoadLibraryA");
if (!vg->ll)
goto free_vg;
vg->fl = (_free_library)_vg_symbol_get("kernel32.dll", "FreeLibrary");
if (!vg->fl)
goto free_vg;
length = GetFullPathName("valgrind_dll.dll", MAX_PATH, buf, NULL);
if (!length)
{
printf ("can't get full path name\n");
goto free_vg;
}
vg->dll_fullname = _strdup(buf);
if (!vg->dll_fullname)
goto free_vg;
vg->dll_length = length + 1;
FreeLibrary(kernel32);
return vg;
free_vg:
free(vg);
free_kernel32:
FreeLibrary(kernel32);
return 0;
}
void
vg_del(Vg *vg)
{
if (!vg)
return;
if (vg->child.process2)
CloseHandle(vg->child.process2);
if (vg->child.thread)
CloseHandle(vg->child.thread);
if (vg->child.process1)
CloseHandle(vg->child.process1);
free(vg->dll_fullname);
free(vg);
}
int vg_dll_inject(Vg *vg, const char *prog)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE process;
HANDLE remote_thread;
LPVOID remote_string;
DWORD exit_code;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
printf (" * creating child process %s... ", prog);
if (!CreateProcess(NULL, (char *)prog, NULL, NULL, TRUE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
printf ("failed\n * can't spawn child process %s\n", prog);
return 0;
}
printf ("done\n");
printf (" * waiting for the child process to initialize... ");
if (!WaitForInputIdle(pi.hProcess, INFINITE))
{
printf("failed\n * no process for %s\n", prog);
goto close_handles;
}
printf ("done\n");
printf (" * opening child process... ");
process = OpenProcess(CREATE_THREAD_ACCESS, FALSE, pi.dwProcessId);
if (!process)
{
printf("failed\n * no process for %s\n", prog);
goto close_handles;
}
printf ("done\n");
printf (" * allocating virtual memory... ");
remote_string = VirtualAllocEx(process, NULL, vg->dll_length, MEM_COMMIT, PAGE_READWRITE);
if (!remote_string)
{
printf("failed\n");
goto close_process;
}
printf ("done\n");
printf(" * writing process in virtual memory... ");
if (!WriteProcessMemory(process, remote_string, vg->dll_fullname, vg->dll_length, NULL))
{
printf("failed\n");
goto virtual_free;
}
printf ("done\n");
printf (" * execute thread... ");
remote_thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)vg->ll, remote_string, 0, NULL);
if (!remote_thread)
{
printf("failed\n");
goto virtual_free;
}
printf ("done\n");
WaitForSingleObject(remote_thread, INFINITE);
printf (" * getting exit code... ");
if (!GetExitCodeThread(remote_thread, &exit_code))
{
printf("failed\n");
goto close_thread;
}
printf ("done\n");
CloseHandle(remote_thread);
VirtualFreeEx(process, remote_string, vg->dll_length + 1, MEM_RELEASE);
printf(" * resume child process\n");
ResumeThread(pi.hThread);
vg->child.process1 = pi.hProcess;
vg->child.thread = pi.hThread;
vg->child.process2 = process;
vg->exit_code = exit_code;
return 1;
close_thread:
CloseHandle(remote_thread);
virtual_free:
VirtualFreeEx(process, remote_string, vg->dll_length, MEM_RELEASE);
close_process:
CloseHandle(process);
close_handles:
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
void
vg_dll_extract(Vg *vg)
{
HANDLE thread;
thread = CreateRemoteThread(vg->child.process2, NULL, 0,
(LPTHREAD_START_ROUTINE)vg->fl,
(void*)vg->exit_code, 0, NULL );
WaitForSingleObject(thread, INFINITE );
CloseHandle(thread );
}
int main(int argc, char *argv[])
{
Vg *vg;
vg = vg_new();
if (!vg)
return -1;
if (!vg_dll_inject(vg, "valgrind_test.exe"))
{
printf(" * injection failed\n * exiting...\n");
goto del_vg;
}
Sleep(2000);
printf(" * fin process\n");
vg_dll_extract(vg);
vg_del(vg);
printf(" * ressources freed\n");
return 0;
del_vg:
vg_del(vg);
return -1;
}
valgrind.dll
#include <stdio.h>
#include <windows.h>
#include <psapi.h>
#include <imagehlp.h>
typedef struct
{
char *func_name_old;
PROC func_proc_old;
PROC func_proc_new;
} Vg_Hook;
typedef LPVOID (WINAPI *vgd_heap_alloc_t) (HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
typedef BOOL (WINAPI *vgd_heap_free_t) (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
typedef void (WINAPI *vgd_get_system_info_t)(LPSYSTEM_INFO lpSystemInfo);
typedef void (WINAPI *vgd_get_system_time_t)(LPSYSTEM_INFO lpSystemTime);
Vg_Hook vg_hooks_kernel32[2];
LPVOID WINAPI VG_HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
{
vgd_heap_alloc_t *ha;
LPVOID data;
printf("HeapAlloc !!!\n");
ha = (vgd_heap_alloc_t *)vg_hooks_kernel32[0].func_proc_old;
data = (*ha)(hHeap, dwFlags, dwBytes);
return data;
}
BOOL WINAPI VG_HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
vgd_heap_free_t *hf;
BOOL res;
printf("HeapFree !!!\n");
hf = (vgd_heap_free_t *)vg_hooks_kernel32[1].func_proc_old;
res = (*hf)(hHeap, dwFlags, lpMem);
return res;
}
void WINAPI VG_GetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
{
vgd_get_system_info_t *gsi;
printf ("GetSystemInfo !!!\n");
gsi = (vgd_get_system_info_t *)vg_hooks_kernel32[0].func_proc_old;
(*gsi)(lpSystemInfo);
}
void WINAPI VG_GetSystemTime(LPSYSTEM_INFO lpSystemTime)
{
vgd_get_system_time_t *gst;
printf ("GetSystemTime !!!\n");
gst = (vgd_get_system_time_t *)vg_hooks_kernel32[1].func_proc_old;
(*gst)(lpSystemTime);
}
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
void
_vgd_modules_hook_set(HMODULE module, const char *lib_name, PROC old_function_proc, PROC new_function_proc)
{
PIMAGE_IMPORT_DESCRIPTOR iid;
PIMAGE_THUNK_DATA thunk;
ULONG size;
iid = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
if (!iid)
return;
while (iid->Name)
{
PSTR module_name;
module_name = (PSTR)((PBYTE) module + iid->Name);
if (_stricmp(module_name, lib_name) == 0)
break;
iid++;
}
if (!iid->Name)
return;
thunk = (PIMAGE_THUNK_DATA)((PBYTE)module + iid->FirstThunk );
while (thunk->u1.Function)
{
PROC *func;
func = (PROC *)&thunk->u1.Function;
if (*func == old_function_proc)
{
MEMORY_BASIC_INFORMATION mbi;
DWORD dwOldProtect;
VirtualQuery(func, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if (!VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect))
return;
*func = *new_function_proc;
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect);
break;
}
thunk++;
}
}
void
_vgd_modules_hook(HMODULE main_module, const char *lib_name)
{
HMODULE mods[1024];
HMODULE lib_module;
DWORD mods_nbr;
unsigned int i;
unsigned int j;
lib_module = LoadLibrary(lib_name);
for (j = 0; vg_hooks_kernel32[j].func_name_old; j++)
vg_hooks_kernel32[j].func_proc_old = GetProcAddress(lib_module, vg_hooks_kernel32[j].func_name_old);
if (!EnumProcessModules(GetCurrentProcess(), mods, sizeof(mods), &mods_nbr))
return;
for (i = 0; i < (mods_nbr / sizeof(HMODULE)); i++)
{
if (mods[i] == main_module)
continue;
for (j = 0; vg_hooks_kernel32[j].func_name_old; j++)
_vgd_modules_hook_set(mods[i], lib_name,
vg_hooks_kernel32[j].func_proc_old,
vg_hooks_kernel32[j].func_proc_new);
}
FreeLibrary(lib_module);
}
void
_vgd_modules_unhook(HMODULE main_module, const char *lib_name)
{
HMODULE mods[1024];
DWORD mods_nbr;
unsigned int i;
unsigned int j;
if (!EnumProcessModules(GetCurrentProcess(), mods, sizeof(mods), &mods_nbr))
return;
for (i = 0; i < (mods_nbr / sizeof(HMODULE)); i++)
{
if (mods[i] == main_module) continue;
for (j = 0; vg_hooks_kernel32[j].func_name_old; j++)
_vgd_modules_hook_set(mods[i], lib_name,
vg_hooks_kernel32[j].func_proc_new,
vg_hooks_kernel32[j].func_proc_old);
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)
{
vg_hooks_kernel32[0].func_name_old = "GetSystemInfo";
vg_hooks_kernel32[0].func_proc_old = NULL;
vg_hooks_kernel32[0].func_proc_new = (PROC)VG_GetSystemInfo;
vg_hooks_kernel32[1].func_name_old = "GetSystemTime";
vg_hooks_kernel32[1].func_proc_old = NULL;
vg_hooks_kernel32[1].func_proc_new = (PROC)VG_GetSystemTime;
vg_hooks_kernel32[2].func_name_old = NULL;
vg_hooks_kernel32[2].func_proc_old = NULL;
vg_hooks_kernel32[2].func_proc_new = NULL;
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
printf ("DLL attach\n");
printf ("hooking... ");
_vgd_modules_hook(hModule, "kernel32.dll");
printf ("finished\n");
break;
case DLL_PROCESS_DETACH:
printf ("DLL detach\n");
break;
}
return TRUE;
}
and the test code :
#include <stdio.h>
#include <windows.h>
int main()
{
SYSTEMTIME st;
GetSystemTime(&st);
return 0;
}
Now, the problems:
- If i don't hook the functions in valgrind.dll, the injection is correctly done (there is a message displayed when the DLLL process is attached and one when the test example is executed).
- If I hook several functions, the test program is executed, but an exception is raised (see the comment at the bottom of the test file. Sorry it is in french...)
I don't understand at all the problem.
Here is an archive of the code (with a Makefile for the gcc users or a visual studio solution) to test the code)
Does someone see the problem ?
thank you
|
|
|
|
|
Hi
I have a MDI application. I added functions for "ID_FILE_SAVE" and "ID_FILE_SAVE_AS". But When I ran the application and tried the "Save" and "Save As" menu, application will never go to the defined function. There is always "File Save as" dialog box show.
How can I catch the "ID_FILE_SAVE"? How can I know where the application goes?
Thanks,
|
|
|
|
|
What do the message map entries for ID_FILE_SAVE and ID_FILE_SAVE_AS look like?"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
I used class property to add "message map entries". But software does not go there. I think I messed up something.
Thanks,
|
|
|
|
|
It works perfectly for me.
I added the event handler called OnFileSave in the view class.
You probably added the event handler in the wrong class that is not part of the doc-view architecture.
|
|
|
|
|
Yes, It works perfectly for other application.
BEGIN_MESSAGE_MAP( CSplitFrame, CMDIChildWnd )
ON_COMMAND( ID_FILE_SAVE, IDFileSave )
ON_COMMAND( ID_FILE_SAVE_AS, IDFileSaveAs )
...
Is there a way to catch the message?modified on Monday, February 15, 2010 10:14 AM
|
|
|
|
|
The problem lies in the class in which you're trying to put a handler for it.
In an MDI application it is the View class that gets the first chance to handle the message.
If there is no handler, the control goes to the document class.
Only then does the child frame get a chance to handle the message.
What you're seeing is the default implementation of the document class.
You can catch the message by adding the handler in the view class or the document class.
|
|
|
|
|
Hi friends
How to compact a database using CDatabase class or any other method in Visual C++
thanks in advance-kk.tvm-
|
|
|
|
|
See, for instance, from the competitors : "Compact an Access Database Programmatically".
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Hi, The OutlookDemo Sample of MFC new Feature pack implements a very good style of CMFCOutlookBarTabCtrl class that when you configure the gui to look in office 2003 and office XP modes the tabs of the CMFCOutlookbar Open and go upward by clicking on them but I couldn't found what to do reach this style of tabs through the sample source code. if any one knows the answer I will be thankful if he could modify my below code so i could reach that style.
m_wndOutlookBar.SetMode2003(true);
m_wndOutlookBar.Create(_T("test"), this, CRect (50, 50, 500, 500), ID_VIEW_OUTLOOKBAR, WS_CHILD | WS_VISIBLE | CBRS_LEFT);
m_wndOutlookPane1.Create (&m_wndOutlookBar,
AFX_DEFAULT_TOOLBAR_STYLE, ID_OUTLOOK_PANE_GENERAL, AFX_CBRS_FLOAT | AFX_CBRS_RESIZE);
m_wndOutlookPane1.EnableDocking (CBRS_ALIGN_ANY);
m_wndOutlookPane1.AddButton (theApp.LoadIcon (IDR_MAINFRAME), L"Open", ID_APP_ABOUT);
m_wndOutlookPane2.Create (&m_wndOutlookBar,
AFX_DEFAULT_TOOLBAR_STYLE, ID_OUTLOOK_PANE_SPECIAL, AFX_CBRS_FLOAT | AFX_CBRS_RESIZE);
m_wndOutlookPane2.EnableDocking (CBRS_ALIGN_ANY);
CMFCOutlookBarTabCtrl::EnableAnimation(TRUE);
CMFCOutlookBarTabCtrl* pOutlookBar =
(CMFCOutlookBarTabCtrl*) m_wndOutlookBar.GetUnderlyingWindow ();
pOutlookBar->EnableInPlaceEdit(TRUE);
pOutlookBar->EnableAnimation(true);
pOutlookBar->EnableScrollButtons();
pOutlookBar->EnableTabSwap(true);
(CMFCBaseTabCtrl*)pOutlookBar->EnableTabDetach(0,true);
pOutlookBar->AddTab (&m_wndOutlookPane1, L"General", (UINT) -1, TRUE);
pOutlookBar->AddTab (&m_wndOutlookPane2, L"Special", (UINT) -1, TRUE);
|
|
|
|
|
I Found Answer By my self ,And It was about the method
m_wndBarOutlook.SetMode2003(TRUE);
Because in the sample program of MSDN in the 2003 style and XP Mode it changes the way I like I never think of that to have this style
I should use it the following way
m_wndBarOutlook.SetMode2003(FALSE);
|
|
|
|
|
I run a worker thread like this:
m_first = AfxBeginThread(MyThreadProcTT1, segmentation,THREAD_PRIORITY_ABOVE_NORMAL);
in the MyThreadProcTT1, i run four worker threads like this:
CWinThread* first=NULL;
first = AfxBeginThread(MyThreadProc, pNewObject,THREAD_PRIORITY_ABOVE_NORMAL);
second = AfxBeginThread(MyThreadProc1, pNewObject1,THREAD_PRIORITY_ABOVE_NORMAL);
third = AfxBeginThread(MyThreadProc2, pNewObject2,THREAD_PRIORITY_ABOVE_NORMAL);
forth = AfxBeginThread(MyThreadProc3, pNewObject3,THREAD_PRIORITY_ABOVE_NORMAL);
WaitForSingleObject(first->m_hThread, INFINITE);
WaitForSingleObject(second->m_hThread, INFINITE);
WaitForSingleObject(third->m_hThread, INFINITE);
WaitForSingleObject(forth->m_hThread, INFINITE);
in most of the time, the program work fine. But in some situations, the program halts and do not anything!
Is there anyone can help me!
Best,
MJM
|
|
|
|
|
I spot an issue in your code: All threads have their priorities set to THREAD_PRIORITY_ABOVE_NORMAL , which I think could be avoided. What is your justification for doing this?
mostafa_pasha wrote: But in some situations, the program halts and do not anything!
And what does that mean? Have you used the debugger to step into the code? Have you verified all the WaitForSingleObject calls have returned (as you're asking the program to wait for an INFINITE amount of time)?!
“Follow your bliss.” – Joseph Campbell
|
|
|
|
|
I taught coping the software is for thread priority.So i tried to change the priority to ABOVE_NORMAL.
About debugging,
i changed the code:
WinThread* first=NULL;
first = AfxBeginThread(MyThreadProcT, &pmom1,THREAD_PRIORITY_ABOVE_NORMAL);
if(first == NULL)
{
AfxMessageBox(_T("Can not run a thread!!!"));
return;
}
CWinThread* second=NULL;
second = AfxBeginThread(MyThreadProcT1, &pmom2,THREAD_PRIORITY_ABOVE_NORMAL);
if(second == NULL)
{
AfxMessageBox(_T("Can not run a thread!!!"));
return;
}
if (WaitForSingleObject(first->m_hThread, INFINITE) == WAIT_FAILED)
{
ErrorExit(TEXT("Thread_First")); // show the GetLastError
}
if (WaitForSingleObject(second->m_hThread, INFINITE))
{
ErrorExit(TEXT("Thread_Second")); // show the GetLastError
}
I caught this message box:
Thread_Second failed with error 6: The Handle is invalid!!!
Does it mean second thread finish before the the first thread?
Best
MJM
|
|
|
|
|
mostafa_pasha wrote: Thread_Second failed with error 6: The Handle is invalid!!!
It could mean that the thread was not even started. Remember that these operations are completely asynchronous. The code has reached the WFSO call does not mean the thread creation function called above that has successfully spawned the thread by then.
I'd strongly recommend that you get your basics right. Read this essay by Dr. Joseph Newcomer, which covers many aspects: Worker Threads[^]
“Follow your bliss.” – Joseph Campbell
|
|
|
|
|
Unfortunately, I used SetEvent , .... in the debug mode, everything is OK.
in the release mode, it seems that the threads can not start!!!
Best,
MJM
|
|
|
|
|