당연하지만 헷갈리는 __try 문 호출 순서
__try __finally 내부의
__try __except 는 쉽게 예상가능하듯 다음과 같은 실행 순서를 갖는다.
__try{ __try{ ③ } |
__try 문 내의 또다른 __try 문에서 Exception 이 발생하면,
Exception 핸들러가 먼저 호출될까 __finally 구문이 먼저 호출될까?
헷갈릴 수 있지만, __finally 가 먼저 호출된다.
__try{ __try{ // 실행되지 않는 라인 |
__try 문 안에서 return 을 하면,
return 에 대한 처리 순서는 다음과 같다.
void fnA()
} |
만약, 동기화객체를 사용하는 함수에서,
동기화를 풀기위해 __finally 구문을 사용하고,
내부에서 (동일한 동기화객체를 사용하는) 다른 함수를 호출하며 리턴한다면
Lock 에 의한 문제가 발생할 수 있으므로 주의해야 한다.
Driver Test Signing 및 테스트 PC 설정 방법
작업은 관리자 권한의 쉘에서 해야합니다.
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
SharepointServer 웹 파트 에서 빠른 실행 보이는법
왼쪽에 나타나는 네비게이션(빠른 실행)이 나타나지 않는다.
Sharepoint Designer 를 이용하여, 페이지를 편집하면 나타나게 할 수 있지만
이 방법은 페이지 마다 해주어야 한다.
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1042\STS\DOCTEMP\SMARTPGS
폴더의 *.aspx 파일들을 열어서
<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 파일을 수정하면 된다.
NtUserMessageCall 내부에서의 메세지 처리
함수원형
__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 |