가끔 어떤 파일이 수정 혹은 삭제 가능한 함수인지 체크해보고 싶을 때가 있습니다. 실제로 수정해보진 않고 말이죠... ^^
예를 들면... 모듈 업데이트 기능에서 전체 업데이트 대상 모듈들에 대해 ALL or NONE 를 구현하고 싶다면... 업데이트 대상 파일들에 대해 쓰기 체크를 해볼 필요가 있겠죠?? ^^

어떤 파일이 수정 불가능한 상태라는 건 여러가지 경우가 있습니다.
1. 핸들이 열려있어 수정이 불가 (ERROR_SHARING_VIOLATION)
2. EXE가 실행중이거나 DLL이 로딩되어 있어 수정 불가 
3. NTFS ACL 상의 권한이 없어 수정 불가 (ERROR_ACCESS_DENIED)
4. 후킹이나 기타 여러가지 이유로 수정 불가

이 중 4번 같은 경우를 제외하면 거의 정확하게 체크 가능한 방법이 있습니다. (사실 후킹을 해서 파일 수정을 차단하는 경우는 대부분 WriteFile이나 DeleteFile이 아니라 핸들을 오픈하는 과정에서 차단하기 때문에... 이 경우에도 "거의" 미리 체크가 된다고 볼수 있습니다. ^^)


비밀은 CreateFile의 세번째 인자 (ShareMode)에 있습니다.

CreateFile(pszFilePath, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);



ShareMode의 의미는 "일단 이 핸들이 열리고 나면 방금 지정한 ShareMode 중 하나라도 포함하지 않은 핸들은 열릴 수 없다" 가 됩니다. 이 항목에 "0"을 지정하는 경우는 두가지 의미를 가지게 되죠.


1. 이 핸들이 열린 이후로는 이 파일에 대해 어떠한 핸들도 열릴 수 없음. 말하자면 파일에 Exclusive Lock을 거는 거죠. 악성코드 들이 곧잘 이 짓을 합니다. ^^

2. 이 CreateFile이 호출되기 전에 해당 파일에 대해 어떠한 핸들이라도 열려있다면 이 호출은 실패함. 왜냐하면... 이전에 호출된 CreateFile의 세번째 인자가 0이 아니었다면... 그 값을 포함하는 CreateFile만 성공할 수 있기 때문에 실패할 것이고, 이전에 호출된  CreateFile의 세번째 인자가 0이었다면... Exclusive하게 핸들이 열려있기 때문에 실패하겠죠. ^^;;;


따라서 ShareMode에 "0"을 지정하여 CreateFile을 호출하는 것은 이전에 열려있는 핸들이 있는지 체크하는 용도로 사용될 수 있습니다. ^^


참고로 MSDN 상의 "dwShareMode"에 대한 설명을 첨부합니다.


dwShareMode [in]

The requested sharing mode of the file or device, which can be read, write, both, delete, all of these, or none (refer to the following table). Access requests to attributes or extended attributes are not affected by this flag.

If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed. For more information, see the Remarks section.

You cannot request a sharing mode that conflicts with the access mode that is specified in an existing request that has an open handle. CreateFile would fail and the GetLastError function would returnERROR_SHARING_VIOLATION.

To enable a process to share a file or device while another process has the file or device open, use a compatible combination of one or more of the following values. For more information about valid combinations of this parameter with the dwDesiredAccess parameter, see Creating and Opening Files.

Note  The sharing options for each open handle remain in effect until that handle is closed, regardless of process context.

ValueMeaning
0
0x00000000

Prevents other processes from opening a file or device if they request delete, read, or write access.

FILE_SHARE_DELETE
0x00000004

Enables subsequent open operations on a file or device to request delete access.

Otherwise, other processes cannot open the file or device if they request delete access.

If this flag is not specified, but the file or device has been opened for delete access, the function fails.

Note  Delete access allows both delete and rename operations.

FILE_SHARE_READ
0x00000001

Enables subsequent open operations on a file or device to request read access.

Otherwise, other processes cannot open the file or device if they request read access.

If this flag is not specified, but the file or device has been opened for read access, the function fails.

FILE_SHARE_WRITE
0x00000002

Enables subsequent open operations on a file or device to request write access.

Otherwise, other processes cannot open the file or device if they request write access.

If this flag is not specified, but the file or device has been opened for write access or has a file mapping with write access, the function fails.


Posted by kuaaan

댓글을 달아 주세요

  1. J.K 스나이퍼 2013.07.18 22:16 신고  댓글주소  수정/삭제  댓글쓰기

    File handle을 open하지 않고 유용하게 수정여부를 파악할 수 있는 이런 신기한 방법이 있었군요! ㅋ 언젠가 요긴하게 쓰일것 같습니다. 감사합니다.



사랑합니다. 편안히 잠드소서

티스토리 툴바