/*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
	urldec Ver.1.00
	Coded by x@rgs

	This code is released under NYSL Version 0.9982
	See NYSL_withfaq.TXT for further details.

	cl urldec.cpp kernel32.lib user32.lib /O1 /GS- /link /subsystem:windows /nodefaultlib /merge:".rdata=.text"
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*/
#define UNICODE
#define _UNICODE
#include<stdio.h>
#include<windows.h>
#include<tchar.h>

void urlDecode(TCHAR* dst,const TCHAR *src){
	TCHAR *p1=NULL,*p2=NULL;
	char utf8_str[5]={};
	int skip=0,pos=0;
	TCHAR* str=(TCHAR*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(lstrlen(src)+1)*sizeof(TCHAR));

	lstrcpy(str,src);
	for(int i=0;i<lstrlen(str);i++)if(str[i]=='+')str[i]=' ';
	p1=str;

	while(1){
		for(p2=p1;*p2&&*p2!='%';p2++);
		if(!*p2){
			lstrcat(dst,p1);
			break;
		}

		lstrcpyn(dst+lstrlen(dst),p1,p2-p1+1);
		p1=(++p2)+2;

		int hex=0;

		for(int i=0;i<2;i++){
			const TCHAR c=*(p2+i);
			if(c>='0'&&c<='9')hex=16*hex+(c-'0');
			else if(c>='a'&&c<='f')hex=16*hex+((c-'a')+10);
			else if(c>='A'&&c<='F')hex=16*hex+((c-'A')+10);
		}

		if(pos==0){
			if(hex<0x80)skip=0;
			else if(hex<0xc2)skip=0;
			else if(hex<0xe0)skip=1;
			else if(hex<0xf0)skip=2;
			else if(hex<0xf5)skip=3;
			else skip=0;
		}

		utf8_str[pos]=hex;

		if(pos<skip){
			pos++;
			continue;
		}

		utf8_str[pos+1]='\0';
		int buffer_size=MultiByteToWideChar(CP_UTF8,0,utf8_str,-1,NULL,0);
		if(buffer_size){
			wchar_t* w_str=(wchar_t*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,buffer_size*sizeof(wchar_t));

			MultiByteToWideChar(CP_UTF8,0,utf8_str,-1,w_str,buffer_size);
			lstrcat(dst,w_str);
			HeapFree(GetProcessHeap(),0,w_str);
		}
		pos=0;
	}
	HeapFree(GetProcessHeap(),0,str);
	return;
}

int getClipboardSize(){
	if(!IsClipboardFormatAvailable(CF_TEXT))return -1;
	if(!OpenClipboard(NULL))return -1;

	HGLOBAL hglobal=GetClipboardData(CF_UNICODETEXT);

	CloseClipboard();
	return GlobalSize(hglobal);
} 

bool setClipboardText(const TCHAR* text,int length){
	bool result=false;

	if(!OpenClipboard(NULL))return result;

	HGLOBAL hglobal=GlobalAlloc(GMEM_MOVEABLE,(length+1)*sizeof(TCHAR));
	if(hglobal!=NULL){
		lstrcpy((TCHAR*)GlobalLock(hglobal),text);
		GlobalUnlock(hglobal);
		EmptyClipboard();
		result=SetClipboardData(CF_UNICODETEXT,hglobal)!=NULL;
	}
	CloseClipboard();
	return result;
}

bool getClipboardText(TCHAR* result){
	if(!IsClipboardFormatAvailable(CF_TEXT))return false;
	if(!OpenClipboard(NULL))return false;

	HGLOBAL hglobal=GetClipboardData(CF_UNICODETEXT);

	lstrcpy(result,(TCHAR*)GlobalLock(hglobal));

	GlobalUnlock(hglobal);
	CloseClipboard();

	return true;
}

extern "C" void WinMainCRTStartup(){
	TCHAR* src=(TCHAR*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,getClipboardSize());
	TCHAR* dst=(TCHAR*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,getClipboardSize());

	if(!src||!dst||!getClipboardText(src))ExitProcess(1);
	urlDecode(dst,src);
	setClipboardText(dst,lstrlen(dst));
	HeapFree(GetProcessHeap(),0,dst);
	HeapFree(GetProcessHeap(),0,src);
	ExitProcess(0);
}
