MFC_PIDINFO_Training/MFC_PIDINFO_Training/MFC_PIDINFO_TrainingDlg.cpp
2021-05-02 15:31:55 +09:00

676 lines
15 KiB
C++

// MFC_PIDINFO_TrainingDlg.cpp : 구현 파일
//
#include "stdafx.h"
#include "MFC_PIDINFO_Training.h"
#include "MFC_PIDINFO_TrainingDlg.h"
#include "DefineData.h"
#include <iphlpapi.h>
#include <vector>
char* g_mibTCPState[] =
{
"???",
"MIB_TCP_STATE_CLOSED",
"MIB_TCP_STATE_LISTEN",
"MIB_TCP_STATE_SYN_SENT",
"MIB_TCP_STATE_SYN_RCVD",
"MIB_TCP_STATE_ESTAB",
"MIB_TCP_STATE_FIN_WAIT1",
"MIB_TCP_STATE_FIN_WAIT2",
"MIB_TCP_STATE_CLOSE_WAIT",
"MIB_TCP_STATE_CLOSING",
"MIB_TCP_STATE_LAST_ACK",
"MIB_TCP_STATE_TIME_WAIT",
"MIB_TCP_STATE_DELETE_TCB"
};
DWORD (WINAPI *pGetExtendedTcpTable)(
PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved
);
std::vector <NETINFO> m_vNetinfo;
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
//#pragma comment(lib, "iphlpapi.lib")
//#pragma comment( lib, "Ws2_32.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다.
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 대화 상자 데이터입니다.
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
// 구현입니다.
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CMFC_PIDINFO_TrainingDlg 대화 상자
CMFC_PIDINFO_TrainingDlg::CMFC_PIDINFO_TrainingDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMFC_PIDINFO_TrainingDlg::IDD, pParent)
, m_szFilePath(_T(""))
, m_dwPid(0)
, m_strIP(_T(""))
, m_bLoadState(FALSE)
, m_nPORT(0)
, m_bScreenAutoCap(FALSE)
, m_D3state(FALSE)
, m_bSnapKeyState(FALSE)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFC_PIDINFO_TrainingDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_INFO, m_lbListBox);
DDX_Text(pDX, IDC_EDIT_FILEPATH, m_szFilePath);
DDX_Control(pDX, IDC_LIST_VECTOR, m_lbVector);
DDX_Check(pDX, IDC_CHECK_AUTOPIC, m_bScreenAutoCap);
}
BEGIN_MESSAGE_MAP(CMFC_PIDINFO_TrainingDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, &CMFC_PIDINFO_TrainingDlg::OnBnClickedOk)
ON_WM_DROPFILES()
ON_BN_CLICKED(IDC_BUTTON_RELOAD, &CMFC_PIDINFO_TrainingDlg::OnBnClickedButtonReload)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_VECTOR, &CMFC_PIDINFO_TrainingDlg::OnBnClickedButtonVector)
ON_BN_CLICKED(IDC_BUTTON_PRTSC, &CMFC_PIDINFO_TrainingDlg::OnBnClickedButtonPrtsc)
ON_BN_CLICKED(IDC_CHECK_AUTOPIC, &CMFC_PIDINFO_TrainingDlg::OnBnClickedCheckAutopic)
ON_WM_DESTROY()
ON_WM_CLIPBOARDUPDATE()
END_MESSAGE_MAP()
// CMFC_PIDINFO_TrainingDlg 메시지 처리기
BOOL CMFC_PIDINFO_TrainingDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.
// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
// 프레임워크가 이 작업을 자동으로 수행합니다.
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.
// TODO: 여기에 추가 초기화 작업을 추가합니다.
hDll = LoadLibraryA( DEF_DLL_NAME );
if( hDll == NULL )
{
m_lbListBox.AddString(_T("FAIL! To Load DLL"));
return 0;
}
//MessageBox( "SUCESS! To Load DLL" );
HookStart = ( PFN_HOOKSTART )GetProcAddress(hDll, DEF_HOOKSTART);
HookStop = ( PFN_HOOKSTOP )GetProcAddress(hDll, DEF_HOOKSTOP);
HookStart();
m_lbListBox.AddString(_T("1. 실행파일 드롭"));
m_lbListBox.AddString(_T("2. 확인"));
m_lbListBox.AddString(_T("3. 벡터확인"));
m_lbListBox.AddString(_T("4. 스크린샷 단축키 F12"));
m_lbListBox.AddString(_T("5. 클립보드 캡쳐는 '흐믓.bmp'에 지속적으로 덮어쓰기 됨"));
m_lbListBox.AddString(_T("== 자동 스크린샷 주기 1초 =="));
return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}
void CMFC_PIDINFO_TrainingDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
// 프레임워크에서 이 작업을 자동으로 수행합니다.
void CMFC_PIDINFO_TrainingDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 아이콘을 그립니다.
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
// 이 함수를 호출합니다.
HCURSOR CMFC_PIDINFO_TrainingDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMFC_PIDINFO_TrainingDlg::OnBnClickedOk()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if(m_szFilePath.IsEmpty())
{
m_lbListBox.AddString(_T("파일을 넣어주세용"));
return;
}
SHELLEXECUTEINFO ShExecInfo;
memset(&ShExecInfo, NULL, sizeof(SHELLEXECUTEINFO));
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.lpFile = m_szFilePath;
ShExecInfo.nShow = SW_SHOW;
BOOL ret = ShellExecuteEx(&ShExecInfo);
if(!ret)
{
m_lbListBox.AddString(_T("열기실패"));
return;
}
m_dwPid = GetProcessId(ShExecInfo.hProcess);
CloseHandle(ShExecInfo.hProcess);
CString add_msg;
add_msg.Format(_T("PID : %ld"), m_dwPid);
m_lbListBox.AddString(add_msg);
}
void CMFC_PIDINFO_TrainingDlg::OnDropFiles(HDROP hDropInfo)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
char FileFath[MAX_PATH];
DragQueryFileA(hDropInfo, 0, FileFath, MAX_PATH);
m_szFilePath = FileFath;
m_lbListBox.AddString(m_szFilePath);
UpdateData(FALSE);
CDialog::OnDropFiles(hDropInfo);
}
BOOL CMFC_PIDINFO_TrainingDlg::initFunctions(void)
{
pGetExtendedTcpTable =
(DWORD (WINAPI *)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG))
GetProcAddress(LoadLibraryA("iphlpapi.dll"), "GetExtendedTcpTable");
if(pGetExtendedTcpTable == NULL) return FALSE;
return TRUE;
}
void CMFC_PIDINFO_TrainingDlg::OnBnClickedButtonReload()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
m_bLoadState = !m_bLoadState;
if(m_bLoadState)
{
m_lbListBox.AddString(_T("갱신시작"));
SetTimer(IP_PORT_RELOAD, 1000, 0);
}
else
{
m_lbListBox.AddString(_T("갱신종료"));
KillTimer(IP_PORT_RELOAD);
}
}
CString CMFC_PIDINFO_TrainingDlg::GetPid2Info(DWORD SrcPid)
{
CString err_msg;
if(!initFunctions()){
err_msg = _T("Needed to have XP SP2, Vista SP1 or Server 2003 SP1 and above");
return err_msg;
}
PVOID pTCPTable = NULL;
DWORD size = 0;
DWORD result = 0;
result = pGetExtendedTcpTable(NULL, &size, true, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
while(result == ERROR_INSUFFICIENT_BUFFER){
if(pTCPTable != NULL){
free(pTCPTable);
}
pTCPTable = malloc(size);
result = pGetExtendedTcpTable(pTCPTable, &size, true, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
if(result != NO_ERROR){
err_msg.Format(_T("Failed to get TCP Table %s"), GetLastError());
free(pTCPTable);
m_lbListBox.AddString(err_msg);
return err_msg;
}
}
if(result != NO_ERROR){
err_msg.Format(_T("Failed to get size estimation %s"), GetLastError());
m_lbListBox.AddString(err_msg);
return err_msg;
}
for(DWORD i = 0; i < ((PMIB_TCPTABLE_OWNER_MODULE)pTCPTable)->dwNumEntries; i++)
{
MIB_TCPROW_OWNER_MODULE module = ((PMIB_TCPTABLE_OWNER_MODULE)pTCPTable)->table[i];
if(SrcPid == module.dwOwningPid)
{
if(module.dwState != MIB_TCP_STATE_LISTEN)
{
CString t1;
int t2;
BOOL trance;
trance = TRUE;
t1.Format(_T("%d.%d.%d.%d"),
(htonl(module.dwRemoteAddr) >> 24) & 0xFF,
(htonl(module.dwRemoteAddr) >> 16) & 0xFF,
(htonl(module.dwRemoteAddr) >> 8) & 0xFF,
(htonl(module.dwRemoteAddr)) & 0xFF);
t2 = (unsigned int)htons((short)module.dwRemotePort);
for(int i=0; i < (int)m_vNetinfo.size(); i++)
{
if(m_vNetinfo[i].IP == t1 && m_vNetinfo[i].PORT == t2 )
{
trance = FALSE;
}
}
if(trance || m_vNetinfo.size() == 0)
{
NETINFO tinfo;
tinfo.IP = t1;
tinfo.PORT = t2;
m_vNetinfo.push_back(tinfo);
}
CString add_msg;
m_strIP = t1;
m_nPORT = t2;
add_msg.Format(_T("IP : %s / PORT : %d"), m_strIP.GetBuffer(), m_nPORT);
m_lbListBox.AddString(add_msg);
}
}
}
if(pTCPTable != NULL)
{
free(pTCPTable);
}
err_msg.Empty();
return err_msg;
}
void CMFC_PIDINFO_TrainingDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
switch(nIDEvent)
{
case IP_PORT_RELOAD:
{
CString t;
t = GetPid2Info(m_dwPid);
if(!t.IsEmpty())
{
m_lbListBox.AddString(t);
}
break;
}
case SCREEN_RELOAD:
{
HWND hwnd = GetWindowHandle(m_dwPid);
HWND2IMG(hwnd);
break;
}
}
CDialog::OnTimer(nIDEvent);
}
void CMFC_PIDINFO_TrainingDlg::OnBnClickedButtonVector()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
m_lbVector.ResetContent();
CString ttt;
for(int i=0; i < (int)m_vNetinfo.size(); i++)
{
ttt.Format(_T("IP : %s / PORT : %d"), m_vNetinfo[i].IP.GetBuffer(), m_vNetinfo[i].PORT);
m_lbVector.AddString(ttt);
}
}
HWND CMFC_PIDINFO_TrainingDlg::GetWindowHandle(DWORD processid)
{
HWND tmpHwnd = ::FindWindow(NULL, NULL);
DWORD idProc = 0;
while(tmpHwnd!= NULL)
{
if( ::GetParent(tmpHwnd) == NULL ) // 최상위 핸들인지 체크, 버튼 등도 핸들을 가질 수 있으므로 무시하기 위해
{
GetWindowThreadProcessId( tmpHwnd, &idProc );
if( processid == idProc)
{
return tmpHwnd;
}
}
tmpHwnd = ::GetWindow(tmpHwnd, GW_HWNDNEXT); // 다음 핸들 찾기
}
return tmpHwnd;
}
void CMFC_PIDINFO_TrainingDlg::OnBnClickedButtonPrtsc()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
HWND m_hwnd_f = GetWindowHandle(m_dwPid);
CString add_msg;
add_msg.Format(_T("HWND : %x"), m_hwnd_f);
m_lbListBox.AddString(add_msg);
if(m_hwnd_f == NULL)
{
m_lbListBox.AddString(_T("핸들을 찾지 못하였습니다."));
m_lbListBox.AddString(_T("(창이 완전히 켜진후에 다시 시도 해보세요)"));
return;
}
//캡처누르기
INPUT inp[4];
ZeroMemory(inp, sizeof(inp));
//press the VK_MENU key
inp[0].type = INPUT_KEYBOARD;
inp[0].ki.wVk = VK_MENU;
//press the VK_SNAPSHOT key
inp[1].type = INPUT_KEYBOARD;
inp[1].ki.wVk = VK_SNAPSHOT;
//release the VK_SNAPSHOT key
inp[2] = inp[1];
inp[2].ki.dwFlags |= KEYEVENTF_KEYUP;
//release the VK_MENU key
inp[3] = inp[0];
inp[3].ki.dwFlags |= KEYEVENTF_KEYUP;
//simulate keyboard events and check success of function
SendInput(4, inp, sizeof(INPUT));
AddClipboardFormatListener(GetSafeHwnd());
m_bSnapKeyState = TRUE;
//캡처누르기 끝
static D3DDISPLAYMODE d3ddm;
if(!m_D3state)
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hwnd_f,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
//D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
&d3dpp, &g_pd3dDevice );
m_D3state = TRUE;
}
CString sizz;
sizz.Format(_T("현재해상도 == W : %d, H : %d"), GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
m_lbListBox.AddString(sizz);
HWND2IMG(m_hwnd_f);
//CaptureScreen(g_pd3dDevice, d3ddm, "함수안에서 작성됨");
//CaptureScreen2(g_pd3dDevice, d3ddm, "함수안에서 작성됨");
//CaptureScreen(g_pd3dDevice, d3ddm, m_hwnd_f, "함수안에서 작성됨");
//CaptureScreen2(g_pd3dDevice, d3ddm, m_hwnd_f, "함수안에서 작성됨");
}
BOOL CMFC_PIDINFO_TrainingDlg::HWND2IMG(HWND DsthWnd)
{
CDC memDC;
CDC *pDC = CDC::FromHandle(::GetDC(DsthWnd));
//CreateOffscreenPlainSurface();
//IDirect3DSurface9
CBitmap MyBitmap, *pOld;
memDC.CreateCompatibleDC(pDC);
CRect rect;
::GetClientRect(DsthWnd, &rect);
CString ttt;
ttt.Format(_T("Width : %d, Height : %d"), rect.Width(), rect.Height());
m_lbListBox.AddString(ttt);
MyBitmap.CreateCompatibleBitmap(pDC, rect.Width(),rect.Height()); // 화면에서 256*256만 가져옵니다.
pOld = memDC.SelectObject(&MyBitmap);
memDC.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
memDC.SelectObject(pOld);
ReleaseDC(&memDC);
CImage image; // Cimage파일을 써서 쉽게 bmp화 시킵니다.
image.Attach(MyBitmap);
CString filename;
CTime filenameset;
filenameset = CTime::GetCurrentTime();
filename = filenameset.Format("%y%m%d%H%M%S");
filename += _T(".png");
image.Save(filename);
return 0;
}
LRESULT CMFC_PIDINFO_TrainingDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
switch( message )
{
case WM_USER+1:
{
OnBnClickedButtonPrtsc();
break;
}
}
return CDialog::WindowProc(message, wParam, lParam);
}
void CMFC_PIDINFO_TrainingDlg::OnBnClickedCheckAutopic()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
UpdateData(TRUE);
if(m_bScreenAutoCap)
{
SetTimer(SCREEN_RELOAD, 1000, 0);
m_lbListBox.AddString(_T("자동스샷 시행"));
}
else
{
KillTimer(SCREEN_RELOAD);
m_lbListBox.AddString(_T("자동스샷 종료"));
}
}
BOOL CMFC_PIDINFO_TrainingDlg::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
return CDialog::Create(lpszTemplateName, pParentWnd);
}
void CMFC_PIDINFO_TrainingDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
if(m_D3state)
{
g_pD3D->Release();
g_pd3dDevice->Release();
}
}
void CMFC_PIDINFO_TrainingDlg::OnClipboardUpdate()
{
// 이 기능을 사용하려면 Windows Vista 이상이 있어야 합니다.
// _WIN32_WINNT 기호는 0x0600보다 크거나 같아야 합니다.
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
if(m_bSnapKeyState)
{
CString filename;
filename = _T("흐믓.bmp");
CString err_msg;
if(!ClipBoard2IMG(filename, NULL, &err_msg))
{
m_lbListBox.AddString(err_msg);
}
}
m_bSnapKeyState = FALSE;
RemoveClipboardFormatListener(GetSafeHwnd());
CDialog::OnClipboardUpdate();
}