
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; StartNRT                                               ;;
;; 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

_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

.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
    push 1024
    call Axrand
    shr eax, 9
    inc eax
    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 and make visible
    ;;
    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
    push SW_SHOWNORMAL
    push _hwnd
    call ShowWindow

    ;;
    ;; Message Loop
    ;;
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:
    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


