#pragma once
#include "typedefs.h"
#include "Vector.h"
#include "FileSystem.h"
#include "desctable.h"
#include "ThreadMan.h"
#include "MemMan.h"
#include <boost\shared_ptr.hpp>

namespace ePAGE_DIR_ENT{
enum ePAGE_DIR_ENT{
	PRESENT = 1 << 0,
	READ_WRITE = 1 << 1,
	USER_SUPER_VISOR = 1 << 2,
	ACCESS = 1 << 5,
	DIRTY = 1 << 6,
	PAGE_SIZE_4M = 1 << 7,
	GLOBAL = 1 << 8
};
}

namespace ePAGE_TABLE_ENT{
enum ePAGE_TABLE_ENT{
	PRESENT = 1 << 0,
	READ_WRITE = 1 << 1,
	USER_SUPER_VISOR = 1 << 2,
	USABLE1 = 1 << 9,
	COMMIT = USABLE1,
	USABLE2 = 1 << 10,
	RESERVE = USABLE2,
	USABLE3 = 1 << 11,
	NEW_PAGE = USABLE3
};
}

const DWORD END_OF_VMEM = 0x80000000;


class Process;

class DLL{
public:
	DLL(const wchar_t *filename);
	~DLL();

	void setpagedir(Process *p);
	bool getprocaddr(const char *name, DWORD *addr);
private:
	//struct SECTION{
	//	BYTE *phyaddr;
	//	DWORD size;
	//};
	//Vector<SECTION> sections;
	boost::shared_ptr<FileSystem::File> file;
	boost::shared_ptr<BYTE> header;
	IMAGE_DOS_HEADER *dos(){return (IMAGE_DOS_HEADER *)header.get();}
	IMAGE_NT_HEADERS *nt(){return (IMAGE_NT_HEADERS *)(header.get() + dos()->e_lfanew);}
	IMAGE_SECTION_HEADER *sec(DWORD i = 0){
		return (IMAGE_SECTION_HEADER *)(header.get() + dos()->e_lfanew
			 + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i);
	}


};

class Process{
public:
	Process(DWORD pid, DWORD cr3, Vector<DLL> &sysdll);
	~Process();

	DWORD VirtualAlloc(DWORD addr, bool phy = false
		, DWORD phyaddr = 0, bool isreadonly = false
		, DWORD pagecount = 1, bool reserve = false, bool onlycommit = false);

	DWORD *getppagedir(){
		return (DWORD *)(cr3 & ~0x3fff);
	}

	DWORD getpid(){
		return pid;
	}

	DWORD getcr3(){
		return cr3;
	}
private:
	DWORD pid;
	DWORD cr3;

	Thread *MainThread;

	DWORD *getpagetableent(DWORD addr);
};

class ProcessMan
{
public:
	static void Init();
	static ProcessMan &Inst(){
		return *(ProcessMan *)buf;
	}

	void CreateProcess(const wchar_t *filename);

	Process *SysProcess(){
		return plist.Get(0);
	}
private:
	static BYTE buf[];
	static void* operator new(size_t size, void* pbuf){ return pbuf; }
	ProcessMan(void);
	~ProcessMan(void);

	DWORD curpid;
	Vector<Process> plist;

	Vector<DLL> sysdll;
};

