최대전절을 유저모드에서 알아채기 Detect Hibernation from User Mode - jialg 16-Mar-09 05:12:32
Good morning David
예전에 유저모드에서 스탠바이와 최대절전을 어떻게 구분하느냐는문제를 다뤄본 적이 있다. 제품 그룹은 디자인적으로 유저모드는 두가지 슬립상태를 구분할 수 없도록 되어 있다고 말했다. 그래서 우린 필요한작업에 맞추어 이 이슈를 피해가도록 했다. 즉, 고객이 왜 최대절전모드를 훅해야 하느냐? 이벤트 말고 같은 결과를 가져다 줄 방법은 없겠느냐? [후략]
I once dealt with a similar case about how to distinguish standby vshibernation in user-mode. The product group's comment on that case was that it is by-design that user-mode cannot tell the difference between thedifferent sleep states. We therefore researched and managed to work around the issue based on the underlying business needs, i.e. why does the customer need to hook the hibernation event? Is there any methods to achieve the same result without the event? David, you mentioned that youneed to perform an action that is required to occur to ensure proper startup from hibernation. May I suggest that you provide with us more info of the action? I will perform the researches from this angle.
WM_POWERBROADCAST / PBT_APMSUSPEND 이벤트는 스탠바이와 최대절전 두가지에들어갈 때 뿌려진다. 윈도우 비스타 이전 시스템에서 시스템이 서스펜드로 들어가기 전의 이벤트 시퀀스는
WM_POWERBROADCAST / PBT_APMSUSPEND events are sent for both Stand-by andHibernation cases. Before Windows Vista, when the system is suspended (either Standby or Hibernate), the sequence of events is
스탠바이와 최대절전의 이벤트 시퀀스는 동일하다. 그래서, 이벤트로는 두 슬립모드를 구분할 수 없다. 한가지 차이점이라면, "스탠바이" 상태일 때에는 PBT_APMRESUMESUSPEND 가 PBT_APMRESUMEAUTOMATIC 뒤따라 올 수도 있다는 것이다. PBT_APMRESUMESUSPEND 은 시스템 리줌이 사용자 입력때문에 일어났다는 걸 알려주는 이벤트이다.
The sequence of events for Standby and Hibernation is identical, thus, theevents cannot distinguish the two sleep modes. One difference between the two cases is that, if it is "StandBy", you may get the eventPBT_APMRESUMESUSPEND after PBT_APMRESUMEAUTOMATIC. PBT_APMRESUMESUSPEND indicates that the resume is triggered by user input, such as pressing a key.
The SYSTEM_POWER_STATE enumeration mentioned by Mike is actually a kernelmode data structure: http://msdn.microsoft.com/en-us/library/bb264568.aspx So it does not help in your user-mode code, either.
슬립, 스탠바이, 최대절전, 파워 상태변화, 로우 배터리, 긴급 중지, AC 파워, 배터리 파워, 배터리 라이프 등의 OS 이벤트에 대한 코드프로젝트 기사가 있다.
Here is a relevant codeproject article about the OS events like Sleep, Stand-by, Hibernate, Power Status Changed, Low Battery, Critial Suspend, AC Power, Battery Power, Battery Life. http://www.codeproject.com/KB/system/OSEvents.aspx
Regards, Jialiang Ge (jialge@online.microsoft.com, remove 'online.') Microsoft Online Community Support
Delighting our customers is our #1 priority. We welcome your comments and suggestions about how we can improve the support we provide to you. Please feel free to let my manager know what you think of the level of service provided. You can send feedback directly to my manager at: msdnmg@microsoft.com.
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 2 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
시스인터널즈 툴 중에 재미있는 게 있다. vmmap 이라는 툴로, 특정 프로세스가 사용하는 가상주소공간을 지금 어떤 것이 얼마나 사용되고 있는지를 나타내 주는 툴이다. 색색깔로 예쁘게 서로 다른 의미로 사용되는 것을 다르게 보여줘서 아주 좋다.
이 툴을 가지고 이것저것 살펴보다가 이상한 것을 발견했다. 아래 그림에서 반전시킨 부분이다.
뭐가 이상하다고 하는 거냐면, 다시 위쪽 부분을 보자.
메모리의 종류에는 Private 이라고 노란색으로 표시된 것이 있는데, 이렇게 딱지가 붙은 것은 다른 프로세스와 공유되지 않는 자기 자신만 사용할 수 있는 그야말로 "개인적인", "자기만의" 공간이다. 그런데, 각 메모리 종류에 대해 상세하게 워킹셋(WS)을 구분하여 보여주는 곳에는 Private, Shareable 이라는 항목으로 나뉘어 보여지고 있으며, 이 Private 이란 곳에 할당되어 사용되는 것 중에서 4K가 Shareable WS 으로 할당되어 있다.
Private 이라면, 자기가 사용하는 모든 것이 Private WS 이어야 하지 않나? Shareable 메모리 타입은 예상대로 모든 WS이 Shareable WS 으로 할당되어 있다.
좀 더 상세한, 아래쪽 패널을 보면,
메모리의 가장 마지막 Private 부분에 Shareable WS 을 갖는 섹션이 있는 걸 알 수 있다.
어떻게 이런 모순적인 게 발생할 수 있는 것인가? 알고싶다. 대답을 아는 분이 이 글을 읽는다면, 댓글을 달아주길 바란다.
워크그룹 머신에서 AD 도메인으로 연결하기 - 조 캐플란 Connecting to an AD domain from a workgroup machine - Joe Kaplan 15-Jun-07 09:34:01
이런 문제(*1)는 워크그룹 컴퓨터를 적용할 때 많이 나오는 문제입니다. 바인딩 문자열로 사용한 LDAP://rootDSE 는 서버나 도메인을 ( LDAP://domain.com/rootDSE 처럼 ) 지정하고 있지 않습니다. 그래서, LDAP API는 도메인은 현재 보안 컨텍스트에서 연결된 도메인에 기반하여 알아내려 합니다. 그러나, 로컬 계정일 경우에는, 연결된 도메인이 없기 때문에 이와 같은 에러를 얻게 되는 것입니다.
All of these problems are typical of a workgroup computer deployment. Your binding string, LDAP://rootDSE, does not specify a server or domain in the path (like LDAP://domain.com/rootDSE), so the LDAP API attempts to figure out the domain to use based on the domain affiliation of the current security context. If that is a local machine account, then there is no domain affiliation and you get the error you see.
The error regarding not being able to convert the datatype happens when the current security context does not have permissions to read the abstract schema in the directory (object pointed to by the subschemaSubentry DN in rootDSE), so it falls back to a default schema which does not have definitions for all AD attributes. To correct this, you must bind as an authenticated domain user, so you would need to provide credentials somehow.
LogonUser can only allow users to logon who are trusted by the machine and a workgroup machine doesn't trust domain users, so they can't logon. You would need to use some sort of approach for remote authentication using SSPI or perhaps an LDAP bind.
Joe K.
-- Joe Kaplan-MS MVP Directory Services Programming Co-author of "The .NET Developer's Guide to Directory Services Programming" http://www.directoryprogramming.net --
(*1) However, it now fails with the error 0x8007054b - 'The specified domain either does not exist or could not be contacted.'
김성우씨의 네트워크 프로그래밍 책의 예제에 기반한 CPP 프로그램을 실행하면서 프로세스 익스플로러로 핸들을 확인했다. 예제는 아주 간단하게 소켙을 만들었다가, 다시 죽이는 것이었고, 내가 수정한 부분은 소켓을 만들었다, 닫는 작업을 반복해 보는 것이었다.
WSAStartup 함수가 실행된 직후이다. 프로그램의 시작부분이라서 쓰레드가 하나 만들어 지는 것 같고, 레지스트리 키 두개를 읽나부다.
레지스트리 키 명을 확인해 보면 HKLM\SYSTEM\ControSet001\Services\WinSock2\Parameters\NameSpace_Catalog5 와 HKLM\SYSTEM\ControlSet001\Services\WinSock2\Parameters\Protocol_Catalog9 이다.
처음으로 socket 함수가 실행되면서, 생성됐다. \Device\Afd 가 만들어졌다. 쓰레드 핸들은 왜 또 하나가 늘어났는지 모르겠다. 위쪽에 있는 (2944): 1612 쓰레드는 디버거인 비주얼 스튜디오의 것이다.
윈도우즈 인터널즈의 Afd에 대한 설명을 인용하자. 윈도우즈 인터널즈 4판 13장 네트워킹
명명된 파이프와 메일슬롯 API처럼 윈속은 Windows I/O 모델과 통합하고 소켓을 나타내기 위해 파일 핸들을 사용한다. 이 지원은 커널 모드 파일 시스템 드라이버의 도움을 필요로 하므로, Msafd.dll은 소켓 기반 함수를 구현하기 위해 보조 함수 드라이버(AFD; Ancillary Function Driver, \Windows\System32\Drivers\Afd.sys)의 서비스를 사용한다. AFD는 TDI 클라이언트이고, TDI IRP를 프로토콜 드라이버에 전송하여 메시지를 보내고 받는 것과 같은 네트워크 소켓 작업을 수행한다.
closesocket 을 하면서 \Device\Afd 가 죽는다. 위에서 생성됐던 쓰레드 핸들은 안 닫힌다. 왜지?
루프른 돌면서 다시 socket 을 했을 때에는 \Device\Afd 만 생성된다. 처음에 생성될 때 열었던 쓰레드 핸들을 다시 열지는 않는다. 루프를 도는 동안, 계속 저 \Device\Afd 만 만들어졌다, 죽었다를 반복한다.
WSACleanup 을 하면서, WSAStartup 에서 열었던 레지스트리키 핸들을 닫는다.
간단한 서버 샘플 프로그램을 디버그모드로 돌리면서, 어떻게 핸들이 생성되는지를 process explorer 로 살펴봤다. 아울러 tcpview 로도 언제 뜨는지를 확인해 봤다. 캡쳐한 그림을 참조.
winsock 초기화. Procexp 핸들 화면을 보면, 아무런 핸들도 생성되지 않았다.
socket 함수가 성공했다. \Device\Afd 핸들이 하나 생성되었음을 확인할 수있다. 아직 소켓만 생성된 상태이고, 이름은 바인드되지 않은 상태이다.
bind 함수가 성공하면서, \Device\Tcp 핸들이 하나 생성된다.
listen 이 성공하면서, \Device\KsecDD 핸들이 생성되고, 드디어 tcpview 에도 Server.exe 가 9000 포트로 LISTENING에 들어갔다는 게 뜬다.
WINDOWS INTERNALS 4판 8장 보안에 다음과 같은 설명이 있다.
커널 보안 장치 드라이버(KSecDD) : 암호화 파일 시스템 같은 커널 모드 보안 구성요소들이 사용자 모드의 Lsass와 통신하는 데 필요한 로컬 프로시저 호출(LPC) 인터페이스를 구현하는 커널 모드 라이브러리. KSecDD는 \WIndows\System32\Drivers\Ksecdd.sys에 들어있다.
이 세가지 핸들들이 언제 생성된다는 것 까진 이제 알았다. 근데 정작 이들이 뭘하는 애들인지는 잘 모르겠다. 클라이언트 쪽에서는 어떻게 생성되는지도 모르겠고.
이제 이 핸들들이 언제 죽는지도 살펴보고, 클라이언트에서는 핸들이 어떻게 만들어지는지 확인해 보는 재미있는 작업을 해 봐야겠다.
Nirsoft 에는 재미있는 툴들이 많이 있다. 이 중에 RegDllView (등록된 DLL 뷰어)란 툴이 있다. 우선 캡쳐화면을 보면 :
현재 시스템에 등록되어 있는 dll/ocx/exe 파일등을 보여주는 툴이다. 액티브엑스를 만들어 테스트할 때, 새로운 버전이 돌고 있는지, 이전 것이 돌고 있는지 헷갈릴 경우가 있었는데, 이 툴을 사용하면, 현재 틍록된 파일의 패쓰까지 보여주고, 등록날짜/시점까지 보여주니까 그런 혼동을 줄일 수 있을 것이다.
이뿐 아니라, CCleaner 에서도 찾아주기는 하지만, 등록은 되어 있는데, 등록된 실제 파일은 존재하지 않는 것도 쉽게 찾을 수 있고, 또, 프로그램 상에서 등록해제도 가능하니까 그 용도로도 쓸 수 있겠다.