Windows_/Windows32_API

Windows :: 윈도우 핸들찾기, pid를 이용하여 핸들 가져오기

sosal 2014. 7. 24. 10:05
반응형

/*

 * http://sosal.kr/

 * made by so_Sal

 */




음.. 이번 포스트에서는 음.. 사실 06 커널오브젝트, 핸들내용에서
넣지못한 글을 간단히 정리해서 올리려고 합니다.

:: struct PROCESS_INFORMATION
::  FindWindow()
::  FindWindowEx()
::  OpenProcess()

::  CloseHandle()
이것들을.. 살펴보고자 합니다 ^-^



PROCESS_INFORMATION 구조체를 선언하여 CreateProcess 함수의 인자로
쓰기는 해보았는데, 가져와서 이용을 한적이 없어요. 한번 살펴보죠. 흠.

typedef struct _PROCESS_INFORMATION
{
    HANDLE hprocess;        //프로세스의 핸들
    HANDLE hprocess;        //쓰레드의 핸들
    DWORD dwProcessId;    //프로세스의 ID
    DWORD dwThreadId;        //쓰레드ID
} PROCESS_INFORMATION;

CreateProcess 함수로 새로운 프로세스를 생성하고, 생성된 프로세스의
정보를 가져올때는 함수호출시 인자로 전달되었던 PROCESS_INFORMATION 구조체로
정보를 가져옵니다.

#include<windows.h>
#include<tchar.h>
#include<iostream>

using namespace std;

int _tmain(void){
 STARTUPINFO si={0,};
 PROCESS_INFORMATION pi;
 si.cb = sizeof(si);
 TCHAR command[] = _T("notepad hi");

 CreateProcess(
  NULL,
  command,
  NULL,NULL,TRUE, 0,NULL,NULL,

  &si,&pi
 );
 cout<<pi.dwProcessId<<endl;
 cout<<pi.dwThreadId<<endl;
 cout<<pi.hProcess<<endl;
 cout<<pi.hThread<<endl;
 Sleep(3000);
 TerminateProcess(pi.hProcess,0);

 

 return 0;
}




notepad라는 프로그램을 자식프로세스로 띄우는 동시에
부모프로세스는 자식프로세스의 정보를 출력합니다.
process ID, thread ID, process HANDLE, thread HANDLE.
3초후에는 TerminateProcess()라는 함수를 호출합니다.
TerminateProcess(HANDLE hProcess, UINT uExitCode)
프로세스 핸들값을 이용하여 프로세스를 죽여버리는 일을 하는 함수입니다.
그럼 저 위에 코드를 실행한 결과는? Notepad가 켜진 후 3초후에 프로그램이 꺼지겠지요.

으앜ㅋ.. 대충 핸들을 이용해서 이상한짓을 한번 해보았습니다.
하여튼, 프로세스를 새로 생성하면서  PROCESS_INFORMATION 라는 구조체로
반환되는 값을 이용하는 방법으로, 프로세스의 핸들값을 가져왔습니다.

프로세스를 새로 생성하지 않고, 윈도우즈 안에 자기멋대로 켜져있는 프로세스의 핸들값을
가져올 수 있어와야 하는데, 그 함수를 살펴보겠습니다.

HWND
FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);
FindWindow 이 함수는 조건에 맞는 윈도우를 검색하여 클레스 이름, 윈도우 이름을 조건으로 찾아냅니다.
lpClassName에게 "Window Class Name"을 전달, lpWindowName에 갭션을 전달해주는데,
둘중에 하나만 전달해줘도 됩니다. (대소문자 구별 X)
하지만 FindWindow는 부분적인 문자들을 검색하지 못하고,
입력 조건과 완벽히 일치하는 윈도우만 검색 가능합니다.
그리고 갭션이 완벽히 같은 두 개 이상의 윈도우가 존재할 수 있기 때문에
검색 결과도 100% 신뢰할 수 없습니다.
(정확도가.. 낮습니다. 데스크탑용 윈도우 핸들을 찾기위한 함수인듯 합니다.)

HWND FindWindowEx(
        HWND hwndParent, HWND hwndChildAfter,
        LPCTSTR lpClassName, LPCTSTR lpWindowName);

hwndParent :: 이 핸들이 가리키는 윈도우의 자식 윈도우들을 찾겠다. 라는 의미입니다.
NULL이 들어가 있을 경우엔 데스크탑 윈도우의 자식윈도우를 검색합니다.

hwndChildAfter 매개변수는 검색을 시작할 자식 윈도우를 지정하는데,
이 자식의 순서 다음부터 검색하겠다는 의미입니다. 
NULL이라면 첫번째 자식 윈도우부터 검색합니다.
검색하는 순서는 화면에서 가장 앞쪽에 떠있는 (사용자가 볼수있도록 가장 앞쪽에..)
그러니까 클릭되어져 있는(?. 흠 화면 제일 앞에 떠있는걸 말하는거에요)
윈도우부터 차례대로 검색해나갑니다. (화면을 xy축이라 하고 이걸 흔히 z축이라 하더군요)

HANDLE OpenProcess(
     DWORD dwDesiredAccess,
     BOOL bInheritHandle,
     DWORD dwProcessID
);

위 함수들은 핸들값을 직접 찾아올 수 있는 유용한 함수 입니다.
OpenProcess도 핸들값을 가져오는데 유용한 함수로 쓰입니다.
원하는 핸들값을 찾기 위해서는 원하는 프로세스를 찾는 단서가 있어야 하는데,
이 함수에서 쓰이는 단서는 PID (Process ID) 입니다.
모든 프로세스는 운영체제(커널)가 관리하기 위해서 각각의 프로세스마다
ID를 공급하는데 (동시에 2개 이상의 프로세스가 하나의 PID를 가질 순 없다.)
이 값은 한 시점에서 고유한 번호이기 때문에 PID를 이용해서
핸들값을 받아올 수 있습니다.

dwDesiredAccess :: 반환되는 핸들의 성격을 결정짓는다.
// PROCESS_ALL_ACCESS    //핸들에 모든 접근을 허용한다.
// PROCESS_QUERY_INFORMATION
// PROCESS_VM_READ

bInheritHandle :: //TRUE / FALSE로 상속 성격 지정

dwProcessID :: //원하는 Process의 ID (PID)를 입력한다.
(PID를 찾기 위해서는 #include<tlhelp32.h> 헤더파일 안에 있는
 CreateToolhelp32Snapshot() 함수와
Process32First(), Process32Next() 함수,
그리고 PROCESSENTRY32 구조체를 공부하셔야 합니다.
( 링크 :: LINK_ )


BOOL CloseHandle(HANDLE hObject);
열려져있는 핸들을 닫는 함수입니다.
간접적인 커널 오브젝트의 연결을 끊어주는 함수.
프로세스간의 연결을 끊는 함수.