//cst.cpp

//######################################################
//
//                 見せられないよ!
//                Ver.1.00 by x@rgs
//
//#####################################################

#define STRICT
#define UNICODE
#define _UNICODE

#include<tchar.h>
#include<windows.h>
#include"resource.h"

bool containsWhiteSpace(const TCHAR* str){
	for(size_t i=0,length=lstrlen(str);i<length;++i){
		if(str[i]==' ')return true;
	}
	return false;
}

bool extractFromResource(const HINSTANCE instance_handle,const WORD id,const TCHAR*type,const TCHAR* file_name){
	HRSRC info=::FindResource(instance_handle,MAKEINTRESOURCE(id),type);
	if(!info)return false;
	HGLOBAL resource_handle=::LoadResource(instance_handle,info);
	if(!resource_handle)return false;

	DWORD resource_size=::SizeofResource(instance_handle,info);
	void* resource_data=::LockResource(resource_handle);

	HANDLE output=CreateFile(file_name,
								GENERIC_READ|GENERIC_WRITE,
								0,
								NULL,
								CREATE_ALWAYS,
								FILE_ATTRIBUTE_NORMAL,
								NULL);

	if(!output)return false;

	HANDLE file_map_handle=::CreateFileMapping(output,
											   NULL,
											   PAGE_READWRITE,
											   0,
											   resource_size,
											   NULL);

	void* base_addr=::MapViewOfFile(file_map_handle,FILE_MAP_WRITE,0,0,0);

	::CopyMemory(base_addr,resource_data,resource_size);

	::UnmapViewOfFile(base_addr);
	::CloseHandle(file_map_handle);
	::CloseHandle(output);
	return true;
}

extern "C" void WinMainCRTStartup(void){
	int argc=0;
	TCHAR **argv=NULL;

	TCHAR dll_path[MAX_PATH]={};

	::GetModuleFileName(NULL,dll_path,MAX_PATH);

	{
		size_t i=0;

		for(i=lstrlen(dll_path);i>=0;--i)if(dll_path[i]=='.')break;
		if(i==0)::ExitProcess(1);
		dll_path[i+1]='d';
		dll_path[i+2]='l';
		dll_path[i+3]='l';
	}

	if(!extractFromResource(NULL,IDR_HOOK_LIB,_T("BINARY"),dll_path))::ExitProcess(1);

	argv=::CommandLineToArgvW(::GetCommandLine(),&argc);

	int buffer_size=0;
	TCHAR* buffer=NULL;
	for(size_t i=1;i<argc;++i)buffer_size+=lstrlen(argv[i])+3;
	if((buffer=static_cast<TCHAR*>(::VirtualAlloc(NULL,buffer_size,MEM_COMMIT,PAGE_READWRITE)))!=NULL){
		for(size_t i=1;i<argc;++i){
			if(containsWhiteSpace(argv[i])){
				lstrcat(buffer,_T("\""));
				lstrcat(buffer,argv[i]);
				lstrcat(buffer,_T("\""));
			}else{
				lstrcat(buffer,argv[i]);
			}
			lstrcat(buffer,_T(" "));
		}

		STARTUPINFO si={sizeof(STARTUPINFO)};
		PROCESS_INFORMATION pi={};

		::CreateProcess(NULL,buffer,NULL,NULL,false,CREATE_SUSPENDED,NULL,NULL,&si,&pi);
		::SetPriorityClass(::GetCurrentProcess(),IDLE_PRIORITY_CLASS);
		::SetProcessWorkingSetSize(::GetCurrentProcess(),0xffffffff,0xffffffff);

		LPVOID remote_memory=::VirtualAllocEx(pi.hProcess,NULL,(lstrlen(dll_path)+1)*sizeof(TCHAR),MEM_COMMIT,PAGE_READWRITE);

		::WriteProcessMemory(pi.hProcess,remote_memory,dll_path,(lstrlen(dll_path)+1)*sizeof(TCHAR),NULL);

		HANDLE remote_thread=::CreateRemoteThread(pi.hProcess,
													NULL,
													0,
													reinterpret_cast<LPTHREAD_START_ROUTINE>(::GetProcAddress(::GetModuleHandle(_T("Kernel32")),"LoadLibraryW")),
													remote_memory,
													0,
													NULL);

		::ResumeThread(pi.hThread);

		::WaitForSingleObject(pi.hProcess,INFINITE);
		::VirtualFree(buffer,0,MEM_RELEASE|MEM_DECOMMIT);
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
	}

	::LocalFree(argv);
	::DeleteFile(dll_path);
	ExitProcess(0);
}
