ファイル操作関連のメモ(3点)

## 1. 他のプロセスがやってるダウンロード始まった？終わった？
他のプロセスがおこなっている外部からのファイルダウンロード完了を、これで検知できるかなぁ。。。

(1) 特定のフォルダーにファイルが作成されたかどうか調べる

```
  char pdir[MAX_PATH]{};
  char cdir[MAX_PATH]{};

  strcpy(pdir, HomeFolderName);
  GetCurrentDirectory(MAX_PATH, cdir);

  HANDLE hdir=CreateFile(pdir, FILE_LIST_DIRECTORY,
                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                         NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
  WCHAR lpBuffer[MAX_PATH]{};
  DWORD  dwNotifyFilter=FILE_NOTIFY_CHANGE_FILE_NAME;
  HANDLE hEventF=CreateEvent(NULL, TRUE, FALSE, NULL);
  OVERLAPPED olp{}; olp.hEvent=hEventF;
  if(hdir!=INVALID_HANDLE_VALUE){
    ReadDirectoryChangesW(hdir, lpBuffer, MAX_PATH, TRUE, dwNotifyFilter, NULL, &olp, NULL);
  }
  
  for(;;){
      if(hdir!=INVALID_HANDLE_VALUE){
        if(WaitForSingleObject(hEventF, 0)!=WAIT_TIMEOUT){
          ResetEvent(hEventF);
          DWORD retsize=0;
          GetOverlappedResult(hdir, &olp, &retsize, FALSE);
          FILE_NOTIFY_INFORMATION *lpInfomation=(FILE_NOTIFY_INFORMATION *)&lpBuffer[0];
          if(lpInfomation!=NULL){
            if(lpInfomation->Action==FILE_ACTION_ADDED){
              char buf[MAX_PATH]{};
              WideCharToMultiByte(CP_ACP, 0, lpInfomation->FileName, -1, buf, MAX_PATH, NULL, NULL);
              printf("new file added '%s'", buf);
            }
            memset(lpBuffer, 0, MAX_PATH*sizeof(wchar_t));
          }
          ReadDirectoryChangesW(hdir, lpBuffer, MAX_PATH, TRUE, dwNotifyFilter, NULL, &olp, NULL);
        }
      }
      Sleep(10);
    }

```

(2) 他のプロセスがファイル作成を完了する(ハンドルを開放する)まで待つ

```
#include <RestartManager.h>
#pragma comment(lib, "Rstrtmgr.lib")
int EnumProcessFileOpened(char filenameA[])
{
  WCHAR filenameW[MAX_PATH];
  MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filenameW, MAX_PATH);

  const int nfiles=1;
  LPCWSTR pszfiles[nfiles];
  pszfiles[0]=filenameW;

  int nproc=-1;
  DWORD dwError;
  DWORD dwSession;
  WCHAR szSessionKey[CCH_RM_SESSION_KEY+1]{};
  dwError=RmStartSession(&dwSession, 0, szSessionKey);
  if(dwError==ERROR_SUCCESS){
    dwError=RmRegisterResources(dwSession, nfiles, pszfiles, 0, NULL, 0, NULL);
    if(dwError==ERROR_SUCCESS){
      UINT nProcInfoNeeded=0;
      UINT nProcInfo=0;
      RM_PROCESS_INFO *rgpi=NULL;
      DWORD dwReason=RmRebootReasonNone;
      dwError=RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, rgpi, &dwReason);
      if(dwError==ERROR_MORE_DATA){
        printf("this file is opened by %d processes", nProcInfoNeeded);
        nproc=nProcInfoNeeded;
      }else if(dwError==ERROR_SUCCESS){
        printf("this file is opened by %d processes", nProcInfoNeeded);
      }else{
        nproc=-1;
      }
    }
    RmEndSession(dwSession);
  }
  return nproc;
}

```

## 2. 読み込みに時間かかってるから途中でキャンセル

読み込みスレッド

```
HANDLE hthread=INVALID_HANDLE_VALUE;
DWORD __stdcall ThreadProc(void *h)
{
  HANDLE *hfile=static_cast<HANDLE *>(h);
  unsigned char buffer[LARGE_SIZE];
  DWORD dwSize;
  ReadFile(*hfile, buffer, LARGE_SIZE, &dwSize, 0);
  return 0;
}
```

呼び出し側

```
  HANDLE hfile=CreateFile("c:\\Work\\test.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  hthread=CreateThread(NULL, 0, ThreadProc, &hfile, 0, NULL);

...

  CancelIoEx(hfile, NULL);
  WaitForSingleObject(hthread, INFINITE);
  CloseFile(hfile);
```

## 3. 書き込んだけど全部キャンセル(トランザクションNTFSの利用)

```
  HANDLE htran=CreateTransaction(NULL, 0, TRANSACTION_DO_NOT_PROMOTE, 0, 0, 0, L"");

  HANDLE hfile=CreateFileTransacted("c:\\Work\\test1.txt", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 
                                    FILE_ATTRIBUTE_NORMAL, NULL,
                                    htran, NULL, NULL);
  DWORD dwSize;
  WriteFile(hfile, "test", 4, &dwSize, NULL);
  CloseHandle(hfile);

  //  CommitTransaction(htran); //Commitする場合には、今までのファイル操作をアトミックに反映
  RollbackTransaction(htran);

  CloseHandle(htran);

```