Sample program to create multiple threads
I used the CreateThread call and the Heap functions to create a simple sample program that spawns a separate thread that displays a MessageBox
Try running it and you will see a MessageBox. However, unlike a normal MessageBox in your application, this one is on a separate thread, and thus the main thread can continue processing.
The code allocates some memory and writes some bytes of x86 machine code to execute. Those bytes simply put up the MessageBox and return.
The MessageBox strings need to be allocated and freed, and the strings and the code must not be freed until after the thread terminates by Returning.
CLEAR ALL
CLEAR
#define CREATE_SUSPENDED 0x00000004
#define INFINITE 0xFFFFFFFF
#define WAIT_TIMEOUT 258
DECLARE integer LoadLibrary IN WIN32API string
DECLARE integer FreeLibrary IN WIN32API integer
DECLARE integer GetProcAddress IN WIN32API integer hModule, string procname
DECLARE integer CreateThread IN WIN32API integer lpThreadAttributes, ;
integer dwStackSize, integer lpStartAddress, integer lpParameter, integer dwCreationFlags, integer @ lpThreadId
DECLARE integer ResumeThread IN WIN32API integer thrdHandle
DECLARE integer CloseHandle IN WIN32API integer Handle
DECLARE integer GetProcessHeap IN WIN32API
DECLARE integer HeapAlloc IN WIN32API integer hHeap, integer dwFlags, integer dwBytes
DECLARE integer HeapFree IN WIN32API integer hHeap, integer dwFlags, integer lpMem
DECLARE integer WaitForSingleObject IN WIN32API integer hHandle, integer dwMilliseconds
hModule = LoadLibrary("user32")
adrMessageBox=GetProcAddress(hModule,"MessageBoxA")
FreeLibrary(hModule)
hProcHeap = GetProcessHeap()
sCaption="This is a MessageBox running in a separate thread"+CHR(0) && null terminate string
adrCaption = HeapAlloc(hProcHeap, 0, LEN(sCaption)) && allocate memory for string
SYS(2600,adrCaption,LEN(sCaption),sCaption) && copy string into allocated mem
* int 3 = cc (Debug Breakpoint: attach a debugger dynamically)
* nop = 90
* push 0 = 6a 00
* push eax = 50
* push 0x12345678 = 68 78 56 34 12
* ret 4 = c2 04 00
* mov eax, esp = 8B c4
* mov eax, 0x12345678 = B8 78 56 34 12
* call eax = ff d0
sCode=""
*sCode = sCode + CHR(0xcc)
sCode = sCode + CHR(0x6a) + CHR(0x00) && push 0
sCode = sCode + CHR(0x68) + BINTOC(adrCaption,"4rs") && push the string caption
sCode = sCode + CHR(0x68) + BINTOC(adrCaption,"4rs") && push the string caption
sCode = sCode + CHR(0x6a) + CHR(0x00) && push the hWnd
sCode = sCode + CHR(0xb8) + BINTOC(adrMessageBox,"4rs") && move eax, adrMessageBox
sCode = sCode + CHR(0xff) + CHR(0xd0) && call eax
sCode = sCode + CHR(0xc2)+CHR(0x04)+CHR(0x00) && ret 4
AdrCode=HeapAlloc(hProcHeap, 0, LEN(sCode)) && allocate memory for the code
SYS(2600,AdrCode, LEN(sCode), sCode) && copy the code into the string
dwThreadId =0
?"Starting thread count = ",GetThreadCount()
hThread = CreateThread(0,1024, AdrCode, 0, CREATE_SUSPENDED, @dwThreadId)
?"Thread handle = ",hThread
?"Thread ID = ", dwThreadID
ResumeThread(hThread) && Start the thread
i=0
DO WHILE WaitForSingleObject(hThread, 100) = WAIT_TIMEOUT && wait 100 msecs for the thread to finish
?i,"Current thread count",GetThreadCount()
i=i+1
ENDDO
?"Final thread count = ",GetThreadCount()
?"Close",CloseHandle(hThread)
HeapFree(hProcHeap, 0, AdrCode) && if the thread hasn't finished, we're releasing the executing code and it'll crash
HeapFree(hProcHeap, 0, adrCaption)
RETURN
PROCEDURE GetThreadCount as Integer
*Use WMI to get process information
objWMIService = GetObject("winmgmts:\\.\root\cimv2")
colItems = objWMIService.ExecQuery("Select * from Win32_Process where processid = "+TRANSFORM(_vfp.ProcessId))
For Each objItem in colItems
nRetval = objItem.ThreadCount
NEXT
RETURN nRetval