9.13(목) 이론-2

2007/10/10 13:45

1. EXE의 종류
   
- Console App : 콘솔창을 생성한다. main, 콘솔(/SUBSYSTEM:CONSOLE)
- GUI App : 윈도우창을 생성.           WinMain,Windows (/SUBSYSTEM:WINDOWS)
- Net App : CLR을 동작한다.

- Linker 옵션의 Subsytem차이 일 뿐이다.
- #pragma comment( linker, "[옵션]" )

- WhatExe ( EXE의 종류를 파악한다. )

[ more.. | less.. ]

#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue))

int main(int argc, char* argv[])
{
    char    *filename   = NULL;
    HANDLE hFile;
    HANDLE hFileMapping;
    PIMAGE_DOS_HEADER dosHeader;
    PBYTE g_pMappedFileBase = 0;

    if(argc != 2)   
    {   
        cout << "WhatEXE.exe [대상파일명]" << endl;
        exit(0);
    } 
    filename = argv[1];

    hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    if ( hFile == INVALID_HANDLE_VALUE )
    {
        cout << "CreateFile() fail" << endl;
        return 0;
    }

    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if ( hFileMapping == 0 )
    {
        CloseHandle(hFile);
        cout << "CreateFileMapping() fail " << endl;
        return 0;
    }

    g_pMappedFileBase = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);
    if ( g_pMappedFileBase == 0 )
    {
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        cout << "MapViewOfFile() fail" << endl;
        return 0;
    }

    dosHeader = (PIMAGE_DOS_HEADER)g_pMappedFileBase;
    PIMAGE_FILE_HEADER pImgFileHdr = (PIMAGE_FILE_HEADER)g_pMappedFileBase;

    if ( dosHeader->e_magic == IMAGE_DOS_SIGNATURE )
    {
        PIMAGE_NT_HEADERS pNTHeader;
        PBYTE pImageBase = (PBYTE)dosHeader;

        // Make pointers to 32 and 64 bit versions of the header.
        pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew );

        // First, verify that the e_lfanew field gave us a reasonable
        // pointer, then verify the PE signature.
        if ( IsBadReadPtr( pNTHeader, sizeof(pNTHeader->Signature) ) )
        {
            cout << "Not EXE" << endl;
            return 0;
        }

        if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
        {
            cout << "Not EXE" << endl;
            return 0;
        }

        char *s;
        UINT width = 30;

        switch( pNTHeader->OptionalHeader.Subsystem )
        {
        case IMAGE_SUBSYSTEM_UNKNOWN: s = "UNKNOWN (0)"; break;
        case IMAGE_SUBSYSTEM_NATIVE: s = "Native"; break;
        case IMAGE_SUBSYSTEM_WINDOWS_GUI: s = "Windows GUI"; break;
        case IMAGE_SUBSYSTEM_WINDOWS_CUI: s = "Windows character"; break;
        case IMAGE_SUBSYSTEM_OS2_CUI: s = "OS/2 character"; break;
        case IMAGE_SUBSYSTEM_POSIX_CUI: s = "Posix character"; break;
        case IMAGE_SUBSYSTEM_NATIVE_WINDOWS: s = "Native Windows (Win9X driver)"; break;
        case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: s = "Windows CE GUI"; break;
        case IMAGE_SUBSYSTEM_EFI_APPLICATION: s = "EFI_APPLICATION"; break;
        case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: s = "EFI_BOOT_SERVICE_DRIVER"; break;
        case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: s = "EFI_RUNTIME_DRIVER"; break;
        case IMAGE_SUBSYSTEM_EFI_ROM: s = "EFI_ROM";
        case IMAGE_SUBSYSTEM_XBOX: s = "XBOX";
        default: s = "unknown";
        }
        cout << filename << "    " << "Subsystem" << "    " <<
                      pNTHeader->OptionalHeader.Subsystem << "    " << s;
    }



 

2. Data Type

P Pointer를 나타낸다. ( ex : PPOINT -> POINT* )
LP 32비트 Code에서는 P와 완전히 같다. WIN32에서 PSTR과 LPSTR은 같은 코드.
T,_t T는 DBCS와 UNICODE Type을 동시에 지원하기 위한 매크로이다.(TCHAR->char,wchar_t)
W UNICODE Type이다.
C const를 의미한다.
STR 문자열을 나타낸다.( ex : PSTR->char*)
H H로 시작하는 대부분의 Type은 핸들형 Type을 나타낸다.( ex : HWND, HPEN, HBRUSH )

- 윈도우 구조체의 크기를 얻는 이유( Window Version이 많아서-_-.. )
- 구조체의 크기는 조건에 따라 달라지므로 구조체에서 크기를 저장하는 변수를 가지고 있다.


3. HANDLE 개념 : 객체를 가리키는 번호, 32bit 정수(long), 고유의 번호를 가진다.

- OS는 HANDLE 번호를 만들어서 리턴해준다.
- HWND : 윈도우 번호
- HPEN : 펜 번호
- HBRUSH : 브러시 번호

4. 윈도우 만들기 GUI 윈도우 생성!!

- 모든 윈도우는 윈도우 클래스로 부터 만들어진다.

- 배경색, 아이콘, 이름, 윈도우틀(클래스).. 이 필요하다.
- 윈도우 클래스를 시스템에 등록한다.
- 등록된 클래스로 윈도우를 생성한다.
- 윈도우를 보여준다.

- 미리 가져다 쓸수 있는 등록된 클래스가 40~50개가 있다.(button, edit...)
- OS는 윈도우클래스모음 List를 가지고 이를 관리한다. 65536개를 관리 가능하다.


5. 윈도우 핸들

- API함수의 대부분은 핸들만 알고 있다면 윈도우를 조작가능 하다. ex) MoveWindow, Setmenu...
- 핸들을 얻을 수 있는 함수들.  ex) FindWindow, WindowFromPoint
- 예제 코드 ( 계산기 자식 윈도우 )
[ more.. | less.. ]

BOOL CALLBACK foo( HWND hwnd,  LPARAM lParam );

int main()
{
    HWND hCalc = FindWindowEx( 0, 0, 0, _T("계산기") );
    if ( hCalc == 0 )
    {
        wcout << _T("Not Calc.exe") << endl;
        return -1;
    }

    EnumChildWindows( hCalc, foo, 0 );
}

BOOL CALLBACK foo( HWND hwnd,  LPARAM lParam )
{
    TCHAR cname[256];
    TCHAR title[256];

    GetClassName( hwnd, cname, 256);
    GetWindowText(hwnd, title, 256);

    wcout << hex << hwnd << "-" << cname << "-"<< title << endl;

    return TRUE;
}

- 예제코드 ( 계산기 자식윈도우 숨기기 )
[ more.. | less.. ]

int main()
{
    HWND hCalc = FindWindow( 0, "계산기" );   

    if ( hCalc == 0 )
    {
        cout << "계산기를 먼저 실행하세요." << endl;
        return 0;
    }

    HWND hCalcChild;
    hCalcChild = FindWindowEx( hCalc, 0, "button", "5" );

    if( IsWindowVisible( hCalcChild ) )
        ShowWindow( hCalcChild, SW_HIDE );
    else
        ShowWindow( hCalcChild, SW_SHOW );

    return 0;
}

Tags

API, 이론