HANDLE WINAPI CreateFile(
  _In_      LPCTSTR lpFileName,
  _In_      DWORD dwDesiredAccess,
  _In_      DWORD dwShareMode,
  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_      DWORD dwCreationDisposition,
  _In_      DWORD dwFlagsAndAttributes,
  _In_opt_  HANDLE hTemplateFile 
);
음... 방금 전에 좀 당황스러운 경험을 했는데요...

CreateFile의 두번째 인자(DesiredAccess)와 세번째 인자(ShareMode)와의 관계를... 제가 잘못 이해하고 있더군요...

(이 정도는 기본 중의 기본이라고 생각했었는데... 아 민망해라... ^^;;;)

찾아보니 이 문제에 대해 제대로 정리된 한글 자료도 없는 것 같고 해서... 제가 한번 정리해 봅니다.

일단... 모든 답은 아래의 MSDN에 들어 있습니다. (들어 있기는 합니다....)

근데 CreateFile의 MSDN 설명을 아무리 봐도... 도통 알쏭달쏭 하죠. ^^;; 테스트를 통해 이해하고 나서 다시한번 MSDN을 보니... 네 설명이 되어 있더군요. (이해 안된 상태에서는 이걸 봐도 모르겠더라구요... ㅋㅋ)

dwDesiredAccess [in]

The requested access to the file or device, which can be summarized as read, write, both or neither zero).

The most commonly used values are GENERIC_READGENERIC_WRITE, or both (GENERIC_READ | GENERIC_WRITE). For more information, see Generic Access RightsFile Security and Access RightsFile Access Rights Constants, and ACCESS_MASK.

If this parameter is zero, the application can query certain metadata such as file, directory, or device attributes without accessing that file or device, even if GENERIC_READ access would have been denied.

You cannot request an access mode that conflicts with the sharing mode that is specified by thedwShareMode parameter in an open request that already has an open handle.

For more information, see the Remarks section of this topic and Creating and Opening Files.

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.


빨간 볼드친 부분을 주목해서 보시면 됩니다. 우리말로 풀어쓰면 다음과 같습니다.


1. CreateFile 호출 시 지정되는 dwDesiredAccess 인자는 기존에 열린 핸들의 dwShareMode와 충돌나면 안된다. (즉, 기존에 열린 모든 핸들의 dwShareMode의 부분집합이어야 한다는 뜻입니다.)


2. CreateFile 호출시 지정되는 dwShareMode 인자는 기존에 열린 핸들의 dwDesiredAccess와  충돌나면 안된다. (즉, 기존에 열린 모든 핸들의 dwDesiredAccess를 포함해야 한다는 뜻입니다..)


핵심은 "DesiredAccess"는 기존에 열린 핸들의 "ShareMode"와, "ShareMode"는 기존에 열린 핸들의 "DesiredAccess"와 비교된다는 점입니다.

(비교시 GENERIC_READ는 FILE_SHARE_READ와, GENERIC_WRITE는 FILE_SHARE_WRITE와 대응된다고 생각하시면 되겠습니다.)


한번 샘플코드를 보시죠.

위의 예제코드에서 두번째 CreateFile은 성공할까요? 네~ 실패합니다. 

두번째 호출에서의 DesiredAccess(GENERIC_READ)가 첫번째 호출시의 ShareMode(FILE_SHARE_WRITE)와 충돌나기 때문입니다. (GENERIC_READ 가 FILE_SHARE_WRITE의 부분집합이 아님)


위의 예제코드는 어떨까요? 결과는 역시 "실패"입니다.

두번째 호출시의 ShareMode(FILE_SHARE_READ)가 첫번째 호출의 DesiredAccess(GENERIC_READ|GENERIC_WRITE)와 충돌나기 때문이죠. (GENERIC_READ|GENERIC_WRITE가 FILE_SHARE_READ 의 부분집합이 아님)


ShareMode를 다음과 같이 수정하면 두번째 호출을 성공시킬 수 있습니다.


이번에는 3단계 테스트입니다.

위의 샘플코드 역시 세번째 CreateFile이 실패합니다. 이유는 세번째 호출 시의 DesiredAccess(GENERIC_WRITE)가 첫번째 호출의 (FILE_SHARE_READ)와 충돌나기 때문인데요... 사실 첫번째, 두번째 호출에서 위와 같이 핸들이 열린 상태에서는 세번째 호출시 DesiredAccess를 "FILE_SHARE_READ" / "FILE_SHARE_WRITE" / "GENERIC_READ|FILE_SHARE_WRITE" 세가지 중 어떤 형태로 지정하더라도 모두 실패하게 됩니다. 첫번째 호출의 ShareMode 에서 FILE_SHARE_READ 가 지정되었으므로 세번째 호출의 DesiredAccess는 FILE_SHARE_READ 의 부분집합이어야 하는데, 두번째 호출의 ShareMode가 FILE_SHARE_WRITE 였으므로 세번째 호출의 DesiredAccess는 동시에 FILE_SHARE_WRITE 의 부분집합이기도 해야 하거든요. 


이런 건 가능합니다.


CreateFile MSDN에 이렇게 나와 있네요. ^^

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.



마지막 퀴즈~


네~ 마지막 샘플코드를 실행하면 세 번의 CreateFile이 모두 성공합니다. 세번째 호출시의 DesiredAccess 는 첫번째 ShareMode (FILE_SHARE_READ)와 두번째 ShareMode (FILE_SHARE_READ | FILE_SHARE_WRITE)를 모두 만족시키고, 세번째 호출의 ShareMode (FILE_SHARE_READ|FILE_SHARE_WRITE)가 첫번째 호출의 DesiredAccess (GENERIC_WRITE)와 두번째 호출의 DesiredAccess (GENERIC_READ)를 모두 만족시키기 때문입니다.






Posted by kuaaan
,


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