ファイルの作成とオープン

CreateFile 関数は、新しいファイルを作成するか、既存のファイルを開くことができます。 ファイル名、作成手順、およびその他の属性を指定する必要があります。 アプリケーションが新しいファイルを作成すると、オペレーティング システムによって指定されたディレクトリに追加されます。

オペレーティング システムは、CreateFile を使用して開いたり作成したりする各ファイルに、ハンドルと呼ばれる一意の識別子を割り当てます。 アプリケーションは、ファイルの読み取り、書き込み、記述を行う関数でこのハンドルを使用できます。 そのハンドルへのすべての参照が閉じられるまで有効です。 アプリケーションは、アプリケーションの起動時に、ハンドルが継承可能として作成された場合に、それを開始したプロセスから開いているすべてのハンドルを継承します。

アプリケーションは、 ハンドルを使用してファイルにアクセスする前に、CreateFile によって返されるハンドルの値をチェックする必要があります。 エラーが発生した場合、ハンドル値は INVALID_HANDLE_VALUE され、アプリケーションは GetLastError 関数を使用して拡張エラー情報を取得できます。

アプリケーションで CreateFile を使用する場合は、 dwDesiredAccess パラメーターを使用して、ファイルからの読み取り、ファイルへの書き込み、読み取りと書き込みの両方を行うかどうかを指定する必要があります。 これは アクセス モードの要求と呼ばれます。 また、アプリケーションでは dwCreationDisposition パラメーターを使用して、ファイルが既に存在する場合に実行するアクション ( 作成処理と呼ばれます) を指定する必要があります。 たとえば、アプリケーションでは、同じ名前のファイルが既に存在する (したがって既存のファイルを上書きする) 場合でも、常に新しいファイルを作成するために、dwCreationDisposition をCREATE_ALWAYSに設定して CreateFile を呼び出すことができます。 これが成功するかどうかは、前のファイルの属性やセキュリティ設定などの要因によって異なります (詳細については、次のセクションを参照してください)。

また、アプリケーションは CreateFile を 使用して、ファイルを読み取り、書き込み、両方、またはどちらも共有しないかどうかを指定します。 これは 共有モードと呼ばれます。 共有されていない開いているファイル (dwShareMode を 0 に設定) は、そのハンドルが閉じられるまで、そのファイルを開いたアプリケーションまたは別のアプリケーションによって再度開くことはできません。 これは排他アクセスとも呼ばれます。

プロセスで CreateFile を 使用して、既に共有モードで開かれているファイル (dwShareMode を有効な 0 以外の値に設定) を開こうとすると、システムは要求されたアクセスモードと共有モードを、ファイルを開いたときに指定されたものと比較します。 前の呼び出しで指定したモードと競合するアクセス モードまたは共有モードを指定すると、 CreateFile は失敗します。

次の表は、さまざまなアクセス モードと共有モード (dwDesiredAccessdwShareMode それぞれ) を使用した CreateFile の 2 つの呼び出しの有効な組み合わせを示しています。 CreateFile 呼び出しがどの順序で行われるかは関係ありません。 ただし、各ファイル ハンドルに対する後続のファイル I/O 操作は、その特定のファイル ハンドルに関連付けられている現在のアクセス モードと共有モードによって引き続き制限されます。

CreateFile の最初の呼び出し CreateFile の有効な 2 回目の呼び出し
GENERIC_READFILE_SHARE_READ
  • GENERIC_READFILE_SHARE_READ
  • GENERIC_READFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_READ
  • GENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READFILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READFILE_SHARE_READ
  • GENERIC_READFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_READ
  • GENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READGENERIC_WRITEFILE_SHARE_READ
  • GENERIC_READGENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_WRITEFILE_SHARE_READ
  • GENERIC_READFILE_SHARE_WRITE
  • GENERIC_READFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_WRITEFILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READFILE_SHARE_WRITE
  • GENERIC_READFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READGENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_READGENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READGENERIC_WRITEFILE_SHARE_READ
  • GENERIC_READFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READGENERIC_WRITEFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
GENERIC_READGENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE
  • GENERIC_READGENERIC_WRITEFILE_SHARE_READFILE_SHARE_WRITE

標準のファイル属性に加えて、CreateFile の 4 番目のパラメーターとしてSECURITY_ATTRIBUTES構造体へのポインターを含めることで、セキュリティ属性を指定することもできます。 ただし、基になるファイル システムは、これを有効にするためにセキュリティをサポートする必要があります (たとえば、NTFS ファイル システムでサポートされていますが、さまざまな FAT ファイル システムではサポートされていません)。 セキュリティ属性の詳細については、「Access Control」を参照してください。

新しいファイルを作成するアプリケーションは、テンプレート ファイルにオプションのハンドルを指定できます。このハンドルから、 CreateFile は新しいファイルを作成するためにファイル属性と拡張属性を受け取ります。

CreateFile シナリオ

CreateFile 関数を使用してファイルへのアクセスを開始するには、いくつかの基本的なシナリオがあります。 これらは、次のように要約されています。

  • その名前のファイルがまだ存在しない場合に、新しいファイルを作成します。
  • 同じ名前のファイルが既に存在する場合でも新しいファイルを作成し、そのデータをクリアして空から開始します。
  • 既存のファイルが存在する場合にのみ開き、そのまま開きます。
  • 既存のファイルが存在する場合にのみ開き、空に切り捨てます。
  • ファイルが存在する場合は、常にそのまま開き、存在しない場合は新しいファイルを作成します。

これらのシナリオは、 dwCreationDisposition パラメーターの適切な使用によって制御されます。 以下は、これらのシナリオがこのパラメーターの値にマップされる方法と、それらのシナリオが使用された場合の動作の内訳を示しています。

その名前のファイルがまだ存在しない場合に新しいファイルを作成または開くとき (dwCreationDispositionCREATE_NEWCREATE_ALWAYS、または OPEN_ALWAYSのいずれかに設定されている場合)、 CreateFile 関数は次のアクションを実行します。

  • dwFlagsAndAttributes で指定されたファイル属性とフラグをFILE_ATTRIBUTE_ARCHIVEと結合します。
  • ファイルの長さを 0 に設定します。
  • hTemplateFile パラメーターが指定されている場合に、テンプレート ファイルによって指定された拡張属性を新しいファイルにコピーします (これにより、前に指定したすべてのFILE_ATTRIBUTE_* フラグがオーバーライドされます)。
  • 指定した場合、bInheritHandle メンバーで指定された継承フラグと、lpSecurityAttributes パラメーター (SECURITY_ATTRIBUTES 構造体) の lpSecurityDescriptor メンバーによって指定されたセキュリティ記述子を設定します。

同じ名前のファイルが既に存在する (dwCreationDispositionCREATE_ALWAYS に設定されている) 場合でも、新しいファイルを作成する場合、 CreateFile 関数は次のアクションを実行します。

  • 書き込みアクセスの現在のファイル属性とセキュリティ設定を確認します。拒否された場合は失敗します。
  • dwFlagsAndAttributes で指定されたファイル属性とフラグを、FILE_ATTRIBUTE_ARCHIVEおよび既存のファイル属性と組み合わせます。
  • ファイルの長さを 0 に設定します (つまり、ファイルに含まれているデータは使用できなくなり、ファイルは空です)。
  • hTemplateFile パラメーターが指定されている場合に、テンプレート ファイルによって指定された拡張属性を新しいファイルにコピーします (これにより、前に指定したすべてのFILE_ATTRIBUTE_* フラグがオーバーライドされます)。
  • 指定した場合、lpSecurityAttributes パラメーター (SECURITY_ATTRIBUTES 構造体) の bInheritHandle メンバーによって指定された継承フラグを設定しますが、SECURITY_ATTRIBUTES構造体の lpSecurityDescriptor メンバーは無視します。
  • それ以外の場合 (つまり、 CreateFile は有効なハンドルを返します)、 GetLastError を呼び出すと、コード ERROR_ALREADY_EXISTSが生成されます。ただし、この特定のユース ケースでは、実際にはこのようなエラーではありません (既存のファイルの代わりに "新規" (空) ファイルを作成する場合)。

既存のファイル (OPEN_EXISTING、OPEN_ALWAYS、またはTRUNCATE_EXISTINGに設定された dwCreationDisposition) を開くと、CreateFile 関数は次のアクションを実行します。

  • 要求されたアクセスの現在のファイル属性とセキュリティ設定を確認します。拒否された場合は失敗します。
  • dwFlagsAndAttributes で指定されたファイル フラグ (FILE_FLAG_*) と既存のファイル属性を結合し、dwFlagsAndAttributes で指定されたファイル属性 (FILE_ATTRIBUTE_*) を無視します。
  • dwCreationDispositionTRUNCATE_EXISTING に設定されている場合にのみ、ファイルの長さを 0 に設定します。それ以外の場合は、現在のファイルの長さが維持され、ファイルがそのまま開かれます。
  • hTemplateFile パラメーターを無視します。
  • 指定した場合、lpSecurityAttributes パラメーター (SECURITY_ATTRIBUTES 構造体) の bInheritHandle メンバーによって指定された継承フラグを設定しますが、SECURITY_ATTRIBUTES構造体の lpSecurityDescriptor メンバーは無視します。

ファイルの属性とディレクトリ

ファイル属性は、ファイルまたはディレクトリに関連付けられているメタデータの一部であり、それぞれに独自の目的と、その設定と変更方法に関する規則が含まれます。 これらの属性の一部はファイルにのみ適用され、一部はディレクトリにのみ適用されます。 たとえば、 FILE_ATTRIBUTE_DIRECTORY 属性はディレクトリにのみ適用されます。これは、ディスク上のオブジェクトがディレクトリであるかどうかを判断するためにファイル システムによって使用されますが、既存のファイル システム オブジェクトに対しては変更できません。

一部のファイル属性はディレクトリに対して設定できますが、既定の属性として機能する、そのディレクトリ内に作成されたファイルに対してのみ意味があります。 たとえば、 FILE_ATTRIBUTE_COMPRESSED はディレクトリ オブジェクトに設定できますが、ディレクトリ オブジェクト自体に実際のデータが含まれていないため、実際には圧縮されません。ただし、この属性でマークされたディレクトリは、そのディレクトリに追加された新しいファイルを圧縮するようにファイル システムに指示します。 ディレクトリで設定でき、そのディレクトリに追加された新しいファイルにも設定されるファイル属性は、 継承された属性と呼ばれます。

CreateFile 関数は、ファイルの作成時に特定のファイル属性を設定するためのパラメーターを提供します。 一般に、これらの属性は、アプリケーションがファイル作成時に使用する最も一般的な属性ですが、 CreateFile で使用可能なすべてのファイル属性を使用できるわけではありません。 一部のファイル属性では、ファイルが既に存在した後に SetFileAttributesDeviceIoControlDecryptFile などの他の関数を使用する必要があります。 FILE_ATTRIBUTE_DIRECTORYの場合、CreateFile ではディレクトリを作成できないため、作成時に CreateDirectory 関数が必要です。 特別な処理を必要とするその他のファイル属性はdeviceIoControl を必要とするFILE_ATTRIBUTE_REPARSE_POINTとFILE_ATTRIBUTE_SPARSE_FILEです。 詳細については、「 SetFileAttributes」を参照してください。

前述のように、ファイル属性の継承は、ファイルが配置されるディレクトリ属性から読み取られたファイル属性を使用してファイルが作成されるときに発生します。 次の表は、これらの継承された属性と、それらが CreateFile 機能とどのように関連しているかをまとめたものです。

ディレクトリ属性の状態 新しいファイルの CreateFile 継承オーバーライド機能
FILE_ATTRIBUTE_COMPRESSED セット。
コントロールなし。 DeviceIoControl を使用してクリアします。
FILE_ATTRIBUTE_COMPRESSED 設定されていません。
コントロールなし。 DeviceIoControl を使用して設定します。
FILE_ATTRIBUTE_ENCRYPTED セット。
コントロールなし。 DecryptFile を使用します。
FILE_ATTRIBUTE_ENCRYPTED 設定されていません。
CreateFile を使用して設定できます。
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED セット。
コントロールなし。 SetFileAttributes を使用してクリアします。
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 設定されていません。
コントロールなし。 SetFileAttributes を使用して設定します。

アクセス制御

CreateFile

DeviceIoControl

ファイル属性定数

ファイルの圧縮と圧縮解除

ファイルの暗号化

ファイル管理の関数

ハンドルとオブジェクト

継承の処理

読み取りまたは書き込みのためにファイルを開く

SetFileAttributes