반응형
드라이버를 unload 하고 재시작시 CreateService에서 정말 아주 가끔씩 ERROR_SERVICE_MARKED_FOR_DELETE 에러를
내뱉으며 드라이버 설치되지 않을 때가 있었다...;;
재현하기 힘든 상태라서 원인을 파악하기엔 어려움이 있었지만...드라이버 언로시에 관련된 함수들을 지우거나 강제로
실패하게 만들어 재현 상태를 가상적으로나마 만들어 봤었다..
문제는 ControlService()함수가 문제였는데..
언로드시 함수 호출 루틴은 다음과 같다.
OpenSCManager -> OpenServiceA -> ControlService -> DeleteService ....
여기서 ControlService 함수에서 서비스 중지 명령을 날린 후 DeleteService 를 호출하는데 ControlService 함수의 실패에 대한
예외처리 없이 바로 DeleteService를 호출하게 됨에 따라 ControlService의 stop명령이 실패됬음에도 불구하고 DeleteService
를 호출하여 다시 드라이버를 로드할 때 CreateService에서 ERROR_SERVICE_MARKED_FOR_DELETE 에러가 발생 한 것이
었다.
이 ControlService 함수의 실패가 아주 가끔 발생했기에 문제가 잘보이지 않다가 실패나면 그런 문제가 발생했나 보다..-_-;;
내뱉으며 드라이버 설치되지 않을 때가 있었다...;;
재현하기 힘든 상태라서 원인을 파악하기엔 어려움이 있었지만...드라이버 언로시에 관련된 함수들을 지우거나 강제로
실패하게 만들어 재현 상태를 가상적으로나마 만들어 봤었다..
문제는 ControlService()함수가 문제였는데..
언로드시 함수 호출 루틴은 다음과 같다.
OpenSCManager -> OpenServiceA -> ControlService -> DeleteService ....
여기서 ControlService 함수에서 서비스 중지 명령을 날린 후 DeleteService 를 호출하는데 ControlService 함수의 실패에 대한
예외처리 없이 바로 DeleteService를 호출하게 됨에 따라 ControlService의 stop명령이 실패됬음에도 불구하고 DeleteService
를 호출하여 다시 드라이버를 로드할 때 CreateService에서 ERROR_SERVICE_MARKED_FOR_DELETE 에러가 발생 한 것이
었다.
이 ControlService 함수의 실패가 아주 가끔 발생했기에 문제가 잘보이지 않다가 실패나면 그런 문제가 발생했나 보다..-_-;;
그래서 이래저래 자료를 찾아보니 마소사이트에서 드라이버 언로드의 해제 소스가 깔끔하게 있는것이 아닌가!?(-_-;)
암튼..그 소스를 긁어왔다.
void CRemoveServiceDlg::OnRemoveService()
{
// TODO: Add your control notification handler code here
SERVICE_STATUS ssStatus; // current status of the service
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR szErr[256];
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager )
{
schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);
if (schService)
{
// try to stop the service
if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
{
_tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
Sleep( 1000 );
while( QueryServiceStatus( schService, &ssStatus ) )
{
if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
{
_tprintf(TEXT("."));
Sleep( 1000 );
}
else
break;
}
if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
_tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );
}
// now remove the service
if( DeleteService(schService) )
_tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));
CloseServiceHandle(schService);
}
else
_tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));
CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
}
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;
dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL );
// supplied buffer is not long enough
if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
lpszBuf[0] = TEXT('\0');
else
{
lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
_stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
}
if ( lpszTemp )
LocalFree((HLOCAL) lpszTemp );
return lpszBuf;
}
while문에서 QueryServiceStatus 요 함수로 계속 상태를 보면서 서비스를 stop시키고 DeleteService 를 수행한다.
정말 나이스구만!
반응형
'Study > Driver' 카테고리의 다른 글
| Win7 64bit Eprocess 구조체 (1) | 2011.11.25 |
|---|---|
| 윈도우7(Win7) 64bit 코드사인 없이 드라이버 로드하기!! (2) | 2011.11.21 |
| Win7 64비트에서 드라이버(sys파일) 빌드하기!! vs2008에서.. (0) | 2011.11.21 |
| NtTerminateProcess 사용!! (0) | 2011.09.28 |
| 버츄얼 PC 공유 폴더 설정 (0) | 2011.09.28 |
댓글