%include "util.mac"
%include "icedump.inc"
%include "vxdn.inc"
%include "wiat.inc"
%include "win32n.inc"
%include "common.inc"
%include "pedata.inc"
%include "memio.inc"

global TaskFirst
global TaskNext
global TaskEnd
global ModFirst
global ModNext
global ModEnd
global KillProcess
global GetModuleInfo
global GetBaseAddress
global GetPIDName
global GetNamePID
global BuildDLLList

extern sdata
extern oMTEList
extern R3TCB.TDBX
extern TDBX.pPDB

bits 32

segment _LTEXT

;-------------------------------------------------------------------------------
; before first use, the following must be called (should have been taken care
; of in WiniceMainHook):
; GetAPIs in winice context then
; GetK32Info in win32 or VxD context
;-------------------------------------------------------------------------------

;BOOL  TaskFirst(Offset TaskEntry);
;
; Fill TaskEntry struct with First task datas.
; Return False if no task anymore

TaskFirst:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	esi
	push	gs

%define TaskEntry ebp+8

	mov	esi,EHS_TaskFirst
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskFirst: failed to install exception handler"
	debug_end

	xor	eax,eax
	jmp	short .ret

@@
	mov	ebx,[TaskEntry]
	mov	dword [ebx+TASKENTRY.te_dwSize],TASKENTRY_size

.protect_start:
	mov	eax,[selKernelVars]		; grab first TaskDB
	movzx	eax,word [eax]
	mov	gs,eax
	mov	eax,[headTDB]
	mov	eax,[eax]
	movzx	eax,word [gs:eax]

@@
	mov	[ebx+TASKENTRY.te_hTask],eax
	mov	gs,eax				; test if win32 task
	test	word [gs:0x16],0x10
	jnz	.protect_end

	movzx	eax,word [gs:0]			; grab next TaskDB
	or	eax,eax
	jnz	@B
	jmp	short .free_eh

.protect_end:

	call	TaskGetProcName
	jmp	short .free_eh

.EH:
	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskFirst: exception, GS:EAX: #gs:#eax"
	debug_end

	xor	eax,eax

.free_eh:
	mov	esi,EHS_TaskFirst
	VMMCall	Remove_Exception_Handler
	jnc	.ret

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskFirst: failed to uninstall exception handler"
	debug_end

.ret:
	pop	gs
	pop	esi
	pop	ebx
	pop	ebp

%undef TaskEntry

	retn	4


segment _LDATA
	align 4
EHS_TaskFirst:
istruc Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd TaskFirst.protect_start
	at EHS_End_EIP,		dd TaskFirst.protect_end
	at EHS_Handler,		dd TaskFirst.EH
iend


segment _LTEXT

;BOOL  TaskNext(Offset TaskEntry);
;
; Fill TaskEntry struct with Next task datas.
; Return False if no task anymore

TaskNext:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	esi
	push	gs

%define TaskEntry ebp+8

	mov	esi,EHS_TaskNext
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskNext: failed to install exception handler"
	debug_end

	xor	eax,eax
	jmp	short .ret

@@
	mov	ebx,[TaskEntry]

.protect_start:
	mov	eax,[ebx+TASKENTRY.te_hTask]	; grab next TaskDB

	mov	gs,eax
	movzx	eax,word [gs:0]
	or	eax,eax
	jz	.free_eh

	mov	[ebx+TASKENTRY.te_hTask],eax

	mov	gs,eax				; test TaskDB.flags
	test	word [gs:0x16],0x10		; win32 task?
	jz	.protect_start

.protect_end:

	call	TaskGetProcName
	jmp	short .free_eh

.EH:
	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskNext: exception, GS:EAX: #gs:#eax"
	debug_end

	xor	eax,eax

.free_eh:
	mov	esi,EHS_TaskNext
	VMMCall	Remove_Exception_Handler
	jnc	.ret

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskNext: failed to uninstall exception handler"
	debug_end

.ret:
	pop	gs
	pop	esi
	pop	ebx
	pop	ebp

%undef TaskEntry

	retn	4


segment _LDATA
	align 4
EHS_TaskNext:
istruc Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd TaskNext.protect_start
	at EHS_End_EIP,		dd TaskNext.protect_end
	at EHS_Handler,		dd TaskNext.EH
iend


segment _LTEXT

;void  TaskEnd(void);
;
; Close Task internal handler - WIN32 compatibility API.

TaskEnd:
	retn


; fill in ProcName
;
; eax: TaskDB, ebx: TASKENTRY
;
; eax: 0 on error

TaskGetProcName:
	push	ecx
	push	esi
	push	edi
	push	gs

	mov	esi,EHS_TaskGetProcName
	VMMCall	Install_Exception_Handler
	jnc	.protect_start

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskGetProcName: failed to install exception handler"
	debug_end

	xor	eax,eax
	jmp	.ret

.protect_start:
	mov	gs,eax
	movzx	eax,word [gs:0x1E]		; grab TaskDB.hMod
	mov	gs,eax
	movzx	esi,word [gs:0x0A]		; hMod.OFSTRUCT
	add	esi,byte 9
	lea	edi,[ebx+TASKENTRY.te_ProcName]

@@
	mov	al,[gs:esi]
	mov	[edi],al
	inc	esi
	inc	edi
	cmp	al,0
	jnz	@B

.protect_end:

	mov	eax,1
	jmp	short .free_eh

.EH:
	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskGetProcName: exception, GS:EAX: #gs:#eax"
	debug_end

	xor	eax,eax

.free_eh:
	mov	esi,EHS_TaskGetProcName
	VMMCall	Remove_Exception_Handler
	jnc	.ret

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: TaskGetProcName: failed to uninstall exception handler"
	debug_end

.ret:
	pop	gs
	pop	edi
	pop	esi
	pop	ecx
	retn


segment _LDATA
	align 4
EHS_TaskGetProcName:
istruc Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd TaskGetProcName.protect_start
	at EHS_End_EIP,		dd TaskGetProcName.protect_end
	at EHS_Handler,		dd TaskGetProcName.EH
iend


segment _LTEXT

;BOOL  ModFirst(Offset ModEntry, PID)
;
; Fill ModEntry struct with First Module datas of given PID.
; Return False if no module anymore

ModFirst:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	esi
	push	gs

%define PID ebp+12
%define ModEntry ebp+8

	mov	esi,EHS_ModFirst
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModFirst: failed to install exception handler"
	debug_end

	xor	eax,eax
	jmp	short .ret

@@
	mov	ebx,[ModEntry]
	mov	dword [ebx+MODULEENTRY.me_dwSize],MODULEENTRY_size

.protect_start:
	mov	eax,[PID]
	mov	gs,eax

;	mov	gs,[gs:0x52]			; TaskDB.selTIB
;	mov	eax,[gs:0x30]			; TIB.ProcessDB

	mov	eax,[gs:0x54]			; TaskDB.R3TCB
	add	eax,[R3TCB.TDBX]

	mov	eax,[eax]			; TDBX
	add	eax,[TDBX.pPDB]

	mov	eax,[eax]			; PDB
	mov	eax,[eax+0x4C]			; grab ProcessDB.ModRefList
	mov	[ebx+MODULEENTRY.me_th32ModuleID],eax
.protect_end:

	call	ModGetData
	jmp	short .free_eh

.EH:
	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModFirst: exception, GS:EAX: #gs:#eax"
	debug_end

	xor	eax,eax

.free_eh:
	mov	esi,EHS_ModFirst
	VMMCall	Remove_Exception_Handler
	jnc	.ret

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModFirst: failed to uninstall exception handler"
	debug_end

.ret:
	pop	gs
	pop	esi
	pop	ebx
	pop	ebp

%undef PID
%undef ModEntry

	retn	8


segment _LDATA
	align 4
EHS_ModFirst:
istruc Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd ModFirst.protect_start
	at EHS_End_EIP,		dd ModFirst.protect_end
	at EHS_Handler,		dd ModFirst.EH
iend


segment _LTEXT

;BOOL  ModNext(Offset ModEntry);
;
; Fill ModEntry struct with Next Module datas.
; Return False if no module anymore

ModNext:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	esi

%define ModEntry ebp+8

	mov	esi,EHS_ModNext
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModNext: failed to install exception handler"
	debug_end

	xor	eax,eax
	jmp	short .ret

@@
	mov	ebx,[ModEntry]

.protect_start:
	mov	eax,[ebx+MODULEENTRY.me_th32ModuleID]
	mov	eax,[eax]		; grab ModRef.NextModRef
	or	eax,eax
	jz	.free_eh

	mov	[ebx+MODULEENTRY.me_th32ModuleID],eax
.protect_end:

	call	ModGetData
	jmp	short .free_eh

.EH:
	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModNext: exception, EAX: #eax"
	debug_end

	xor	eax,eax

.free_eh:
	mov	esi,EHS_ModNext
	VMMCall	Remove_Exception_Handler
	jnc	.ret

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModNext: failed to uninstall exception handler"
	debug_end

.ret:
	pop	esi
	pop	ebx
	pop	ebp

%undef ModEntry

	retn	4


segment _LDATA
	align 4
EHS_ModNext:
istruc Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd ModNext.protect_start
	at EHS_End_EIP,		dd ModNext.protect_end
	at EHS_Handler,		dd ModNext.EH
iend


segment _LTEXT

;void  ModEnd(void);
;
; Close Mod internal handler - WIN32 compatibility API.

ModEnd:
	retn


; fill in module info
;
; EAX: ModRef, ebx: MODULEENTRY
;
; EAX: 0 on error

ModGetData:
	push	ecx
	push	edx
	push	esi
	push	edi

	mov	esi,EHS_ModGetData
	VMMCall	Install_Exception_Handler
	jnc	@F

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModGetData: failed to install exception handler"
	debug_end

	xor	eax,eax
	jmp	.ret

@@
	mov	edx,[oMTEList]
	mov	edx,[edx]			; edx: MTEList

	test	edx,edx
	jnz	.protect_start

	xor	eax,eax
	jmp	short .free_eh

.protect_start:
	movzx	eax,word [eax+0x10]		; grab ModRef.MTEIndex
	mov	eax,[edx+4*eax]			; grab MTE

	movzx	ecx,word [eax+0x14]		; grab MTE.cbFileName
	mov	esi,[eax+0x0C]			; grab MTE.FileName
	lea	edi,[ebx+MODULEENTRY.me_ExePath]
	rep	movsb
	mov	byte [edi],0

	movzx	ecx,word [eax+0x16]		; grab MTE.cbModName
	mov	esi,[eax+0x10]			; grab MTE.ModName
	lea	edi,[ebx+MODULEENTRY.me_ModuleName]
	rep	movsb
	mov	byte [edi],0

	mov	eax,[eax+0x04]			; grab MTE.PEHeaders
	mov	ecx,[eax+0x34]			; imagebase
	mov	[ebx+MODULEENTRY.me_modBaseAddr],ecx
	mov	[ebx+MODULEENTRY.me_hModule],ecx

	mov	ecx,[eax+0x50]			; imagesize
	mov	[ebx+MODULEENTRY.me_modBaseSize],ecx
.protect_end:

	mov	eax,1
	jmp	short .free_eh

.EH:
	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModGetData: exception, EAX: #eax"
	debug_end

	xor	eax,eax

.free_eh:
	mov	esi,EHS_ModGetData
	VMMCall	Remove_Exception_Handler
	jnc	.ret

	debug_start debugflags, ICEDUMP_DEBUG_TASKMOD
	Trace_Out "ICEDUMP: ModGetData: failed to uninstall exception handler"
	debug_end

.ret:
	pop	edi
	pop	esi
	pop	edx
	pop	ecx
	retn


segment _LDATA
	align 4
EHS_ModGetData:
istruc Exception_Handler_Struc
	at EHS_Reserved,	dd 0
	at EHS_Start_EIP,	dd ModGetData.protect_start
	at EHS_End_EIP,		dd ModGetData.protect_end
	at EHS_Handler,		dd ModGetData.EH
iend


segment _LTEXT

;BOOL  KillProcess(DWORD PID);
;
; Terminate given PID.
; Return TRUE on success.

;KillProcess:
;	push	ebp
;	mov	ebp,esp
;
;%define PID ebp+8
;
;
;	pop	ebp
;
;%undef PID
;
;	retn	4


;DWORD GetModuleInfo(char *FNAME, DWORD PID);
;
; Retrieve size and Base address of module FNAME of given PID.
; Size is in EAX (0 on failure), Base in EBX.

;GetModuleInfo:
;	push	ebp
;	mov	ebp,esp
;
;%define FNAME ebp+8
;%define PID ebp+12
;
;
;	pop	ebp
;
;%undef FNAME
;%undef PID
;
;	retn	8


;DWORD GetBaseAddress(PID,Offset Size);
;
; Retrieve Base Address and size of Given PID.
; Base in EAX (0 on failure), Size stored in Size Variable.

;GetBaseAddress:
;	push	ebp
;	mov	ebp,esp
;
;%define PID ebp+8
;%define Size ebp+12
;
;
;	pop	ebp
;
;%undef PID
;%undef Size
;
;	retn	8


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Get PID of a given Name.
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : Filename
;
;EAX=PID
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
GetPIDName:
	push	ebp
	mov	ebp, esp
	sub	esp, TASKENTRY_size
	push	ebx

	lea	ebx, [ebp-TASKENTRY_size]
	push 	ebx
	Call 	TaskFirst

.CompareFN:
	test 	eax, eax
	jz   	.GetPIDEnd

	push 	dword [ebp+08h]
	lea	eax, [ebx+TASKENTRY.te_ProcName]
	push 	eax
	Call 	strcmp
	jz   	.ProcFetched

	push 	ebx
	call 	TaskNext
	jmp  	.CompareFN

.ProcFetched:
	mov  	eax, [ebx+TASKENTRY.te_hTask]
	Call 	TaskEnd

.GetPIDEnd:
	pop	ebx
	add	esp, TASKENTRY_size
	pop	ebp
	retn  	04h


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Get Name of a given PID.
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;ebp+8 : PID
;ebp+0c : Filename buffer
;
;EAX=1 on succes.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
GetNamePID:
	push	ebp
	mov	ebp, esp
	sub	esp, TASKENTRY_size
	push	ebx
	push 	esi
	push 	edi

	lea	ebx, [ebp-TASKENTRY_size]
	mov	eax, [ebp+8]
	call	TaskGetProcName
	test	eax, eax
	jz	.GetNameEnd

.NameFetched:
	lea	esi, [ebx+TASKENTRY.te_ProcName]
	push	dword [ebp+0Ch]
	push	esi
	call	strcopy
	xor	eax, eax
	inc	eax

.GetNameEnd:
	pop 	edi
	pop 	esi
	pop	ebx
	add	esp, TASKENTRY_size
	pop	ebp
	retn	08h
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; macros Definitions
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
%macro pushr 0
 push esi
 push edi
 push ebx
 push edx
 push ecx
%endmacro

%macro popr 0
 pop  ecx
 pop  edx
 pop  ebx
 pop  edi
 pop  esi
%endmacro
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
; Construct DLL list of associated PID.
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
;esp+4 : PID
;esp+8 : DLL List Holder.
;esp+c : ImageBase to exclude.
;
;eax=1 on success.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
BuildDLLList:
	push	ebp
	mov	ebp, esp
	sub	esp, MODULEENTRY_size+MAX_PATH
	pushr

	lea	ebx,[ebp-(MODULEENTRY_size+MAX_PATH)]
	push	ebx
	push	dword [ebp+08]
	Call	GetNamePID
	test	eax, eax
	jz	near .ExitBuild
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Count number of DLL.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	xor	ecx, ecx

	push	dword [ebp+08h]
	lea	edx, [ebp-MODULEENTRY_size]
	push	edx
	Call	ModFirst
	test	eax, eax
	jz	near .ExitBuild
.LoopCountMod:
	inc	ecx
	push	edx
	Call	ModNext
	test	eax, eax
	jnz	.LoopCountMod

	Call	ModEnd
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Allocate DLL List buffer.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	eax, DLLList_size
	xor	edx, edx
	inc	ecx		; For zero record
	mul	ecx

	push	eax
	Call	GetMem
	test	eax, eax
	jz	near .ExitBuild

	mov	ebx, [ebp+0Ch]
	mov	[ebx], eax
	mov	ebx, eax
	lea	edx, [ebp-MODULEENTRY_size]
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Fill DLL List buffer.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	push	dword [ebp+08h]
	push	edx
	Call	ModFirst
	test	eax, eax
	jz	.ExitBuild
.LoopStoreDLL:
	lea	eax, [ebp-(MODULEENTRY_size+MAX_PATH)]
	push	eax
	lea	eax, [edx+MODULEENTRY.me_ExePath]
	push	eax
	call	strcmp
	test	eax, eax
	jz	.GetNextItem

	mov	eax, [edx+MODULEENTRY.me_hModule]
	cmp	eax, [ebp+10h]
	jz	.GetNextItem

	mov	[ebx+DLLList.Base], eax
	mov	eax, [edx+MODULEENTRY.me_modBaseSize]
	mov	[ebx+DLLList.Size], eax

	lea	eax, [edx+MODULEENTRY.me_ExePath]
	push	eax
	Call	CharUpper

	push	ebx
	lea	eax, [edx+MODULEENTRY.me_ExePath]
	push	eax
	Call	strcopy

	add	ebx, DLLList_size
.GetNextItem:
	push	edx
	Call	ModNext
	test	eax, eax
	jnz	.LoopStoreDLL

	Call	ModEnd
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Store Zero record.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	mov	edi, ebx
	mov	ecx, DLLList_size
	xor	eax, eax
	rep	stosb
.Success:
	xor	eax, eax
	inc	eax
.ExitBuild:
	popr
	add	esp, MODULEENTRY_size+MAX_PATH
	pop	ebp
	retn	0Ch
