반응형
드라이버를 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 |
댓글