.386

.model flat, stdcall

option casemap:none

include Uninstaller.inc

.code
start:

 	;---------------------------------------------------------------
	; Get the Commandline
	;---------------------------------------------------------------

	Invoke	GetCommandLine
	push	esi
	mov		esi, eax

	;---------------------------------------------------------------	
	; Load the application name
	;---------------------------------------------------------------
	
	; 22h = the " character ie. We have a long pathname
	; that includes spaces
	cmp		byte ptr [esi], 22h
	jne		BypassExeName
	inc		esi	; Bypass the "
	lea		ecx, szExeName

	; While the byte pointed to by eax isn't a "...
BypassFullPath:
	cmp		byte ptr [esi], 22h
	je		AddNullTerminator
	mov		dl, [esi]
	mov		byte ptr [ecx], dl
	inc		esi
	inc		ecx
	jmp		BypassFullPath
	
	AddNullTerminator:
	mov		byte ptr [ecx], 0
	jmp		BypassWhitespace

	; short pathname that doesn't include spaces
BypassExeName:
	Invoke	GetModuleFileName, NULL, addr szExeName, MAX_PATH
	add		esi, 9 ; the commandline must be at least 9 chars long

	BypassExeNameLoop:
	cmp		byte ptr [esi], 20h ; space character
	je		BypassWhitespace
	cmp		byte ptr [esi], 0
	je		firstTimeExeRun
	inc		esi
	jmp		BypassExeNameLoop

BypassWhitespace:
	inc		esi
	cmp		byte ptr [esi], 20h
	je		BypassWhitespace

	; eax will point to the first argument (if there is one)
	cmp		byte ptr [esi], 0
	je		firstTimeExeRun


	;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
	; This is the cloned version - do the uninstall
	; and then delete self
	;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

	;---------------------------------------------------------------	
	; Convert the second commandline parameter to a number
	;---------------------------------------------------------------	

	xor		eax, eax
	mov		ecx, 10
	atoi:
	add		al, [esi]
	inc		esi
	sub		eax, 30h
	cmp		byte ptr [esi], 20h ; space character
	je		MovProcessOrig
	mul		ecx
	jmp		atoi
	
	MovProcessOrig:
	mov		hProcessOrig, eax
	
	BypassWhitespace2:
	inc		esi
	cmp		byte ptr [esi], 20h
	je		BypassWhitespace2
	
	; Wait for the first instance to finish running
	Invoke	WaitForSingleObject, eax, INFINITE
	Invoke	CloseHandle, hProcessOrig
	Invoke	DeleteFile, esi
	pop		esi

	; Remove the application file(s)

	; Remove data files

	; Remove directory - directory must be empty or RemoveDirectory will fail

	; Remove registry entries

	; Remove start menu links

	; Uninstall complete and successful(!)
	
	;---------------------------------------------------------------	
	; Attempt to quietly delete this file
	;---------------------------------------------------------------	

	Invoke	GetShortPathName, addr szExeName, addr szExeName, MAX_PATH
	or		eax, eax
	jz		ExitProc
	Invoke	lstrcpy, addr szCmd, addr szDelete
	Invoke	lstrcat, addr szCmd, addr szExeName
	Invoke	lstrcat, addr szCmd, addr szNull;

	Invoke	GetEnvironmentVariable, addr szComSpec, addr szExeName, MAX_PATH
	or		eax, eax
	jz		ExitProc
	Invoke	ShellExecute, 0, 0, addr szExeName, addr szCmd, 0, SW_HIDE
	jmp		ExitProc


	;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
	; This is the first time the .exe has run - spawn the clone
	;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

	firstTimeExeRun:
	Invoke	GetTempPath, MAX_PATH, addr szClone
	Invoke	GetTempFileName, addr szClone, addr szPrefix, 0, addr szClone
	Invoke	CopyFile, addr szExeName, addr szClone, FALSE

	; Create the clone process
	Invoke	GetCurrentProcessId
	Invoke	OpenProcess, SYNCHRONIZE, TRUE, eax
	Invoke	wsprintf, addr szCmd, addr szCmdLine, addr szClone, eax, addr szExeName
	Invoke	CreateProcess, NULL, addr szCmd, NULL, NULL, TRUE, 0, NULL, NULL, addr sinfo, addr pinfo
	Invoke	CloseHandle, pinfo.hProcess
	Invoke	CloseHandle, pinfo.hThread
	; This original process can now terminate

	ExitProc:
	Invoke	ExitProcess, 0

end start
