(Win32 : WindowsProgramming-14) Kernel Object

Posted by : at

Category : win32   WindowsProgramming


Object Categories

A, B라는 별도의 프로세스가 존재할 시

  • A의 핸들을 B에서 받아서 사이즈 조정이 가능할까? -> 가능(윈도우 핸들은 public to all processes)
  • A에서 만든 GUI 팬을 B에서 그림그리기가 가능할까? -> 불가능(private to a process)
  • A에서 만든 파일을 B에서 파일핸들을 통해 접근이 가능할까 -> 상황에 따라 다름(process specific) 어떻게 핸들을 전달했느냐에 따라 다르다

세 가지 경우의 수가 있는데 어떤경우 인지 자세히 살펴보자.


  • 모두 CreateXXX을 통해 만든다
  • CreateXXX로 생성할 경우 Window Object가 생성되며 세 가지 종류로 나뉜다

  • User Object
    • 윈도우와 관련된 Object (윈도우 창, 메뉴 창 등)
    • public to all processes
    • 파괴 함수 : DestroyXXX()
    • 관련 DLL : User32.dll
  • GDI Object
    • 그래픽 관련 Object (폰트, 프러쉬 등)
    • private to a process
    • 파괴 함수 : DeleteXXX()
    • 관련 DLL : Gdi32.dll
  • Kernel Object
    • 파일, 메모리, 프로세스등 UI 이외의 작업에 관련된 Object
    • process specific
    • 파괴 함수 : CloseHandleXXX()
    • 관련 DLL : Kernel.dll
  • 참고사이트

Kernel Object

커널(Kernel Object)는 아래와 같이 구성되어있다


보안 속성(Security Attribute)
이름
참조 계수(Reference Counting)
SIGNAL
WAIT LIST
...(기타)

대표적인 예로 CreateWaitableTimerEx를 보자면
이게 User, GDI, Kernel Object중 뭐인지 헷갈릴수 있는데 보안설정을 설정함을 봐선 Kernel Object임을 안다

HANDLE CreateWaitableTimerExW(
  LPSECURITY_ATTRIBUTES lpTimerAttributes,      // 보안속성을 설정함을 볼수있음
  LPCWSTR               lpTimerName,
  DWORD                 dwFlags,
  DWORD                 dwDesiredAccess
);

자세한 설명은 이후에 진행된다.

우선은 커널오브젝트 핸들을 다른 프로세스에 넘길수 있을까?

#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

int _tmain()
{
    HANDLE hFile = CreateFile(_T("a.txt"), /* ... */);
    _tprintf(_T("FILE HANDLE : %x\n"), hFile);

    // 다른 프로세스에 파일 핸들 전달?
    HWND hwnd = FindWindow(0, _T("Friend"));
    SendMessage(hwnd, WM_APP+100, 0, (LPARAM)hFile);
}

일단 다른 프로세스에서 파일의 핸들을 사용하지 못한다.
넘겨준 핸들은 실제 물리적 주소값을 의미하는 것이 아니라 Kernel내부적으로 관리하는 Object Table내의 index이다.
해당 index에서 파일이 접근 가능한지 쓸 수 있는지 등을 OS에서 알려주고 파일에 접근하게 된다.
따라서 파일의 핸들(단순 index)만으론 파일에 접근이 불가능 하다

  • 좀 더 자세히 설명하자면 프로세스마다 PKO(Process Kernel Object)를 관리한다.
  • CreateFile을 할경우 File Kernel Object가 생성되며 내부에 참조계수를 1 올린다
  • File Kernel Object를 생성한 프로세스는 PKO에서 생성된 File Kernel Object를 등록하고 물리주소를 기록한다
  • 따라서 그냥 HANDLE을 전달한다면 전달받은 프로세스는 자신의 PKO에서 HANDLE을 찾아보고 없다면 사용불가!

  • 그래도 하고싶다면? -> DuplicateHandle()과 같은 Win32에서 제공하는 API를 사용해야 한다.
  • DuplicateHandle()는 PKO 주소자체를 복사해준다
  • 그렇게 되는순간 File Kernel Object의 참조계수는 1증가한다

  • 참고) 참조 계수로 관리되는 Kernel Object는 프로세스의 생명주기와 일치하지 않기에 OS가 소유한다고 한다
  • 참고) CloseHandle()을 통해서 참조 계수의 카운트를 1줄이게 된다
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

int _tmain()
{
    HANDLE hFile = CreateFile(_T("a.txt"), /* ... */);
    _tprintf(_T("FILE HANDLE : %x\n"), hFile);

    // DuplicateHandle 써보기
    HWND hwnd = FindWindow(0, _T("Friend"));

    // FILE의 핸들을 다른 프로세스에 복사하기
    // 1. 프로세스 ID구하기
    DWORD pid;
    DWORD tid = GetWindowThreadProcessId(hwnd, &pid);

    // 2. 프로세스 ID를 가지고 핸들 얻기
    HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, 0, pid);

    // 3. DuplicateHandle() 함수로 핸들 복사
    HANDLE handle;  // 상대방 테이블의 핸들
    DuplicateHandle(GetCurrentProcess(), hFile,
                    hProcess, &handle,
                    DUPLICATE_SAME_ACCESS, 0, 0);

    SendMessage(hwnd, WM_APP + 100, 0, (LPARAM)handle);
}
LRESULT __stdcall WndProc(HWND /* ... */)
{
    switch(message)
    {
    case WM_APP + 100;
    {
        HANDLE hFile = (HANDLE)lParam;

        DWORD len;
        char data[256] = "hello";

        BOOL b = WriteFile(hFile, data, 256, &len);

        CloseHandle(hFile);
    }
    }
}

PKO를 보고싶다면??

ProcessExplorer.exe를 이용하자(주의할 점은 관리자 모드로 실행)

int _tmain()
{
    getchar();
    HANDLE h1 = CreateFile(_T("a.txt"),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                0, CREATE_ALWAYS,
                FILE_ATTRIBUTE_NORMAL, 0);

    getchar();
    HANDLE h2 = CreateEvent(0, 0, 0, _T("MyEvent"));

    getchar();
    HANDLE h3 = CreateMutex(0, 0, _T("MyMutex"));

    getchar(); CloseHandle(h3);
    getchar(); CloseHandle(h2);
    getchar(); CloseHandle(h1);
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links