;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; StartNRT2 ;; ;; Written- (crafted somewhat wickedly) by Chris Millward ;; ;; www.chrismillward.com/winprog.html?req=d7 ;; ;; email: chris@chrismillward.com ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .586 .model flat, stdcall option casemap :none WINVER equ 0x0500h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _CXDLU equ 190 _CYDLU equ 80 _CXMDLU equ 7 _CYMDLU equ 7 _CYPRDLU equ 10 _CFLOAT equ 500 _CFINAL equ 2000 _CPULSE equ 50 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; include \masm32\include\windows.inc include \masm32\include\gdi32.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\gdi32.lib includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .data _hInst dd 0 _hwnd dd 0 _pszDir dd 0 _pszParam0 dd 0 _pszParam1 dd 0 _pszTargetExe dd 0 _Initial dd "RAND" _nullstr db 0, 0 _szBaseFont db "T", 0, "a", 0, "h", 0, "o", 0, "m", 0, "a", 0, 0, 0 _szWndCls db "C", 0, "M", 0, 0, 0 _hBaseFont dd 0 _startupinfo dd 72, 0 dup(71) _hTargetProc dd 0 _hThread dd 0 _cxChar dd 0 _cyChar dd 0 _cxMarginPx dd 0 _cyMarginPx dd 0 _cyPRPx dd 0 _progress dd 0 _bDone db 0 _dwDoneAt dd 0 _msg dd 0 dup(7) _cxBorderPx dd 0 _cyBorderPx dd 0 _hbStockWhite dd 0 _hpStockBlack dd 0 _hfStockSys dd 0 _hdc dd 0 _mdc dd 0 _mbm dd 0 _dwStartTime dd 0 _hStartFGWnd dd 0 .code ;; ;; Axrand ;; - http://www.masm32.com/board/index.php?topic=11679.msg122749#msg122749 ;; option prologue:none option epilogue:none Axrand proc STDCALL dwRange:DWORD xor edx, edx mov eax, _Initial mov ecx, eax div dword ptr [esp+4] push edx mov eax, ecx xor eax, dword ptr [esp+4] ; just one more seed imul eax, 12347 add eax, 17 bswap eax mov _Initial, eax pop eax ret 4 Axrand endp option prologue:PrologueDef option epilogue:EpilogueDef ;; ;; _Draw() ;; _Draw proc STDCALL hdc:HDC push ecx push edx push ebx mov ebx, 1526 mov eax, _progress shl eax, 1 sub ebx, eax push ebx call Axrand shr eax, 9 inc eax ;; must be non-0 add _progress, eax cmp _progress, 100 jbe progdone0 mov _progress, 100 progdone0: push 0 call CreateCompatibleDC mov _mdc, eax push 0 push 0 push 0 push 0 mov ebx, esp push ebx push _hwnd call GetClientRect add ebx, 8 mov eax, [ebx] add ebx, 4 mov ebx, [ebx] push ebx push eax push hdc call CreateCompatibleBitmap mov _mbm, eax pop eax pop eax pop ecx pop edx push edx push ecx push _mbm push _mdc call SelectObject pop ecx pop edx push eax ;;* push edx push ecx push SRCCOPY push 0 push 0 push hdc push edx push ecx push 0 push 0 push _mdc call BitBlt pop ecx pop edx push edx push ecx sub ecx, _cxBorderPx sub edx, _cyBorderPx push edx push ecx push _cyBorderPx push _cxBorderPx mov ebx, esp push COLOR_WINDOW call GetSysColorBrush push eax push ebx push _mdc call FillRect add esp, 16 pop ecx pop edx push edx push ecx sub ecx, _cxMarginPx sub edx, _cyMarginPx push edx push ecx sub edx, _cyPRPx push edx push _cxMarginPx push _hbStockWhite push _mdc call SelectObject push _hpStockBlack push _mdc call SelectObject push _mdc call Rectangle pop ecx pop edx push edx push ecx sub ecx, _cxMarginPx sub edx, _cyMarginPx push edx push 100 push _progress sub ecx, _cxMarginPx push ecx call MulDiv mov ecx, eax add ecx, _cxMarginPx pop edx push edx push ecx sub edx, _cyPRPx push edx push _cxMarginPx push COLOR_HIGHLIGHT call GetSysColorBrush push eax push _mdc call SelectObject push _mdc call Rectangle push _hBaseFont push _mdc call SelectObject push TRANSPARENT push _mdc call SetBkMode push COLOR_WINDOWTEXT call GetSysColor push eax push _mdc call SetTextColor pop ecx pop edx push edx push ecx push edx push ecx push 0 push 0 mov eax, esp push DT_WORDBREAK push eax push INVALID_HANDLE_VALUE ;; -1 push _pszParam1 push _mdc call DrawTextW add esp, 16 push SYSTEM_FONT call GetStockObject push eax push _mdc call SelectObject push WHITE_BRUSH call GetStockObject push eax push _mdc call SelectObject pop ecx pop edx push SRCCOPY push 0 push 0 push _mdc push edx push ecx push 0 push 0 push hdc call BitBlt push _mdc call SelectObject ;;* push _mbm call DeleteObject push _mdc call DeleteDC pop ebx pop edx pop ecx mov eax, hdc ret _Draw endp ;; ;; TP() ;; TP proc STDCALL param:HANDLE push INFINITE push param call WaitForInputIdle ret TP endp ;; ;; WP() ;; WP proc STDCALL hwnd:HWND, iMsg:UINT, wParam:WPARAM, lParam:LPARAM cmp iMsg, WM_CREATE jne nextmchk0 push SM_CXBORDER call GetSystemMetrics mov _cxBorderPx, eax push SM_CYBORDER call GetSystemMetrics mov _cyBorderPx, eax push WHITE_BRUSH call GetStockObject mov _hbStockWhite, eax push BLACK_PEN call GetStockObject mov _hpStockBlack, eax push SYSTEM_FONT call GetStockObject mov _hfStockSys, eax push 0 push _CPULSE push 1 push hwnd call SetTimer jmp default0 nextmchk0: cmp iMsg, WM_ERASEBKGND jne nextmchk1 push 0 push 0 push WM_USER push hwnd call PostMessageW push wParam call _Draw mov eax, 1 ret nextmchk1: cmp iMsg, WM_PAINT jne nextmchk2 push 0 push 0 push WM_USER push hwnd call PostMessageW push ebx sub esp, sizeof PAINTSTRUCT mov ebx, esp push ebx push hwnd call BeginPaint push ebx push hwnd call EndPaint add esp, sizeof PAINTSTRUCT pop ebx mov eax, 0 ret nextmchk2: cmp iMsg, WM_USER jne nextmchk3 sub esp, sizeof MSG mov ebx, esp purgeloop0: push PM_REMOVE push iMsg push iMsg push hwnd push ebx call PeekMessageW cmp eax, 0 je contmsg0 jmp purgeloop0 contmsg0: add esp, sizeof MSG push 0 push hwnd call ValidateRect push hwnd call GetDC push eax call _Draw push eax push hwnd call ReleaseDC mov eax, 0 ret nextmchk3: cmp iMsg, WM_TIMER jne nextmchk4 push 0 push 0 push WM_USER push hwnd call PostMessageW mov eax, 0 ret nextmchk4: cmp iMsg, WM_CLOSE jne nextmchk5 ret nextmchk5: cmp iMsg, WM_DESTROY jne default0 push 1 push hwnd call KillTimer push 0 call PostQuitMessage ret default0: push lParam push wParam push iMsg push hwnd call DefWindowProcW ret WP endp start: ;; Get command line (unicode) call GetCommandLineW ;; See if left L'\"' present ;; and advance stored addr if so mov dl, 0 mov bx, word ptr [eax] cmp bx, 0022h jne nlquot0 add eax, 2 mov dl, 1 nlquot0: ;; Extract dir and params from ;; command line mov _pszDir, eax sub eax, 2 loop0: add eax, 2 mov bx, word ptr [eax] cmp bx, 0 je endstr cmp bx, 0020h ;; L' ' jne loop0 cmp dl, 0 je skipchk0 sub eax, 2 mov bx, word ptr [eax] add eax, 2 cmp bx, 0022h ;; L'\"' jne loop0 ;; continue if char b4 space not rquot skipchk0: mov word ptr [eax], 0 ;; term the string cmp _pszParam0, 0 jne param1 cmp dl, 0 je nrquot0 sub eax, 2 mov word ptr [eax], 0 ;; term b4 trailing L'\"' push eax loop1: ;; term at char after last L'\\' sub eax, 2 mov bx, word ptr [eax] cmp bx, 005ch ;; L'\\' jne loop1 add eax, 2 mov word ptr [eax], 0 pop eax add eax, 2 nrquot0: mov dl, 0 add eax, 2 mov bx, word ptr [eax] cmp bx, 0022h ;; L'\"' jne nlquot1 add eax, 2 mov dl, 1 nlquot1: mov _pszParam0, eax jmp loop0 param1: ;; no need to check _pszParam1 against 0 ;; but might as well check _pszParam0 ;; for trailing L'\"' sub eax, 2 mov bx, word ptr [eax] cmp bx, 0022h ;; L'\"' jne nrquot1 mov word ptr [eax], 0 nrquot1: add eax, 4 mov bx, word ptr [eax] cmp bx, 0022h ;; L'\"' jne nlquot2 add eax, 2 nlquot2: mov _pszParam1, eax jmp loop0 endstr: ;; Check for trailing L'\"' ;; (assumed param1) sub eax, 2 mov bx, word ptr [eax] cmp bx, 0022h ;; L'\"' jne nrquot2 mov word ptr [eax], 0 nrquot2: ;; Check that we have 2 params cmp _pszParam0, 0 je quit0 cmp _pszParam1, 0 je quit0 ;; Concatenate dir & filename push 20000h push LPTR call LocalAlloc mov _pszTargetExe, eax push _pszDir push eax call lstrcpyW push _pszParam0 push eax call lstrcatW ;; ;; Make base font for DLU sizing and alignment ;; push DEFAULT_GUI_FONT Call GetStockObject sub esp, 92 ;; sizeof LOGFONTW mov ebx, esp push ebx push 92 ;; sizeof LOGFONTW push eax call GetObjectW lea eax, _szBaseFont push eax add ebx, 28 push ebx call lstrcpyW push esp call CreateFontIndirectW add esp, 92 cmp eax, 0 je quit0 mov _hBaseFont, eax ;; ;; Register window class ;; lea eax, _szWndCls push eax push 0 push 0 push IDC_APPSTARTING push 0 call LoadCursorW push eax push 0 push 0 call GetModuleHandleW mov _hInst, eax push eax push 0 push 0 mov eax, WP push eax push 0 push esp call RegisterClassW add esp, 40 ;; sizeof WNDCLASSW cmp eax, 0 je quit0 ;; ;; Start target application ;; sub esp, 16 ;; sizeof PROCESS_INFORMATIONW mov ebx, esp push ebx lea eax, _startupinfo push eax push 0 push 0 push 0 push 0 push 0 push 0 push _pszTargetExe push 0 call CreateProcessW cmp eax, 0 jne running0 add esp, 16 jmp quit0 running0: mov edx, [ebx] mov _hTargetProc, edx add ebx, 4 push [ebx] call CloseHandle add esp, 16 cmp edx, 0 je quit0 ;; ;; Create secondary thread to exist parallel to ;; process becomming input-idle ;; push 0 push esp push CREATE_SUSPENDED push _hTargetProc mov eax, TP push eax push 0 push 0 call CreateThread add esp, 4 cmp eax, 0 je quit0 mov _hThread, eax push THREAD_PRIORITY_BELOW_NORMAL push eax call SetThreadPriority push _hThread call ResumeThread ;; ;; Get base font avg dimensions ;; push 0 call GetDC mov _hdc, eax push eax push eax push _hBaseFont push eax call SelectObject push eax sub esp, 60 ;; sizeof TEXTMETRICW push esp push _hdc call GetTextMetricsW mov eax, esp mov ebx, [eax] mov _cyChar, ebx add eax, 20 mov ebx, [eax] add eax, 4 mov ecx, [eax] add ebx, ecx mov eax, ebx shr eax, 2 mov _cxChar, eax add esp, 60 ;; sizeof TEXTMETRICW call SelectObject call ReleaseDC ;; ;; Calc offsets for _Draw() ;; push 4 push _cxChar push _CXMDLU call MulDiv mov _cxMarginPx, eax push 8 push _cyChar push _CYMDLU call MulDiv mov _cyMarginPx, eax push 8 push _cyChar push _CYPRDLU call MulDiv mov _cyPRPx, eax ;; ;; Make (one-and-only) window ;; push 0 push _hInst push 0 push 0 push 8 push _cyChar push _CYDLU call MulDiv push eax push 4 push _cxChar push _CXDLU call MulDiv push eax push 0 push 0 push 80400000h ;; WS_POPUP|WS_DLGFRAME lea eax, _nullstr push eax lea eax, _szWndCls push eax push 80h ;; WS_EX_TOOLWINDOW call CreateWindowExW cmp eax, 0 je quit0 mov _hwnd, eax ;; ;; Position window but ;; don't make visible (yet) ;; push 0 push 0 push 0 push 0 push esp push eax call GetWindowRect pop eax pop ebx pop ecx pop edx push ecx push edx push SM_CYSCREEN call GetSystemMetrics pop edx sub eax, edx shr eax, 1 mov ebx, eax push edx push SM_CXSCREEN call GetSystemMetrics pop edx pop ecx sub eax, ecx shr eax, 1 push edx push ecx push ebx push eax push _hwnd call MoveWindow ;; ;; Message Loop ;; call GetTickCount mov _dwStartTime, eax call GetForegroundWindow mov _hStartFGWnd, eax msgloop0: push QS_ALLINPUT push INFINITE push 0 lea eax, _hThread push eax push 1 call MsgWaitForMultipleObjects cmp eax, WAIT_OBJECT_0 jne handlemsgs0 cmp _progress, 99 jnb cmpprog0 mov _progress, 99 cmpprog0: cmp _progress, 100 jne handlemsgs0 cmp _bDone, 0 jne seedestroy0 mov _bDone, 1 call GetTickCount mov _dwDoneAt, eax seedestroy0: call GetTickCount sub eax, _dwDoneAt cmp eax, _CFINAL jna handlemsgs0 push _hwnd call DestroyWindow jmp quit0 handlemsgs0: ;; ;; If window not yet visible then show it, ;; provided target process still not input- ;; idle, that float time has gone, and that ;; the result of GetForegroundWindow() ;; is the same as before msgloop0 ;; push _hwnd call IsWindowVisible cmp eax, 0 jne conthandlemsgs0 call GetTickCount sub eax, _dwStartTime cmp eax, _CFLOAT jng conthandlemsgs0 push 0 push _hTargetProc call WaitForSingleObject cmp eax, WAIT_OBJECT_0 je conthandlemsgs0 call GetForegroundWindow cmp eax, _hStartFGWnd jne conthandlemsgs0 push SW_SHOWNORMAL push _hwnd call ShowWindow conthandlemsgs0: push 1 ;; PM_REMOVE push 0 push 0 push 0 lea ebx, _msg push ebx call PeekMessageW cmp eax, 0 je msgloop0 mov edx, ebx add edx, 4 mov edx, [edx] cmp edx, WM_KEYFIRST jl chkmouse0 cmp edx, WM_KEYLAST jng handlemsgs0 chkmouse0: cmp edx, WM_MOUSEFIRST jl dispatch0 cmp edx, WM_MOUSELAST jng handlemsgs0 dispatch0: push ebx call DispatchMessageW jmp handlemsgs0 quit0: push _hTargetProc call CloseHandle push _hThread call CloseHandle push _pszTargetExe call LocalFree push _hBaseFont call DeleteObject push 0 call ExitProcess end start