Registry

6월 26, 2006 at 10:31 오전 (Visual C++)

이번시간 부터는 레지스트리에 대한 것에 대해 알아 보겠습니다. 혹시 레지스트리라는것을 들어 보았습니까? 윈도우즈에서는 레지스트리라는 것이 존재하는데 이것은 일종의 하드웨어적, 소프트웨어적인 정보를 저장하고 있는 매체입니다. 우리가 앞에서 배운 win.ini 파일에도 다양한 정보가 저장되어 있는데 사실 이것은 윈도우즈 3.1때와의 호환 때문에 존재하는 것이고 실제로 우리가 다루어야 할 것은 바로 이 레지스트리입니다. 음.. 예를들어서 win.ini 파일에 프로그램이 설치되어 있는 디렉토리 정보가 들어 있었죠? 아마 인스톨 쉴드라는 인스톨 툴로 인스톨 프로그램을 만들면 인스톨시에 win.ini 파일에 디렉토리 정보 저장 기능은 없을 겁니다.

그러나 레지스트리에 설치된 디렉토리를 저장할 수 있는 기능은 있죠. 바로 레지스트리에도 설치된 디렉토리 정보가 들어 있다는 말과도 같습니다. 그것 뿐만 아닙니다. PNP 하드웨어의 정보도 다 들어 있죠. 모뎀 포트를 자동으로 찾는다거나 하는 작업을 바로 이 레지스트리를 검색해서 할수 있는 것입니다. 여러분들 넷스케이프 사용해 봤습니까? 거기에 보면 홈 디렉토리를 지정할 수 있는 메뉴 아이템이 있을겁니다. MS 익스플로어의 요즘 버전은 제가 사용해 보지 않았지만 예전에 사용할 때에는 이 기능이 없더군요. 그래서 항상 홈 디렉토리가 마이크로 소프트사였습니다. 그런데 이 홈 디렉토리 정보가 레지스트리에 등록되어 있다는 것을 우연히 알게 되었습니다. 물론 그것을 바꿔서 홈 디렉토리를 바꾸었죠.

너무 서론이 길었죠? 그렇다면 이러한 레지스트리를 어떻게 원하는데로 바꿀 수 있을까요? 윈도우즈가 설치되어 있는 디렉토리에 보면 regedit.exe 파일이 있을 겁니다. 이 실행 파일을 실행시켜서 레지스트리 정보를 볼 수도 있고 또 수정할 수도 있습니다. 이 프로그램을 레지스트리 편집기라고도 하죠.

한번 실행해 보세요.

어때요? 크게 6개의 폴더가 보이죠? 각 커다란 폴더에는 의미가 있습니다.

HKEY_CLASSES_ROOT

이 하위에 있는 정보들은 문서의 형태, 파일연관상태에 대한 정보가 들어 있습니다. 실제로 하위 폴더를 보면 아래아 한글 문서의 확장자, 압축 파일 확장자들의 정보가 들어 있음을 확인할 수 있습니다.

HKEY_CURRENT_USER

각각 사용자에 따른 사용자 정보를 가지고 있습니다.

HKEY_LOCAL_MACHINE

하드웨어, 네트워크, 소프트웨어 정보가 이곳에 있습니다. 실제로 프로그램이 설치되어 있는 디렉토리, PNP 하드웨어 등록 정보들이 이곳에 있는 거죠.

HKEY_USERS

각각 사용자에 대한 시스템 정보를 가지고 있습니다.

HKEY_CURRENT_CONFIG

하드웨어 설정에 대한 정보값이 들어 있습니다.

HKEY_DYN_DATA

역시 하드웨어적인 정보값이 들어 있습니다.

자 각각에 대해 알아 보았으니 각 서브 폴더를 확인해 보시기 바랍니다. 폴더 옆에 보면 플러스 기호가 있는데 여기에 마우스의 왼쪽 버튼으로 클릭하면 마이너스 기호로 바뀌고 그곳에 속해 있는 서브 폴더를 보여주게 됩니다. 다시 클릭하면 감춰지죠. 서브 폴더를 보다보면 폴더 왼쪽에 아무 기호도 없는 폴더들이 있을 겁니다. 그것은 서브 폴더를 가지지 않음을 의미하는 것입니다. 그렇다면 서브 폴더를 가지지 않은 폴더에 클릭한 후에 오른쪽에 있는 창을 보십시요.

어때요? 네임에 어떤 이름이 있고 데이터에 값이 들어 있죠? 물론 아무 값도 가지지 않는 경우도 있습니다. 서브 풀더를 가지고 있는 것도 마찬가지입니다. 왼쪽에 있는 기호에 클릭하지 않고 바로 그 폴더를 클릭하면 네임과 데이터에 값이 표시될 것입니다.

자 새로운 용어를 알아 봅시다. 우리가 앞에서 언급한 폴더를 키라고 합니다. 각 키는 물론 서브 키를 가질 수 있고 각 키에는 네임과 데이터를 가집니다. 물론 하나의 키는 여러개의 네임과 데이터를 가질 수 있습니다. 이해가 가죠?

자 이제부터 우리는 기존에 등록되어 있는 키, 네임, 데이터를 읽는 것을 프로그램 상으로 어떻게 구현하는지 알아 볼 것입니다. 물론 등록하는 방법도 알아 볼 거구요.

그러면 시작해 봅시다.

먼저 등록되어 있는 정보를 읽어오는 방법부터 알아 봅시다. 처음에 정보를 가져올 키가 어떤 것인지 지정해서 열어 주어야 합니다.

LONG RegOpenKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    REGSAM  samDesired,
    PHKEY  phkResult
   );   

위 함수를 이용해서 레지스트리에 설정되어 있는 키를 열 수 있습니다. 첫번째 파라미터에 제일 상단에 있는 루트키를 지정하면 되는데 이 키는 레지스트리 편지기를 실행했을 때 볼 수 있는 값을 지정하면 되는 겁니다. 아래 값들 중 하나가 되겠군요.

HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA

두번째 파라미터에는 우리가 정보를 가져올 서브키를 지정해 주면 됩니다. 서브키 내에 또다른 서브키가 있으면 서브 디렉토리를 표시하던 식인 \\식으로 표시해 주면 됩니다. 세번째 파라미터에는 0을 지정하면 되고 네번째 파라미터에는 지정된 예약어를 지정해주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

마지막 파라미터에는 서브키를 열었을때 얻어진 키 핸들을 저장할 변수의 주소를 지정해 주면 됩니다.

자 이제 서브키를 열었으니 그 키가 가지는 데이터를 가져오기만 하면 될 겁니다.

LONG RegQueryValueEx(
    HKEY  hkey,
    LPTSTR  lpszValueName,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );

위 함수를 이용해서 데이터를 가져올 수 있습니다. 첫번째 파라미터에는 위 RegOpenKeyEx() 함수에서 얻은 키 핸들을 지정하면 되고 두번째 파라미터에는 가져올 데이터가 가지는 네임을 지정해 주면 됩니다. 네임이 Default로 되어 있으면 그냥 ""식으로 지정해 주면 됩니다. 세번째 파라미터에는 0을 지정해 주면되고 네번째 파라미터에는 데이터의 저장형태가 저장될 변수의 주소를 지정해주면 됩니다. 이 저장형태는 뒤에 가서 레지스트리에 정보를 기록할때 다시 설명드리겠습니다.

그리고 다섯번째 파라미터에는 읽어온 데이터가 저장될 주소를 지정하면 됩니다. 마지막 파라미터에는 이 읽어온 데이터의 크기가 저장될 변수의 주소를 지정하면 됩니다.

데이터를 읽어오는 과정이 어렵지 않죠? 키를 열어서 작업을 다 했으면 그 키를 닫아 주어야 합니다.

LONG RegCloseKey(
    HKEY  hkey
   );

위 함수를 이용해서 연 키를 닫을수 있습니다. 물론 새로 생성한 키도 위 함수를 이용해서 닫아주면 되죠.

그러면 이번에는 정보를 기록하는 방법에 대해 알아 봅시다. 마찬가지로 어렵지 않습니다. 먼저 새로운 키를 생성하는 과정이 필요한데 그것은 아래 함수를 이용해서 하면 됩니다.

LONG RegCreateKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    LPTSTR  lpszClass,
    DWORD  fdwOptions,
    REGSAM  samDesired,
    LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
    PHKEY  phkResult,
    LPDWORD  lpdwDisposition
   );

첫번째 파라미터에는 제일 상단에 있는 루트키를 지정해 주면 되는데 이 루트키는 이미 RegOpenKeyEx() 함수때 설명드렸을 겁니다. 두번째 파라미터에는 서브키를 지정해 주면 됩니다. 세번째 파라미터에는 NULL을 지정하면 되고 네번째 파라미터에는 클래스 이름을 지정해 주면 됩니다. 보통 NULL을 지정하죠. 다섯번째 파라미터에는 지정된 예약어를 지정해 주면 되는데 이때 지정될 수 있는 예약어는 다음과 같습니다.

REG_OPTION_VOLATILE         메모리에만 저장됩니다.
REG_OPTION_NON_VOLATILE     파일에 저장됩니다.

첫번째 예약어를 사용하게 되면 메모리에만 저장되므로 시스템이 재시작되면 무효가 되나 두번째 예약어를 사용하게 되면 파일에 저장되므로 그 값이 계속 유효하게 됩니다. 어떤 차이인지 알겠죠?

여섯번째 파라미터에는 어세스 옵션을 지정해 주면 되는데 다음과 같은 예약어를 지정해 주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

앞에서 알아본 RegOpenKeyEx()함수의 예약어와 같죠? 일곱번째 파라미터에는 NULL을 지정하면 되고 여덟번째 파라미터에는 이 키에 대한 핸들을 기억할 키 변수의 핸들을 지정해 주면 됩니다. 마지막 파라미터에는 키에 대한 결과가 저장될 변수의 주소를 지정해 주면 됩니다.

이제 키를 생성하는 함수를 알아보았으니 원하는 네임에 데이터를 지정하는 함수를 알아 봅시다.

LONG RegSetValueEx(
    HKEY  hkey,
    LPCTSTR  lpszValueName,
    DWORD  dwReserved,
    DWORD  fdwType,
    CONST BYTE *  lpbData,
    DWORD  cbData
   );

위 함수를 이용해서 원하는 네임과 데이터를 지정해줄수 있는데 각 파라미터의 의미를 알아 봅시다.

첫번째 파라미터에는 RegCreateKeyEx()함수로 얻은 키 핸들을 지정해주면 되고 두번째 파라미터에는 네임을 지정해 주면됩니다. 세번째 파라미터에는 NULL을 지정해주면 되고 네번째 파라미터에는 데이터의 타입을 지정해주면 됩니다. 데이터의 타입은 아래의 예약어를 이용하면 됩니다.

REG_BINARY      바이너리 형태입니다.
REG_DWORD       더블워드 형태입니다.
REG_LINK        심볼릭 링크 형태입니다.
REG_NONE        아무 형태도 아닙니다.
REG_SZ          문자열의 형태입니다.

다섯번째 파라미터에는 데이터를 지정해주면 됩니다. 마지막 파라미터에는 데이터의 길이를 지정해 주면 되구요.

자 그러면 이번에는 키를 삭제하는 방법을 알아 봅시다.

먼저 지울 키를 RegOpenKeyEx()함수를 이용해서 핸들 형태로 반환을 받아야 합니다. 그래서 그 핸들을 이용해서 원하는 네임의 데이터를 삭제하면 되죠.

원하는 네임의 데이터를 지울 때에는 아래 함수를 사용하면 됩니다.

LONG RegDeleteValue(
    HKEY  hkey,
    LPTSTR  lpszValue
   );

첫번째 파라미터에 지울 네임이 속해 있는 키의 핸들을 지정해 주면 됩니다. 두번째 파라미터에는 지울 데이터의 네임을 지정해 주면 되구요.

이번에는 키 자체를 없애는 함수입니다.

LONG RegDeleteKey(
    HKEY  hkey,
    LPCTSTR  lpszSubKey
   );

첫번째 파라미터에는 최상위 루트 키의 이름을 지정해주면 되고 두번째 파라미터에는 그 안에 포함된 지울 서브키의 이름을 지정해 주면 됩니다. 사용방법이 간단하죠.

자 그러면 위에서 배운 함수들을 이용해서 실제로 프로그램을 만들어 봅시다.

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 47

안녕하세요……..돌팔이 황동준입니다……………..

이번시간에는 저번시간에 알아 본 함수들을 이용해서 프로그램을 만들어 보겠습니다.

아래 프로그램은 레지스트리에 원하는 키를 생성해서 거기에 데이터를 기록한 뒤 실제로 그 데이터를 가져오고 하는 기능을 가졌습니다. 물론 지우는 기능도 있구요. 앞부분에서 함수를 잘 이해한 분들은 그렇게 어렵지 않을 겁니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Get Registry", 200
        MENUITEM "&Delete Registry", 300
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
char* GetRegistry(void);
void DeleteRegistry(void);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        strcpy(szBuff, GetRegistry());
                        if(strcmp(szBuff, "ERROR"))
                            MessageBox(hWnd, szBuff, "", MB_OK);
                        else
                            MessageBox(hWnd, "Value not found!!", "", MB_OK);
                        break;

                    case 300 :

                        DeleteRegistry();
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

char* GetRegistry(void)
{
    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{
    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);
    RegDeleteValue(hKey, "Install");
    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");
    RegCloseKey(hKey);
}

자 프로그램을 실행시켜 첫번째 메뉴 아이템인 Set Registry를 선택해 보세요. 그리고 진짜로 그 키가 생성되었는지 레지스트리 편집기로 확인해 보시기 바랍니다. 어때요? 정말로 생성되어 있죠? 자 그러면 소스를 보도록 합시다.

제가 만든 세개의 함수 루틴만 보면 되겠네요.

BOOL SetRegistry(void)
{

이 함수는 새로운 키를 생성하는 역할을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);

HKEY_LOCAL_MACHINE 부분에 있는 Software내에 DORAN 20이라는 키를 생성하고 있는 구문입니다. 물론 Software라는 서브키가 존재하지 않으면 새로 생성합니다.

    if(lRet != ERROR_SUCCESS)
        return FALSE;

성공적으로 함수가 수행되면 ERROR_SUCESS라는 리터값이 발생된다는 것을 위 구문으로 짐작할 수 있을 겁니다.

    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));

Install이라는 네임에 c:\doran20이라는 데이터를 저장하는 구문입니다.

    if(lRet != ERROR_SUCCESS)
    {

역시 함수가 성공적으로 수행되면 ERROR_SUCCESS라는 리턴값이 발생되는군요.

        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);

생성한 키를 닫는 구문입니다.

    return TRUE;
}

char* GetRegistry(void)
{

이 함수는 원하는 서브키의 데이터를 가져오는 역할을 합니다.

    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

데이터를 가져올 서브키를 열고 있습니다.

    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);

Install이라는 네임에 해당하는 데이터를 가져오고 있습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{

이 함수는 첫번째 메뉴 아이템에 의해 생성된 키와 데이터를 삭제하는 역할을 합니다.

    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);

지울 키를 얻고 있습니다.

    RegDeleteValue(hKey, "Install");

Install 네임을 가지고 있는 데이터를 삭제하는 구문입니다.

    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");

서브 키를 없애는 구문입니다.

    RegCloseKey(hKey);
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 48

안녕하세요…………돌팔이 황동준입니다……………

이번시간에도 레지스트리에 대해 더 알아 보겠습니다. 이번에 알아 볼 것은 어떤 키에 속해있는 서브키를 어떻게 얻을 수 있는지 입니다. 물론 우리는
서브키에 속해 있는 네임에 해당하는 데이터를 얻는 방법은 압니다. 그러나 문제가 있죠. 바로 이 키에 어떤 서브키가 있는지 모른다면 할 수가 없습니다. 그렇죠? 그렇기 때문에 이 방법을 알아야 합니다. 좀더 들어간다면 어떤 서브키에 어떤 네임들이 있는지도 아는 방법이 있습니다. 그것도 우리가 지금 알아 볼 방법을 응용하면 됩니다. 자 그러면 시작해 봅시다.

먼저 크게 두단계로 나누어서 합니다. 첫번째 단계는 바로 원하는 키에 서브키가 몇개 있는지 개수를 알아내는 것입니다. 두번째 단계는 이 개수를 가지고 차례로 키 포인터를 이동시켜 서브키를 얻는 것입니다.

자 그러면 실제로 어떤 식으로 구현하는지 필요한 함수를 보도록 합시다. 먼저 서브키의 개수를 알아야 하는데 이때 필요한 함수의 첫번째 파라미터에 키 핸들을 지정해야 하는데 이 키 핸들은 앞에서 배운 RegOpenKeyEx()함수를 이용하면 됩니다. 그러면 키의 개수를 얻을 수 있는 함수를 보도록 합시다.

LONG RegQueryInfoKey (
    HKEY  hkey,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    LPDWORD  lpdwReserved,
    LPDWORD  lpcSubKeys,
    LPDWORD  lpcchMaxSubkey,
    LPDWORD  lpcchMaxClass,
    LPDWORD  lpcValues,
    LPDWORD  lpcchMaxValueName,
    LPDWORD  lpcbMaxValueData,
    LPDWORD  lpcbSecurityDescriptor,
    PFILETIME  lpftLastWriteTime
   );

첫번째 파라미터로 RegOpenKeyEx()함수에서 얻은 키 핸들을 지정하면 됩니다. 두번째 파라미터에는 클래스 이름이 저장될 버퍼의 주소를 세번째 파라미터에는 그 클래스 버퍼의 크기를 가지고 있는 변수의 주소를 지정해 주면 됩니다.

네번째 파라미터에는 0을 지정하면되고 다섯번째 파라미터인 lpcSubKeys에는 서브키의 개수가 저장될 변수의 주소를 지정해 주면 됩니다. 여섯번째 파라미터에는 서브키의 이름중 가장 긴 이름을 가진 서브키의 길이가 저장될 변수의 주소를 지정해주면 됩니다. 사실 이 값은 잘 쓰이지 않죠. 역시 일곱번째 파라미터도 서브키에 대한 클래스이름이 가장 긴 길이가 저장될 변수의 주소를 지정해주면 됩니다.

여덟번째 파라미터인 lpcValues에는 지정해준 키에 대한 데이터의 개수가 저장 될 변수의 주소를 지정해주면 되는데 우리가 지금 만들어볼 프로그램은 단지 서브키의 개수만 알아볼거니 사실 이 값이 필요없습니다. 그러나 다음 프로그램에서는 이 값을 이용할테니 그 의미를 알아 두시기 바랍니다.

아홉번째 파라미터에는 가장 긴 네임에 대한 길이가 저장될 변수의 주소를 지정해주면 되고 열번째 파라미터에는 가장긴 데이터의 길이가 저장될 변수의 주소를 지정해 주면 됩니다. 열한번째 파라미터에는 NULL을 지정하면 되고 마지막 파라미터에는 주어진 키에대한 시간정보를 저장할 구조체 변수의 주소를 지정해 주면 됩니다. 이 구조체는 이미 앞에서 알아보았고 또 어떻게 다루었는지도 알아 보았을 겁니다.

자 서브키나 데이터의 개수를 위 함수로 알아 냈으니 이번에는 실제로 그 서브키나 데이터가 무엇인지 알아내는 함수를 알아 봅시다.

LONG RegEnumKeyEx(
    HKEY  hkey,
    DWORD  iSubkey,
    LPTSTR  lpszName,
    LPDWORD  lpcchName,
    LPDWORD  lpdwReserved,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    PFILETIME  lpftLastWrite
   );

바로 위 함수를 이용해서 알아 낼 수 있습니다. 첫번째 파라미터에 알아낼 서브키가 속해있는 루트 키의 핸들을 지정해 주면 되고 두번째 파라미터에 서브키의 인덱스를 지정해주면 됩니다. 서브키의 인덱스는 0부터 시작합니다. 예를 들어 우리가 위의 RegQueryInfoKey() 함수로 서브키의 개수를 알아 내었다면 0부터 차례로 그 개수에서 1을 뺀값까지 이 파라미터로 지정해주면 되겠죠.

세번째 파라미터에는 해당하는 인텍스의 서브키가 들어갈 버퍼를 지정해 주면 되고 네번째 파라미터에는 그 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

다섯번째 파라미터에는 NULL을 지정해 주면 되고 여섯번째 파라미터에는 클래스 이름이 저장될 버퍼를 지정해주면 됩니다. 일곱번째 파라미터에는 클래스 이름이 저장 될 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

마지막 파라미터는 설명 드릴필요는 없겠군요. 앞의 RegQueryInfoKey() 함수의 마지막 파라미터와 의미가 같습니다.

자 그러면 실제로 이것을 이용한 프로그램을 만들어 봅시다. 아래 프로그램은 새로운 키를 생성하고 그 키에 포함된 서브키가 어떤것들인지 화면에 출력해 주는 기능을 가졌습니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey)

;
    return TRUE;
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 49

안녕하세요………….돌팔이 황동준입니다…………………

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

제가 만든 두개의 함수만 알아 보면 되겠죠?

BOOL SetRegistry(void)
{

이 함수는 우리가 어떤 서브키가 있는지 테스트해보기 위해 임시로 서브키를 만드는 기능을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

어떤 서브키를 만드는지 굳이 설명드릴 필요는 없죠? 바로 Install이라는 서브키를 만들고 Install이라는 네임에 c:\doran20이라는 데이터를 저장하고 있는 구문입니다.

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;

앞에서 만든 DORAN 20이라는 서브키에 다시 Version이라는 서브키를 생성하고 네임에 Version을 그 네임에 해당하는 데이터는 2.0을 지정하는 구문입니다.

}

앞에서 한부분이므로 이해가 안가는 부분은 없을 겁니다. 위 함수가 수행되면 DORAN 20이라는 서브키에 Install, Version이라는 서브키가 생성되어 있을 겁니다.

BOOL PrintSubRegistry(HWND hWnd)
{

이 함수는 DORAN 20 서브키에 속해 있는 서브키를 찾아서 화면에 출력해주는 역할을 합니다.

    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

    if(lRet != ERROR_SUCCESS)
        return FALSE;

알아 볼 서브키가 포함되어 있는 부모 키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

이번에 알아 볼것은 단지 서브키의 개수이므로 데이터의 개수가 저장될 파라미터에는 NULL을 지정하였습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;

서브키의 개수만큼 인덱스를 증가하기 위해 위 dwCount라는 변수를 사용하였습니다.

    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

인덱스에 해당하는 서브키를 얻고 있는 구문입니다.

        dwSubKeySize = 80;

위 함수가 수행되면 dwSubKeySize에 실제 크기가 저장되므로 이 값을 다시 초기화해주고 있습니다. 왜냐하면 위 함수를 사용할 때 버퍼의 크기가 저장된 변수의 주소를 지정하기 때문이죠.

        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);

얻은 서브키를 화면에 출력해 주는 구문입니다.

        dwCount++;

인덱스를 증가하고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문을 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

자 그러면 이번에는 좀더 진보적인 프로그램을 만들어 봅시다. 바로 서브키만 알아내는 것이 아니라 그 안에 속해있는 네임과 데이터도 알아내는 거죠.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);
        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);
        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {
            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);
            dwNameSize = dwValueSize = 80;
            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;
            dwValueCount++;
        }
        RegCloseKey(hSubKey);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey);
    return TRUE;

}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 50

안녕하세요…………..돌팔이 황동준입니다………….

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

이번에는 함수 하나만 알아보면 되겠네요.

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;

정보를 알아볼 서브키의 루크키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

서브키의 개수를 알아내고 있습니다.

    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

서브키를 알아내고 있는 구문입니다.

        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);

        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

알아낸 서브키를 열고 있는 구문입니다.

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);

그 서브키가 가지는 데이터의 개수를 얻고 있습니다.

        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {

데이터의 개수만큼 루프문을 반복하고 있습니다.

            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);

위 함수로 인덱스에 해당하는 네임과 데이터를 얻을 수 있는데 위에서 이 함수에 대해 설명드리지 않았군요.

LONG RegEnumValue(
    HKEY  hkey,
    DWORD  iValue,
    LPTSTR  lpszValue,
    LPDWORD  lpcchValue,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );   

첫번째 파라미터에는 얻을 네임이 포함되어 있는 서브키의 핸들을 지정해 주면됩니다. 두번째 파라미터에는 네임의 인덱스를 지정해 주면 되는데 역시 0부터 지정해주면 됩니다. 세번째 파라미터에는 네임이 저장될 버퍼를 네번째 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다. 다섯 번째 파라미터에는 NULL을 지정하면 되고 여섯번째 파라미터에는 데이터의 타입이 저장될 변수의 주소를 지정해 주면 됩니다. 이 데이터 타입은 앞에서 이미 알아 본 것입니다. 아래와 같은 예약어들이 함수 사용한 후에 저장되겠군요.

REG_BINARY
REG_DWORD
REG_LINK
REG_NONE
REG_SZ

그 의미는 이미 앞에서 설명드렸을 겁니다.

일곱번째 파라미터에는 데이터가 저장될 버퍼를 지정하면 되고 마지막 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다.

함수 설명을 했으니 계속해서 해당 루틴을 알아 보도록 하겠습니다.

            dwNameSize = dwValueSize = 80;

역시 길이를 초기화 해주고 있습니다.

            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;

얻은 네임과 데이터를 화면에 출력해 주고 있습니다.

            dwValueCount++;

네임에 대한 인덱스를 증가해주고 있습니다.

        }
        RegCloseKey(hSubKey);
        dwCount++;

서브키에 대한 인덱스를 증가해주고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문이 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

Permalink 댓글 남기기

Registry

6월 26, 2006 at 10:31 오전 (Visual C++)

이번시간 부터는 레지스트리에 대한 것에 대해 알아 보겠습니다. 혹시 레지스트리라는것을 들어 보았습니까? 윈도우즈에서는 레지스트리라는 것이 존재하는데 이것은 일종의 하드웨어적, 소프트웨어적인 정보를 저장하고 있는 매체입니다. 우리가 앞에서 배운 win.ini 파일에도 다양한 정보가 저장되어 있는데 사실 이것은 윈도우즈 3.1때와의 호환 때문에 존재하는 것이고 실제로 우리가 다루어야 할 것은 바로 이 레지스트리입니다. 음.. 예를들어서 win.ini 파일에 프로그램이 설치되어 있는 디렉토리 정보가 들어 있었죠? 아마 인스톨 쉴드라는 인스톨 툴로 인스톨 프로그램을 만들면 인스톨시에 win.ini 파일에 디렉토리 정보 저장 기능은 없을 겁니다.

그러나 레지스트리에 설치된 디렉토리를 저장할 수 있는 기능은 있죠. 바로 레지스트리에도 설치된 디렉토리 정보가 들어 있다는 말과도 같습니다. 그것 뿐만 아닙니다. PNP 하드웨어의 정보도 다 들어 있죠. 모뎀 포트를 자동으로 찾는다거나 하는 작업을 바로 이 레지스트리를 검색해서 할수 있는 것입니다. 여러분들 넷스케이프 사용해 봤습니까? 거기에 보면 홈 디렉토리를 지정할 수 있는 메뉴 아이템이 있을겁니다. MS 익스플로어의 요즘 버전은 제가 사용해 보지 않았지만 예전에 사용할 때에는 이 기능이 없더군요. 그래서 항상 홈 디렉토리가 마이크로 소프트사였습니다. 그런데 이 홈 디렉토리 정보가 레지스트리에 등록되어 있다는 것을 우연히 알게 되었습니다. 물론 그것을 바꿔서 홈 디렉토리를 바꾸었죠.

너무 서론이 길었죠? 그렇다면 이러한 레지스트리를 어떻게 원하는데로 바꿀 수 있을까요? 윈도우즈가 설치되어 있는 디렉토리에 보면 regedit.exe 파일이 있을 겁니다. 이 실행 파일을 실행시켜서 레지스트리 정보를 볼 수도 있고 또 수정할 수도 있습니다. 이 프로그램을 레지스트리 편집기라고도 하죠.

한번 실행해 보세요.

어때요? 크게 6개의 폴더가 보이죠? 각 커다란 폴더에는 의미가 있습니다.

HKEY_CLASSES_ROOT

이 하위에 있는 정보들은 문서의 형태, 파일연관상태에 대한 정보가 들어 있습니다. 실제로 하위 폴더를 보면 아래아 한글 문서의 확장자, 압축 파일 확장자들의 정보가 들어 있음을 확인할 수 있습니다.

HKEY_CURRENT_USER

각각 사용자에 따른 사용자 정보를 가지고 있습니다.

HKEY_LOCAL_MACHINE

하드웨어, 네트워크, 소프트웨어 정보가 이곳에 있습니다. 실제로 프로그램이 설치되어 있는 디렉토리, PNP 하드웨어 등록 정보들이 이곳에 있는 거죠.

HKEY_USERS

각각 사용자에 대한 시스템 정보를 가지고 있습니다.

HKEY_CURRENT_CONFIG

하드웨어 설정에 대한 정보값이 들어 있습니다.

HKEY_DYN_DATA

역시 하드웨어적인 정보값이 들어 있습니다.

자 각각에 대해 알아 보았으니 각 서브 폴더를 확인해 보시기 바랍니다. 폴더 옆에 보면 플러스 기호가 있는데 여기에 마우스의 왼쪽 버튼으로 클릭하면 마이너스 기호로 바뀌고 그곳에 속해 있는 서브 폴더를 보여주게 됩니다. 다시 클릭하면 감춰지죠. 서브 폴더를 보다보면 폴더 왼쪽에 아무 기호도 없는 폴더들이 있을 겁니다. 그것은 서브 폴더를 가지지 않음을 의미하는 것입니다. 그렇다면 서브 폴더를 가지지 않은 폴더에 클릭한 후에 오른쪽에 있는 창을 보십시요.

어때요? 네임에 어떤 이름이 있고 데이터에 값이 들어 있죠? 물론 아무 값도 가지지 않는 경우도 있습니다. 서브 풀더를 가지고 있는 것도 마찬가지입니다. 왼쪽에 있는 기호에 클릭하지 않고 바로 그 폴더를 클릭하면 네임과 데이터에 값이 표시될 것입니다.

자 새로운 용어를 알아 봅시다. 우리가 앞에서 언급한 폴더를 키라고 합니다. 각 키는 물론 서브 키를 가질 수 있고 각 키에는 네임과 데이터를 가집니다. 물론 하나의 키는 여러개의 네임과 데이터를 가질 수 있습니다. 이해가 가죠?

자 이제부터 우리는 기존에 등록되어 있는 키, 네임, 데이터를 읽는 것을 프로그램 상으로 어떻게 구현하는지 알아 볼 것입니다. 물론 등록하는 방법도 알아 볼 거구요.

그러면 시작해 봅시다.

먼저 등록되어 있는 정보를 읽어오는 방법부터 알아 봅시다. 처음에 정보를 가져올 키가 어떤 것인지 지정해서 열어 주어야 합니다.

LONG RegOpenKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    REGSAM  samDesired,
    PHKEY  phkResult
   );   

위 함수를 이용해서 레지스트리에 설정되어 있는 키를 열 수 있습니다. 첫번째 파라미터에 제일 상단에 있는 루트키를 지정하면 되는데 이 키는 레지스트리 편지기를 실행했을 때 볼 수 있는 값을 지정하면 되는 겁니다. 아래 값들 중 하나가 되겠군요.

HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA

두번째 파라미터에는 우리가 정보를 가져올 서브키를 지정해 주면 됩니다. 서브키 내에 또다른 서브키가 있으면 서브 디렉토리를 표시하던 식인 \\식으로 표시해 주면 됩니다. 세번째 파라미터에는 0을 지정하면 되고 네번째 파라미터에는 지정된 예약어를 지정해주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

마지막 파라미터에는 서브키를 열었을때 얻어진 키 핸들을 저장할 변수의 주소를 지정해 주면 됩니다.

자 이제 서브키를 열었으니 그 키가 가지는 데이터를 가져오기만 하면 될 겁니다.

LONG RegQueryValueEx(
    HKEY  hkey,
    LPTSTR  lpszValueName,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );

위 함수를 이용해서 데이터를 가져올 수 있습니다. 첫번째 파라미터에는 위 RegOpenKeyEx() 함수에서 얻은 키 핸들을 지정하면 되고 두번째 파라미터에는 가져올 데이터가 가지는 네임을 지정해 주면 됩니다. 네임이 Default로 되어 있으면 그냥 ""식으로 지정해 주면 됩니다. 세번째 파라미터에는 0을 지정해 주면되고 네번째 파라미터에는 데이터의 저장형태가 저장될 변수의 주소를 지정해주면 됩니다. 이 저장형태는 뒤에 가서 레지스트리에 정보를 기록할때 다시 설명드리겠습니다.

그리고 다섯번째 파라미터에는 읽어온 데이터가 저장될 주소를 지정하면 됩니다. 마지막 파라미터에는 이 읽어온 데이터의 크기가 저장될 변수의 주소를 지정하면 됩니다.

데이터를 읽어오는 과정이 어렵지 않죠? 키를 열어서 작업을 다 했으면 그 키를 닫아 주어야 합니다.

LONG RegCloseKey(
    HKEY  hkey
   );

위 함수를 이용해서 연 키를 닫을수 있습니다. 물론 새로 생성한 키도 위 함수를 이용해서 닫아주면 되죠.

그러면 이번에는 정보를 기록하는 방법에 대해 알아 봅시다. 마찬가지로 어렵지 않습니다. 먼저 새로운 키를 생성하는 과정이 필요한데 그것은 아래 함수를 이용해서 하면 됩니다.

LONG RegCreateKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    LPTSTR  lpszClass,
    DWORD  fdwOptions,
    REGSAM  samDesired,
    LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
    PHKEY  phkResult,
    LPDWORD  lpdwDisposition
   );

첫번째 파라미터에는 제일 상단에 있는 루트키를 지정해 주면 되는데 이 루트키는 이미 RegOpenKeyEx() 함수때 설명드렸을 겁니다. 두번째 파라미터에는 서브키를 지정해 주면 됩니다. 세번째 파라미터에는 NULL을 지정하면 되고 네번째 파라미터에는 클래스 이름을 지정해 주면 됩니다. 보통 NULL을 지정하죠. 다섯번째 파라미터에는 지정된 예약어를 지정해 주면 되는데 이때 지정될 수 있는 예약어는 다음과 같습니다.

REG_OPTION_VOLATILE         메모리에만 저장됩니다.
REG_OPTION_NON_VOLATILE     파일에 저장됩니다.

첫번째 예약어를 사용하게 되면 메모리에만 저장되므로 시스템이 재시작되면 무효가 되나 두번째 예약어를 사용하게 되면 파일에 저장되므로 그 값이 계속 유효하게 됩니다. 어떤 차이인지 알겠죠?

여섯번째 파라미터에는 어세스 옵션을 지정해 주면 되는데 다음과 같은 예약어를 지정해 주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

앞에서 알아본 RegOpenKeyEx()함수의 예약어와 같죠? 일곱번째 파라미터에는 NULL을 지정하면 되고 여덟번째 파라미터에는 이 키에 대한 핸들을 기억할 키 변수의 핸들을 지정해 주면 됩니다. 마지막 파라미터에는 키에 대한 결과가 저장될 변수의 주소를 지정해 주면 됩니다.

이제 키를 생성하는 함수를 알아보았으니 원하는 네임에 데이터를 지정하는 함수를 알아 봅시다.

LONG RegSetValueEx(
    HKEY  hkey,
    LPCTSTR  lpszValueName,
    DWORD  dwReserved,
    DWORD  fdwType,
    CONST BYTE *  lpbData,
    DWORD  cbData
   );

위 함수를 이용해서 원하는 네임과 데이터를 지정해줄수 있는데 각 파라미터의 의미를 알아 봅시다.

첫번째 파라미터에는 RegCreateKeyEx()함수로 얻은 키 핸들을 지정해주면 되고 두번째 파라미터에는 네임을 지정해 주면됩니다. 세번째 파라미터에는 NULL을 지정해주면 되고 네번째 파라미터에는 데이터의 타입을 지정해주면 됩니다. 데이터의 타입은 아래의 예약어를 이용하면 됩니다.

REG_BINARY      바이너리 형태입니다.
REG_DWORD       더블워드 형태입니다.
REG_LINK        심볼릭 링크 형태입니다.
REG_NONE        아무 형태도 아닙니다.
REG_SZ          문자열의 형태입니다.

다섯번째 파라미터에는 데이터를 지정해주면 됩니다. 마지막 파라미터에는 데이터의 길이를 지정해 주면 되구요.

자 그러면 이번에는 키를 삭제하는 방법을 알아 봅시다.

먼저 지울 키를 RegOpenKeyEx()함수를 이용해서 핸들 형태로 반환을 받아야 합니다. 그래서 그 핸들을 이용해서 원하는 네임의 데이터를 삭제하면 되죠.

원하는 네임의 데이터를 지울 때에는 아래 함수를 사용하면 됩니다.

LONG RegDeleteValue(
    HKEY  hkey,
    LPTSTR  lpszValue
   );

첫번째 파라미터에 지울 네임이 속해 있는 키의 핸들을 지정해 주면 됩니다. 두번째 파라미터에는 지울 데이터의 네임을 지정해 주면 되구요.

이번에는 키 자체를 없애는 함수입니다.

LONG RegDeleteKey(
    HKEY  hkey,
    LPCTSTR  lpszSubKey
   );

첫번째 파라미터에는 최상위 루트 키의 이름을 지정해주면 되고 두번째 파라미터에는 그 안에 포함된 지울 서브키의 이름을 지정해 주면 됩니다. 사용방법이 간단하죠.

자 그러면 위에서 배운 함수들을 이용해서 실제로 프로그램을 만들어 봅시다.

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 47

안녕하세요……..돌팔이 황동준입니다……………..

이번시간에는 저번시간에 알아 본 함수들을 이용해서 프로그램을 만들어 보겠습니다.

아래 프로그램은 레지스트리에 원하는 키를 생성해서 거기에 데이터를 기록한 뒤 실제로 그 데이터를 가져오고 하는 기능을 가졌습니다. 물론 지우는 기능도 있구요. 앞부분에서 함수를 잘 이해한 분들은 그렇게 어렵지 않을 겁니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Get Registry", 200
        MENUITEM "&Delete Registry", 300
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
char* GetRegistry(void);
void DeleteRegistry(void);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        strcpy(szBuff, GetRegistry());
                        if(strcmp(szBuff, "ERROR"))
                            MessageBox(hWnd, szBuff, "", MB_OK);
                        else
                            MessageBox(hWnd, "Value not found!!", "", MB_OK);
                        break;

                    case 300 :

                        DeleteRegistry();
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

char* GetRegistry(void)
{
    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{
    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);
    RegDeleteValue(hKey, "Install");
    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");
    RegCloseKey(hKey);
}

자 프로그램을 실행시켜 첫번째 메뉴 아이템인 Set Registry를 선택해 보세요. 그리고 진짜로 그 키가 생성되었는지 레지스트리 편집기로 확인해 보시기 바랍니다. 어때요? 정말로 생성되어 있죠? 자 그러면 소스를 보도록 합시다.

제가 만든 세개의 함수 루틴만 보면 되겠네요.

BOOL SetRegistry(void)
{

이 함수는 새로운 키를 생성하는 역할을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);

HKEY_LOCAL_MACHINE 부분에 있는 Software내에 DORAN 20이라는 키를 생성하고 있는 구문입니다. 물론 Software라는 서브키가 존재하지 않으면 새로 생성합니다.

    if(lRet != ERROR_SUCCESS)
        return FALSE;

성공적으로 함수가 수행되면 ERROR_SUCESS라는 리터값이 발생된다는 것을 위 구문으로 짐작할 수 있을 겁니다.

    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));

Install이라는 네임에 c:\doran20이라는 데이터를 저장하는 구문입니다.

    if(lRet != ERROR_SUCCESS)
    {

역시 함수가 성공적으로 수행되면 ERROR_SUCCESS라는 리턴값이 발생되는군요.

        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);

생성한 키를 닫는 구문입니다.

    return TRUE;
}

char* GetRegistry(void)
{

이 함수는 원하는 서브키의 데이터를 가져오는 역할을 합니다.

    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

데이터를 가져올 서브키를 열고 있습니다.

    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);

Install이라는 네임에 해당하는 데이터를 가져오고 있습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{

이 함수는 첫번째 메뉴 아이템에 의해 생성된 키와 데이터를 삭제하는 역할을 합니다.

    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);

지울 키를 얻고 있습니다.

    RegDeleteValue(hKey, "Install");

Install 네임을 가지고 있는 데이터를 삭제하는 구문입니다.

    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");

서브 키를 없애는 구문입니다.

    RegCloseKey(hKey);
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 48

안녕하세요…………돌팔이 황동준입니다……………

이번시간에도 레지스트리에 대해 더 알아 보겠습니다. 이번에 알아 볼 것은 어떤 키에 속해있는 서브키를 어떻게 얻을 수 있는지 입니다. 물론 우리는
서브키에 속해 있는 네임에 해당하는 데이터를 얻는 방법은 압니다. 그러나 문제가 있죠. 바로 이 키에 어떤 서브키가 있는지 모른다면 할 수가 없습니다. 그렇죠? 그렇기 때문에 이 방법을 알아야 합니다. 좀더 들어간다면 어떤 서브키에 어떤 네임들이 있는지도 아는 방법이 있습니다. 그것도 우리가 지금 알아 볼 방법을 응용하면 됩니다. 자 그러면 시작해 봅시다.

먼저 크게 두단계로 나누어서 합니다. 첫번째 단계는 바로 원하는 키에 서브키가 몇개 있는지 개수를 알아내는 것입니다. 두번째 단계는 이 개수를 가지고 차례로 키 포인터를 이동시켜 서브키를 얻는 것입니다.

자 그러면 실제로 어떤 식으로 구현하는지 필요한 함수를 보도록 합시다. 먼저 서브키의 개수를 알아야 하는데 이때 필요한 함수의 첫번째 파라미터에 키 핸들을 지정해야 하는데 이 키 핸들은 앞에서 배운 RegOpenKeyEx()함수를 이용하면 됩니다. 그러면 키의 개수를 얻을 수 있는 함수를 보도록 합시다.

LONG RegQueryInfoKey (
    HKEY  hkey,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    LPDWORD  lpdwReserved,
    LPDWORD  lpcSubKeys,
    LPDWORD  lpcchMaxSubkey,
    LPDWORD  lpcchMaxClass,
    LPDWORD  lpcValues,
    LPDWORD  lpcchMaxValueName,
    LPDWORD  lpcbMaxValueData,
    LPDWORD  lpcbSecurityDescriptor,
    PFILETIME  lpftLastWriteTime
   );

첫번째 파라미터로 RegOpenKeyEx()함수에서 얻은 키 핸들을 지정하면 됩니다. 두번째 파라미터에는 클래스 이름이 저장될 버퍼의 주소를 세번째 파라미터에는 그 클래스 버퍼의 크기를 가지고 있는 변수의 주소를 지정해 주면 됩니다.

네번째 파라미터에는 0을 지정하면되고 다섯번째 파라미터인 lpcSubKeys에는 서브키의 개수가 저장될 변수의 주소를 지정해 주면 됩니다. 여섯번째 파라미터에는 서브키의 이름중 가장 긴 이름을 가진 서브키의 길이가 저장될 변수의 주소를 지정해주면 됩니다. 사실 이 값은 잘 쓰이지 않죠. 역시 일곱번째 파라미터도 서브키에 대한 클래스이름이 가장 긴 길이가 저장될 변수의 주소를 지정해주면 됩니다.

여덟번째 파라미터인 lpcValues에는 지정해준 키에 대한 데이터의 개수가 저장 될 변수의 주소를 지정해주면 되는데 우리가 지금 만들어볼 프로그램은 단지 서브키의 개수만 알아볼거니 사실 이 값이 필요없습니다. 그러나 다음 프로그램에서는 이 값을 이용할테니 그 의미를 알아 두시기 바랍니다.

아홉번째 파라미터에는 가장 긴 네임에 대한 길이가 저장될 변수의 주소를 지정해주면 되고 열번째 파라미터에는 가장긴 데이터의 길이가 저장될 변수의 주소를 지정해 주면 됩니다. 열한번째 파라미터에는 NULL을 지정하면 되고 마지막 파라미터에는 주어진 키에대한 시간정보를 저장할 구조체 변수의 주소를 지정해 주면 됩니다. 이 구조체는 이미 앞에서 알아보았고 또 어떻게 다루었는지도 알아 보았을 겁니다.

자 서브키나 데이터의 개수를 위 함수로 알아 냈으니 이번에는 실제로 그 서브키나 데이터가 무엇인지 알아내는 함수를 알아 봅시다.

LONG RegEnumKeyEx(
    HKEY  hkey,
    DWORD  iSubkey,
    LPTSTR  lpszName,
    LPDWORD  lpcchName,
    LPDWORD  lpdwReserved,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    PFILETIME  lpftLastWrite
   );

바로 위 함수를 이용해서 알아 낼 수 있습니다. 첫번째 파라미터에 알아낼 서브키가 속해있는 루트 키의 핸들을 지정해 주면 되고 두번째 파라미터에 서브키의 인덱스를 지정해주면 됩니다. 서브키의 인덱스는 0부터 시작합니다. 예를 들어 우리가 위의 RegQueryInfoKey() 함수로 서브키의 개수를 알아 내었다면 0부터 차례로 그 개수에서 1을 뺀값까지 이 파라미터로 지정해주면 되겠죠.

세번째 파라미터에는 해당하는 인텍스의 서브키가 들어갈 버퍼를 지정해 주면 되고 네번째 파라미터에는 그 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

다섯번째 파라미터에는 NULL을 지정해 주면 되고 여섯번째 파라미터에는 클래스 이름이 저장될 버퍼를 지정해주면 됩니다. 일곱번째 파라미터에는 클래스 이름이 저장 될 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

마지막 파라미터는 설명 드릴필요는 없겠군요. 앞의 RegQueryInfoKey() 함수의 마지막 파라미터와 의미가 같습니다.

자 그러면 실제로 이것을 이용한 프로그램을 만들어 봅시다. 아래 프로그램은 새로운 키를 생성하고 그 키에 포함된 서브키가 어떤것들인지 화면에 출력해 주는 기능을 가졌습니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey)

;
    return TRUE;
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 49

안녕하세요………….돌팔이 황동준입니다…………………

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

제가 만든 두개의 함수만 알아 보면 되겠죠?

BOOL SetRegistry(void)
{

이 함수는 우리가 어떤 서브키가 있는지 테스트해보기 위해 임시로 서브키를 만드는 기능을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

어떤 서브키를 만드는지 굳이 설명드릴 필요는 없죠? 바로 Install이라는 서브키를 만들고 Install이라는 네임에 c:\doran20이라는 데이터를 저장하고 있는 구문입니다.

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;

앞에서 만든 DORAN 20이라는 서브키에 다시 Version이라는 서브키를 생성하고 네임에 Version을 그 네임에 해당하는 데이터는 2.0을 지정하는 구문입니다.

}

앞에서 한부분이므로 이해가 안가는 부분은 없을 겁니다. 위 함수가 수행되면 DORAN 20이라는 서브키에 Install, Version이라는 서브키가 생성되어 있을 겁니다.

BOOL PrintSubRegistry(HWND hWnd)
{

이 함수는 DORAN 20 서브키에 속해 있는 서브키를 찾아서 화면에 출력해주는 역할을 합니다.

    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

    if(lRet != ERROR_SUCCESS)
        return FALSE;

알아 볼 서브키가 포함되어 있는 부모 키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

이번에 알아 볼것은 단지 서브키의 개수이므로 데이터의 개수가 저장될 파라미터에는 NULL을 지정하였습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;

서브키의 개수만큼 인덱스를 증가하기 위해 위 dwCount라는 변수를 사용하였습니다.

    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

인덱스에 해당하는 서브키를 얻고 있는 구문입니다.

        dwSubKeySize = 80;

위 함수가 수행되면 dwSubKeySize에 실제 크기가 저장되므로 이 값을 다시 초기화해주고 있습니다. 왜냐하면 위 함수를 사용할 때 버퍼의 크기가 저장된 변수의 주소를 지정하기 때문이죠.

        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);

얻은 서브키를 화면에 출력해 주는 구문입니다.

        dwCount++;

인덱스를 증가하고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문을 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

자 그러면 이번에는 좀더 진보적인 프로그램을 만들어 봅시다. 바로 서브키만 알아내는 것이 아니라 그 안에 속해있는 네임과 데이터도 알아내는 거죠.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);
        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);
        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {
            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);
            dwNameSize = dwValueSize = 80;
            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;
            dwValueCount++;
        }
        RegCloseKey(hSubKey);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey);
    return TRUE;

}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 50

안녕하세요…………..돌팔이 황동준입니다………….

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

이번에는 함수 하나만 알아보면 되겠네요.

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;

정보를 알아볼 서브키의 루크키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

서브키의 개수를 알아내고 있습니다.

    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

서브키를 알아내고 있는 구문입니다.

        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);

        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

알아낸 서브키를 열고 있는 구문입니다.

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);

그 서브키가 가지는 데이터의 개수를 얻고 있습니다.

        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {

데이터의 개수만큼 루프문을 반복하고 있습니다.

            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);

위 함수로 인덱스에 해당하는 네임과 데이터를 얻을 수 있는데 위에서 이 함수에 대해 설명드리지 않았군요.

LONG RegEnumValue(
    HKEY  hkey,
    DWORD  iValue,
    LPTSTR  lpszValue,
    LPDWORD  lpcchValue,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );   

첫번째 파라미터에는 얻을 네임이 포함되어 있는 서브키의 핸들을 지정해 주면됩니다. 두번째 파라미터에는 네임의 인덱스를 지정해 주면 되는데 역시 0부터 지정해주면 됩니다. 세번째 파라미터에는 네임이 저장될 버퍼를 네번째 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다. 다섯 번째 파라미터에는 NULL을 지정하면 되고 여섯번째 파라미터에는 데이터의 타입이 저장될 변수의 주소를 지정해 주면 됩니다. 이 데이터 타입은 앞에서 이미 알아 본 것입니다. 아래와 같은 예약어들이 함수 사용한 후에 저장되겠군요.

REG_BINARY
REG_DWORD
REG_LINK
REG_NONE
REG_SZ

그 의미는 이미 앞에서 설명드렸을 겁니다.

일곱번째 파라미터에는 데이터가 저장될 버퍼를 지정하면 되고 마지막 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다.

함수 설명을 했으니 계속해서 해당 루틴을 알아 보도록 하겠습니다.

            dwNameSize = dwValueSize = 80;

역시 길이를 초기화 해주고 있습니다.

            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;

얻은 네임과 데이터를 화면에 출력해 주고 있습니다.

            dwValueCount++;

네임에 대한 인덱스를 증가해주고 있습니다.

        }
        RegCloseKey(hSubKey);
        dwCount++;

서브키에 대한 인덱스를 증가해주고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문이 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

Permalink 댓글 남기기

Registry

6월 26, 2006 at 10:30 오전 (Visual C++)

이번시간 부터는 레지스트리에 대한 것에 대해 알아 보겠습니다. 혹시 레지스트리라는것을 들어 보았습니까? 윈도우즈에서는 레지스트리라는 것이 존재하는데 이것은 일종의 하드웨어적, 소프트웨어적인 정보를 저장하고 있는 매체입니다. 우리가 앞에서 배운 win.ini 파일에도 다양한 정보가 저장되어 있는데 사실 이것은 윈도우즈 3.1때와의 호환 때문에 존재하는 것이고 실제로 우리가 다루어야 할 것은 바로 이 레지스트리입니다. 음.. 예를들어서 win.ini 파일에 프로그램이 설치되어 있는 디렉토리 정보가 들어 있었죠? 아마 인스톨 쉴드라는 인스톨 툴로 인스톨 프로그램을 만들면 인스톨시에 win.ini 파일에 디렉토리 정보 저장 기능은 없을 겁니다.

그러나 레지스트리에 설치된 디렉토리를 저장할 수 있는 기능은 있죠. 바로 레지스트리에도 설치된 디렉토리 정보가 들어 있다는 말과도 같습니다. 그것 뿐만 아닙니다. PNP 하드웨어의 정보도 다 들어 있죠. 모뎀 포트를 자동으로 찾는다거나 하는 작업을 바로 이 레지스트리를 검색해서 할수 있는 것입니다. 여러분들 넷스케이프 사용해 봤습니까? 거기에 보면 홈 디렉토리를 지정할 수 있는 메뉴 아이템이 있을겁니다. MS 익스플로어의 요즘 버전은 제가 사용해 보지 않았지만 예전에 사용할 때에는 이 기능이 없더군요. 그래서 항상 홈 디렉토리가 마이크로 소프트사였습니다. 그런데 이 홈 디렉토리 정보가 레지스트리에 등록되어 있다는 것을 우연히 알게 되었습니다. 물론 그것을 바꿔서 홈 디렉토리를 바꾸었죠.

너무 서론이 길었죠? 그렇다면 이러한 레지스트리를 어떻게 원하는데로 바꿀 수 있을까요? 윈도우즈가 설치되어 있는 디렉토리에 보면 regedit.exe 파일이 있을 겁니다. 이 실행 파일을 실행시켜서 레지스트리 정보를 볼 수도 있고 또 수정할 수도 있습니다. 이 프로그램을 레지스트리 편집기라고도 하죠.

한번 실행해 보세요.

어때요? 크게 6개의 폴더가 보이죠? 각 커다란 폴더에는 의미가 있습니다.

HKEY_CLASSES_ROOT

이 하위에 있는 정보들은 문서의 형태, 파일연관상태에 대한 정보가 들어 있습니다. 실제로 하위 폴더를 보면 아래아 한글 문서의 확장자, 압축 파일 확장자들의 정보가 들어 있음을 확인할 수 있습니다.

HKEY_CURRENT_USER

각각 사용자에 따른 사용자 정보를 가지고 있습니다.

HKEY_LOCAL_MACHINE

하드웨어, 네트워크, 소프트웨어 정보가 이곳에 있습니다. 실제로 프로그램이 설치되어 있는 디렉토리, PNP 하드웨어 등록 정보들이 이곳에 있는 거죠.

HKEY_USERS

각각 사용자에 대한 시스템 정보를 가지고 있습니다.

HKEY_CURRENT_CONFIG

하드웨어 설정에 대한 정보값이 들어 있습니다.

HKEY_DYN_DATA

역시 하드웨어적인 정보값이 들어 있습니다.

자 각각에 대해 알아 보았으니 각 서브 폴더를 확인해 보시기 바랍니다. 폴더 옆에 보면 플러스 기호가 있는데 여기에 마우스의 왼쪽 버튼으로 클릭하면 마이너스 기호로 바뀌고 그곳에 속해 있는 서브 폴더를 보여주게 됩니다. 다시 클릭하면 감춰지죠. 서브 폴더를 보다보면 폴더 왼쪽에 아무 기호도 없는 폴더들이 있을 겁니다. 그것은 서브 폴더를 가지지 않음을 의미하는 것입니다. 그렇다면 서브 폴더를 가지지 않은 폴더에 클릭한 후에 오른쪽에 있는 창을 보십시요.

어때요? 네임에 어떤 이름이 있고 데이터에 값이 들어 있죠? 물론 아무 값도 가지지 않는 경우도 있습니다. 서브 풀더를 가지고 있는 것도 마찬가지입니다. 왼쪽에 있는 기호에 클릭하지 않고 바로 그 폴더를 클릭하면 네임과 데이터에 값이 표시될 것입니다.

자 새로운 용어를 알아 봅시다. 우리가 앞에서 언급한 폴더를 키라고 합니다. 각 키는 물론 서브 키를 가질 수 있고 각 키에는 네임과 데이터를 가집니다. 물론 하나의 키는 여러개의 네임과 데이터를 가질 수 있습니다. 이해가 가죠?

자 이제부터 우리는 기존에 등록되어 있는 키, 네임, 데이터를 읽는 것을 프로그램 상으로 어떻게 구현하는지 알아 볼 것입니다. 물론 등록하는 방법도 알아 볼 거구요.

그러면 시작해 봅시다.

먼저 등록되어 있는 정보를 읽어오는 방법부터 알아 봅시다. 처음에 정보를 가져올 키가 어떤 것인지 지정해서 열어 주어야 합니다.

LONG RegOpenKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    REGSAM  samDesired,
    PHKEY  phkResult
   );   

위 함수를 이용해서 레지스트리에 설정되어 있는 키를 열 수 있습니다. 첫번째 파라미터에 제일 상단에 있는 루트키를 지정하면 되는데 이 키는 레지스트리 편지기를 실행했을 때 볼 수 있는 값을 지정하면 되는 겁니다. 아래 값들 중 하나가 되겠군요.

HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA

두번째 파라미터에는 우리가 정보를 가져올 서브키를 지정해 주면 됩니다. 서브키 내에 또다른 서브키가 있으면 서브 디렉토리를 표시하던 식인 \\식으로 표시해 주면 됩니다. 세번째 파라미터에는 0을 지정하면 되고 네번째 파라미터에는 지정된 예약어를 지정해주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

마지막 파라미터에는 서브키를 열었을때 얻어진 키 핸들을 저장할 변수의 주소를 지정해 주면 됩니다.

자 이제 서브키를 열었으니 그 키가 가지는 데이터를 가져오기만 하면 될 겁니다.

LONG RegQueryValueEx(
    HKEY  hkey,
    LPTSTR  lpszValueName,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );

위 함수를 이용해서 데이터를 가져올 수 있습니다. 첫번째 파라미터에는 위 RegOpenKeyEx() 함수에서 얻은 키 핸들을 지정하면 되고 두번째 파라미터에는 가져올 데이터가 가지는 네임을 지정해 주면 됩니다. 네임이 Default로 되어 있으면 그냥 ""식으로 지정해 주면 됩니다. 세번째 파라미터에는 0을 지정해 주면되고 네번째 파라미터에는 데이터의 저장형태가 저장될 변수의 주소를 지정해주면 됩니다. 이 저장형태는 뒤에 가서 레지스트리에 정보를 기록할때 다시 설명드리겠습니다.

그리고 다섯번째 파라미터에는 읽어온 데이터가 저장될 주소를 지정하면 됩니다. 마지막 파라미터에는 이 읽어온 데이터의 크기가 저장될 변수의 주소를 지정하면 됩니다.

데이터를 읽어오는 과정이 어렵지 않죠? 키를 열어서 작업을 다 했으면 그 키를 닫아 주어야 합니다.

LONG RegCloseKey(
    HKEY  hkey
   );

위 함수를 이용해서 연 키를 닫을수 있습니다. 물론 새로 생성한 키도 위 함수를 이용해서 닫아주면 되죠.

그러면 이번에는 정보를 기록하는 방법에 대해 알아 봅시다. 마찬가지로 어렵지 않습니다. 먼저 새로운 키를 생성하는 과정이 필요한데 그것은 아래 함수를 이용해서 하면 됩니다.

LONG RegCreateKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    LPTSTR  lpszClass,
    DWORD  fdwOptions,
    REGSAM  samDesired,
    LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
    PHKEY  phkResult,
    LPDWORD  lpdwDisposition
   );

첫번째 파라미터에는 제일 상단에 있는 루트키를 지정해 주면 되는데 이 루트키는 이미 RegOpenKeyEx() 함수때 설명드렸을 겁니다. 두번째 파라미터에는 서브키를 지정해 주면 됩니다. 세번째 파라미터에는 NULL을 지정하면 되고 네번째 파라미터에는 클래스 이름을 지정해 주면 됩니다. 보통 NULL을 지정하죠. 다섯번째 파라미터에는 지정된 예약어를 지정해 주면 되는데 이때 지정될 수 있는 예약어는 다음과 같습니다.

REG_OPTION_VOLATILE         메모리에만 저장됩니다.
REG_OPTION_NON_VOLATILE     파일에 저장됩니다.

첫번째 예약어를 사용하게 되면 메모리에만 저장되므로 시스템이 재시작되면 무효가 되나 두번째 예약어를 사용하게 되면 파일에 저장되므로 그 값이 계속 유효하게 됩니다. 어떤 차이인지 알겠죠?

여섯번째 파라미터에는 어세스 옵션을 지정해 주면 되는데 다음과 같은 예약어를 지정해 주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

앞에서 알아본 RegOpenKeyEx()함수의 예약어와 같죠? 일곱번째 파라미터에는 NULL을 지정하면 되고 여덟번째 파라미터에는 이 키에 대한 핸들을 기억할 키 변수의 핸들을 지정해 주면 됩니다. 마지막 파라미터에는 키에 대한 결과가 저장될 변수의 주소를 지정해 주면 됩니다.

이제 키를 생성하는 함수를 알아보았으니 원하는 네임에 데이터를 지정하는 함수를 알아 봅시다.

LONG RegSetValueEx(
    HKEY  hkey,
    LPCTSTR  lpszValueName,
    DWORD  dwReserved,
    DWORD  fdwType,
    CONST BYTE *  lpbData,
    DWORD  cbData
   );

위 함수를 이용해서 원하는 네임과 데이터를 지정해줄수 있는데 각 파라미터의 의미를 알아 봅시다.

첫번째 파라미터에는 RegCreateKeyEx()함수로 얻은 키 핸들을 지정해주면 되고 두번째 파라미터에는 네임을 지정해 주면됩니다. 세번째 파라미터에는 NULL을 지정해주면 되고 네번째 파라미터에는 데이터의 타입을 지정해주면 됩니다. 데이터의 타입은 아래의 예약어를 이용하면 됩니다.

REG_BINARY      바이너리 형태입니다.
REG_DWORD       더블워드 형태입니다.
REG_LINK        심볼릭 링크 형태입니다.
REG_NONE        아무 형태도 아닙니다.
REG_SZ          문자열의 형태입니다.

다섯번째 파라미터에는 데이터를 지정해주면 됩니다. 마지막 파라미터에는 데이터의 길이를 지정해 주면 되구요.

자 그러면 이번에는 키를 삭제하는 방법을 알아 봅시다.

먼저 지울 키를 RegOpenKeyEx()함수를 이용해서 핸들 형태로 반환을 받아야 합니다. 그래서 그 핸들을 이용해서 원하는 네임의 데이터를 삭제하면 되죠.

원하는 네임의 데이터를 지울 때에는 아래 함수를 사용하면 됩니다.

LONG RegDeleteValue(
    HKEY  hkey,
    LPTSTR  lpszValue
   );

첫번째 파라미터에 지울 네임이 속해 있는 키의 핸들을 지정해 주면 됩니다. 두번째 파라미터에는 지울 데이터의 네임을 지정해 주면 되구요.

이번에는 키 자체를 없애는 함수입니다.

LONG RegDeleteKey(
    HKEY  hkey,
    LPCTSTR  lpszSubKey
   );

첫번째 파라미터에는 최상위 루트 키의 이름을 지정해주면 되고 두번째 파라미터에는 그 안에 포함된 지울 서브키의 이름을 지정해 주면 됩니다. 사용방법이 간단하죠.

자 그러면 위에서 배운 함수들을 이용해서 실제로 프로그램을 만들어 봅시다.

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 47

안녕하세요……..돌팔이 황동준입니다……………..

이번시간에는 저번시간에 알아 본 함수들을 이용해서 프로그램을 만들어 보겠습니다.

아래 프로그램은 레지스트리에 원하는 키를 생성해서 거기에 데이터를 기록한 뒤 실제로 그 데이터를 가져오고 하는 기능을 가졌습니다. 물론 지우는 기능도 있구요. 앞부분에서 함수를 잘 이해한 분들은 그렇게 어렵지 않을 겁니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Get Registry", 200
        MENUITEM "&Delete Registry", 300
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
char* GetRegistry(void);
void DeleteRegistry(void);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        strcpy(szBuff, GetRegistry());
                        if(strcmp(szBuff, "ERROR"))
                            MessageBox(hWnd, szBuff, "", MB_OK);
                        else
                            MessageBox(hWnd, "Value not found!!", "", MB_OK);
                        break;

                    case 300 :

                        DeleteRegistry();
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

char* GetRegistry(void)
{
    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{
    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);
    RegDeleteValue(hKey, "Install");
    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");
    RegCloseKey(hKey);
}

자 프로그램을 실행시켜 첫번째 메뉴 아이템인 Set Registry를 선택해 보세요. 그리고 진짜로 그 키가 생성되었는지 레지스트리 편집기로 확인해 보시기 바랍니다. 어때요? 정말로 생성되어 있죠? 자 그러면 소스를 보도록 합시다.

제가 만든 세개의 함수 루틴만 보면 되겠네요.

BOOL SetRegistry(void)
{

이 함수는 새로운 키를 생성하는 역할을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);

HKEY_LOCAL_MACHINE 부분에 있는 Software내에 DORAN 20이라는 키를 생성하고 있는 구문입니다. 물론 Software라는 서브키가 존재하지 않으면 새로 생성합니다.

    if(lRet != ERROR_SUCCESS)
        return FALSE;

성공적으로 함수가 수행되면 ERROR_SUCESS라는 리터값이 발생된다는 것을 위 구문으로 짐작할 수 있을 겁니다.

    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));

Install이라는 네임에 c:\doran20이라는 데이터를 저장하는 구문입니다.

    if(lRet != ERROR_SUCCESS)
    {

역시 함수가 성공적으로 수행되면 ERROR_SUCCESS라는 리턴값이 발생되는군요.

        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);

생성한 키를 닫는 구문입니다.

    return TRUE;
}

char* GetRegistry(void)
{

이 함수는 원하는 서브키의 데이터를 가져오는 역할을 합니다.

    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

데이터를 가져올 서브키를 열고 있습니다.

    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);

Install이라는 네임에 해당하는 데이터를 가져오고 있습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{

이 함수는 첫번째 메뉴 아이템에 의해 생성된 키와 데이터를 삭제하는 역할을 합니다.

    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);

지울 키를 얻고 있습니다.

    RegDeleteValue(hKey, "Install");

Install 네임을 가지고 있는 데이터를 삭제하는 구문입니다.

    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");

서브 키를 없애는 구문입니다.

    RegCloseKey(hKey);
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 48

안녕하세요…………돌팔이 황동준입니다……………

이번시간에도 레지스트리에 대해 더 알아 보겠습니다. 이번에 알아 볼 것은 어떤 키에 속해있는 서브키를 어떻게 얻을 수 있는지 입니다. 물론 우리는
서브키에 속해 있는 네임에 해당하는 데이터를 얻는 방법은 압니다. 그러나 문제가 있죠. 바로 이 키에 어떤 서브키가 있는지 모른다면 할 수가 없습니다. 그렇죠? 그렇기 때문에 이 방법을 알아야 합니다. 좀더 들어간다면 어떤 서브키에 어떤 네임들이 있는지도 아는 방법이 있습니다. 그것도 우리가 지금 알아 볼 방법을 응용하면 됩니다. 자 그러면 시작해 봅시다.

먼저 크게 두단계로 나누어서 합니다. 첫번째 단계는 바로 원하는 키에 서브키가 몇개 있는지 개수를 알아내는 것입니다. 두번째 단계는 이 개수를 가지고 차례로 키 포인터를 이동시켜 서브키를 얻는 것입니다.

자 그러면 실제로 어떤 식으로 구현하는지 필요한 함수를 보도록 합시다. 먼저 서브키의 개수를 알아야 하는데 이때 필요한 함수의 첫번째 파라미터에 키 핸들을 지정해야 하는데 이 키 핸들은 앞에서 배운 RegOpenKeyEx()함수를 이용하면 됩니다. 그러면 키의 개수를 얻을 수 있는 함수를 보도록 합시다.

LONG RegQueryInfoKey (
    HKEY  hkey,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    LPDWORD  lpdwReserved,
    LPDWORD  lpcSubKeys,
    LPDWORD  lpcchMaxSubkey,
    LPDWORD  lpcchMaxClass,
    LPDWORD  lpcValues,
    LPDWORD  lpcchMaxValueName,
    LPDWORD  lpcbMaxValueData,
    LPDWORD  lpcbSecurityDescriptor,
    PFILETIME  lpftLastWriteTime
   );

첫번째 파라미터로 RegOpenKeyEx()함수에서 얻은 키 핸들을 지정하면 됩니다. 두번째 파라미터에는 클래스 이름이 저장될 버퍼의 주소를 세번째 파라미터에는 그 클래스 버퍼의 크기를 가지고 있는 변수의 주소를 지정해 주면 됩니다.

네번째 파라미터에는 0을 지정하면되고 다섯번째 파라미터인 lpcSubKeys에는 서브키의 개수가 저장될 변수의 주소를 지정해 주면 됩니다. 여섯번째 파라미터에는 서브키의 이름중 가장 긴 이름을 가진 서브키의 길이가 저장될 변수의 주소를 지정해주면 됩니다. 사실 이 값은 잘 쓰이지 않죠. 역시 일곱번째 파라미터도 서브키에 대한 클래스이름이 가장 긴 길이가 저장될 변수의 주소를 지정해주면 됩니다.

여덟번째 파라미터인 lpcValues에는 지정해준 키에 대한 데이터의 개수가 저장 될 변수의 주소를 지정해주면 되는데 우리가 지금 만들어볼 프로그램은 단지 서브키의 개수만 알아볼거니 사실 이 값이 필요없습니다. 그러나 다음 프로그램에서는 이 값을 이용할테니 그 의미를 알아 두시기 바랍니다.

아홉번째 파라미터에는 가장 긴 네임에 대한 길이가 저장될 변수의 주소를 지정해주면 되고 열번째 파라미터에는 가장긴 데이터의 길이가 저장될 변수의 주소를 지정해 주면 됩니다. 열한번째 파라미터에는 NULL을 지정하면 되고 마지막 파라미터에는 주어진 키에대한 시간정보를 저장할 구조체 변수의 주소를 지정해 주면 됩니다. 이 구조체는 이미 앞에서 알아보았고 또 어떻게 다루었는지도 알아 보았을 겁니다.

자 서브키나 데이터의 개수를 위 함수로 알아 냈으니 이번에는 실제로 그 서브키나 데이터가 무엇인지 알아내는 함수를 알아 봅시다.

LONG RegEnumKeyEx(
    HKEY  hkey,
    DWORD  iSubkey,
    LPTSTR  lpszName,
    LPDWORD  lpcchName,
    LPDWORD  lpdwReserved,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    PFILETIME  lpftLastWrite
   );

바로 위 함수를 이용해서 알아 낼 수 있습니다. 첫번째 파라미터에 알아낼 서브키가 속해있는 루트 키의 핸들을 지정해 주면 되고 두번째 파라미터에 서브키의 인덱스를 지정해주면 됩니다. 서브키의 인덱스는 0부터 시작합니다. 예를 들어 우리가 위의 RegQueryInfoKey() 함수로 서브키의 개수를 알아 내었다면 0부터 차례로 그 개수에서 1을 뺀값까지 이 파라미터로 지정해주면 되겠죠.

세번째 파라미터에는 해당하는 인텍스의 서브키가 들어갈 버퍼를 지정해 주면 되고 네번째 파라미터에는 그 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

다섯번째 파라미터에는 NULL을 지정해 주면 되고 여섯번째 파라미터에는 클래스 이름이 저장될 버퍼를 지정해주면 됩니다. 일곱번째 파라미터에는 클래스 이름이 저장 될 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

마지막 파라미터는 설명 드릴필요는 없겠군요. 앞의 RegQueryInfoKey() 함수의 마지막 파라미터와 의미가 같습니다.

자 그러면 실제로 이것을 이용한 프로그램을 만들어 봅시다. 아래 프로그램은 새로운 키를 생성하고 그 키에 포함된 서브키가 어떤것들인지 화면에 출력해 주는 기능을 가졌습니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey)

;
    return TRUE;
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 49

안녕하세요………….돌팔이 황동준입니다…………………

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

제가 만든 두개의 함수만 알아 보면 되겠죠?

BOOL SetRegistry(void)
{

이 함수는 우리가 어떤 서브키가 있는지 테스트해보기 위해 임시로 서브키를 만드는 기능을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

어떤 서브키를 만드는지 굳이 설명드릴 필요는 없죠? 바로 Install이라는 서브키를 만들고 Install이라는 네임에 c:\doran20이라는 데이터를 저장하고 있는 구문입니다.

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;

앞에서 만든 DORAN 20이라는 서브키에 다시 Version이라는 서브키를 생성하고 네임에 Version을 그 네임에 해당하는 데이터는 2.0을 지정하는 구문입니다.

}

앞에서 한부분이므로 이해가 안가는 부분은 없을 겁니다. 위 함수가 수행되면 DORAN 20이라는 서브키에 Install, Version이라는 서브키가 생성되어 있을 겁니다.

BOOL PrintSubRegistry(HWND hWnd)
{

이 함수는 DORAN 20 서브키에 속해 있는 서브키를 찾아서 화면에 출력해주는 역할을 합니다.

    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

    if(lRet != ERROR_SUCCESS)
        return FALSE;

알아 볼 서브키가 포함되어 있는 부모 키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

이번에 알아 볼것은 단지 서브키의 개수이므로 데이터의 개수가 저장될 파라미터에는 NULL을 지정하였습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;

서브키의 개수만큼 인덱스를 증가하기 위해 위 dwCount라는 변수를 사용하였습니다.

    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

인덱스에 해당하는 서브키를 얻고 있는 구문입니다.

        dwSubKeySize = 80;

위 함수가 수행되면 dwSubKeySize에 실제 크기가 저장되므로 이 값을 다시 초기화해주고 있습니다. 왜냐하면 위 함수를 사용할 때 버퍼의 크기가 저장된 변수의 주소를 지정하기 때문이죠.

        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);

얻은 서브키를 화면에 출력해 주는 구문입니다.

        dwCount++;

인덱스를 증가하고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문을 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

자 그러면 이번에는 좀더 진보적인 프로그램을 만들어 봅시다. 바로 서브키만 알아내는 것이 아니라 그 안에 속해있는 네임과 데이터도 알아내는 거죠.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);
        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);
        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {
            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);
            dwNameSize = dwValueSize = 80;
            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;
            dwValueCount++;
        }
        RegCloseKey(hSubKey);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey);
    return TRUE;

}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 50

안녕하세요…………..돌팔이 황동준입니다………….

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

이번에는 함수 하나만 알아보면 되겠네요.

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;

정보를 알아볼 서브키의 루크키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

서브키의 개수를 알아내고 있습니다.

    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

서브키를 알아내고 있는 구문입니다.

        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);

        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

알아낸 서브키를 열고 있는 구문입니다.

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);

그 서브키가 가지는 데이터의 개수를 얻고 있습니다.

        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {

데이터의 개수만큼 루프문을 반복하고 있습니다.

            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);

위 함수로 인덱스에 해당하는 네임과 데이터를 얻을 수 있는데 위에서 이 함수에 대해 설명드리지 않았군요.

LONG RegEnumValue(
    HKEY  hkey,
    DWORD  iValue,
    LPTSTR  lpszValue,
    LPDWORD  lpcchValue,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );   

첫번째 파라미터에는 얻을 네임이 포함되어 있는 서브키의 핸들을 지정해 주면됩니다. 두번째 파라미터에는 네임의 인덱스를 지정해 주면 되는데 역시 0부터 지정해주면 됩니다. 세번째 파라미터에는 네임이 저장될 버퍼를 네번째 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다. 다섯 번째 파라미터에는 NULL을 지정하면 되고 여섯번째 파라미터에는 데이터의 타입이 저장될 변수의 주소를 지정해 주면 됩니다. 이 데이터 타입은 앞에서 이미 알아 본 것입니다. 아래와 같은 예약어들이 함수 사용한 후에 저장되겠군요.

REG_BINARY
REG_DWORD
REG_LINK
REG_NONE
REG_SZ

그 의미는 이미 앞에서 설명드렸을 겁니다.

일곱번째 파라미터에는 데이터가 저장될 버퍼를 지정하면 되고 마지막 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다.

함수 설명을 했으니 계속해서 해당 루틴을 알아 보도록 하겠습니다.

            dwNameSize = dwValueSize = 80;

역시 길이를 초기화 해주고 있습니다.

            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;

얻은 네임과 데이터를 화면에 출력해 주고 있습니다.

            dwValueCount++;

네임에 대한 인덱스를 증가해주고 있습니다.

        }
        RegCloseKey(hSubKey);
        dwCount++;

서브키에 대한 인덱스를 증가해주고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문이 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

Permalink 댓글 남기기

Registry

6월 26, 2006 at 10:30 오전 (Visual C++)

이번시간 부터는 레지스트리에 대한 것에 대해 알아 보겠습니다. 혹시 레지스트리라는것을 들어 보았습니까? 윈도우즈에서는 레지스트리라는 것이 존재하는데 이것은 일종의 하드웨어적, 소프트웨어적인 정보를 저장하고 있는 매체입니다. 우리가 앞에서 배운 win.ini 파일에도 다양한 정보가 저장되어 있는데 사실 이것은 윈도우즈 3.1때와의 호환 때문에 존재하는 것이고 실제로 우리가 다루어야 할 것은 바로 이 레지스트리입니다. 음.. 예를들어서 win.ini 파일에 프로그램이 설치되어 있는 디렉토리 정보가 들어 있었죠? 아마 인스톨 쉴드라는 인스톨 툴로 인스톨 프로그램을 만들면 인스톨시에 win.ini 파일에 디렉토리 정보 저장 기능은 없을 겁니다.

그러나 레지스트리에 설치된 디렉토리를 저장할 수 있는 기능은 있죠. 바로 레지스트리에도 설치된 디렉토리 정보가 들어 있다는 말과도 같습니다. 그것 뿐만 아닙니다. PNP 하드웨어의 정보도 다 들어 있죠. 모뎀 포트를 자동으로 찾는다거나 하는 작업을 바로 이 레지스트리를 검색해서 할수 있는 것입니다. 여러분들 넷스케이프 사용해 봤습니까? 거기에 보면 홈 디렉토리를 지정할 수 있는 메뉴 아이템이 있을겁니다. MS 익스플로어의 요즘 버전은 제가 사용해 보지 않았지만 예전에 사용할 때에는 이 기능이 없더군요. 그래서 항상 홈 디렉토리가 마이크로 소프트사였습니다. 그런데 이 홈 디렉토리 정보가 레지스트리에 등록되어 있다는 것을 우연히 알게 되었습니다. 물론 그것을 바꿔서 홈 디렉토리를 바꾸었죠.

너무 서론이 길었죠? 그렇다면 이러한 레지스트리를 어떻게 원하는데로 바꿀 수 있을까요? 윈도우즈가 설치되어 있는 디렉토리에 보면 regedit.exe 파일이 있을 겁니다. 이 실행 파일을 실행시켜서 레지스트리 정보를 볼 수도 있고 또 수정할 수도 있습니다. 이 프로그램을 레지스트리 편집기라고도 하죠.

한번 실행해 보세요.

어때요? 크게 6개의 폴더가 보이죠? 각 커다란 폴더에는 의미가 있습니다.

HKEY_CLASSES_ROOT

이 하위에 있는 정보들은 문서의 형태, 파일연관상태에 대한 정보가 들어 있습니다. 실제로 하위 폴더를 보면 아래아 한글 문서의 확장자, 압축 파일 확장자들의 정보가 들어 있음을 확인할 수 있습니다.

HKEY_CURRENT_USER

각각 사용자에 따른 사용자 정보를 가지고 있습니다.

HKEY_LOCAL_MACHINE

하드웨어, 네트워크, 소프트웨어 정보가 이곳에 있습니다. 실제로 프로그램이 설치되어 있는 디렉토리, PNP 하드웨어 등록 정보들이 이곳에 있는 거죠.

HKEY_USERS

각각 사용자에 대한 시스템 정보를 가지고 있습니다.

HKEY_CURRENT_CONFIG

하드웨어 설정에 대한 정보값이 들어 있습니다.

HKEY_DYN_DATA

역시 하드웨어적인 정보값이 들어 있습니다.

자 각각에 대해 알아 보았으니 각 서브 폴더를 확인해 보시기 바랍니다. 폴더 옆에 보면 플러스 기호가 있는데 여기에 마우스의 왼쪽 버튼으로 클릭하면 마이너스 기호로 바뀌고 그곳에 속해 있는 서브 폴더를 보여주게 됩니다. 다시 클릭하면 감춰지죠. 서브 폴더를 보다보면 폴더 왼쪽에 아무 기호도 없는 폴더들이 있을 겁니다. 그것은 서브 폴더를 가지지 않음을 의미하는 것입니다. 그렇다면 서브 폴더를 가지지 않은 폴더에 클릭한 후에 오른쪽에 있는 창을 보십시요.

어때요? 네임에 어떤 이름이 있고 데이터에 값이 들어 있죠? 물론 아무 값도 가지지 않는 경우도 있습니다. 서브 풀더를 가지고 있는 것도 마찬가지입니다. 왼쪽에 있는 기호에 클릭하지 않고 바로 그 폴더를 클릭하면 네임과 데이터에 값이 표시될 것입니다.

자 새로운 용어를 알아 봅시다. 우리가 앞에서 언급한 폴더를 키라고 합니다. 각 키는 물론 서브 키를 가질 수 있고 각 키에는 네임과 데이터를 가집니다. 물론 하나의 키는 여러개의 네임과 데이터를 가질 수 있습니다. 이해가 가죠?

자 이제부터 우리는 기존에 등록되어 있는 키, 네임, 데이터를 읽는 것을 프로그램 상으로 어떻게 구현하는지 알아 볼 것입니다. 물론 등록하는 방법도 알아 볼 거구요.

그러면 시작해 봅시다.

먼저 등록되어 있는 정보를 읽어오는 방법부터 알아 봅시다. 처음에 정보를 가져올 키가 어떤 것인지 지정해서 열어 주어야 합니다.

LONG RegOpenKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    REGSAM  samDesired,
    PHKEY  phkResult
   );   

위 함수를 이용해서 레지스트리에 설정되어 있는 키를 열 수 있습니다. 첫번째 파라미터에 제일 상단에 있는 루트키를 지정하면 되는데 이 키는 레지스트리 편지기를 실행했을 때 볼 수 있는 값을 지정하면 되는 겁니다. 아래 값들 중 하나가 되겠군요.

HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA

두번째 파라미터에는 우리가 정보를 가져올 서브키를 지정해 주면 됩니다. 서브키 내에 또다른 서브키가 있으면 서브 디렉토리를 표시하던 식인 \\식으로 표시해 주면 됩니다. 세번째 파라미터에는 0을 지정하면 되고 네번째 파라미터에는 지정된 예약어를 지정해주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

마지막 파라미터에는 서브키를 열었을때 얻어진 키 핸들을 저장할 변수의 주소를 지정해 주면 됩니다.

자 이제 서브키를 열었으니 그 키가 가지는 데이터를 가져오기만 하면 될 겁니다.

LONG RegQueryValueEx(
    HKEY  hkey,
    LPTSTR  lpszValueName,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );

위 함수를 이용해서 데이터를 가져올 수 있습니다. 첫번째 파라미터에는 위 RegOpenKeyEx() 함수에서 얻은 키 핸들을 지정하면 되고 두번째 파라미터에는 가져올 데이터가 가지는 네임을 지정해 주면 됩니다. 네임이 Default로 되어 있으면 그냥 ""식으로 지정해 주면 됩니다. 세번째 파라미터에는 0을 지정해 주면되고 네번째 파라미터에는 데이터의 저장형태가 저장될 변수의 주소를 지정해주면 됩니다. 이 저장형태는 뒤에 가서 레지스트리에 정보를 기록할때 다시 설명드리겠습니다.

그리고 다섯번째 파라미터에는 읽어온 데이터가 저장될 주소를 지정하면 됩니다. 마지막 파라미터에는 이 읽어온 데이터의 크기가 저장될 변수의 주소를 지정하면 됩니다.

데이터를 읽어오는 과정이 어렵지 않죠? 키를 열어서 작업을 다 했으면 그 키를 닫아 주어야 합니다.

LONG RegCloseKey(
    HKEY  hkey
   );

위 함수를 이용해서 연 키를 닫을수 있습니다. 물론 새로 생성한 키도 위 함수를 이용해서 닫아주면 되죠.

그러면 이번에는 정보를 기록하는 방법에 대해 알아 봅시다. 마찬가지로 어렵지 않습니다. 먼저 새로운 키를 생성하는 과정이 필요한데 그것은 아래 함수를 이용해서 하면 됩니다.

LONG RegCreateKeyEx(
    HKEY  hkey,
    LPCTSTR  lpszSubKey,
    DWORD  dwReserved,
    LPTSTR  lpszClass,
    DWORD  fdwOptions,
    REGSAM  samDesired,
    LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
    PHKEY  phkResult,
    LPDWORD  lpdwDisposition
   );

첫번째 파라미터에는 제일 상단에 있는 루트키를 지정해 주면 되는데 이 루트키는 이미 RegOpenKeyEx() 함수때 설명드렸을 겁니다. 두번째 파라미터에는 서브키를 지정해 주면 됩니다. 세번째 파라미터에는 NULL을 지정하면 되고 네번째 파라미터에는 클래스 이름을 지정해 주면 됩니다. 보통 NULL을 지정하죠. 다섯번째 파라미터에는 지정된 예약어를 지정해 주면 되는데 이때 지정될 수 있는 예약어는 다음과 같습니다.

REG_OPTION_VOLATILE         메모리에만 저장됩니다.
REG_OPTION_NON_VOLATILE     파일에 저장됩니다.

첫번째 예약어를 사용하게 되면 메모리에만 저장되므로 시스템이 재시작되면 무효가 되나 두번째 예약어를 사용하게 되면 파일에 저장되므로 그 값이 계속 유효하게 됩니다. 어떤 차이인지 알겠죠?

여섯번째 파라미터에는 어세스 옵션을 지정해 주면 되는데 다음과 같은 예약어를 지정해 주면 됩니다.

KEY_ALL_ACCESS              아래 모든 예약어를 만족합니다.
KEY_CREATE_LINK             다른 키로부터의 링크를 허락합니다.
KEY_CREATE_SUB_KEY          서브키의 생성을 허락합니다.
KEY_ENUMERATE_SUB_KEYS      서브키의 보여줌을 허락합니다.
KEY_EXECUTE                 서브키의 데이터를 가져오는 것을 허락합니다.
KEY_QUERY_VALUE             서브키의 데이터를 가져오는 것을 허락합니다.
KEY_READ                    서브키의 데이터를 가져오는 것을 허락합니다.
KEY_SET_VALUE               서브키의 데이터를 지정하는 것을 허락합니다.
KEY_WRITE                   서브키의 데이터를 지정하는 것을 허락합니다.

앞에서 알아본 RegOpenKeyEx()함수의 예약어와 같죠? 일곱번째 파라미터에는 NULL을 지정하면 되고 여덟번째 파라미터에는 이 키에 대한 핸들을 기억할 키 변수의 핸들을 지정해 주면 됩니다. 마지막 파라미터에는 키에 대한 결과가 저장될 변수의 주소를 지정해 주면 됩니다.

이제 키를 생성하는 함수를 알아보았으니 원하는 네임에 데이터를 지정하는 함수를 알아 봅시다.

LONG RegSetValueEx(
    HKEY  hkey,
    LPCTSTR  lpszValueName,
    DWORD  dwReserved,
    DWORD  fdwType,
    CONST BYTE *  lpbData,
    DWORD  cbData
   );

위 함수를 이용해서 원하는 네임과 데이터를 지정해줄수 있는데 각 파라미터의 의미를 알아 봅시다.

첫번째 파라미터에는 RegCreateKeyEx()함수로 얻은 키 핸들을 지정해주면 되고 두번째 파라미터에는 네임을 지정해 주면됩니다. 세번째 파라미터에는 NULL을 지정해주면 되고 네번째 파라미터에는 데이터의 타입을 지정해주면 됩니다. 데이터의 타입은 아래의 예약어를 이용하면 됩니다.

REG_BINARY      바이너리 형태입니다.
REG_DWORD       더블워드 형태입니다.
REG_LINK        심볼릭 링크 형태입니다.
REG_NONE        아무 형태도 아닙니다.
REG_SZ          문자열의 형태입니다.

다섯번째 파라미터에는 데이터를 지정해주면 됩니다. 마지막 파라미터에는 데이터의 길이를 지정해 주면 되구요.

자 그러면 이번에는 키를 삭제하는 방법을 알아 봅시다.

먼저 지울 키를 RegOpenKeyEx()함수를 이용해서 핸들 형태로 반환을 받아야 합니다. 그래서 그 핸들을 이용해서 원하는 네임의 데이터를 삭제하면 되죠.

원하는 네임의 데이터를 지울 때에는 아래 함수를 사용하면 됩니다.

LONG RegDeleteValue(
    HKEY  hkey,
    LPTSTR  lpszValue
   );

첫번째 파라미터에 지울 네임이 속해 있는 키의 핸들을 지정해 주면 됩니다. 두번째 파라미터에는 지울 데이터의 네임을 지정해 주면 되구요.

이번에는 키 자체를 없애는 함수입니다.

LONG RegDeleteKey(
    HKEY  hkey,
    LPCTSTR  lpszSubKey
   );

첫번째 파라미터에는 최상위 루트 키의 이름을 지정해주면 되고 두번째 파라미터에는 그 안에 포함된 지울 서브키의 이름을 지정해 주면 됩니다. 사용방법이 간단하죠.

자 그러면 위에서 배운 함수들을 이용해서 실제로 프로그램을 만들어 봅시다.

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 47

안녕하세요……..돌팔이 황동준입니다……………..

이번시간에는 저번시간에 알아 본 함수들을 이용해서 프로그램을 만들어 보겠습니다.

아래 프로그램은 레지스트리에 원하는 키를 생성해서 거기에 데이터를 기록한 뒤 실제로 그 데이터를 가져오고 하는 기능을 가졌습니다. 물론 지우는 기능도 있구요. 앞부분에서 함수를 잘 이해한 분들은 그렇게 어렵지 않을 겁니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Get Registry", 200
        MENUITEM "&Delete Registry", 300
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
char* GetRegistry(void);
void DeleteRegistry(void);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        strcpy(szBuff, GetRegistry());
                        if(strcmp(szBuff, "ERROR"))
                            MessageBox(hWnd, szBuff, "", MB_OK);
                        else
                            MessageBox(hWnd, "Value not found!!", "", MB_OK);
                        break;

                    case 300 :

                        DeleteRegistry();
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

char* GetRegistry(void)
{
    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{
    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);
    RegDeleteValue(hKey, "Install");
    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");
    RegCloseKey(hKey);
}

자 프로그램을 실행시켜 첫번째 메뉴 아이템인 Set Registry를 선택해 보세요. 그리고 진짜로 그 키가 생성되었는지 레지스트리 편집기로 확인해 보시기 바랍니다. 어때요? 정말로 생성되어 있죠? 자 그러면 소스를 보도록 합시다.

제가 만든 세개의 함수 루틴만 보면 되겠네요.

BOOL SetRegistry(void)
{

이 함수는 새로운 키를 생성하는 역할을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", NULL,
        NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);

HKEY_LOCAL_MACHINE 부분에 있는 Software내에 DORAN 20이라는 키를 생성하고 있는 구문입니다. 물론 Software라는 서브키가 존재하지 않으면 새로 생성합니다.

    if(lRet != ERROR_SUCCESS)
        return FALSE;

성공적으로 함수가 수행되면 ERROR_SUCESS라는 리터값이 발생된다는 것을 위 구문으로 짐작할 수 있을 겁니다.

    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));

Install이라는 네임에 c:\doran20이라는 데이터를 저장하는 구문입니다.

    if(lRet != ERROR_SUCCESS)
    {

역시 함수가 성공적으로 수행되면 ERROR_SUCCESS라는 리턴값이 발생되는군요.

        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);

생성한 키를 닫는 구문입니다.

    return TRUE;
}

char* GetRegistry(void)
{

이 함수는 원하는 서브키의 데이터를 가져오는 역할을 합니다.

    HKEY hKey;
    LONG lRet;
    DWORD dwByte, dwType;
    static char szBuff[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

데이터를 가져올 서브키를 열고 있습니다.

    if(lRet != ERROR_SUCCESS)
        return "ERROR";
    lRet = RegQueryValueEx(hKey, "Install", 0, &dwType,
        (unsigned char *)szBuff, &dwByte);

Install이라는 네임에 해당하는 데이터를 가져오고 있습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return "ERROR";
    }
    RegCloseKey(hKey);
    return szBuff;
}

void DeleteRegistry(void)
{

이 함수는 첫번째 메뉴 아이템에 의해 생성된 키와 데이터를 삭제하는 역할을 합니다.

    HKEY hKey;

    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0, KEY_ALL_ACCESS,
        &hKey);

지울 키를 얻고 있습니다.

    RegDeleteValue(hKey, "Install");

Install 네임을 가지고 있는 데이터를 삭제하는 구문입니다.

    RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\DORAN 20");

서브 키를 없애는 구문입니다.

    RegCloseKey(hKey);
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 48

안녕하세요…………돌팔이 황동준입니다……………

이번시간에도 레지스트리에 대해 더 알아 보겠습니다. 이번에 알아 볼 것은 어떤 키에 속해있는 서브키를 어떻게 얻을 수 있는지 입니다. 물론 우리는
서브키에 속해 있는 네임에 해당하는 데이터를 얻는 방법은 압니다. 그러나 문제가 있죠. 바로 이 키에 어떤 서브키가 있는지 모른다면 할 수가 없습니다. 그렇죠? 그렇기 때문에 이 방법을 알아야 합니다. 좀더 들어간다면 어떤 서브키에 어떤 네임들이 있는지도 아는 방법이 있습니다. 그것도 우리가 지금 알아 볼 방법을 응용하면 됩니다. 자 그러면 시작해 봅시다.

먼저 크게 두단계로 나누어서 합니다. 첫번째 단계는 바로 원하는 키에 서브키가 몇개 있는지 개수를 알아내는 것입니다. 두번째 단계는 이 개수를 가지고 차례로 키 포인터를 이동시켜 서브키를 얻는 것입니다.

자 그러면 실제로 어떤 식으로 구현하는지 필요한 함수를 보도록 합시다. 먼저 서브키의 개수를 알아야 하는데 이때 필요한 함수의 첫번째 파라미터에 키 핸들을 지정해야 하는데 이 키 핸들은 앞에서 배운 RegOpenKeyEx()함수를 이용하면 됩니다. 그러면 키의 개수를 얻을 수 있는 함수를 보도록 합시다.

LONG RegQueryInfoKey (
    HKEY  hkey,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    LPDWORD  lpdwReserved,
    LPDWORD  lpcSubKeys,
    LPDWORD  lpcchMaxSubkey,
    LPDWORD  lpcchMaxClass,
    LPDWORD  lpcValues,
    LPDWORD  lpcchMaxValueName,
    LPDWORD  lpcbMaxValueData,
    LPDWORD  lpcbSecurityDescriptor,
    PFILETIME  lpftLastWriteTime
   );

첫번째 파라미터로 RegOpenKeyEx()함수에서 얻은 키 핸들을 지정하면 됩니다. 두번째 파라미터에는 클래스 이름이 저장될 버퍼의 주소를 세번째 파라미터에는 그 클래스 버퍼의 크기를 가지고 있는 변수의 주소를 지정해 주면 됩니다.

네번째 파라미터에는 0을 지정하면되고 다섯번째 파라미터인 lpcSubKeys에는 서브키의 개수가 저장될 변수의 주소를 지정해 주면 됩니다. 여섯번째 파라미터에는 서브키의 이름중 가장 긴 이름을 가진 서브키의 길이가 저장될 변수의 주소를 지정해주면 됩니다. 사실 이 값은 잘 쓰이지 않죠. 역시 일곱번째 파라미터도 서브키에 대한 클래스이름이 가장 긴 길이가 저장될 변수의 주소를 지정해주면 됩니다.

여덟번째 파라미터인 lpcValues에는 지정해준 키에 대한 데이터의 개수가 저장 될 변수의 주소를 지정해주면 되는데 우리가 지금 만들어볼 프로그램은 단지 서브키의 개수만 알아볼거니 사실 이 값이 필요없습니다. 그러나 다음 프로그램에서는 이 값을 이용할테니 그 의미를 알아 두시기 바랍니다.

아홉번째 파라미터에는 가장 긴 네임에 대한 길이가 저장될 변수의 주소를 지정해주면 되고 열번째 파라미터에는 가장긴 데이터의 길이가 저장될 변수의 주소를 지정해 주면 됩니다. 열한번째 파라미터에는 NULL을 지정하면 되고 마지막 파라미터에는 주어진 키에대한 시간정보를 저장할 구조체 변수의 주소를 지정해 주면 됩니다. 이 구조체는 이미 앞에서 알아보았고 또 어떻게 다루었는지도 알아 보았을 겁니다.

자 서브키나 데이터의 개수를 위 함수로 알아 냈으니 이번에는 실제로 그 서브키나 데이터가 무엇인지 알아내는 함수를 알아 봅시다.

LONG RegEnumKeyEx(
    HKEY  hkey,
    DWORD  iSubkey,
    LPTSTR  lpszName,
    LPDWORD  lpcchName,
    LPDWORD  lpdwReserved,
    LPTSTR  lpszClass,
    LPDWORD  lpcchClass,
    PFILETIME  lpftLastWrite
   );

바로 위 함수를 이용해서 알아 낼 수 있습니다. 첫번째 파라미터에 알아낼 서브키가 속해있는 루트 키의 핸들을 지정해 주면 되고 두번째 파라미터에 서브키의 인덱스를 지정해주면 됩니다. 서브키의 인덱스는 0부터 시작합니다. 예를 들어 우리가 위의 RegQueryInfoKey() 함수로 서브키의 개수를 알아 내었다면 0부터 차례로 그 개수에서 1을 뺀값까지 이 파라미터로 지정해주면 되겠죠.

세번째 파라미터에는 해당하는 인텍스의 서브키가 들어갈 버퍼를 지정해 주면 되고 네번째 파라미터에는 그 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

다섯번째 파라미터에는 NULL을 지정해 주면 되고 여섯번째 파라미터에는 클래스 이름이 저장될 버퍼를 지정해주면 됩니다. 일곱번째 파라미터에는 클래스 이름이 저장 될 버퍼의 크기가 저장된 변수의 주소를 지정해 주면 됩니다.

마지막 파라미터는 설명 드릴필요는 없겠군요. 앞의 RegQueryInfoKey() 함수의 마지막 파라미터와 의미가 같습니다.

자 그러면 실제로 이것을 이용한 프로그램을 만들어 봅시다. 아래 프로그램은 새로운 키를 생성하고 그 키에 포함된 서브키가 어떤것들인지 화면에 출력해 주는 기능을 가졌습니다.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey)

;
    return TRUE;
}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 49

안녕하세요………….돌팔이 황동준입니다…………………

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

제가 만든 두개의 함수만 알아 보면 되겠죠?

BOOL SetRegistry(void)
{

이 함수는 우리가 어떤 서브키가 있는지 테스트해보기 위해 임시로 서브키를 만드는 기능을 합니다.

    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

어떤 서브키를 만드는지 굳이 설명드릴 필요는 없죠? 바로 Install이라는 서브키를 만들고 Install이라는 네임에 c:\doran20이라는 데이터를 저장하고 있는 구문입니다.

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;

앞에서 만든 DORAN 20이라는 서브키에 다시 Version이라는 서브키를 생성하고 네임에 Version을 그 네임에 해당하는 데이터는 2.0을 지정하는 구문입니다.

}

앞에서 한부분이므로 이해가 안가는 부분은 없을 겁니다. 위 함수가 수행되면 DORAN 20이라는 서브키에 Install, Version이라는 서브키가 생성되어 있을 겁니다.

BOOL PrintSubRegistry(HWND hWnd)
{

이 함수는 DORAN 20 서브키에 속해 있는 서브키를 찾아서 화면에 출력해주는 역할을 합니다.

    HDC hDC;
    HKEY hKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwSubKeySize = 80;
    FILETIME FileTime;
    static char szSubKey[80];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);

    if(lRet != ERROR_SUCCESS)
        return FALSE;

알아 볼 서브키가 포함되어 있는 부모 키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

이번에 알아 볼것은 단지 서브키의 개수이므로 데이터의 개수가 저장될 파라미터에는 NULL을 지정하였습니다.

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;

서브키의 개수만큼 인덱스를 증가하기 위해 위 dwCount라는 변수를 사용하였습니다.

    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

인덱스에 해당하는 서브키를 얻고 있는 구문입니다.

        dwSubKeySize = 80;

위 함수가 수행되면 dwSubKeySize에 실제 크기가 저장되므로 이 값을 다시 초기화해주고 있습니다. 왜냐하면 위 함수를 사용할 때 버퍼의 크기가 저장된 변수의 주소를 지정하기 때문이죠.

        hDC = GetDC(hWnd);
        TextOut(hDC, 0, 20*dwCount, szSubKey, strlen(szSubKey));
        ReleaseDC(hWnd, hDC);

얻은 서브키를 화면에 출력해 주는 구문입니다.

        dwCount++;

인덱스를 증가하고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문을 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

자 그러면 이번에는 좀더 진보적인 프로그램을 만들어 봅시다. 바로 서브키만 알아내는 것이 아니라 그 안에 속해있는 네임과 데이터도 알아내는 거죠.

MyMenu MENU
BEGIN
    POPUP "&Registry"
    BEGIN
        MENUITEM "&Set Registry", 100
        MENUITEM "&Print Registry", 200
    END
END

#include <windows.h>
#include <string.h>
#include <stdio.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL SetRegistry(void);
BOOL PrintSubRegistry(HWND hWnd);

int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
        static char szAppName[] = "Registry Example";
        HWND hWnd;
        MSG msg;
        WNDCLASS WndClass;

        WndClass.style = CS_HREDRAW|CS_VREDRAW;
        WndClass.lpfnWndProc = WndProc;
        WndClass.cbClsExtra = 0;
        WndClass.cbWndExtra = 0;
        WndClass.hInstance = hInstance;
        WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
        WndClass.lpszMenuName = "MyMenu";
        WndClass.lpszClassName = szAppName;
        if(!RegisterClass(&WndClass))
                return FALSE;

        hWnd = CreateWindow(
                szAppName,
                szAppName,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL
        );

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static char szBuff[80];

        switch(message)
        {
            case WM_COMMAND :

                switch(LOWORD(wParam))
                {
                    case 100 :

                        if(!SetRegistry())
                            MessageBox(hWnd, "Create Fail", "Error", MB_OK);
                        break;

                    case 200 :

                        if(!PrintSubRegistry(hWnd))
                            MessageBox(hWnd, "Print Fail", "Error", MB_OK);
                        break;
                }
                return 0;

            case WM_DESTROY :

                PostQuitMessage(0);
                return 0;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
}

BOOL SetRegistry(void)
{
    HKEY hKey;
    DWORD dwState;
    LONG lRet;

    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Install",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Install", NULL, REG_SZ,
        (unsigned char *)"c:\\doran20", strlen("c:\\doran20"));
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20\\Version",
        NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
            &dwState);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegSetValueEx(hKey, "Version", NULL, REG_SZ,
        (unsigned char *)"2.0", strlen("2.0"));

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    RegCloseKey(hKey);
    return TRUE;
}

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;
    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);
    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }
    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);
        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);
        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);
        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {
            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);
            dwNameSize = dwValueSize = 80;
            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;
            dwValueCount++;
        }
        RegCloseKey(hSubKey);
        dwCount++;
    } while(dwCount<dwSubKeyNumber);
    RegCloseKey(hKey);
    return TRUE;

}

오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~~~~~

 

  윈도우 32비트 프로그래밍 50

안녕하세요…………..돌팔이 황동준입니다………….

이번시간에는 저번시간에 만든 프로그램을 분석해 보겠습니다.

이번에는 함수 하나만 알아보면 되겠네요.

BOOL PrintSubRegistry(HWND hWnd)
{
    HDC hDC;
    HKEY hKey, hSubKey;
    LONG lRet;
    DWORD dwSubKeyNumber, dwCount, dwValueNumber, dwValueCount,
        dwSubKeySize = 80;
    DWORD dwNameSize = 80, dwValueSize = 80;
    FILETIME FileTime;
    int n=0;
    static char szSubKey[80], szName[80], szValue[80];
    static char szBuff[80], szPrint[256];

    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\DORAN 20", 0,
        KEY_ALL_ACCESS, &hKey);
    if(lRet != ERROR_SUCCESS)
        return FALSE;

정보를 알아볼 서브키의 루크키를 여는 구문입니다.

    lRet = RegQueryInfoKey(hKey, NULL, 0, 0, &dwSubKeyNumber, NULL, NULL,
        NULL, NULL, NULL, NULL, &FileTime);

    if(lRet != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return FALSE;
    }

서브키의 개수를 알아내고 있습니다.

    dwCount = 0;
    do
    {
        RegEnumKeyEx(hKey, dwCount, szSubKey, &dwSubKeySize, NULL,
            NULL, 0, &FileTime);

서브키를 알아내고 있는 구문입니다.

        dwSubKeySize = 80;
        strcpy(szBuff, "Software\\DORAN 20");
        strcat(szBuff, "\\");
        strcat(szBuff, szSubKey);

        lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, KEY_ALL_ACCESS,
            &hSubKey);

알아낸 서브키를 열고 있는 구문입니다.

        lRet = RegQueryInfoKey(hSubKey, NULL, 0, 0, NULL, NULL, NULL,
            &dwValueNumber, NULL, NULL, NULL, &FileTime);

그 서브키가 가지는 데이터의 개수를 얻고 있습니다.

        dwValueCount = 0;
        while(dwValueNumber > dwValueCount)
        {

데이터의 개수만큼 루프문을 반복하고 있습니다.

            RegEnumValue(hSubKey, dwValueCount, szName, &dwNameSize, NULL,
                NULL, (unsigned char *)szValue, &dwValueSize);

위 함수로 인덱스에 해당하는 네임과 데이터를 얻을 수 있는데 위에서 이 함수에 대해 설명드리지 않았군요.

LONG RegEnumValue(
    HKEY  hkey,
    DWORD  iValue,
    LPTSTR  lpszValue,
    LPDWORD  lpcchValue,
    LPDWORD  lpdwReserved,
    LPDWORD  lpdwType,
    LPBYTE  lpbData,
    LPDWORD  lpcbData
   );   

첫번째 파라미터에는 얻을 네임이 포함되어 있는 서브키의 핸들을 지정해 주면됩니다. 두번째 파라미터에는 네임의 인덱스를 지정해 주면 되는데 역시 0부터 지정해주면 됩니다. 세번째 파라미터에는 네임이 저장될 버퍼를 네번째 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다. 다섯 번째 파라미터에는 NULL을 지정하면 되고 여섯번째 파라미터에는 데이터의 타입이 저장될 변수의 주소를 지정해 주면 됩니다. 이 데이터 타입은 앞에서 이미 알아 본 것입니다. 아래와 같은 예약어들이 함수 사용한 후에 저장되겠군요.

REG_BINARY
REG_DWORD
REG_LINK
REG_NONE
REG_SZ

그 의미는 이미 앞에서 설명드렸을 겁니다.

일곱번째 파라미터에는 데이터가 저장될 버퍼를 지정하면 되고 마지막 파라미터에는 이 버퍼의 크기가 저장되어 있는 변수의 주소를 지정해 주면 됩니다.

함수 설명을 했으니 계속해서 해당 루틴을 알아 보도록 하겠습니다.

            dwNameSize = dwValueSize = 80;

역시 길이를 초기화 해주고 있습니다.

            sprintf(szPrint, "%s : %s", szName, szValue);
            hDC = GetDC(hWnd);
            TextOut(hDC, 0, 20*n, szPrint, strlen(szPrint));
            ReleaseDC(hWnd, hDC);
            n++;

얻은 네임과 데이터를 화면에 출력해 주고 있습니다.

            dwValueCount++;

네임에 대한 인덱스를 증가해주고 있습니다.

        }
        RegCloseKey(hSubKey);
        dwCount++;

서브키에 대한 인덱스를 증가해주고 있습니다.

    } while(dwCount<dwSubKeyNumber);

서브키의 개수만큼 루프문이 돌고 있습니다.

    RegCloseKey(hKey);
    return TRUE;
}

Permalink 댓글 남기기

레지스트리에 값 저장하기!

6월 26, 2006 at 10:28 오전 (Visual C++)

그냥 맴버함수로 선언하시고 쓰세요 그게 편해요 ㅋㅋ

//레지스트리값 읽어오기 함수

int ReadRegVal(char *reg_path, char *key, char *val, int val_buf_size )

{

    HKEY phk=0;

    DWORD nEC = REG_BINARY;                                         // 바이너리모드로 읽기

    DWORD size = val_buf_size;                                            // 레지스트리읽기시 버퍼크기

    memset(val,0,val_buf_size);                                              //mem clear

    RegOpenKey(HKEY_LOCAL_MACHINE,reg_path,&phk);

    RegQueryValueEx(phk, key, NULL,&nEC, (LPBYTE)val, &size );  //읽기 값은 val에 저장

   //val은 걍 맘편히 타입케스팅 바로 하셔서 쓰세요….

    RegCloseKey(phk);

    return 0;

}

//레지스트리값 저장하기 함수

int WriteRegVal(char *reg_path, char *key, char *val)          //reg write

{

    HKEY phk=0;

    long nRet;

    RegCreateKey(HKEY_LOCAL_MACHINE, reg_path, &phk);

    nRet = RegSetValueEx(phk, key, 0, REG_SZ, (LPBYTE)val, strlen(val));

    RegCloseKey(phk);

    if(ERROR_SUCCESS == nRet)   return 0;

    return 1;

}

사용법:

//레지스터 읽기.

char test[50];

if(ReadRegVal("SOFTWARE\\MYTEST", "test" , test, sizeof(test))==0)

{

    //레지스터 쓰기.

    WriteRegVal("SOFTWARE\\MYTEST", "test", "lee" );

}

레지스트리 값 읽어 오는 함수는 윗님이 말씀하신대로 RegQueryValueEx()를 쓰시면되구요.

RegOpenKey()을 안하셔서 못받아 오셨을 수도 있으니까 확인하시고 직접 MSDN보시면서 테스트해보세요!!!

ps. 문자는 REG_SZ, 숫자는 REG_DWORD 로 변경하시고 val타입을 맞게 지정하면되겠죠. 걍 char로 받아서 atoi로 변환해줘도 되고요

Permalink 댓글 남기기

XP/XPE 방화벽 참조 URl

6월 26, 2006 at 10:20 오전 (XP/XPE)

http://msdn.microsoft.com/embedded/community/community/tips/xp/firewall/default.aspx

xpe의 방화벽 설정 컴포넌트는 core networkingsettingsWindows Firewall/Internet Connection Sharing (ICS)

Permalink 댓글 남기기

netsh

6월 26, 2006 at 5:34 오전 (XP/XPE)

Download: how_to_netsh.doc

출처: http://blog.naver.com/greatshe?Redirect=Log&logNo=110005366569

GUI 로 친숙한 방화벽 정책 설정을 하면 되는 것을 왜 궂이 CLI로 하려고 하는지 묻는다면 설정에 대한 재미도 있을 수 있고 GUI로 보지만 가끔 시스템 상에 문제가 되었을 때 GUI가 열리지 않는다거나 숨겨진 방화벽 설정을 볼 때에는 이 netsh 를 이용하여 설정하는 방법도 매우 빠르며 유용 할 수 있다. netsh 는 비단 방화벽만 설정 할 수 있는 것이 아닌 RAS, NAT, OSPF도 설정을 할 수 있다. 요즘 들어 MS 운영체제의 취약성을 이용하여 웜 감염 후 netsh를 이용하여 네트워크를 조작하는 수법도 존재한다. 그 이유는 GUI를 통하지 않고도 명령어를 통한 배치 파일로 DNS 조작도 시도 할 수 있으며, 악의적인 DNS 서버에 Domain Name 을 Query 할 때 악의적인 사용자가 미리 지정한 IP로 접속을 유도도 할 수 도 있기 때문이다. 이러한 기법은 파밍(Pharming) 기법으로도 응용할 수 있는 부분이다. Window Support Tool 로 사용하는 ipseccmd 를 (GUI로는 secpol.msc) 사용하여 in, outbound 로 포트에 대한 차단을 할 수 있다면, netsh 는 윈도우 XP 방화벽은 IP및 포트에 대한 inbound 그리고 어플리케이션 프로그램에 대한 in, outbound에 대한 차단 및 허용이 가능하다. 엄밀히 따져보면 Stateful Inspection 방화벽이라고 말하지만 Outbound에 대한 IP 및 포트 정책이 없는 방화벽이 과연 데이터 스트림까지 지원하는 Stateful inspection 방화벽이라고 하기엔 조금 미흡한 점이 있지 않나 싶다. netsh 를 사용하는 것은 위의 그림처럼 클릭 할 때의 설정과 그 결과값이 똑같다. CLI 를 싫어하시는 분들이 많을지 모르나 시간, 속도, GUI로 볼 수 없는 숨겨진 기능을 볼 수 있다는 장점이 있다. 즉 한눈에 일목요연하게 보고 싶거나 정보 수집용으로도 손색이 없을 것이다.각 구문만 쉽게 눈에 들어오고 익힌다면 빠른 설정을 할 수 있을 것이다. 네트워크 방화벽처럼 윈도우 방화벽 설정시에 기본적인 정책은 Deny 이다. (방화벽을 enable 시켰을 때) 윈도우 시작->실행->cmd->netsh 를 TYPE 해 보자.여기서는 CD (Change Directory)가 안 되므로, 각 디렉토리 이동은 (..) Double Dot 또는 (.) Single Dot 를 이용하여 이동하자. 또한 모든 명령어는 ? 로 확인한다. 이렇게 설정하지 않아도 직접적으로 명령어를 이어서 사용함으로써 한 번에 설정이 가능하다.아래의 실제 방화벽 설정의 예제들을 보자.다음의 명령어를 보자.

C:\>netsh firewall show ?
다음 명령을 사용할 수 있습니다.
이 컨텍스트에 있는 명령:
show allowedprogram – 방화벽 허용 프로그램 구성을 표시합니다
.
show config – 방화벽 구성 정보를 표시합니다
.
show currentprofile – 현재 방화벽 프로필을 표시합니다
.
show icmpsetting – 방화벽 ICMP 구성을 표시합니다
.
show logging – 방화벽 로깅 구성을 표시합니다
.
show multicastbroadcastresponse-방화벽 멀티캐스트/브로드캐스트 응답 구성을 표시합니다
.
show notifications – 방화벽 알림 구성을 표시합니다
.
show opmode – 방화벽 작동 구성을 표시합니다
.
show portopening – 방화벽 포트 구성을 표시합니다
.
show service – 방화벽 서비스 구성을 표시합니다
.
show state – 현재 방화벽 상태를 표시합니다.

눈여겨 볼 만한 명령어는 위 굵은 글씨체를 참고하라. 그럼 방화벽 정책을 설정하기 위한 Steb-by-Step을 해보자.■ 현재 열려져 있거나 열려져 있지 않은 포트를 상세히 보려면 아래의 명령어를 사용.netsh firewall show portopening verbose = enable
netsh firewall show config verbose = enable
netsh firewall show state verbose = enable
netsh firewall show portopening verbose = enable | findstr VNC
특정한 부분이 열렸는지만 볼 때.물론 verbose = disable 도 있지만, 궂이 상세하게 보지 않겠다는 옵션을 줄 필요는 없다.
이 중에서 한가지 기본 규칙만을 지킨다면 응용은 그렇게 어렵지만은 않다.
실제, netstat 로 확인한 결과 Listening 된 포트가 있다 하더라도, 실제 열려진 포트를 보려면 위의 세 가지 명령어를 통하여 확연히 구분 지을 수 있다. 중복되는 내용들이 많지만 정확한 설정 값 및 포트 오픈 및 현재의 방화벽 상태를 확인하려면, 위의 세 명령어를 사용해도 무방할 것 같다.
아래의 규칙을 기억하자. (순서는 바뀌어도 상관은 없지만 대부분 이런 수순)

Scope 이 생소하겠지만 여기서 Scope은 Subnet , Custom , All 이 있다. 보안상 이 부분 역시 좋은 부분인 것 같다. Netbios 같은 경우 인터넷 외부에서의 연결은 보안상 위험하다. 그래서 이러한 Netbios 포트는 기본적으로 자기 네트워크에 속한 대역(서브넷)만을 액세스 할 수 있게 설정하는 것이 좋다. 때론 Access List 처럼 작용하는 것으로 보일 수 있으나, subnet을 선택할 경우 자신의 속한 네트워크 브로드캐스트 영역을 보므로 자신의 전체 내부 네트워크에서는 이러한 프로그램 및 포트는 접근 가능할 수 있다. 그러므로 Custom 에서의 선택을 하여 일일이 네트워크 및 IP Address 및 네트워크 대역을 지정하는 것이 보안상 좋은 방법일 것이다. - Subnet : 자신이 속한 네트워크 대역
- Custom : 일일이 접근 IP 또는 접근 네트워크 대역을 지정할 수 있다
.
- All : 모든 IP 및 네트워크 주소
본격적으로 방화벽 정책을 설정해 보자. set 은 현설정에 대한 편집이거나 추가이며, add 는 추가만 할 수 있다. 아래 예들은 모두 set 으로 설정 하였다.
포트 오픈 하기 ≠ 서비스 오픈 ( set portopening 또는 add portopening )
C:\>netsh firewall set portopening TCP 5900 VNC_ServerPort
확인됨.
아래 그림을 보면 생성이 되어져 있음을 볼 수 있다.
또한 findstr 구문을 통하여 현재 설정 상태도 확인을 할 수 있다.
- netsh firewall show portopening | findstr VNC구체적으로 이러한 포트 오픈은 내가 속한 네트워크 대역 서브넷(subnet)안에서만 허용하고 싶다면 조금 다르게 옵션을 설정을 해 주어야 한다. C:\>netsh firewall set portopening protocol = TCP port = 5800 name = VNC_HTTP
scope = subnet mode = enable

확인됨 C:\>netsh firewall set portopening protocol = TCP port = 23456 name = Ahnlabcoconut_FTP scope = CUSTOM addresses = 192.168.1.3,LocalSubnet
확인됨
이것은 로컬 서브넷에서만 접근 가능하고, 외부 192.168.1.3 에서 이 서비스를 사용할 수 있다라는 뜻이다. GUI 에서는 아래와 같다.참고 URL :http://www.microsoft.com/technet/prodtechnol/winxppro/deploy/depfwset/wfsp2apb.mspx ■ 서비스 설정하기 ( set service 또는 add service) 서비스 종류는 아래와 같은 종류로 국한하기 때문에 서비스를 생성(포트 오픈)해야 할 필요성은 느끼지 못한다. (터미널 서비스 : TCP 3389 )
위 에서 설명했듯이 이 netsh 의 포트 오픈과 서비스 오픈과는 약간의 차이가 있다.아래는 서비스 Open에 관련된 서비스 내용 들이다. 실제 이 서비스들도 설정해야 하고 시스템 등록 정보의 [원격] 탭에서 설정을 해야만 비로서 아래와 같은 서비스들을 정상적으로 사용 할 수가 있다.

FILEANDPRINT 파일 및 프린터 공유
REMOTEADMIN 원격 관리
REMOTEDESKTOP 원격 지원 및 원격 데스크톱
UPNP UPnP 프레임워크
ALL 모든 종류

이 윈도우 XP 방화벽에서의 서비스는 말 그대로 윈도우가 제공해 주는 서비스를 말하고 실제 포트 오픈은 이전에 Bulit-in 된 원격데스크톱 및 원격지원 서비스에 V 체크만 하면 된다. 그림에서 보듯이 원격 데스크탑 및 원격 지원은 Windows 방화벽에서 삭제(D) 버튼을 누를 수
없다. 이는 아래 그림처럼 [내컴퓨터] ▶ [오른쪽 마우스 클릭] ▶ [속성] ▶ [원격] 부분.
이 부분에 속해 있기 때문이다. 왜 이렇게 설정을 했는지는 잘 모르겠지만, 어쨌든 이 원격지원 부분과 원격 데스크톱 부분의 체크박스에 체크를 하지 않으면 아래 그림처럼 자동적으로 체크 박스에 v 체크가 없어지는 것을 볼 수 있다. 하지만 이는 역으로는 성립이 되지 않는다. 즉 이 윈도우 방화벽에서의 원격 데스크톱이나 원격지원을 v 체크를 한다 하더라도, 시스템 등록정보에서의 [원격] 탭에서는 v 체크가 되지 않으면 외부에서 접속을 하지 못하게 된다. 결론적으로 이러한 서비스를 사용하기 위해서는 당연히 RDP 서비스는 띄워져 있어야 하며, 우선적용이 되는 시스템 등록정보에 대한 체크박스에 V 체크가 되어져 있어야 하는 것이다. 이 시스템 등록정보에 V 체크가 되지 않으면 TCP 3389 포트에 대하여 Listening 이 보이지를 않는다. 그런 이유에서 만약 외부에서 RDP 를 사용할 수 없거나, 원격지원을 사용할 수 없을 경우에는 이러한 서비스들이 윈도우 방화벽에서는 열려 있음에도 불구하고 서비스가 안 되면 시스템 등록 정보에서 확인을 하면 될 것이다.1. Remote Desktop 서비스를 사용하려면
netsh firewall set serv REMOTEDESKTOP enable 또는
netsh firewall set serv type = REMOTEDESKTOP mode = enable scope = all
2. 원격 접속 관리를 사용하기 위해서는
netsh firewall set REMOTEADMIN enable 또는
netsh firewall set serv type = REMOTEADMIN mode = enable scope = all
■ Application Program 오픈 하기 ( set allowedprogram 또는 add allowdprogram )set allowedprogram program = C:\Temp\AhnSV.exe name = AntiVirus mode =
ENABLE scope = CUSTOM addresses = 192.168.1.1,LocalSubnet
이러한 네트워크 설정은 여러 인터넷 검색 엔진 사이트에서 찾아 보며 참고하면 될 것 같다.네트워크 설정은 설명이 필요한 것 보단 이러한 환경이 필요한 곳에서 사용하면 더 할 나위 없이 유용하다. 같이 사용하는 IDC에서의 공유형 노트북(?)에서의 자신만의 고유 정적 IP가 있는 곳, 또는 DHCP로 사용해야만 하는 곳, 네트워크의 일부 GUI로 변경 없이 다음과 같은 명령어 행만으로 네트워크 설정을 쉽게 바꿀 수 있다.
시스템 정보 및 네트워크 정보를 GUI로 결과를 보고 싶다!
netsh diag gui
■ IP 수동 변경 (Static)
netsh -c int ip set address name="AhnlabCoCoNut" source=static addr=192.168.1.2 mask=255.255.255.0 gateway=192.168.1.1 gwmetric=0
■ IP 수동 변경 (로컬)
netsh -c int ip set address localhost static 192.168.1.2 mask 255.255.255.0 1
■ IP 자동 변경 ( DHCP )
netsh -c int ip set address name="AhnlabCoCoNut" source=dhcp
■ DNS 수동 변경(Static)
netsh -c int ip set dns name="AhnlabCoCoNut" source=static addr=168.126.63.2 register=PRIMARY
add dns name="AhnlabCoCoNut" addr=168.126.63.2 index=2
■ DNS 자동 변경 ( DHCP )
netsh -c int ip set dns name="AhnlabCoCoNut" source=dhcp
위와 같이 설정된 현재 네트워크 설정 저장
netsh -c interface dump > AhnlabCoCoNut.txt위 설정 그대로 사용
netsh exec AhnlabCoCoNut.txt이러한 DOS Command 모드로써의 중요한 점은 GUI로 된 네트워크 설정의 마우스를 사용하지 못할 때 유용하다고 할 수 있다 1. 내 컴퓨터에서 과연 어떠한 트래픽이 들어오고 나가고 Drop이 되는가?
이벤트 뷰어(eventvwr.msc)에서도 보안 설정을 하면 볼 수 있지만 더욱 상세하게 보여주는 것은 이 방화벽 로그일 것이다. 방화벽의 로깅 기능을 사용한다.물론 GUI도 있지만 여기선 netsh 만을 위주로 말하겠다.■ 현재 로깅 설정 현황 보기netsh firewall show logging로깅 설정하기 ( Drop 패킷 및 Connection 패킷 모두)
(손실된 패킷 ,성공한 연결 이 두가지를 로깅한다
.)
어떠한 패킷이 손실되는지만 본다면 droppedpackets = enable 옵션만 주면 될 것이다.
netsh firewall set logging droppedpackets = enable connections = enable filelocation = 2nd.txt 4096■ 현재 로깅 되는 로그 보기윈도우에서 로깅 되는 로그는 아래와 같다. 엑셀로 편집하여 나온 결과이다.
인바운드인지 아웃바운드 패킷인지의 구분은 없으며 단지 자신의 IP가 외부로 나가면 아웃바운드 자신의 IP가 Dst-IP로 로깅되어져 있으면 인바운드로 구분 할 수 밖에 없다
.
(실제 로깅 정보를 볼 때는 구분이 좀 어렵다.)

- 위에서 본 결과처럼 Action 부분에서 Open, Drop, Close 로 현재의 방화벽에서 패킷이 어떻게 취해지는가에 대한 판단을 할 수 도 있을 것이다. 특히 TCP 의 Flag 를 볼 경우 Syn 을 보냈음에도 ACK가 Drop이 되지 않는지 혹은 ACK 자체를 볼 수 없는지에 대하여 판단 할 때, 내 자체 윈도우 방화벽에서 막혔는지 혹은 그 앞단의 방화벽 및 네트워크 장비에서 막혔는지도 판단을 할 수 있을 것이다. 2. 윈도우 XP에서의 트래픽 흐름을 전혀 볼 수 없고 알 수 없을 때 트러블 슈팅 할 때 가장 먼저 윈도우 자체 내장 방화벽을 Disable 한 상태로 확인을 한다.netsh firewall set opmode enable [방화벽을 설정할 때]
netsh firewall set opmode disable [방화벽을 설정하지 않을 때]

그룹 명령 설명
Add netsh firewall add allowedprogram Windows 방화벽에 허용된 프로그램 구성 추가
netsh firewall add portopening Windows 방화벽에 포트 구성 추가
delete netsh firewall delete allowedprogram Windows 방화벽에서 허용된 프로그램 구성 삭제
netsh firewall delete portopening Windows 방화벽에서 포트 구성 삭제
reset netsh firewall reset Windows 방화벽 구성을 기본값으로 다시 설정
Set netsh firewall set allowedprogram Windows 방화벽의 허용된 프로그램 구성 편집
netsh firewall set icmpsettings Windows 방화벽의 ICMP 구성 편집
netsh firewall set logging Windows 방화벽의 로깅 구성 편집
netsh firewall set notifications Windows 방화벽의 알림 구성 편집
netsh firewall set opmode Windows 방화벽의 작동 구성 편집
netsh firewall set portopening Windows 방화벽의 포트 구성 편집
netsh firewall set service Windows 방화벽의 서비스 구성 편집
show netsh firewall show allowedprogram Windows 방화벽에서 허용된 프로그램 구성 표시
netsh firewall show config Windows 방화벽 구성 표시
netsh firewall show currentprofile Windows 방화벽의 현재 프로필 표시
netsh firewall show icmpsettings Windows 방화벽의 ICMP 구성 표시
netsh firewall show logging Windows 방화벽의 로깅 구성 표시
netsh firewall show notifications Windows 방화벽의 알림 구성 표시
netsh firewall show opmode Windows 방화벽의 작동 구성 표시
netsh firewall show portopening Windows 방화벽의 포트 구성 표시
netsh firewall show service Windows 방화벽의 서비스 구성 표시
netsh firewall show state Windows 방화벽의 현재 상태 표시

■ TCP/UDP/ICMP Connection 및 통계 체크 우선 서비스에 Remote Access Service 가 시작되어 있어야 한다.
net start remoteaccess 로 서비스를 시작 하자.
그런 후 아래와 같은 명령어로 현재의 연결 상태를 알아보자.- netsh interface ip show tcpstat : TCP 통계를 표시 ( netstat -s -v -p tcp )
- netsh interface ip show udpstat : UDP 통계를 표시
( netstat -s -v -p udp )
- netsh interface ip show tcpconn : TCP 연결을 표시
( netstat -an -p tcp )
- netsh interface ip show udpconn : UDP 연결을 표시
( netstat -an -p udp )
- netsh interface ip show config : 현재 네트워크 설정 상태 표시

( ipconfig /all 과 같은 결과
)
- netsh interface ip show address : ipconfig 결과

- netsh interface ip show interface : 상세한 인터페이스 정보

- netsh interface ip show dns
- netsh interface ip show icmp :ICMP
통계 자료 ( netstat -s -p icmp )
- netsh interface dump : 인터페이스에 대한 현재 방화벽 설정 전체를 보여준다.한글윈도우 XP Pro (SP2)에서의 netstat 와 netsh 의 차이점이 무엇이냐 하면, 결과를 보면 알겠지만 netstat 는 영문으로 결과를 보여주고 , netsh 는 친절하게도 한글로 보여준다는 것이다. 

Permalink 댓글 남기기

레지스트리 등록

6월 26, 2006 at 12:57 오전 (Visual C++)

Registry 등록

=====================================================================================

int SetRegistry(char* lpsz)
{
HKEY hKey;
DWORD dwState;
LONG lRet;

lRet = RegCreateKeyEx(HKEY_CURRENT_USER, 경로명, NULL,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
&dwState);
if(lRet != ERROR_SUCCESS)
return FALSE;
lRet = RegSetValueEx(hKey, ITEM명, NULL, REG_SZ,
(BYTE*)lpsz, strlen(lpsz));
if(lRet != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return FALSE;
}
RegCloseKey(hKey);
return TRUE;
}

Registry에서 값 얻어옴

=====================================================================================
char* GetRegistry(void)
{
HKEY hKey;
LONG lRet;
DWORD dwByte, dwType;
static char szBuff[80];

lRet = RegOpenKeyEx(HKEY_CURRENT_USER,경로명, 0,
KEY_ALL_ACCESS, &hKey);
if(lRet != ERROR_SUCCESS)
return "ERROR";
lRet = RegQueryValueEx(hKey, ITEM명, 0, &dwType,
(unsigned char *)szBuff, &dwByte);
if(lRet != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return "ERROR";
}
RegCloseKey(hKey);
return szBuff;
}

Permalink 댓글 남기기

인터넷으로 라디오 듣기

6월 22, 2006 at 7:19 오전 (ETC)

Permalink 댓글 남기기

파이널 판타지 뮤비 10 오프닝

6월 22, 2006 at 2:28 오전 (ETC)

Permalink 댓글 남기기

« Previous page · 다음 장 »