함수포인터를 이용한 유용한 기법중 하나인 “메세지 기법”에 대하서 정리했다.

struct MFT_Entry_Attribute_Type
{
    unsigned short	usNum;
    const char *	cDes;
    void (*fp)(void *);
} MFT_Attr_Type[] = {
    { 16, "$STANDARD_INFORMATION", Content_STD_INFO}
    ,{ 32, "$ATTRIBUTE_LIST",0}
    ,{ 48, "$FILE_NAME",Content_FILE_NAME}
    ,{ 64, "$VOLUME_VERSION or $OBJECT_ID",0}
    ,{ 80, "$SECURITY_DESCRIPTOR",0}
    ,{ 96, "$VOLUME_NAME",0}
    ,{112, "$VOLUME_INFORMATION",0}
    ,{128, "$DATA",0}
    ,{144, "$INDEX_ROOT",0}
    ,{160, "$INDEX_ALLOCATION",0}
    ,{176, "$BITMAP",0}
    ,{192, "$SYMBOLICK_LINK or REPARSE_POINT",0}
    ,{208, "$EA_INFORMATION",0}
    ,{224, "$EA",0}
    ,{256, "$LOGGED_UTILITY_STREAM",0}
    ,{257, "Unknown",0}
};
MFT_Entry_Attribute_Type 구조체는
  • 직접적인 비교에 쓰일 변수 한 개와
  • 메세지 출력을 위한 const char * 형의 변수 한 개,
  • 필요에 따라 함수를 호출할 수 있도록 함수 포인터 선언

으로 이루어져 있으며 소스에서 보는 바와 같이 구조체 선언과 동시에 구조체 배열 변수를 선언해 두었다.


이것을 어떻게 사용하는지 아래 소스에서 살펴보면,

void * test(void *p)            /* 213 페이지 */
{
    struct MFT_Entry_Attribute_Type * stpAttType;

    printf("========================= MFT Entry Attribute Analysis =========================\n");
    printf("Attribute Type                   : ");
    stpAttType = MFT_Attr_Type;
    while(1)
    {
        if(257 == (stpAttType->usNum))
        {
            break;
        }
        else if ((*((U32*)((U8*)p+0))) == stpAttType->usNum) /* 이동은 U8만큼으로 하고 보는건 U32로 보겠다 */
        {
            break;
        }
        ++stpAttType;
    }
    printf("%s\n", stpAttType->cDes);
    printf("Lenth of Attribute               : %dBytes\n", *((U32*)((U8*)p+4))); /* 이 길이를 알아내면 #2의 위치를 알 수 있다. */
    printf("Non-Resident Attribute           : %s\n", 1==(*((U8*)p+8)) ? "Yes":"No");
    printf("Lenth of Name                    : %d\n", *((U8*)p+9));
    printf("Offset to Name                   : %d\n", *((U16*)((U8*)p+10)));
    printf("Attribute Flags                  : ");
    if ( 0 != (0x0001 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Compressed ");
    }
    if ( 0 != (0x4000 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Encrypted ");
    }
    if ( 0 != (0x8000 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Sparse ");
    }
    if ( 0 == (0xC001 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Nothing");
    }
    putchar('\n');
    printf("Attribute Identifier             : 0x%04X\n", *((U16*)((U8*)p+14)));

    if(0==(*((U8*)p+8)))	// Resident Attribute 
    {
        printf("=== Resident Attribute========================\n");
        printf("====== Size of Content           : %d\n", *((U32*)((U8*)p+16)));
        printf("====== Offset to Content         : %d\n", *((U16*)((U8*)p+20)));
        printf("====== Index Flag                : %s\n", 1==(*((U8*)p+22)) ? "Yes":"No");
        printf("====== Padding                   : 0x%02X\n", *((U8*)p+23)); /* Reserve ㅇ */
        printf("==============================================\n");
    }
    else					// Non-Resident Attribute 
    {
    }
	
    if(0!=(stpAttType->fp))     /* 호출 함수가 있다면 호출 한다. */
    {
        (stpAttType->fp)(    (U8*)p + (*((U8*)p+20))     ); /* 함수 포인터 */
    }
    return (U8*)p + (*((U32*)((U8*)p+4))) ;
}
  • 3번 줄에서 위에서 선언한 MFT_Entry_Attribute_Type * stpAttType 포인터 변수 선언
  • 7번에서 전역으로 선언된 MFT_Attr_Type을 stpAttType에 대입
  • 8번줄에서 무한 루프를 돌면서 해당하는 값이 있는지 찾고 없으면 다음 값으로
  • 20번줄에서 해당 메세지를 출력
  • 58번줄에서 함수포인터 사용여부를 검사하여 호출 또는 넘어간다.

위와 같은 기법을 이용하면 메뉴 호출또는 메세지등을 손쉽게 할 수 있다.


저작자 표시
신고

'컴퓨터 언어 > C' 카테고리의 다른 글

pThread를 이용한 Thread  (0) 2013.03.05
Static 변수  (0) 2013.02.25
메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10


티스토리 툴바