MSI카페에 올린 김에 간만에 블로그에 글도 쓸 겸해서 올리는,
이번에 구입한 MSI의 게이밍고사양 노트북을 2주간 사용해본 소감입니다. 

 

1. 소음과 발열

CPU 또는 GPU 풀 로드시 미칠듯한 발열까지는 아니더라도
다소 부담스러운 발열이 발생합니다.

노트북 자체의 온도가 느리지만 꾸준한 속도로 올라가면서 쿨러가
점점 빠르게 돌게되고, 이것이 소음의 주 원인이 됩니다.

문명5를 창모드로 켠 상태에서 GPU-Z로 그래픽 카드 온도를 계속 살펴보았는데
GPU사용률 95%를 쭉 유지하면서 거의 10분에 1~2도 정도 씩 꾸준하게 올라갑니다.

76도쯤 되었을 때 잠시 터보팬을 켜봤는데 약 2~3분 정도 걸려서
69도 이하로 떨어지는 모습을 확인할 수 있었습니다.

한 5분쯤 지나니까 66도까지 떨어졌습니다만,
터보 팬을 계속해서 켤만한 인내심이 바닥나서 꺼버렸습니다(...)

반대로 단순한 문서 작업 (오피스/PDF) 정도로 부하가 적을 경우에는 팬이 꽤 조용하게
돌아가고 GPU온도도 45~50도 내외로 나름 안정적인 온도를 유지하더군요.
대신 터보 켜면 5~8도 정도 더 올라가는 듯 합니다.

물론 GT680이나 GX660같은 제품들이 워드 문서 작성하라고 있는 건 아닙니다만
어쨋든 적어도 필요에 의해서 쿨링이 적절히 조절되는 모습을 볼 수 있었습니다. 

 

2. 성능

네, 흡족합니다.

데스크탑 대용으로 쓸 수 있는 성능에 적절한 가성비는 크고 아름다운(...)
외적인 단점이 눈에 안들어오게 해줍니다.

어지간한 게임은 다 풀옵이나 하이옵으로 돌아가서 주인에게 뭘 할지 햄볶는 고민을 쥐어줄만큼
구입하신 거의 모든 분들이 동의하시는 부분이 바로 이 성능이죠. 

제가 최근에 즐기는건 더 길드2 / 스타2 / 문명5 / Anno 1404로 모두 잘 돌아갑니다.
제가 온라인 게임을 즐기지 않아서 최근의 게임들을 못 돌려본게 아쉬울만큼요. 

발열 소음 살짝 포기하고 터보 모드를 켜면 어지간한 데탑이 부럽지 않고,
95W짜리 벽돌 어댑터도 요즘 데탑의 그 전력 소모를 생각해보면 나름 이뻐보입니다.(...)

노트북 치고는 스피커도 괜찮은 수준이며 단점으로 꼽히는 LCD패널도
실제 사용 시에는 생각만큼 큰 문제같지는 않았습니다. 

화면을 연결하거나, 노트북 스탠드 + 무선 키보드 사용 시에는 시야각이 크게 변하지 않게 되는데
노트북에 광시각이 사치긴 합니다만, 그래도 LCD 패널이 좀 저렴해보인다는건 확실한 것 같습니다.

악명 높은 빛 샘 현상으로 결제를 망설이게 했던 MSI입니다만,
G계열은 자사의 하이엔드 브랜드라서 그런지 받자마자 빛 샘 현상이나
패널에 큰 문제가 있다는 글은 아직까지 보지 못했습니다.

 

3.휴대성

역시 크기와 무게 때문에 휴대성은 떨어지는 편입니다. 물론 성능을 고려했을때
이정도의 휴대성도 괜찮다고 해야겠지만 사용자로서는 2% 아쉬운 부분입니다.

그나마 어댑터를 버리고 본체만 들고 다닐 경우에는 그럭저럭 휴대할만 하군요.
용산까지 가는데 40분쯤 걸리는 거리를 옆으로 메고 서있었는데 전 버틸만 하더라고요. 

하지만 역시나 본격적으로 휴대하고 다니시려면 괜찮은 백팩 하나 장만하시는 것이 좋겠습니다.

 

4. 확장성 

USB 3.0 x 2 / 2.0 x 2 / E-Sata / HDMI / D-Sub / 노트북 치고는 풍성한 오디오 단자들
블루투스와 Intel MyWiFi 지원. 웹 캠과 내장 마이크 지원.

스펙은 흐뭇합니다만 한 가지 아쉬운 점이라면 USB 2.0 단자가 양 옆에 각각 하나씩 있어서
Y자 형 USB 케이블을 사용하기가 조금 껄끄럽다는 것입니다.
USB 3.0 단자에 꽂자면 아무래도 좀 아깝죠.

그리고 이 정도의 고 사양 / 고가의 제품인데도 불구하고 켄싱턴 락이 없다는건 좀 의아합니다.
단가 낮추려고 그랬을까요 (...) 

전반적으로 성능에 중심을 둔 제품이지만 그렇다고해서
소음과 발열/ 휴대성을 완전히 무시한 제품도 아닙니다.

예상외로 성능에 비해서 발열이 적은 편이고 
팬 소음이 못 들어줄 정도로 시끄럽지도 않습니다.

가격대 성능비도 발군이고, 용던 고렙존 어느 정도 PC관련 지식이 있는 분들이라면
나름 좋은 제품이 될 것 같군요.

 

번외편. 쿨러 대전 - CoolMaster(Notepal) ErgoStand Vs Zalman ZM NC3000U

 

이 비교 결과가 궁금해서 구글링도 해보고(양키 검색(...) 드래곤마운틴 던전 용산 상가에서 물어도보고심지어 실제로 팬이 돌아가는 곳에 손과 귀를 대보기까지 했으나 직접적인 비교를 할 수 없었습니다.

GT680은 집에서 데탑 대용으로, 홈플러스에서 구입한 접이형 좌식 테이블에 올려놓을 계획이었기에
디스플레이 위치를 고려해서 ErgoStand를 먼저 구입했죠.

구입한 당일 날 온도를 체크해가며 사용해봤는데 나름 만족스러운 편이었습니다.
온도도 7도 정도 떨어지고 뭣보다 거북목에서 탈출했다는게 기쁘더군요. 

그리고 일주일 뒤, 업무용 HP EliteBook 8530p로 가상 PC를 돌리던 중 통풍구가 타버릴 듯한
위협을 느끼고 대책 마련에 나섰습니다만, 청소 안 한지 오래됬는데다가 바이오스 비번 크리로
팬 속도 조절이 안되서 내친 김에 잘만 쿨러를 사러 용던 출격.

일단 집에 들고와서 ErgoStand와 NC3000U 중에 쿨링 성능이 더 좋은 것을 집에 두고
나머지 한 개를 사무실에서 쓰기로 했죠. 

거두 절미하고 결과는
그놈이 그놈입니다. 

터보팬으로 올라간 온도를 급속히 식히면서 두 제품을 세번씩 바꿔서 테스트 해보았으나
ErgoStand가 1~2도 정도 쿨링이 더 되는 반면 최고속에서는 조금 더 시끄럽습니다.

그나마도 ErgoStand는 스탠드 겸용이라 바닥에서 떨어져있다는 점을 감안하면
바닥에 뉘였을 때 두 제품의 차이는 거의 없다고 봐도 좋을 것 같습니다. 

거기에 소음 측면에서는 게임하면 어차피 본체 소음에 쿨러 소음 따위는 90% 묻힙니다.
둘 다 저속모드에서는 소리가 거의 없다시피 한 건 매한가지이므로 실질적인 차이가 꽤 적습니다. 

물론 소음에 제법 민감하다 하시는 분들에게는 잘만을 추천합니다.
아주 정숙한데다가 쿨링 성능도 괜찮은데, 한가지 주의점이라면
17인치용이라서 크다는 점을 감안하셔야 합니다.

기능상 NC3000U는 Y자 케이블과 3개의 USB포트를 지원하고
ErgoStand는 단일 케이블과 4개의 USB포트를 지원합니다만,
여기에도 한가지 생각해볼 문제가 있습니다.

ErgoStand가 단일 케이블이지만 전력 공급에는 문제가 있는데,
로지텍 G700 유무선 마우스를 충전하면서 시게이트 GoFlex를 USB2.0 케이블로 동시에 연결했을 때GoFlex외장하드가 전력 부족으로 괴악한 소리를 내면서 맛이 가는  멈추는 것을 발견했습니다.

반대로 NC3000U의 Y자 케이블을 한 쪽만 노트북에 연결해도 쿨러는 잘만 돌아가고
무선 수신기도 멀쩡히 동작하는 괴악한 모양새를 확인할 수 있었습니다.

둘다 어댑터 별매(이나라의 상도덕)이므로 실질적인 차이는
ErgoStand가 USB 포트가 하나 더 많다는 정도입니다.

사실 노트북에 이것저것 주렁주렁 달아봐야 좋을 것 없기에 
확장 포트는 3개나 4개나 사용 시 큰 차이는 없을 것 같군요.

ErgoStand가 Stand 겸용이고 USB가 하나 많다는 장점이 있다면
NC3000U는 17인치용의 드넓은 크기와 그에 반해 정숙하다는 장점이 있습니다. 

서로의 장점과 단점을 상쇄시킨다고 할 수 있는 제품들이니 만큼
용도에 알맞게 구입하시면 그만인 것 같습니다.

어째 쓰다보니 장문의 리뷰가 되어버렸군요.
그래도 쿨러놓고 고민하시는 분들에게 도움이 되었으면 싶어서 이렇게 글을 올렸습니다.

 

3주 뒤 한달 차에 다시 리뷰를 올려보겠습니다.
사진도 좀 찍고 해서요.

사실 그때는 중고로 팔고 GT780 지를지도(...)

Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

   10 Jul 2009 4:21 PM

I had a question come up in response to another post:

I also have another side effect from this change.  I have a process that tracks processes via JobObjects.  With Vista I had to add a Manifest file to all my processes so PCA would not track them and I could continue to track with my custom tool.  It appears I need to modify the manifests again with a compatibility tag for Windows7.  The problem is I will have to do this for every new OS, or find an alternative to jobObjects.

So, I figured I’d dive in to PCA. Because, believe it or not, it’s even possible for an application compatibility technology to have an application compatibility impact, as this customer discovered! (I’ve said it before – this stuff is really hard.)

You see, the underlying problem is that application compatibility technologies in Windows have to follow the same rules as any other application running on Windows. It’s kind of like The Matrix. We have Agents on the system, trying to keep things working. They have to obey the rules of the system, though they can stretch some of the rules and have a certain mastery of them that many applications wouldn’t have (access to the source and the developers). It’s precisely because we are bound by the same rules that we can land ourselves in trouble.

The Program Compatibility Assistant (PCA) is one such system, and in this example the rules it’s following are the rules of Job objects. Let’s work our way through this system and find out how it hurt our friend and what options he has.

We’ll be making most of our way through the system using Process Explorer to discover what’s going on, so if you have that handy, you can follow along. (I have it as an auto-start program, personally.)

First, we want to elevate Process Explorer if it isn’t running elevated already so we can see some details of system processes.

If you do a handle search for PCA_ it will take you to an instance of svchost.exe, and if you mouse over the exe you’ll see that it is hosting the Program Compatibility Assistance Service [PcaSvc]. In the list of handles for that service, you’ll see a number of handles to Job objects, such as:

\BaseNamedObjects\PCA_{EE416CB2-DD81-4EE5-A3FD-B36EA4503301}

PCA does its monitoring through jobs, and you can see them here. What’s more, you can see them in the process list below. By default, Process Explorer will highlight processes which are enclosed in jobs with a brown color. Double click on one, and you’ll be able to see the job information:

image

OK, so PCA is looking after processes by adding them to a job object. What for? Well, I haven’t reversed this completely, but my (educated) guess would be so that it could leverage JOB_OBJECT_MSG_EXIT_PROCESS to perform its work after the process exits. So far, so good.

But wait … there’s one catch. From the SDK:

“A process can be associated only with a single job.”

Oh, and then there is this:

“After you associate a process with a job, the association cannot be broken.”

Ah. Well, that kind of puts some sand in the ointment. Anything launched using ShellExecute(Ex) that doesn’t meet the PCA exclusion criteria is going to be assigned to a PCA job, and that means you can’t assign them to another job. Effectively, we just took back part of the platform from you. (Caveat – if you called ShellExecute with SEE_MASK_FLAG_NO_UI, then you would not have PCA applied.)

OK, so what can our friend who wants to use job objects do now?

Well, one option is to manifest everything that they want to track with a Windows 7 manifest. (Yes, there is a bitter irony that, in order to support an application compatibility technology designed to keep things unchanged working on current versions of Windows you have to change some things.) Of course, that also means that, if we changed nothing about the implementation, you’d have to do that again with every new version of Windows if you want to use job objects – not cool. So, what else can you do?

If you can control the creation of processes, then you can wiggle right out of PCA.

In addition to the ShellExecute escape hatch mentioned above, CreateProcess lets you specifically opt out of inheriting a job, assuming that the job allows you to (which the PCA job does). Let’s see.

First, I can create an app that serves as my launcher. It will get the PCA job applied to it, as a non-Windows 7-manifested application. But I’m not worried about it – I’m worried about the child processes that my job is going to be watching over. So, let’s create a job object:

HANDLE myJob;
myJob = CreateJobObject(NULL, TEXT("JobsAndPca"));

I’m going to elide the CreateProcess setup and cleanup work, and instead just dive right in to creating a process and assigning it to a job. Without PCA monitoring, here’s what I’d have:

if (CreateProcess(szPath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
    if (AssignProcessToJobObject(myJob, pi.hProcess)) {
        // Success! (I don’t get here)
    } else {
        // Failure – couldn’t add to job (I probably get here)
    }
} else {
    // Failure – couldn’t create the process (I probably don’t get here)
}

So, I’ve just reproduced the failure – I can’t get in there with a job. However, if I create my process differently, I can:

if (CreateProcess(szPath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi)) {
    if (AssignProcessToJobObject(myJob, pi.hProcess)) {
        // Success! (I probably get here)
    } else {
        // Failure – couldn’t add to job (I probably don’t get here)
    }
} else {
    // Failure – couldn’t create process (I probably don’t get here)
}

So, our final answer is:

If you are the creator of the process you want to monitor, then you can escape the PCA job. Otherwise, you’re going to have to re-manifest for Windows 7 compatibility.

We’re already thinking ahead to future versions of Windows, and having just told you to manifest your application for Windows 7, as the app compat team, we don’t want everything to automatically risk breaking again in future versions of Windows because our app compat stuff gets in the way, nor do we want to have to make you change your manifest every time (because, well, that kind of defeats the purpose of app compat if none of your apps are compatible without modification). How do we go about always doing right by everybody? Well, that’s a hard problem. And one that you deserve a great answer for. If the current rules require us to get in your way, then we may very well just have to change the rules…


윈도우 칠득이에서 JobObject로 고민 하던 차에 찾은 포스트 s( =_=)v-~@

출처 : MSDN Blogs > Chris Jackson's Semantic Consonance

Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

가짜 백신 AVE.exe

2010. 3. 24. 09:55

그저께 황당한 일을 겪었습니다.

귀차니즘에 데스크탑 관리를 안했더니 바이러스로 짐작되는 현상이 다수 일어나길래
맥아피를 설치하려고 보니까 셋업 파일이 NotePad로 열립니다.

설상가상으로 실행 창에 cmd나 regedit를 쳐봐도 똑같은 증상이 일어나고
뜬금없이 윈도우 보안센터가 표시되더니 지 혼자서 뭔가 검사를 하고는 백신을 구입하랍니다.

얌마, 한글 윈도운데 뭔 영문 메뉴판이냐 ㄱ-.

...어처구니 없는 이 사기 백신을 어떻게 처리할까 이래저래 수를 내봤습니다.
신종 바이러스 때문에 울며겨자먹기로 포맷하는 거기 당신.
딱 30분 정도만 더 투자해보십시다.

새퀴바이러스가 어떤건지 궁금하시면 1.을 참고하시고 급하시면 2.로 넘어가주시길.



1. 바이러스의 구동 방식.

ave.exe는 사실상 가장 마지막 단계에 실행되는 프로세스로 보입니다.
첫 번째로 구동되는 것은 바이러스 실행파일로 추정되는 aiw3356.exe 라는 파일입니다.
아마도 파일명은 제멋대로겠죠.

이 녀석이 실행되면 각 로컬 디스크 드라이브 루트에 자신을 복제하는 걸로 보입니다.
아니면 제가 같은 놈을 저도 모르게 여러개를 받았겠죠. [..]

내 컴퓨터를 더블클릭하면 바이러스가 깨어나 활동을 시작합니다.
이 녀석은 아래 설명할 드라이버 파일을 시스템에 로드하고
레지스트리를 수정해 내 컴퓨터를 열 때 자신이 실행되도록 만들고
세번 째의 autorun.inf의 실행을 위해서 자동 실행 설정을 건드리는것 같군요.

자신을 포함해 이제부터 설명할 모든 파일들을 숨김 파일로 만들고
레지스트리에서 숨김 파일 보기를 바꿀 수 없게 변경해서
폴더 옵션에서 숨김 파일을 보도록 설정할 수 없게 만들어버립니다.

두 번째로 구동되는 것은 로컬 디스크 드라이브를 CD-ROM인 것 마냥
인식하게 하는 드라이버 파일입니다. 위의 aiw.3356 요녀석이 뱉아내는 듯.

정확한 파일명과 위치가 기억이 안나는데 대충
C:\WINDOWS\system32\config\systemprofile\Application Data\ 폴더에
cdxxx.sys 파일로 저장됩니다.


세번 째로 동작하는게 autorun.inf 파일입니다.
아시는 분은 아실테지만 CD-ROM에 CD를 넣을 때 CD안에 있는 이 파일을 읽어서
파일 안의 내용물이 실행되게 하는 역할을 합니다.

이녀석이 아래 설명할 6b.exe를 실행시킵니다. 물론 이 이름도 제멋대로겠죠 아마.
진짜 문제는 지금부터 입니다.

세번 째의 autorun.inf는 내 컴퓨터에서 주소창으로 들어가던가, 폴더 바로가기를
클릭해서 폴더를 연다던가 여러가지 방법으로 피할 수 있습니다만
6b.exe가 실행되면 레지스트리의 HKEY_CLASSES_ROOT에 .exe 키의 기본 값(ProgID)
을 exefile에서 secfile라는 괴상한 녀석으로 바꿔버립니다.

이때부터는 뭔가 exe파일을 클릭해도 exefile이 아니라 secfile의 실행 방식을 따르게되는데
이 녀석의 실행 키(HKEY_CLASSES_ROOT\secfile\Shell\Open\Command 키의 기본 값)
를 확인해보면 ave.exe /START 를 실행시키는 것을 확인할 수 있습니다.

즉, 사용자가 exe파일을 실행시키는 걸 감지해서 바이러스를 먼저 실행시킨 다음,
바이러스가 exe를 실행시키는 방식입니다.

그나마 여기까지라면 애교로 봐줄만한데[..?] 이 녀석은 Windows\SYSTEM32 폴더에 있는
Notepad.exe를 6b332ab.exe(가칭)으로 복사한 뒤에, 자신의 입맛에 맞는 몇몇 프로그램 외에는
6b332ab.exe로 exe파일을 열어버립니다. 메모장에 알 수 없는 문자가 나열되죠.

아마도 윈도우 기본 프로그램 몇몇 외에는 전부 그런듯합니다.
레지스트리 편집기도 저런식으로 열리기 때문에 멋모르는 사용자는
손가락만 빨고 있다가 삭제도 못하는 가짜 백신이 실행되서
'어익후 바이러스가 검출되었는데 공짜로는 안되겠고 싸게 모실게'
하고 꼬드기는데 넘어가 결제하도록 만드는 그런 물건입니다.



2. 퇴치과정


먼저 Ctrl+Alt+Del 로 작업 관리자를 열어서 ave.exe와 6b332ab.exe(가칭)를 강제 종료 시킵니다.
그런 다음 C:\Windows\SYSTEM32 폴더에서 6b332ab.exe를 찾아서 삭제합니다.
이 녀석은 항상 리젠[..]되므로 폴더를 열어둔 채 보이는 족족 삭제해줍시다.

이 상태로 아무거나 exe 파일 하나를 실행시키면 6b332ab.exe를 찾을 수 없기 때문에
연결 프로그램을 선택하라는 창이 표시됩니다.

exe파일 속성 창의 연결 프로그램을 바꿔도 마찬가지의 창이 표시되겠지만
실제로 바꿀 수 있는지 확인은 못해봤습니다.

C:\Windows\System32 폴더에서 cmd.exe를 찾아서 선택한 뒤에 연결프로그램으로 선택한 뒤
윈도우키+ R로 실행 창을 열고 regedit를 입력해 레지스트리 편집기를 실행합니다.
수단 방법 안가리고 레지스트리 편집기만 실행할 수 있다면 뭐든지 OK.

이쯤에서 바로 백신 프로그램을 설치하셔도 괜찮을 것 같지만
일단 제가 했던 과정 그대로 써보죠.

HKEY_CLASSES_ROOT\.exe 키의 기본 값이 secfile로 되있을겁니다.
exefile로 고쳐줍니다. 혹시나 실수하실 분들을 위해서...값의 형식은 REG_SZ 입니다.

HKEY_CLASSES_ROOT\exefile\Shell\Open\Command\로 가서
기본 값을 "%1" %* 인지 확인합니다. 이상한 실행 파일 경로가 있다면 백방 바이러스니까
폴더 뒤져서 혼내줍시다. 삭제 고고씽 ㄱ-. 기본값을 "%1" %* 로 수정해줍니다.

마찬가지로
HKEY_CLASSES_ROOT\secfile\Shell\Open\Command\로 가서
이상한 경로가 있다면 secfile 키에서 delete를 눌러 통채로 삭제해버립니다.

이 시점에서 슬슬 실시간 감시 기능이 있는 최신의 백신이 필요한데,
저는 간편함 때문에 알약을 선택했습니다.

설치 파일이 2008년 버전인데 업데이트 해야한다던가 하면 잘 안될 수 있으므로 주의요망.
여하튼 웹 브라우저를 실행해서 다운로드를 받던가 USB로 복사해서 백신을 설치합니다.
웹브라우저를 사용한 경우 exe가 한 번 실행되면서 6b332ab.exe가 다시 복사될 수 있으므로
역시 보이는 족족 삭제합니다.

cmd가 백신 셋업 프로그램을 실행해주면 6b332ab.exe가 또 살아났는지 확인하고 삭제해 준뒤에
백신이 깔리는 것을 흐뭇하게 지켜봅시다.

백신 설치가 완료되면 재부팅을 합니다.
이후로는 백신이 알아서 때려잡아줄...것 같기는 개뿔 ㄱ-.

다행히 백신덕택에 실행은 안됩니다만 바이러스 파일로 인식을 안하는건지
치료목록에 뜨는건 1.에서 설명한 cdxxx.sys 드라이버와 autorun.inf 정도군요.
백신이라고 얄짤없어서 숨김 파일 해제도 복구 안해줍니다 쳇 ㄱ-.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
\CurrentVersion\Explorer\Advanced\Folder\Hidden\SHOWALL

...아 길다...하여간 저 키를 찾은 뒤에
CheckedValue 값을 1로 바꿉니다.

이제 폴더 옵션에서 숨김 파일 표시하기를 선택하면 숨김 파일이 나옵니다.
1. 2.를 진행하면서 걸린 새퀴들바이러스들을 다 지워주시면
기나긴 퇴치행도 막을 내립니다.



전 이 새퀴바이러스 덕분에 3시간 가까이 허비해버렸습니다.
똑같은 피해자가 나오지 않았으면 좋겠네요.


Q. 왜 스샷이 없습니까?
A. 내 코가 석잔데 스샷 찍고 앉아있게 생겼습? ㄱ-

Q. 30분이면 된다메?
A. 윈도우 깔 때 몇 분 기다리면 된다는거 시간 지키는거 보셨습니까
    못 봤으면 말을 마세...[퍽]


덧. CD-ROM 드라이버가 감염된 경우 백신으로 치료하는 도중에 드라이버 파일이 삭제되어서
     재부팅 이후 부터 CD-ROIM이 안보이는 경우가 있습니다.
     이럴 경우 드라이버를 다시 설치해줘야 하는데, 보통은 장치 관리자에서 CD-ROM을
     제거한 다음 하드웨어 자동 검색을 사용해서 다시 인식시키면 됩니다.
     이렇게해도 안될 경우에는 드라이버를 직접 설치해주시면 될겁니다. Maybe [..]

Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 111
    2010.03.26 23:31
    댓글 주소 수정/삭제 댓글
    저희 집도 가짜백신때문에 곤란을 겪고있습니다ㅜㅜ 작엽관리자를 열면 6b332ab.exe가 아예 없는데 어떻게하면좋죠ㅜㅜㅜㅜ??
  2. 2010.04.05 13:29 신고
    댓글 주소 수정/삭제 댓글
    헐 며칠 출장 때문에 안봤더니[..]

    일단 업데이트가 가능한 무료백신을 써보세요.
    제 경우와 비슷한 증상을 겪고 계신다면
    백신 성능보다 최신의 업데이트가 중요한 케이스 같네요.

    잘 안될 경우 카스퍼스키나 Nod32를 사용해보시길.
    3개월 정도의 무료버전을 다운 받아서 사용하실 수 있을겁니다 아마.

컴퓨터에서 하드웨어 DEP 사용 가능하고 구성되어 있는지 확인하는 방법

 

소개

DEP(데이터 실행 방지) 악의적인 코드가 실행되는 것을 방지하기 위해 메모리를 추가로 확인하는 하드웨어 소프트웨어 기술입니다.하드웨어 ...

DEP(데이터 실행 방지) 악의적인 코드가 실행되는 것을 방지하기 위해 메모리를 추가로 확인하는 하드웨어 소프트웨어 기술입니다.

하드웨어 적용 DEP 해당 위치에 명시적으로 실행 코드가 포함되어 있는 경우를 제외하고 프로세스의 모든 메모리 위치에서 실행할 없도록 표시합니다. DEP 실행할 없도록 표시된 메모리 위치에서 코드를 삽입하고 실행하려는 악의적인 코드 공격을 차단하고 예외를 발생시키는 방법으로 이러한 공격을 방지합니다.

문서에서는 하드웨어 적용 DEP 사용하기 위한 요구 사항과 Windows에서 하드웨어 DEP 작동하는지 확인하는 방법에 대해 설명합니다.

위로 가기

추가 정보

하드웨어 적용 DEP 사용하기 위한 요구 사항하드웨어 적용 DEP 사용하려면 다음과 같은 조건을 모두 충족해야 합니다. 컴퓨터의 프로세서가...

하드웨어 적용 DEP 사용하기 위한 요구 사항

하드웨어 적용 DEP 사용하려면 다음과 같은 조건을 모두 충족해야 합니다.

1.    컴퓨터의 프로세서가 하드웨어 적용 DEP 지원해야 합니다.

대부분의 최신 프로세서는 하드웨어 적용 DEP 지원합니다. AMD(Advanced Micro Devices) Intel Corporation에서는 DEP 호환되는 Windows 호환 아키텍처를 규정하고 제공하고 있습니다. 이러한 프로세서 지원은 NX(No-eXecute) 또는 XD(eXecute Disable) 기술이라고도 있습니다. 컴퓨터의 프로세서가 하드웨어 적용 DEP 지원하는지 여부를 확인하려면 컴퓨터 제조업체에 문의하십시오.

2.    BIOS에서 하드웨어 적용 DEP 사용할 있도록 설정해야 합니다.

일부 컴퓨터에서는 BIOS에서 하드웨어 적용 DEP 대한 프로세서 지원을 사용할 없도록 설정할 있습니다. 지원을 사용할 없도록 설정하면 됩니다. 지원을 사용할 없도록 설정하는 옵션은 컴퓨터 제조업체에 따라 "Data Execution Prevention", "XD", "Execute Disable" 또는 "NX" 표시될 있습니다.

3.    컴퓨터에 Windows XP 서비스 2 또는 Windows Server 2003 서비스 1 설치되어 있어야 합니다.

참고 32비트 버전 64비트 버전의 Windows 모두 하드웨어 적용 DEP 지원합니다. Windows XP Media Center Edition 2005 Microsoft Windows XP Tablet PC Edition 2005에는 Windows XP SP2 기능과 구성 요소가 모두 포함되어 있습니다.

4.    컴퓨터의 프로그램에 대해 하드웨어 적용 DEP 사용할 있도록 설정해야 합니다.

64
비트 버전의 Windows에서는 기본 64비트 프로그램에 대해 하드웨어 적용 DEP 항상 사용할 있도록 설정되지만 구성에 따라 32비트 프로그램에 대해서는 하드웨어 적용 DEP 사용할 없도록 설정될 있습니다.


DEP, DEP
구성 하드웨어 DEP 지원하는 운영 체제 목록에 대한 자세한 내용은 Microsoft 기술 자료의 다음 문서를 참조하십시오.


875352
  (http://support.microsoft.com/kb/875352/ ) Windows XP 서비스 2 Windows XP Tablet PC Edition 2005 Windows Server 2003 데이터 실행 방지 기능에 대한 상세한 설명


Windows XP
서비스 2에서 메모리 보호를 구성하는 방법에 대한 자세한 내용은 다음 Microsoft 사이트를 참조하십시오.

http://www.microsoft.com/technet/security/prodtech/windowsxp/depcnfxp.mspx (http://www.microsoft.com/technet/security/prodtech/windowsxp/depcnfxp.mspx) (영문)

 

Windows에서 하드웨어 DEP 작동하는지 확인하는 방법

Windows에서 하드웨어 DEP 작동하는지 확인하려면 다음 방법 하나를 사용하십시오.

방법 1: Wmic 명령줄 도구 사용

Wmic 명령줄 도구를 사용하여 DEP 설정을 검사할 있습니다. 하드웨어 적용 DEP 사용할 있는지 여부를 확인하려면 다음과 같이 하십시오.

1.    시작, 실행 차례로 누르고 열기 상자에 cmd 입력한 다음 확인 누릅니다.

2.    명령 프롬프트에서 다음 명령을 입력한 Enter 키를 누릅니다.

wmic OS Get DataExecutionPrevention_Available

"TRUE" 출력되면 하드웨어 적용 DEP 사용할 있습니다.

현재 DEP 지원 정책을 확인하려면 다음과 같이 하십시오.

1.    시작, 실행 차례로 누르고 열기 상자에 cmd 입력한 다음 확인 누릅니다.

2.    명령 프롬프트에서 다음 명령을 입력한 Enter 키를 누릅니다.

wmic OS Get DataExecutionPrevention_SupportPolicy

그러면 값으로 0, 1, 2 또는 3 반환됩니다. 값은 다음 표에서 설명하는 DEP 지원 정책 하나입니다.

DataExecutionPrevention_SupportPolicy 축소표 확대

속성

정책 수준

설명

2

OptIn(기본 구성)

Windows 시스템 구성 요소 시스템에만 DEP 적용됩니다.

3

OptOut

DEP 모든 프로세스에 대해 사용할 있도록 설정됩니다. 관리자는 DEP 적용되지 않는 특정 응용 프로그램 목록을 수동으로 만들 있습니다.

1

AlwaysOn

DEP 모든 프로세스에 대해 사용할 있도록 설정됩니다.

0

AlwaysOff

DEP 모든 프로세스에 대해 사용할 없도록 설정됩니다.

참고 Windows에서 하드웨어 적용 DEP 사용할 있도록 설정되어 있는지 확인하려면 Win32_OperatingSystem 클래스의 DataExecutionPrevention_Drivers 속성을 조사하십시오. 일부 시스템 구성에서는 Boot.ini 파일에서 /nopae 또는 /execute 스위치를 사용하여 하드웨어 DEP 사용할 없도록 설정할 있습니다. 속성을 확인하려면 명령 프롬프트에서 다음 명령을 입력하십시오.

wmic OS Get DataExecutionPrevention_Drivers

 

방법 2: 그래픽 사용자 인터페이스 사용

그래픽 사용자 인터페이스를 사용하여 DEP 사용할 있는지 여부를 확인하려면 다음과 같이 하십시오.

1.    시작, 실행 차례로 누르고 열기 상자에 wbemtest 입력한 다음 확인 누릅니다.

2.    WMI 테스터 대화 상자에서 연결 누릅니다.

3.    연결 대화 상자의 위에 있는 상자에 root\cimv2 입력한 다음 연결 누릅니다.

4.    인스턴스 열거 누릅니다.

5.    클래스 정보 대화 상자의 수퍼클래스 이름 입력 상자에 Win32_OperatingSystem 입력한 다음 확인 누릅니다.

6.    쿼리 결과 대화 상자에서 위에 있는 항목을 누릅니다.

참고 항목의 이름은 "Win32_OperatingSystem.Name=Microsoft..." 시작합니다.

7.    개체 편집기 대화 상자의 속성 영역에서 DataExecutionPrevention_Available 속성을 찾습니다.

8.    DataExecutionPrevention_Available 누릅니다.

9.    속성 편집기 대화 상자에서 상자에 있는 값을 확인합니다.

값이 TRUE이면 하드웨어 DEP 사용할 있습니다.


참고

·         DEP 실행 모드를 확인하려면 Win32_OperatingSystem 클래스의 DataExecutionPrevention_SupportPolicy 속성을 조사하십시오. 방법 1 끝에 있는 표에는 지원되는 정책 값에 대한 설명이 나와 있습니다.

·         Windows에서 하드웨어 DEP 사용할 있도록 설정되어 있는지 확인하려면 Win32_OperatingSystem 클래스의 DataExecutionPrevention_Drivers 속성을 조사하십시오. 일부 시스템 구성에서는 Boot.ini 파일에서 /nopae 또는 /execute 스위치를 사용하여 하드웨어 DEP 사용할 없도록 설정할 있습니다.

문서에 나와 있는 다른 공급업체 제품은 Microsoft 무관한 회사에서 제조한 것입니다. Microsoft 이러한 제품의 성능이나 신뢰성에 관하여 명시적이든 묵시적이든 어떠한 보증도 하지 않습니다.



Microsoft
제품 관련 기술 전문가들과 온라인으로 정보를 교환하시려면 Microsoft 뉴스 그룹 (http://support.microsoft.com/newsgroups/default.aspx) 참여하시기 바랍니다.

위로 가기


문서의 정보는 다음의 제품에 적용됩니다.

·         Microsoft Windows Server 2003 Service Pack 1 () 다음과 함께 사용했을

 o    Microsoft Windows Server 2003, Datacenter Edition (32-bit x86)

 o    Microsoft Windows Server 2003, Enterprise Edition (32-bit x86)

 o    Microsoft Windows Server 2003, Standard Edition (32-bit x86)

 o    Microsoft Windows Server 2003, Web Edition

 o    Microsoft Windows Server 2003, Datacenter Edition for Itanium-Based Systems

 o    Microsoft Windows Server 2003, Enterprise Edition for Itanium-based Systems

 

·         Microsoft Windows XP Service Pack 2 () 다음과 함께 사용했을

 o    Microsoft Windows XP Professional

 o    Microsoft Windows XP Home Edition

 o    Microsoft Windows XP Media Center Edition

 o    Microsoft Windows XP Professional x64 Edition

 o    Microsoft Windows XP Tablet PC Edition

 o    Microsoft Windows XP Tablet PC Edition 2005

 o    Microsoft Windows XP for Itanium-based Systems Version 2003

 o    Microsoft Windows XP Professional 64-Bit Edition (Itanium)

 o    Microsoft Windows XP Media Center Edition 2004

 o    Microsoft Windows XP Media Center Edition 2005

 

키워드 : kbhowto kbinfo kbsecurity kbexpertiseinter KB912923

Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

LPVOID lpMsgBuf;
 FormatMessage(
  FORMAT_MESSAGE_ALLOCATE_BUFFER |
  FORMAT_MESSAGE_FROM_SYSTEM |
  FORMAT_MESSAGE_IGNORE_INSERTS,
  NULL,
  GetLastError(),
  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  (LPTSTR) &lpMsgBuf,
  0,
  NULL
 );
 MessageBox( NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
 LocalFree( lpMsgBuf );
Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

어지간하면 포스팅 안하려고 했는데 이거 원....
보고 어이가 없어서 장광설을 늘어놓기 전에 갈무리.
양심이 있어야지...

티맥스라는 기업도 문제지만 교묘하게 본질적인 문제를 가리려는
저런 수작들도 마음에 안듭니다.

자신의 부하직원이 일에 치여서 이혼한건 절대 자랑이 아니올시다 이양반들아.
IT업체 이전에 그 구성원인 개발자는 아주 뒷전에 처밖아두셨어들.

한가지만 더, React OS는 샘플링만 한건가?
오픈 소스진영에서 소송을 준비한다는 소문이 있던데 실제로 어떻게 될진 모르겠습니다.

http://economysegye.segye.com/articles/view.html?aid=20090903003110&cid=7113010000000
Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


Gurps 4판/ 국문 2판의 캐릭터 시트입니다.

시트 툴은 언제 MFC로 컨버전하나[..]



Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

Getting the System Version

The following example uses the GetVersionEx, GetSystemMetrics, GetProductInfo, and GetNativeSystemInfo functions to determine the version information of the currently running operating system. The example displays the information to the console.

Relying on version information is not the best way to test for a feature. Instead, refer to the documentation for the feature of interest. For more information on common techniques for feature detection, see Operating System Version.

If you must require a particular operating system, be sure to use it as a minimum supported version, rather than design the test for the one operating system. This way, your detection code will continue to work on future versions of Windows.

 
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#define BUFSIZE 256

typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);

BOOL GetOSDisplayString( LPTSTR pszOS)
{
   OSVERSIONINFOEX osvi;
   SYSTEM_INFO si;
   PGNSI pGNSI;
   PGPI pGPI;
   BOOL bOsVersionInfoEx;
   DWORD dwType;

   ZeroMemory(&si, sizeof(SYSTEM_INFO));
   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

   if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
      return 1;

   // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

   pGNSI = (PGNSI) GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), 
      "GetNativeSystemInfo");
   if(NULL != pGNSI)
      pGNSI(&si);
   else GetSystemInfo(&si);

   if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && 
        osvi.dwMajorVersion > 4 )
   {
      StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));

      // Test for the specific product.

      if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
      {
         if( osvi.wProductType == VER_NT_WORKSTATION )
             StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
         else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));

         pGPI = (PGPI) GetProcAddress(
            GetModuleHandle(TEXT("kernel32.dll")), 
            "GetProductInfo");

         pGPI( 6, 0, 0, 0, &dwType);

         switch( dwType )
         {
            case PRODUCT_ULTIMATE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
               break;
            case PRODUCT_HOME_PREMIUM:
               StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
               break;
            case PRODUCT_HOME_BASIC:
               StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
               break;
            case PRODUCT_ENTERPRISE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
               break;
            case PRODUCT_BUSINESS:
               StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
               break;
            case PRODUCT_STARTER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
               break;
            case PRODUCT_CLUSTER_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
               break;
            case PRODUCT_DATACENTER_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
               break;
            case PRODUCT_DATACENTER_SERVER_CORE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
               break;
            case PRODUCT_ENTERPRISE_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
               break;
            case PRODUCT_ENTERPRISE_SERVER_CORE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
               break;
            case PRODUCT_ENTERPRISE_SERVER_IA64:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
               break;
            case PRODUCT_SMALLBUSINESS_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
               break;
            case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
               StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
               break;
            case PRODUCT_STANDARD_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
               break;
            case PRODUCT_STANDARD_SERVER_CORE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
               break;
            case PRODUCT_WEB_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
               break;
         }
         if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
            StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
         else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
            StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
      {
         if( GetSystemMetrics(SM_SERVERR2) )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
         else if ( osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
         else if( osvi.wProductType == VER_NT_WORKSTATION &&
                  si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
         {
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
         }
         else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));

         // Test for the server type.
         if ( osvi.wProductType != VER_NT_WORKSTATION )
         {
            if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
            {
                if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
                else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
            }

            else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
            {
                if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
                else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
                else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
            }

            else
            {
                if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
                else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
                else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
                else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
                else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
            }
         }
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
      {
         StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
         if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
         else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
      {
         StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));

         if ( osvi.wProductType == VER_NT_WORKSTATION )
         {
            StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
         }
         else 
         {
            if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
               StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
            else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
               StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
            else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
         }
      }

       // Include service pack (if any) and build number.

      if( _tcslen(osvi.szCSDVersion) > 0 )
      {
          StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
          StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
      }

      TCHAR buf[80];

      StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
      StringCchCat(pszOS, BUFSIZE, buf);

      return TRUE; 
   }

   else
   {  
      printf( "This sample does not support this version of Windows.\n");
      return FALSE;
   }
}













출처는 M$DN
Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

생일

2008. 7. 11. 17:54

뜬금없는 미역국을 마시고도 모르고있다가
알고보니 생일이더군요.

음력 생일이다보니 본인도 잘 모르는 [..]
..라지만 미역국 안의 쇠고기에 더 신경이 쓰이는건 기분 탓 입니까 [..]

오늘은 다행히 모든 문제가 잘 해결된 것 같습니다.
제 개발 일정만 빼고 [..]

뭐 그저께 짤릴 법[..]한 미스 때문에 난리친 뒤니까
바람직한 현상이로군요.

오늘 회식만 잘 가면 되겠습니다.




Ps.  일본 쪽과 작업하는건 무섭게 꼼꼼해야 합니다.
       ( 한국과는 다르다! 한국과는 (...) )

Ps2. 이사님 ㄳ [..]
Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. Wishsong
    2008.07.11 19:00
    댓글 주소 수정/삭제 댓글
    생일 축하드립니다!
  2. 2008.07.12 00:26
    댓글 주소 수정/삭제 댓글
    생일 축하요~ 짤리지 않은 걸 계기로(?) 꼼꼼함을 한 단계 업그레이드하시는 겁니다!
    • 2008.07.12 00:45 신고
      댓글 주소 수정/삭제
      회식때 그이야기 들었죠
      한 번만 더 그러면 짤라버리겠다는 엄포와
      경험이 생겼으니 그만큼 신뢰하겠다는 양날의 검을 [..]
  3. 2008.07.14 10:06
    댓글 주소 수정/삭제 댓글
    오. 생일 축하합니다~~~
    안 짤렸으면 되는 겁니다~ ㅎ

출처는 데브피아



윈도 탐색기로 부터 정보 빼오기


본 문서는 http://blogs.msdn.com/oldnewthing/archive/2004/07/20/188696.aspx
에서 가져와  본인이 직접 번역한 문서임을 밝혀 드립니다.
본 문서는 역자의 동의 없이 마음대로 복사/배포 할 수 있으며
만약 오역이나 오타가 있으면 댓글로 남겨주세요.


때로 Sotware 개발은 새로운 것들을 만들어낸다.
하지만 때로는 가지고 있는 것들을 조합하기도 한다.
오늘의 문제는 두번째 문제에 대한 것 중의 하나다.

윈도 핸들을 가지고 어떤게 윈도 탐색기인지 알아낼 수 있다,
그리고 만약 그렇다면 어떤 폴더를 보고있고, 어떤 항목이 focus되어있을까..?

이는 본래부터 어려운 작업이 아니다. 단순히 수 많은 작은 조각들을 껴 맞추기만 하면 된다.

열린 shell window들을 가져올 수 있는  ShellWindows object에서 부터 시작하자.
그러면 Item프로퍼티를 가지고 이 모든 항목들을 열거할 수 있다.
이 ShellWindows 객체는 Javascript나 Visual Basic과 같은 스크립팅 언어가 사용하도록
고안되어 있기 때문에 C++에서 사용하기에는 쫌..... 거시기하다.

- Shell Interface가 호환성을 비롯한 여러가지 이유로 COM Interface로 제작됬기 때문입니다.


 IShellWindows *psw;
 if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL,
                                IID_IShellWindows, (void**)&psw))) {
  VARIANT v;
  V_VT(&v) = VT_I4;
  IDispatch  *pdisp;
  BOOL fFound = FALSE;
  for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK;
       V_I4(&v)++) {
    ...
    pdisp->Release();
  }
  psw->Release();
 }

각각의 item으로부터 우리는 item의 윈도 핸들을 가져올 수 있고,
그게 우리가 원하는 것이면 볼 수도 있다.

   IWebBrowserApp *pwba;
   if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
     HWND hwndWBA;
     if (SUCCEEDED(pwba->get_HWND((LONG_PTR*)&hwndWBA)) &&
       hwndWBA == hwndFind) {
       fFound = TRUE;
       ...
     }
     pwba->Release();
   }

됐다. 이제 우리는 IWebBrowserApp 인터페이스를 통해 폴더를 알아냈으니
Top shell browser로 가야한다.  
이 작업은 SID_STopLevelBrowsser 서비스를 쿼리하고
IShellBrowser인터페이스를 요청함으로 해결된다.

       IServiceProvider *psp;
       if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
         IShellBrowser *psb;
         if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,
                              IID_IShellBrowser, (void**)&psb))) {
           ...
           psb->Release();
         }
         psp->Release();
       }

IShellBrowser로부터 우리는 QueryActiveShellView 매서드를 통해 현재 Shell View를 가져올 수 있다.

           IShellView *psv;
           if (SUCCEEDED(psb->QueryActiveShellView(&psv))) {
             ...
             psv->Release();
           }

당연한 이야기지만, 우리가 원하는것은 모든 알짜배기 데이터 값들이 저장되어있는 자동화 객체인
IFolderView인터페이스이다.

             IFolderView *pfv;
             if (SUCCEEDED(psv->QueryInterface(IID_IFolderView,
                                               (void**)&pfv))) {
               ...
               pfv->Release();
             }

OK, 우리는 다 얻었다. 이제 당신은 구한 view로 부터 무엇을 얻으려고 하는가?
현재 보여지고 있는 IShellFolder의 위치를 구해보는건 어떨까?
이 일을 하기 위해 우리는 IPersistFolder2::GetCurFolder매서드를 사용해야 한다.
GetFolder 매서드는 우리에게 IPersistFolder2 인터페이스를 요구함으로 인해
shell folder로 접근이 가능하게 한다.
( 대부분의 경우 IShellFolder 인터페이스만 있으면 될 것이다.
왜냐면 여기서 대부분 대단한 작업(cool stuff)이 끝나기 때문이다. )

               IPersistFolder2 *ppf2;
               if (SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2,
                                            (void**)&ppf2))) {
                 LPITEMIDLIST pidlFolder;
                 if (SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) {
                   ...
                   CoTaskMemFree(pidlFolder);
                 }
                 ppf2->Release();
               }

여기서 우리 노력의 결실을 출력하기 위해 pidl을 path로 바꾸자.

                   if (!SHGetPathFromIDList(pidlFolder, g_szPath)) {
                     lstrcpyn(g_szPath, TEXT("<not a directory>"), MAX_PATH);
                   }
                   ...

- 당연한 이야기겠지만 내 컴퓨터나 내 네트워크 환경, 휴지통 같은 가상 폴더는 Path가 없습니다. IShellFolder 인터페이스를 얻었다면 다음과 같이 확인할 수 있습니다.
 
ulAttribs =  SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CONTENTSMASK |
    SFGAO_CANRENAME | SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_LINK |
    SFGAO_SHARE | SFGAO_GHOSTED | SFGAO_REMOVABLE | SFGAO_NONENUMERATED;
/*
이중에서 필요한 속성을 선택하면 됩니다.
IShellFolder::GetAttributesOf 함수의 3번째 인자는 IN OUT 용입니다.
*/
   pShellFolderParent->GetAttributesOf(1, (LPCITEMIDLIST *)&pidlSub, &ulAttribs);
   if ( !(ulAttribs & SFGAO_GHOSTED) )
   {
// 이 폴더는 가상 폴더입니다.
}

우리가 얻은 것을 가지고 다른 어떤것을 또 할 수 있을까...? 아~~ 맞다. 현재 focus된 객체가 무엇인지 알아보자.

                   int iFocus;
                   if (SUCCEEDED(pfv->GetFocusedItem(&iFocus))) {
                     ...
                   }

focus된 항목의 이름을 출력하자. 이를 위해 우리는 그 항목의 pidl과  IShellFolder가 필요하다.
(자, 내가 대단한 물건(cool stuff)가 있는 곳에 IShellFolder가 있다고 말했지.)
우리가 원하는 항목은 Item 매서드를 통해 나온다(놀랄만큼 충분하다).

                     LPITEMIDLIST pidlItem;
                     if (SUCCEEDED(pfv->Item(iFocus, &pidlItem))) {
                       ...
                       CoTaskMemFree(pidlItem);
                     }

( 만약 우리가 선택된 항목들의 리스트릴 원했더라면
  Items 매서드에 VGIO_SELECTION을 넣어 사용할 수 있었다. )

우리가 item의 pidl을 구한 후에도 역시 IShellFolder인터페이스가 필요하다 :

                       IShellFolder *psf;
                       if (SUCCEEDED(ppf2->QueryInterface(IID_IShellFolder,
                                                          (void**)&psf))) {
                         ...
                         psf->Release();
                       }

그런 다음, 항목의 출력용 이름을 얻기 위해 GetDisplayNameOf매서드의 도움으로
이 2가지를 같이 끼워 넣는다.

                         STRRET str;
                         if (SUCCEEDED(psf->GetDisplayNameOf(pidlItem,
                                                   SHGDN_INFOLDER,
                                                   &str))) {
                           ...
                         }

우리는 괴짜 STRRET구조체를 따분한 문자열 버퍼로 변환하기 위해
GetDisplayNameOf() 함수를 사용할 수 있다.
(괴짜 STRRET 구조체의 이야기는 또 다른 날을 기다려야 할 것이다.)

                           StrRetToBuf(&str, pidlItem, g_szItem, MAX_PATH);	

됐군, 이제 이 모든것을 함께 넣어보세.
이 모든것들을 보조 함수로 자르지 않고 커다란 함수 하나에 몽땅 집어 넣으니
오히려 추악해 보이는군...
하지만 "내 인생"에서는 이들이 더 관리가 잘 될 수있도록 작은 보조 함수들로 나눌것이다.

scratch program으로 시작하고 이 새로운 함수를 추가하라:

#include <shlobj.h>
#include <exdisp.h>

TCHAR g_szPath[MAX_PATH];
TCHAR g_szItem[MAX_PATH];

void CALLBACK RecalcText(HWND hwnd, UINT, UINT_PTR, DWORD)
{
 HWND hwndFind = GetForegroundWindow();
 g_szPath[0] = TEXT('\0');
 g_szItem[0] = TEXT('\0');

 IShellWindows *psw;
 if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL,
                                IID_IShellWindows, (void**)&psw))) {
  VARIANT v;
  V_VT(&v) = VT_I4;
  IDispatch  *pdisp;
  BOOL fFound = FALSE;
  for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK;
       V_I4(&v)++) {
   IWebBrowserApp *pwba;
   if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
     HWND hwndWBA;
     if (SUCCEEDED(pwba->get_HWND((LONG_PTR*)&hwndWBA)) &&
       hwndWBA == hwndFind) {
       fFound = TRUE;
       IServiceProvider *psp;
       if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
         IShellBrowser *psb;
         if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,
                              IID_IShellBrowser, (void**)&psb))) {
           IShellView *psv;
           if (SUCCEEDED(psb->QueryActiveShellView(&psv))) {
             IFolderView *pfv;
             if (SUCCEEDED(psv->QueryInterface(IID_IFolderView,
                                               (void**)&pfv))) {
               IPersistFolder2 *ppf2;
               if (SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2,
                                            (void**)&ppf2))) {
                 LPITEMIDLIST pidlFolder;
                 if (SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) {
                   if (!SHGetPathFromIDList(pidlFolder, g_szPath)) {
                     lstrcpyn(g_szPath, TEXT("<not a directory>"), MAX_PATH);
                   }
                   int iFocus;
                   if (SUCCEEDED(pfv->GetFocusedItem(&iFocus))) {
                     LPITEMIDLIST pidlItem;
                     if (SUCCEEDED(pfv->Item(iFocus, &pidlItem))) {
                       IShellFolder *psf;
                       if (SUCCEEDED(ppf2->QueryInterface(IID_IShellFolder,
                                                          (void**)&psf))) {
                         STRRET str;
                         if (SUCCEEDED(psf->GetDisplayNameOf(pidlItem,
                                                   SHGDN_INFOLDER,
                                                   &str))) {
                           StrRetToBuf(&str, pidlItem, g_szItem, MAX_PATH);
                         }
                         psf->Release();
                       }
                       CoTaskMemFree(pidlItem);
                     }
                   }
                   CoTaskMemFree(pidlFolder);
                 }
                 ppf2->Release();
               }
               pfv->Release();
             }
             psv->Release();
           }
           psb->Release();
         }
         psp->Release();
       }
     }
     pwba->Release();
   }
    pdisp->Release();
  }
  psw->Release();
 }
 InvalidateRect(hwnd, NULL, TRUE);
}

이제 우리가 해야할 일은 이 함수를 주기적으로 호출하고 결과를 출력하는 것이다.

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
    SetTimer(hwnd, 1, 1000, RecalcText);
    return TRUE;
}

void
PaintContent(HWND hwnd, PAINTSTRUCT *pps)
{
  TextOut(pps->hdc, 0, 0, g_szPath, lstrlen(g_szPath));
  TextOut(pps->hdc, 0, 20, g_szItem, lstrlen(g_szItem));
}

이제 굴릴 준비가 되었다. 이 프로그램을 실행하고 옆에다 두어라.
그 다음에 윈도 탐색기를 실행하고 방금 실행한 프로그램을 보고 선택한 항목이 무엇인지
당신이 어떤 폴더에 있는지 추적하여라.

자... 어쨌든 나는 내 목적을 이루었다:)
때론 당신이 원하는 조각들이 이미 거기에 있다
그리고 당신은 단지 어떻게 그것들을 함께 껴 넣을 수 있는지를 알기만 하면 된다.
각각의 그 조각들에 대해 그 자체는 아주 크지 않다는 것을 알아두라.
당신은 단시 얘네들이 흥미가 있는 방향으로 껴넣어질 수 있다는 것을 알아야 한다.

숙제 : 이 프로그램을 수정해서 폴더를 가져와서 detail view로 바꿔보도록 하라.

- IShellView2::GetView Method 를 사용하면 자세히 / 간단히 / 크게 / 작게 / 미리보기의
  뷰를 얻을 수 있습니다. 다른 방법도 있을 것 같은데 당장은 이것만 생각나는군요.



감사합니다.

최대한 원 글쓴이의 어투에 맞도록 했는데 어색한곳은 없는지요.

오타/오역이 있으면 댓글로 남겨주세요.

박명정 (kingsky) 





적당히 주석을 달려고 했는데 정신이 없군요. 시간 되는대로 부가적인 주석을 달아봐야겠습니다.
Posted by Xenosia

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


BLOG main image
Find the way you shall within yourself! by Xenosia

공지사항

카테고리

분류 전체보기 (48)
일상 (17)
RPG (8)
건담 (1)
Programming (18)
게임 (2)

글 보관함

달력

«   2020/01   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Total : 39,525
Today : 3 Yesterday : 0