#include "../BasicCompiler_Common/common.h"
#include "opcode.h"

ULONG_PTR rva_to_real(DWORD p){
	extern DWORD ImageBase;
	extern int MemPos_CodeSection;
	return p+ImageBase+MemPos_CodeSection;
}

void ShowVarList(DEBUG_EVENT *pde,BOOL bExit){
	extern DWORD ImageBase;
	extern DWORD _DebugSys_dwThreadID[256];
	extern HANDLE hDebugProcess;
	extern int MemPos_RWSection;
	SIZE_T stAccBytes;
	ReadProcessMemory(hDebugProcess,
		(void *)(LONG_PTR)(ImageBase+MemPos_RWSection),
		_DebugSys_dwThreadID,sizeof(DWORD)*256,&stAccBytes);

	//デバッグダイアログを表示
	extern HINSTANCE hInst;
	extern HWND hMainDlg;
	extern HWND hDebugWnd;
	extern DWORD dwStepRun;
	dwStepRun=0;
	if(!hDebugWnd) SendMessage(hMainDlg,WM_SHOWVARLIST,0,pde->dwThreadId);
	else InitVarList(pde->dwThreadId);

	if(bExit){
		//"中断"
		SetDlgItemText(hMainDlg,IDOK,STRING_CLOSE);

		extern HWND hDebuggerToolbar;
		SendMessage(hDebuggerToolbar,TB_SETSTATE,IDC_DEBUG_START,TBSTATE_INDETERMINATE);
		SendMessage(hDebuggerToolbar,TB_SETSTATE,IDC_DEBUG_STEPOVER,TBSTATE_INDETERMINATE);
		SendMessage(hDebuggerToolbar,TB_SETSTATE,IDC_DEBUG_STEPIN,TBSTATE_INDETERMINATE);
	}
	else{
		//"継続"
		SetDlgItemText(hDebugWnd,IDCANCEL,STRING_CONTINUE);
	}
	while(hDebugWnd&&dwStepRun==0) Sleep(1);
}
void DebugMessage(char *buffer){
	extern HWND hMainDlg;
	int pos;

	if(!IsWindowEnabled(GetDlgItem(hMainDlg,IDC_DEBUGLIST))){
		SetDlgItemText(hMainDlg,IDC_DEBUGLIST,"");
		EnableWindow(GetDlgItem(hMainDlg,IDC_DEBUGLIST),1);
	}

	pos=GetWindowTextLength(GetDlgItem(hMainDlg,IDC_DEBUGLIST));
	SendDlgItemMessage(hMainDlg,IDC_DEBUGLIST,EM_SETSEL,pos,pos);
	SendDlgItemMessage(hMainDlg,IDC_DEBUGLIST,EM_REPLACESEL,0,(LPARAM)buffer);
}
SUBINFO *GetSubFromObp(ULONG_PTR pos){
	extern SUBINFO **ppSubHash;
	SUBINFO *psi;
	int i2;

	for(i2=0;i2<MAX_HASH;i2++){
		psi=ppSubHash[i2];
		while(psi){
			if(rva_to_real(psi->CompileAddress) <= pos  &&
				pos < rva_to_real(psi->EndOpAddr))
				return psi;

			psi=psi->pNextData;
		}
	}
	return 0;
}
void ReleaseSingleStep(HANDLE hThread,CONTEXT *pContext){
	//以前にシングルステップ実行をした場合
	extern HANDLE hDebugProcess;
	extern DWORD *lpdwDebugThreadID;
	extern HANDLE *lphDebugThread;
	extern int DebugThreadNum;
	extern DWORD ImageBase;
	extern int MemPos_CodeSection;
	extern int FileSize_CodeSection;
	extern char *OpBuffer;
	int i2;
	SIZE_T stAccBytes;

	//シングルステップOFF
	WriteProcessMemory(hDebugProcess,
		(void *)(LONG_PTR)(ImageBase+MemPos_CodeSection),
		OpBuffer,FileSize_CodeSection,&stAccBytes);

	if(ImageBase+MemPos_CodeSection <= pContext->Rip &&
		pContext->Rip < ImageBase+MemPos_CodeSection+FileSize_CodeSection){
		//オリジナルコード内のみ、シングルステップ用の"int 3"を考慮
		pContext->Rip--;
		SetThreadContext(hThread,pContext);
	}

	//他のスレッドのサスペンドを解除
	for(i2=0;i2<DebugThreadNum;i2++){
		if(hThread!=lphDebugThread[i2])
			ResumeThread(lphDebugThread[i2]);
	}
}
void SetThreadId_ToProcessMemory(DWORD dwThreadId,BOOL bReset){
	extern DWORD ImageBase;
	extern int MemPos_RWSection;
	extern HANDLE hDebugProcess;

	DWORD array_dwData[256];
	SIZE_T stAccBytes;

	ReadProcessMemory(hDebugProcess,
		(void *)(LONG_PTR)(ImageBase+MemPos_RWSection),
		array_dwData,sizeof(DWORD)*256,&stAccBytes);

	int i2;
	for(i2=0;i2<256;i2++){
		if(bReset==0){
			if(array_dwData[i2]==0){
				array_dwData[i2]=dwThreadId;
				break;
			}
		}
		else{
			if(array_dwData[i2]==dwThreadId){
				array_dwData[i2]=0;
				break;
			}
		}
	}

	WriteProcessMemory(hDebugProcess,
		(void *)(LONG_PTR)(ImageBase+MemPos_RWSection),
		array_dwData,sizeof(DWORD)*256,&stAccBytes);
}
void AddThread(DWORD dwThreadId, HANDLE hThread){
	extern HANDLE hDebugProcess;
	extern DWORD ImageBase;
	extern int MemPos_RWSection;

	//プロセスIDをターゲットアプリのメモリに書き込む
	SetThreadId_ToProcessMemory(dwThreadId,0);

	extern int DebugThreadNum;

	//デバッグID
	extern DWORD *lpdwDebugThreadID;
	lpdwDebugThreadID=(DWORD *)HeapReAlloc(hHeap,0,lpdwDebugThreadID,(DebugThreadNum+1)*sizeof(DWORD));
	lpdwDebugThreadID[DebugThreadNum]=dwThreadId;

	//デバッグハンドル
	extern HANDLE *lphDebugThread;
	lphDebugThread=(HANDLE *)HeapReAlloc(hHeap,0,lphDebugThread,(DebugThreadNum+1)*sizeof(HANDLE));
	lphDebugThread[DebugThreadNum]=hThread;

	//カウンタ
	DebugThreadNum++;
}
void ReadOpBuffer(){
	extern int FileSize_CodeSection;

	extern char *OpBuffer;
	if(OpBuffer) HeapDefaultFree(OpBuffer);
	OpBuffer=(char *)HeapAlloc(hHeap,0,FileSize_CodeSection);

	extern HANDLE hDebugProcess;
	extern DWORD ImageBase;
	extern int MemPos_CodeSection;
	SIZE_T stAccByte;
	ReadProcessMemory(hDebugProcess,(void *)(LONG_PTR)(ImageBase+MemPos_CodeSection),OpBuffer,FileSize_CodeSection,&stAccByte);
}
char *MakeSingleStepCode(){
	extern DWORD ImageBase;
	extern int MemPos_CodeSection;

	extern int FileSize_CodeSection;
	char *buffer;
	buffer=(char *)HeapAlloc(hHeap,0,FileSize_CodeSection);

	extern char *OpBuffer;
	memcpy(buffer,OpBuffer,FileSize_CodeSection);

	extern int MaxLineInfoNum;
	extern LINEINFO *pLineInfo;
	int i2;
	for(i2=0;i2<MaxLineInfoNum;i2++){
		if(!(
			pLineInfo[i2].dwCodeType&CODETYPE_SYSTEMPROC||
			pLineInfo[i2].dwCodeType&CODETYPE_DEBUGPROC
			)){
			//int 3
			buffer[pLineInfo[i2].TopObp]=(char)0xCC;
		}
	}

	return buffer;
}
void DeleteDebugInfo(void);
void DebugProgram(void){
	extern HWND hMainDlg;
	extern char OutputFileName[MAX_PATH];
	extern DWORD ImageBase;
	extern int MemPos_CodeSection;
	extern int MemPos_RWSection;
	extern int FileSize_CodeSection;
	extern char *OpBuffer;
	int i2,i3,i4;
	char temporary[VN_SIZE];
	DWORD dwData[256];
	SIZE_T stAccBytes;

	extern BOOL bDll;
	char ExeFilePathForDll[MAX_PATH];
	if(bDll){
		//DLLをデバッグする場合
		extern char szDebugExeForDll[1024];
		if(szDebugExeForDll[0]){
			//指定済み
			lstrcpy(ExeFilePathForDll,szDebugExeForDll);
		}
		else{
			//ユーザーに実行ファイルを選択させる
			extern HWND hOwnerEditor;
			extern LPSTR ExeFileFilter;
			if(!GetFilePathDialog(hOwnerEditor,ExeFilePathForDll,ExeFileFilter,"デバッグ用の実行可能ファイルを指定してください。",1)) return;
		}
	}

	//"中断"
	SetDlgItemText(hMainDlg,IDOK,STRING_STOP);

	//スレッド情報
	extern DWORD *lpdwDebugThreadID;
	extern HANDLE *lphDebugThread;
	extern int DebugThreadNum;
	lpdwDebugThreadID=(DWORD *)HeapAlloc(hHeap,0,1);
	lphDebugThread=(HANDLE *)HeapAlloc(hHeap,0,1);
	DebugThreadNum=0;

	//カレントディレクトリを設定
	extern char BasicCurDir[MAX_PATH];
	SetCurrentDirectory(BasicCurDir);

	SendDlgItemMessage(hMainDlg,IDC_SHOWERROR,BM_SETCHECK,BST_UNCHECKED,0);
	SendDlgItemMessage(hMainDlg,IDC_SHOWDEBUG,BM_SETCHECK,BST_CHECKED,0);
	SendMessage(hMainDlg,WM_COMMAND,IDC_SHOWDEBUG,0);



	extern BOOL bAttach;
	if(bAttach){
		extern DWORD dwAttachProcessId;

		//プロセスIDを元にハンドルを取得
		HANDLE hProcess;
		hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,dwAttachProcessId);
		if(!hProcess) goto AttachError;

		//そのプロセスにおける実行モジュールのインスタンスハンドルを取得
		HINSTANCE hModule;
		DWORD cbReturned;
		if(!EnumProcessModules( hProcess, &hModule, sizeof(HINSTANCE), &cbReturned )) goto AttachError;

		//実行ファイル名を取得
		GetModuleFileNameEx(hProcess,hModule,OutputFileName,MAX_PATH);

		CloseHandle(hProcess);


		//デバッグ用の拡張情報を取得
		ReadDebugFile();

		if(!DebugActiveProcess(dwAttachProcessId)){
AttachError:
			DebugMessage("アタッチに失敗しました。");
			return;
		}
	}
	else{
		if(!ReadDebugFile()){
			extern BOOL bDebugCompile;
			bDebugCompile=1;
			OutputExe();
			ReadDebugFile();
		}

		//スレッドを生成
		STARTUPINFO si;
		PROCESS_INFORMATION pi;
		memset(&si,0,sizeof(STARTUPINFO));
		si.cb=sizeof(STARTUPINFO);
		if(!bDll){
			//EXEファイルをデバッグ
			CreateProcess(OutputFileName,"",NULL,NULL,0,NORMAL_PRIORITY_CLASS|DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&si,&pi);
		}
		else{
			//DLLファイルをデバッグ
			CreateProcess(ExeFilePathForDll,"",NULL,NULL,0,NORMAL_PRIORITY_CLASS|DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&si,&pi);
		}

		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
	}



	extern BOOL bClipCompileView;
	//"プログラムを実行しています（デバッグ中）"
	MakeMessageText(temporary,STRING_DEBUGGING,0);
	SetDlgItemText(hMainDlg,IDC_MESSAGE,temporary);
	if(bClipCompileView) InvalidateRect(GetDlgItem(hMainDlg,IDC_PROGRESS),NULL,1);

	char *SingleStepCodeBuffer;
	SingleStepCodeBuffer=0;

	SUBINFO *psi;

	extern DWORD dwStepRun;
	BOOL bFirstBreak=1;
	CONTEXT Context;
	HANDLE hMainThread;
	extern HANDLE hDebugProcess;

	DEBUG_EVENT de;
	memset(&de,0,sizeof(DEBUG_EVENT));

	while(WaitForDebugEvent(&de,INFINITE)){
		if(de.dwDebugEventCode==LOAD_DLL_DEBUG_EVENT){
			WCHAR wcBuf[MAX_PATH];
			LONG_PTR lpData;

			wcBuf[0]=0;
			temporary[0]=0;

			if(de.u.LoadDll.lpImageName){
				if(!ReadProcessMemory(hDebugProcess,de.u.LoadDll.lpImageName,&lpData,sizeof(LONG_PTR),&stAccBytes)){
					sprintf(temporary,"ロードされたDLLの名前取得（アドレス:&H%08x）に失敗しました。\r\n",(DWORD)(LONG_PTR)de.u.LoadDll.lpImageName);
					DebugMessage(temporary);
					goto NextContinue;
				}
				if(!ReadProcessMemory(hDebugProcess,(void *)lpData,wcBuf,sizeof(WCHAR)*MAX_PATH,&stAccBytes)){
					sprintf(temporary,"ロードされたDLLの名前取得（アドレス:&H%08x）に失敗しました。\r\n",lpData);
					DebugMessage(temporary);
					goto NextContinue;
				}

				if(de.dwThreadId,de.u.LoadDll.fUnicode)
					WideCharToMultiByte(CP_ACP,0,wcBuf,-1,temporary,255,NULL,NULL);
				else lstrcpy(temporary,(char *)wcBuf);
			}
			else{
				//アタッチした場合
				GetModuleFileNameEx(hDebugProcess,(HINSTANCE)de.u.LoadDll.lpBaseOfDll,temporary,MAX_PATH);
			}

			char temp2[1024];
			sprintf(temp2,"\"%s\" をロードしました。\r\n",temporary);
			DebugMessage(temp2);

			if(lstrcmpi(temporary, OutputFileName)==0){
				ImageBase=(DWORD)(LONG_PTR)de.u.LoadDll.lpBaseOfDll;
				AddThread(de.dwThreadId,hMainThread);

				//実行用コードバッファを読み取る
				ReadOpBuffer();

				//シングルステップ用のコードバッファを作成
				SingleStepCodeBuffer=MakeSingleStepCode();
			}
		}

		else if(de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT){
			hDebugProcess=de.u.CreateProcessInfo.hProcess;
			hMainThread=de.u.CreateProcessInfo.hThread;
			if(bDll) goto NextContinue;

			//実行用コードバッファを読み取る
			ReadOpBuffer();

			//シングルステップ用のコードバッファを作成
			SingleStepCodeBuffer=MakeSingleStepCode();

			AddThread(de.dwThreadId,de.u.CreateProcessInfo.hThread);
		}
		else if(de.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT){
			AddThread(de.dwThreadId,de.u.CreateThread.hThread);
		}
		else if(de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT){
			//プロセスIDをターゲットアプリのメモリから消去
			SetThreadId_ToProcessMemory(de.dwThreadId,1);

			//"スレッド(&H%X)はコード &H%X で終了しました。\r\n"
			sprintf(temporary,STRING_DEBUG_THREADFINISH,de.dwThreadId,de.u.ExitProcess.dwExitCode);
			DebugMessage(temporary);

			//"デバッグは正常に終了しました。"
			MakeMessageText(temporary,STRING_DEBUG_FINISH,0);
			SetDlgItemText(hMainDlg,IDC_MESSAGE,temporary);
			if(bClipCompileView) InvalidateRect(GetDlgItem(hMainDlg,IDC_PROGRESS),NULL,1);

			//"プログラムはコード &H%X で終了しました。\r\n"
			sprintf(temporary,STRING_DEBUG_PROCESSFINISH,de.u.ExitProcess.dwExitCode);
			DebugMessage(temporary);
			break;
		}
		else if(de.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT){
			//プロセスIDをターゲットアプリのメモリから消去
			SetThreadId_ToProcessMemory(de.dwThreadId,1);

			//"スレッド(&H%X)はコード &H%X で終了しました。\r\n"
			sprintf(temporary,STRING_DEBUG_THREADFINISH,de.dwThreadId,de.u.ExitThread.dwExitCode);
			DebugMessage(temporary);

			//以前にシングルステップ実行をした場合
			//ステップ実行を解除
			if(dwStepRun){
				extern HWND hDebugWnd;
				if(hDebugWnd) SendMessage(hDebugWnd,WM_VARLIST_CLOSE,0,0);

				for(i4=0;i4<DebugThreadNum;i4++){
					if(de.dwThreadId==lpdwDebugThreadID[i4]) break;
				}
				Context.ContextFlags=CONTEXT_CONTROL;
				GetThreadContext(lphDebugThread[i4],&Context);

				ReleaseSingleStep(lphDebugThread[i4],&Context);
			}

			for(i2=0;i2<DebugThreadNum;i2++){
				if(lpdwDebugThreadID[i2]==de.dwThreadId){
					DebugThreadNum--;
					for(;i2<DebugThreadNum;i2++){
						lpdwDebugThreadID[i2]=lpdwDebugThreadID[i2+1];
						lphDebugThread[i2]=lphDebugThread[i2+1];
					}
					break;
				}
			}
		}
		else if(de.dwDebugEventCode==OUTPUT_DEBUG_STRING_EVENT){
			ReadProcessMemory(hDebugProcess,(void *)de.u.DebugString.lpDebugStringData,temporary,de.u.DebugString.nDebugStringLength,&stAccBytes);
			DebugMessage(temporary);
		}
		else if(de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT){

			//初回例外は無視
			if(bFirstBreak){
				bFirstBreak=0;
				goto NextContinue;
			}

			if(de.u.Exception.ExceptionRecord.ExceptionCode==STATUS_INVALID_HANDLE){

				//"スレッド(&H%X)でハンドル違反がありました(EPI=&H%08X)。\r\n"
				sprintf(temporary,STRING_DEBUG_THREAD_INVALID_HANDLE,de.dwThreadId,(LONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress);
				DebugMessage(temporary);

				MessageBeep(MB_ICONEXCLAMATION);
				ShowVarList(&de,1);
				break;
			}
			if(de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_ACCESS_VIOLATION){

				//"スレッド(&H%X)でアクセス違反がありました(EPI=&H%08X)。\r\n"
				sprintf(temporary,STRING_DEBUG_THREAD_ACCESSVIOLATION,de.dwThreadId,(LONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress);
				DebugMessage(temporary);

				MessageBeep(MB_ICONEXCLAMATION);
				ShowVarList(&de,1);
				break;
			}
			else if(de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT){
				i3=dwStepRun;

				for(i4=0;i4<DebugThreadNum;i4++){
					if(de.dwThreadId==lpdwDebugThreadID[i4]) break;
				}
				Context.ContextFlags=CONTEXT_CONTROL;
				GetThreadContext(lphDebugThread[i4],&Context);

				if(i3==0||
					i3&&(!(ImageBase+MemPos_CodeSection<=Context.Rip&&Context.Rip<ImageBase+MemPos_CodeSection+FileSize_CodeSection))
					){
					//"スレッド(&H%X)のブレーク ポイント(EPI=&H%08X)。\r\n"
					sprintf(temporary,STRING_DEBUG_BREAKPOINT,de.dwThreadId,(LONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress);
					DebugMessage(temporary);
				}

				ShowVarList(&de,0);

				//以前にシングルステップ実行をした場合
				//ステップ実行を解除
				if(i3) ReleaseSingleStep(lphDebugThread[i4],&Context);

				if(dwStepRun){
					//新たにシングルステップを行う場合

					if(ImageBase+MemPos_CodeSection <= Context.Rip &&
						Context.Rip < ImageBase+MemPos_CodeSection+FileSize_CodeSection){
						//Debug命令語が続く場合はシングルステップは不要になるので、無効にする
						//（オリジナルコード内のみ）
						if(OpBuffer[Context.Rip-ImageBase-MemPos_CodeSection]==(char)0xCC)
							dwStepRun=0;
					}
					if(dwStepRun==1){
						//ステップイン
StepIn:
						//シングルステップON
						WriteProcessMemory(hDebugProcess,
							(void *)(LONG_PTR)(ImageBase+MemPos_CodeSection),
							SingleStepCodeBuffer,FileSize_CodeSection,&stAccBytes);

						//次の命令語のブレーク命令は解除しておく（シングルステップ実行後のみ）
						//（オリジナルコード内のみ）
						if(i3&&ImageBase+MemPos_CodeSection<=Context.Rip&&Context.Rip<ImageBase+MemPos_CodeSection+FileSize_CodeSection)
							WriteProcessMemory(hDebugProcess,(void *)Context.Rip,&OpBuffer[Context.Rip-ImageBase-MemPos_CodeSection],1,&stAccBytes);

						//他のスレッドを一時中断
						for(i4=0;i4<DebugThreadNum;i4++){
							if(de.dwThreadId!=lpdwDebugThreadID[i4])
								SuspendThread(lphDebugThread[i4]);
						}
					}
					else if(dwStepRun==2){
						//ステップオーバー

						BOOL bRet;
						bRet=ReadProcessMemory(hDebugProcess,
							(void *)Context.Rip,
							temporary,
							5,
							&stAccBytes);
						if(!bRet) MessageBox(hMainDlg,"プロセスメモリーの読み込みに失敗","error",MB_OK);

						extern SUBINFO *pSub_DebugSys_EndProc;
						if((BYTE)temporary[0]==0xE8&&
							*((long *)(temporary+1))+5==(long)rva_to_real(pSub_DebugSys_EndProc->CompileAddress)-(long)Context.Rip){
							//プロシージャの終端位置の場合はステップインを行う
							goto StepIn;
						}

						//スレッドのプロシージャ実行状況を取得
						bRet=ReadProcessMemory(hDebugProcess,
							(void *)(LONG_PTR)(ImageBase+MemPos_RWSection),
							dwData,sizeof(DWORD)*256,&stAccBytes);
						if(!bRet) MessageBox(hMainDlg,"プロセスメモリーの読み込みに失敗","error",MB_OK);
						for(i2=0;;i2++){
							if(dwData[i2]==de.dwThreadId) break;
						}
						GetDebugThreadInfo(i2);

						extern int GlobalOpBufferSize;
						extern DEBUG_PROCINFO dpi;
						if(ImageBase+MemPos_CodeSection<=dpi.lpqwObp[dpi.num]&&
							dpi.lpqwObp[dpi.num]<ImageBase+MemPos_CodeSection+GlobalOpBufferSize){
							//シングルステップON
							WriteProcessMemory(hDebugProcess,
								(void *)(LONG_PTR)(ImageBase+MemPos_CodeSection),
								SingleStepCodeBuffer,
								GlobalOpBufferSize,
								&stAccBytes);
						}
						else{
							//プロシージャを識別
							psi=GetSubFromObp(dpi.lpqwObp[dpi.num]);

							//シングルステップON
							WriteProcessMemory(hDebugProcess,
								(void *)(LONG_PTR)rva_to_real(psi->CompileAddress),
								SingleStepCodeBuffer+psi->CompileAddress,
								psi->EndOpAddr-psi->CompileAddress,
								&stAccBytes);
						}
						DeleteDebugThreadInfo();

						//次の命令語のブレーク命令は解除しておく（シングルステップ実行後のみ）
						//（オリジナルコード内のみ）
						if(i3&&ImageBase+MemPos_CodeSection<=Context.Rip&&Context.Rip<ImageBase+MemPos_CodeSection+FileSize_CodeSection)
							WriteProcessMemory(hDebugProcess,(void *)Context.Rip,&OpBuffer[Context.Rip-ImageBase-MemPos_CodeSection],1,&stAccBytes);

						//他のスレッドを一時中断
						for(i4=0;i4<DebugThreadNum;i4++){
							if(de.dwThreadId!=lpdwDebugThreadID[i4])
								SuspendThread(lphDebugThread[i4]);
						}
					}
				}
			}
			else if(de.u.Exception.ExceptionRecord.ExceptionCode==STATUS_INTEGER_DIVIDE_BY_ZERO){
				//"0による除算が行われました。スレッド(&H%X) ブレーク ポイント(EPI=&H%08X)。\r\n"
				sprintf(temporary,STRING_DEBUG_DIVIDE_BY_ZERO,de.dwThreadId,(LONG_PTR)de.u.Exception.ExceptionRecord.ExceptionAddress);
				DebugMessage(temporary);

				ShowVarList(&de,1);
				break;
			}
			else{
				//"例外処理\ncode:%X"
				sprintf(temporary,STRING_DEBUG_ERROR,de.u.Exception.ExceptionRecord.ExceptionCode);
				MessageBox(0,temporary,"ActiveBasic Debug",0);
			}
		}
NextContinue:
		ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);
	}

	//シングルステップ用のコードバッファを解放
	if(SingleStepCodeBuffer) HeapDefaultFree(SingleStepCodeBuffer);

	extern HWND hDebugWnd;
	if(hDebugWnd) SendMessage(hDebugWnd,WM_COMMAND,IDCANCEL,0);

	//スレッド情報を解放
	HeapDefaultFree(lpdwDebugThreadID);
	HeapDefaultFree(lphDebugThread);

	//デバッグに利用した情報を解放（ReadDebugで確保した情報）
	DeleteDebugInfo();

	//"閉じる"
	SetDlgItemText(hMainDlg,IDOK,STRING_CLOSE);
}
void DeleteDebugInfo(void){
	int i2;

	//インクルード情報を解放
	extern INCLUDEFILEINFO IncludeFileInfo;
	for(i2=0;i2<IncludeFileInfo.FilesNum;i2++)
		HeapDefaultFree(IncludeFileInfo.ppFileNames[i2]);
	HeapDefaultFree(IncludeFileInfo.ppFileNames);

	//グローバル変数に関する情報を解放
	extern VARIABLE *GlobalVar;
	HeapDefaultFree(GlobalVar);

	//ローカル変数に関する情報を解放
	extern SUBINFO **ppSubHash;
	SUBINFO *psi;
	for(i2=0;i2<MAX_HASH;i2++){
		psi=ppSubHash[i2];
		while(psi){
			if(psi->bCompile)
				HeapDefaultFree(psi->pVar);

			psi=psi->pNextData;
		}
	}

	//列挙型に関するメモリを解放
	DeleteEnumInfo();

	//クラスに関するメモリを解放
	delete pobj_DBClass;
	pobj_DBClass=0;

	//サブルーチン情報のメモリ解放
	DeleteSubInfo();

	//定数に関する情報を解放
	DeleteConstInfo();

	//ソースコードを解放
	extern char *pBaseBuffer;
	HeapDefaultFree(pBaseBuffer);

	//コードと行番号の関係を解放
	extern LINEINFO *pLineInfo;
	HeapDefaultFree(pLineInfo);

	//コードバッファを解放
	extern char *OpBuffer;
	if(OpBuffer){
		HeapDefaultFree(OpBuffer);
		OpBuffer=0;
	}
}
