; all default options are specified explicitly for easier changing
format PE GUI 4.0 at $100000 ;on "stub.exe"
;       Reserve,        Commit
stack	$1000,		$1000
heap	$10000, 	$10000


section '.bitRAKE' code import readable executable writeable

dd 0,0,0,	RVA kernel_name,	RVA kernel_table
dd 0,0,0,	RVA user_name,		RVA user_table
dd 0,0,0,	0,			0

kernel_table:
 ExitProcess		  dd RVA _ExitProcess
 GetCurrentProcess	  dd RVA _GetCurrentProcess
 GlobalMemoryStatus	  dd RVA _GlobalMemoryStatus
 SetProcessWorkingSetSize dd RVA _SetProcessWorkingSetSize
 VirtualAlloc		  dd RVA _VirtualAlloc
 VirtualLock		  dd RVA _VirtualLock
 dd 0
user_table:
 MessageBoxA		  dd RVA _MessageBoxA
 dd 0

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

macro call proc*,[arg] {
  common
    if ~ arg eq
  reverse
    pushd arg
  common
    end if
    call proc
}

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


struc MEMORYSTATUS {
.dwiLength	 dd 32
.dwMemoryLoad	 dd ?
.dwTotalPhys	 dd ?
.dwAvailPhys	 dd ?
.dwTotalPageFile dd ?
.dwAvailPageFile dd ?
.dwTotalVirtual  dd ?
.dwAvailVirtual  dd ?
}

entry $
	call [GlobalMemoryStatus],gms
	mov ebx,[gms.dwAvailPhys]
.0:	sub ebx,64*1024
	;MEM_COMMIT pages for PAGE_EXECUTE_READWRITE
	call [VirtualAlloc],0,ebx,$1000,$40
	test eax,eax
	je .0
; largest block of contigious memory at EAX of length EBX
	mov ebp,eax


; this is going to take some time
; should notify user (c:


	; can't lock this much without this
	call [GetCurrentProcess]
	lea ecx,[ebx+1024*1024]
	call [SetProcessWorkingSetSize],eax,ecx,-1
	test eax,eax
	je AhFuck
	; no page faults
	call [VirtualLock],ebp,ebx
	test eax,eax
	je AhFuck

BLOCK_SIZE = 8
	mov eax,ebp
	lea edx,[ebp+ebx]
.1:	add eax,BLOCK_SIZE
	mov [eax-BLOCK_SIZE],eax
	cmp eax,edx
	jc .1
	; last block points to zero
	mov dword [eax-BLOCK_SIZE],0

macro getBlock reg0*,reg1*{
	mov reg0,reg1
	mov reg1,[reg1]
}
macro putBlock reg0*,reg1*{
	mov [reg0],reg1
	mov reg1,reg0
}




	pushd 0
	call @F
	db 'Memory Locked!',0



AhFuck: pushd 0
	call @F
	db 'Error: Not enough memory!',0
     @@:pushd [esp]
	pushd 0
	call	[MessageBoxA]
	call	[ExitProcess],0

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

kernel_name	db 'KERNEL32',0
_ExitProcess	db 0,0,'ExitProcess',0
_GetCurrentProcess db 0,0,'GetCurrentProcess',0
_GlobalMemoryStatus db 0,0,'GlobalMemoryStatus',0
_SetProcessWorkingSetSize db 0,0,'SetProcessWorkingSetSize',0
_VirtualAlloc	db 0,0,'VirtualAlloc',0
_VirtualLock	db 0,0,'VirtualLock',0

user_name	db 'USER32',0
_MessageBoxA	db 0,0,'MessageBoxA',0

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

gms MEMORYSTATUS
