겸손한 개발을 위한 자양분

__try __finally 내부의

__try __except 는 쉽게 예상가능하듯 다음과 같은 실행 순서를 갖는다.

 

     __try{

        __try{
            //Exception Occured!
        }
        __except(EXCEPTION_EXECUTE_HANDLER){
           
        }

       

    }
    __finally{
       
    }

 

 

__try 문 내의 또다른 __try 문에서 Exception 이 발생하면,

Exception 핸들러가 먼저 호출될까 __finally 구문이 먼저 호출될까?

헷갈릴 수 있지만, __finally 가 먼저 호출된다.

 

     __try{

        __try{
            //Exception Occured!
        }
        __finally{
           
        }

        // 실행되지 않는 라인
    }
    __except(EXCEPTION_EXECUTE_HANDLER){
       
    }

 

 

__try 문 안에서 return 을 하면,

return 에 대한 처리 순서는 다음과 같다.

 

 void fnA()
{
   
}


void main()
{
    __try{
       
        return fnA();

    }
    __finally{
       
    }
}

만약, 동기화객체를 사용하는 함수에서,

동기화를 풀기위해 __finally 구문을 사용하고,

내부에서 (동일한 동기화객체를 사용하는) 다른 함수를 호출하며 리턴한다면

Lock 에 의한 문제가 발생할 수 있으므로 주의해야 한다.

 

작업은 관리자 권한의 쉘에서 해야합니다.

 

MakeCert, SignTool 과 같은 Signing Tool 은 Vista 버전 이후의 DDK 에 포함되어있습니다.

 

 

개발 PC

 

1. Test Signing 을 위한 테스트 인증서 생성

 > MakeCert -r -pe -ss MyTestCertStore -n "CN=MyCert" MyCertFile.cer

 

2. 테스트 인증서 설치 

 > CertMgr /add MyCertFile.cer /s /r localMachine root

 

3. Driver Test Signing 

 > SignTool sign /v /s MyTestCertStore /n MyCert /t http://timestamp.verisign.com/scripts/timstamp.dll driver.sys

 

 

테스트 PC

 

1. 개발 PC 에서 생성한 테스트 인증서(MyCertFile.cer) 복사

 

2. 테스트 인증서 설치

 > CertMgr /add MyCertFile.cer /s /r localMachine root

 혹은

 > CertMgr /add MyCertFile.cer /s /r localMachine trustedpublisher

 

3. 테스트 사이닝된 드라이버가 사용 가능하도록 부팅 메니져 설정 

 > Bcdedit -set TESTSIGNING ON

 

4. 재부팅

 

 

 

참고.

http://msdn.microsoft.com/en-us/library/windows/hardware/ff548693(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/hardware/ff553467(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/hardware/ff553563(v=vs.85).aspx

Sharepoint Server 2007 에서, 웹 파트 페이지를 생성하고 문서를 만들면
왼쪽에 나타나는 네비게이션(빠른 실행)이 나타나지 않는다.

Sharepoint Designer 를 이용하여, 페이지를 편집하면 나타나게 할 수 있지만
이 방법은 페이지 마다 해주어야 한다.

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1042\STS\DOCTEMP\SMARTPGS

폴더의 *.aspx 파일들을 열어서

</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderPageImage" runat="server"></asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderLeftNavBar" runat="server"></asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderNavSpacer" runat="server"></asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

붉은 색으로 표시된 열을 삭제하면, 모든 웹 파트 페이지에서 빠른실행을 볼 수 있게 된다.

마찬가지로,
기본페이지 에 빠른실행을 나타내려면

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1042\STS\DOCTEMP\BLANKPGS

의 aspx 파일을 수정하면 된다.

함수원형

 

__declspec(naked) LRESULT __stdcall NtUserMessageCall(

    HWND        hwnd,

    UINT        msg,

    WPARAM      wParam,

    LPARAM      lParam,

    ULONG_PTR   xParam,

    DWORD       xpfnProc,

    BOOL        bAnsi )

 

NtUserMessageCall … SendMessage 에 해당하는 시스템 서비스던가…? 기억력 감퇴;;

 

어찌되었든, NtUserMessageCall 에서의 메시지 처리는 xpfnProc 인자를 통해 이뤄집니다.

해당 인자는 Message를 처리해야 하는 win32k 의 처리 procedure 를 가리킵니다.

 

 

확인을 해보면,

가령 NtUserMessageCall 을 호출하는 RealDefWindowProcWorker 의 경우

.text:77D7AEB2 loc_77D7AEB2:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)-81C1j

.text:77D7AEB2                                         ; RealDefWindowProcWorker(x,x,x,x,x)+B2C9j ...

.text:77D7AEB2                 push    [ebp+lpMultiByteStr]

.text:77D7AEB5                 push    2B0h         // FNID_SENDMESSAGEEX

.text:77D7AEBA                 push    0

.text:77D7AEBC                 push    0

.text:77D7AEBE                 push    [ebp+hMem]

.text:77D7AEC1                 push    128h

.text:77D7AEC6

.text:77D7AEC6 loc_77D7AEC6:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)-81CAj

.text:77D7AEC6                                         ; RealDefWindowProcWorker(x,x,x,x,x)+3029Fj

.text:77D7AEC6                 push    ebx

.text:77D7AEC7                 jmp     loc_77D4C756

 

.text:77D4C756 loc_77D4C756:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)+2FE07j

.text:77D4C756                 call    ds:_gapfnScSendMessage ; NtUserMessageCall(x,x,x,x,x,x,x)

xpfnProc 0x2B0h

 

.text:77D4B2A5 loc_77D4B2A5:                           ; CODE XREF: RealDefWindowProcWorker(x,x,x,x,x)+38j

.text:77D4B2A5                 cmp     edi, 400h

.text:77D4B2AB                 push    [ebp+lpMultiByteStr] ; int

.text:77D4B2AE                 push    29Eh          // FNID_DEFWINDOWPROC

.text:77D4B2B3                 push    0               ; int

.text:77D4B2B5                 push    [ebp+hMem]      ; hMem

.text:77D4B2B8                 push    dword ptr [ebp+WideCharStr] ; int

.text:77D4B2BB                 push    edi             ; int

.text:77D4B2BC                 push    eax             ; int

.text:77D4B2BD                 jnb     loc_77D7AB10

.text:77D4B2C3                 xor     ecx, ecx

.text:77D4B2C5                 mov     cl, ds:_MessageTable[edi]

.text:77D4B2CB                 and     ecx, 3Fh        ; int

.text:77D4B2CE                 call    ds:_gapfnScSendMessage[ecx*4] ; NtUserMessageCall(x,x,x,x,x,x,x)

xpfnProc 0x29Eh

 

위의 두 부분에서 NtUserMessageCall 을 호출하고 있으며,

이때, NtUserMessageCall 에서는 이를 다음과 같이 처리합니다.

bf834b50 8b4d1c          mov     ecx,dword ptr [ebp+1Ch] // xpfnProc

bf834b53 83c106          add     ecx,6

bf834b56 83e11f          and     ecx,1Fh

bf834b59 ff7518          push    dword ptr [ebp+18h]

bf834b5c 50              push    eax

bf834b5d ff7510          push    dword ptr [ebp+10h]

bf834b60 ff750c          push    dword ptr [ebp+0Ch]

bf834b63 ff7508          push    dword ptr [ebp+8]

bf834b66 a158859abf      mov     eax,dword ptr [win32k!gpsi (bf9a8558)]

bf834b6b ff54880c        call    dword ptr [eax+ecx*4+0Ch]

 

위의 어셈 코드에서, 호출되는 procedure 의 주소를 보면,

bc5d0650  00200031

bc5d0654  00000000

bc5d0658  00000155

bc5d065c  bf90ade2 win32k!xxxWrapSBWnd16Proc

bc5d0660  bf80f420 win32k!xxxWrapRealDefWindowProc

bc5d0664  bf86a712 win32k!xxxWrapMenuWindowProc

bc5d0668  bf915448 win32k!xxxWrapDesktopWndProc

bc5d066c  bf80f420 win32k!xxxWrapRealDefWindowProc    >> (29E+6) & 1F

bc5d0670  bf80f420 win32k!xxxWrapRealDefWindowProc

bc5d0674  bf8cb6f2 win32k!xxxWrapSwitchWndProc

bc5d0678  bf942a7c win32k!xxxUnusedFunctionId

bc5d067c  bf942a7c win32k!xxxUnusedFunctionId

bc5d0680  bf942a7c win32k!xxxUnusedFunctionId

bc5d0684  bf942a7c win32k!xxxUnusedFunctionId

bc5d0688  bf942a7c win32k!xxxUnusedFunctionId

bc5d068c  bf942a7c win32k!xxxUnusedFunctionId

bc5d0690  bf942a7c win32k!xxxUnusedFunctionId

bc5d0694  bf942a7c win32k!xxxUnusedFunctionId

bc5d0698  bf942a7c win32k!xxxUnusedFunctionId

bc5d069c  bf90b699 win32k!fnHkINLPCWPEXSTRUCT

bc5d06a0  bf92f155 win32k!fnHkINLPCWPRETEXSTRUCT

bc5d06a4  bf942a7c win32k!xxxUnusedFunctionId

bc5d06a8  bf942a7c win32k!xxxUnusedFunctionId

bc5d06ac  bf942a7c win32k!xxxUnusedFunctionId

bc5d06b0  bf942a7c win32k!xxxUnusedFunctionId

bc5d06b4  bf831785 win32k!xxxWrapSendMessage          >> (2B0+6) & 1F

bc5d06b8  bf8a003f win32k!xxxSendMessageFF

bc5d06bc  bf82eedc win32k!xxxSendMessageEx

bc5d06c0  bf89ef23 win32k!xxxWrapCallWindowProc

bc5d06c4  bf8622d9 win32k!xxxWrapSendMessageBSM

bc5d06c8  bf942a7c win32k!xxxUnusedFunctionId

bc5d06cc  bf942a7c win32k!xxxUnusedFunctionId

bc5d06d0  bf82f3dd win32k!xxxWrapSendNotifyMessage

bc5d06d4  bf82f461 win32k!xxxWrapSendMessageCallback

bc5d06d8  bf942a7c win32k!xxxUnusedFunctionId

bc5d06dc  bf90a41b win32k!xxxSBWndProc

bc5d06e0  bf80d027 win32k!xxxDefWindowProc

bc5d06e4  bf865f56 win32k!xxxMenuWindowProc

bc5d06e8  bf87fac4 win32k!xxxDesktopWndProc

bc5d06ec  bf80d027 win32k!xxxDefWindowProc

bc5d06f0  bf80d027 win32k!xxxDefWindowProc

 

위와 같이 메시지를 처리하는 실제 procedure 들의 주소가 담긴 테이블을 확인할 수 있으며,

RealDefWindowProcWorker 가 호출하는 0x2B0, 0x29E 인자에 대응하는 실제 procedure 를 찾을 수 있습니다.

 

다음은 xpfnProc에 대응하는 FNID 값입니다.

#define FNID_START                  0x0000029A

#define FNID_WNDPROCSTART           0x0000029A

 

#define FNID_SCROLLBAR              0x0000029A      // xxxSBWndProc;

#define FNID_ICONTITLE              0x0000029B      // xxxDefWindowProc;

#define FNID_MENU                   0x0000029C      // xxxMenuWindowProc;

#define FNID_DESKTOP                0x0000029D      // xxxDesktopWndProc;

#define FNID_DEFWINDOWPROC          0x0000029E      // xxxDefWindowProc;

 

#define FNID_WNDPROCEND             0x0000029E      // see PatchThreadWindows

#define FNID_CONTROLSTART           0x0000029F

 

#define FNID_BUTTON                 0x0000029F      // No server side proc

#define FNID_COMBOBOX               0x000002A0      // No server side proc

#define FNID_COMBOLISTBOX           0x000002A1      // No server side proc

#define FNID_DIALOG                 0x000002A2      // No server side proc

#define FNID_EDIT                   0x000002A3      // No server side proc

#define FNID_LISTBOX                0x000002A4      // No server side proc

#define FNID_MDICLIENT              0x000002A5      // No server side proc

#define FNID_STATIC                 0x000002A6      // No server side proc

 

#define FNID_IME                    0x000002A7      // No server side proc

#define FNID_CONTROLEND             0x000002A7

 

#define FNID_HKINLPCWPEXSTRUCT      0x000002A8

#define FNID_HKINLPCWPRETEXSTRUCT   0x000002A9

#define FNID_DEFFRAMEPROC           0x000002AA      // No server side proc

#define FNID_DEFMDICHILDPROC        0x000002AB      // No server side proc

#define FNID_MB_DLGPROC             0x000002AC      // No server side proc

#define FNID_MDIACTIVATEDLGPROC     0x000002AD      // No server side proc

#define FNID_SENDMESSAGE            0x000002AE

 

#define FNID_SENDMESSAGEFF          0x000002AF

#define FNID_SENDMESSAGEEX          0x000002B0

#define FNID_CALLWINDOWPROC         0x000002B1

#define FNID_SENDMESSAGEBSM         0x000002B2

#define FNID_SWITCH                 0x000002B3      // Just used by GetTopMostInserAfter

#define FNID_TOOLTIP                0x000002B4

#define FNID_END                    0x000002B4