BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
    switch (fdwReason)  {
    case DLL_PROCESS_ATTACH:
        LogFileOpen();
        break;
    case DLL_PROCESS_DETACH:
        LogFileClose();
        break;
    }
    return TRUE;
}
 
나는 해당 DLL을 로드한 프로세스가 종료될때 까지 다른 프로세스가 로그파일에 접근하지 못하도록 DLL이 로드될때 파일을 열고 DLL이 언로드될때 파일 핸들을 닫아주도록 구현을 하려고 했다.
그러나 위 방식대로 구현을 하니 DOS 명령 kill의 경우나 Procexp로 프로세스를 죽이는 경우에는 로그파일이 제대로 생성되지 않았다.
즉 외부 프로세스가 강제로 해당 DLL을 로딩중인 프로세스를 끄려고 할 경우 DLL_PROCESS_DETACH로 들어가지 않는것을 확인했다.
 
MSDN에서는 FreeLibrary API를 통해 가상메모리에서 언로드 될때 그리고 프로세스가 종료될때 DLL_PROCESS_DETACH에 들어온다고 정의한다.
그래서 당연히 나는 어떤식으로든 프로세스가 종료되면 DLL_PROCESS_DETACH로 들어갈거라고 생각했다.
그러나 MSDN에서 정의하는 프로세스가 종료되는 순간은 지극히 정상종료를 의미하는것 같다.
 
프로세스가 정상적으로 종료될때 메인스레드에 진입하는 메인함수들(main, winmain, dllmain…)이 반환되면 CRT(C/C++ RunTime Library)에 제어권이 돌아가고 OS에서 메인스레드 종료작업 후 메인함수의 리턴값을 가지고 ExitProcess API를 호출한다.
이 ExitProcess API에서 해당 프로세스에 로드된 DLL들에 DLL_PROCESS_DETACH를 인자로 dllmain을 호출한다고 한다. 
그러나 TerminateProcess API를 통해 프로세스를 죽이면 CRT로 제어권이 안돌아갈 뿐더러 어떠한 메인스레드 종료작업도 하지못하고 그냥 강제로 종료된다.
 
 
MSDN에서 또한 TerminateProcess를 사용한다면 DLL에서 사용되는 데이터를 보장받지 못할것이라고 말한다.
 
결론은 타 프로세스가 TerminateProcess를 통해 프로세스를 종료시키면 DLL_PROCESS_DETACH로 안들어간다.
 
VOID WaitThreadStart() {
    hEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, TEXT("finish"));
    hThread = (HANDLE)_beginthreadex(NULL, 0, WaitForExit, NULL, 0, (unsigned*)& dwThreadID);
}
UINT WINAPI WaitForExit(LPVOID lpParam){
    WaitForSingleObject(hEvent, INFINITE);
 
    ExitProcess(1);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){
    switch (fdwReason)  {
    case DLL_PROCESS_ATTACH:
        LogFileOpen();
        WaitThreadStart();
        break;
    case DLL_PROCESS_DETACH:
        LogFileClose();
        OutputDebugString(TEXT("finish"));
        break;
    }
    return TRUE;
}
 
내 문제에서는 DLL을 인젝션 해주는 에이전트 프로세스에서 CreateEvent로 이벤트를 만들고 종료를 원하는 순간 SetEvent를 통해 해당 DLL을 로드한 모든 프로세스가 종료되도록 함으로써 
DLL을 로드한 모든 프로세스가 실행중인 동안에는 타 프로세스의 로그파일 접근을 막았지만 이건 내 문제에서 이벤트를 통한 해결방법이다.
 
DLL_PROCESS_DETACH를 너무 믿지 말자.
 

'C&C++' 카테고리의 다른 글

How To Use Unit Test In C++  (0) 2020.01.13
WINAPI How To Hook ConnectEx  (0) 2019.11.06
WINAPI Options Using Bit Flag  (0) 2019.08.07
WINAPI CreateProcess Suspend State  (0) 2019.07.11
Incremental Linking  (0) 2019.07.10

+ Recent posts