Criação e abertura de arquivos

A função CreateFile pode criar um novo arquivo ou abrir um arquivo existente. Você deve especificar o nome do arquivo, as instruções de criação e outros atributos. Quando um aplicativo cria um novo arquivo, o sistema operacional o adiciona ao diretório especificado.

O sistema operacional atribui um identificador exclusivo, chamado de identificador, a cada arquivo aberto ou criado usando CreateFile. Um aplicativo pode usar esse identificador com funções que leem, gravam e descrevem o arquivo. Ele é válido até que todas as referências a esse identificador sejam fechadas. Quando é iniciado, um aplicativo herda todos os identificadores abertos do processo que o iniciou se os identificadores foram criados como herdáveis.

Um aplicativo deve verificar o valor do identificador retornado por CreateFile antes de tentar usar o identificador para acessar o arquivo. Se ocorrer um erro, o valor do identificador será INVALID_HANDLE_VALUE e o aplicativo poderá usar a função GetLastError para obter informações de erro estendidas.

Quando usa CreateFile, um aplicativo deve usar o parâmetro dwDesiredAccess para especificar se pretende ler a partir do arquivo, gravar no arquivo, ler e gravar ou nada. Isso é conhecido como solicitação de um modo de acesso. O aplicativo também deve usar o parâmetro dwCreationDisposition para especificar qual ação tomar se o arquivo já existir, conhecida como a disposição de criação. Por exemplo, um aplicativo pode chamar CreateFile com dwCreationDisposition definido como CREATE_ALWAYS para sempre criar um novo arquivo, mesmo que um arquivo com o mesmo nome já exista (substituindo, assim, o arquivo existente). Se isso será bem-sucedido ou não depende de fatores como os atributos do arquivo anterior e as configurações de segurança (consulte as seções a seguir para obter mais informações).

Um aplicativo também usa CreateFile para especificar se deseja compartilhar o arquivo para leitura, gravação, ambos ou nada. Isso é conhecido como modo de compartilhamento. Um arquivo aberto que não é compartilhado (dwShareMode definido como zero) não pode ser reaberto, seja pelo aplicativo que o abriu ou por outro aplicativo, até que o identificador tenha sido fechado. Isso também é conhecido como acesso exclusivo.

Quando um processo usa CreateFile para tentar abrir um arquivo que já foi aberto em um modo de compartilhamento (dwShareMode definido como um valor válido diferente de zero), o sistema compara os modos de acesso e compartilhamento solicitados com aqueles especificados quando o arquivo foi aberto. Se você especificar um modo de acesso ou compartilhamento que entre em conflito com os modos especificados na chamada anterior, CreateFile falhará.

A tabela a seguir ilustra as combinações válidas de duas chamadas para CreateFile usando vários modos de acesso e modos de compartilhamento (dwDesiredAccess, dwShareMode, respectivamente). Não importa em que ordem as chamadas CreateFile são feitas. No entanto, todas as operações de E/S de arquivo subsequentes em cada identificador de arquivo ainda estarão restritas pelos modos atuais de acesso e compartilhamento associados a esse identificador de arquivo em especial.

Primeira chamada para CreateFile Segundas chamadas válidas para CreateFile
GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ FILE_SHARE_WRITE
GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_WRITE, FILE_SHARE_READ FILE_SHARE_WRITE
GENERIC_READ, FILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_WRITE, FILE_SHARE_READ FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE
  • GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE

Além dos atributos de arquivo padrão, você também pode especificar atributos de segurança, inclusive um ponteiro para uma estrutura SECURITY_ATTRIBUTES como o quarto parâmetro de CreateFile. No entanto, o sistema de arquivos subjacente deve dar suporte à segurança para que isso tenha algum efeito (por exemplo, o sistema de arquivos NTFS dá suporte a ele, mas os vários sistemas de arquivos FAT, não). Para obter mais informações sobre atributos de segurança, consulte Access Control.

Um aplicativo que cria um novo arquivo pode fornecer um identificador opcional para um arquivo de modelo, do qual CreateFile obtém atributos de arquivo e atributos estendidos para a criação do novo arquivo.

Cenários de CreateFile

Há vários cenários fundamentais para iniciar o acesso a um arquivo usando a função CreateFile. Eles são resumidos como:

  • Criação de um novo arquivo quando um arquivo com esse nome ainda não existe.
  • Criação de um novo arquivo mesmo que um arquivo com o mesmo nome já exista, apagando os dados e começando vazio.
  • Abertura de um arquivo existente somente se ele existir e só estiver intacto.
  • Abertura de um arquivo existente somente se ele existir, truncando-o para permanecer vazio.
  • Abertura de um arquivo sempre: como está se existir, criar um novo se não existir.

Esses cenários são controlados pelo uso indicado do parâmetro dwCreationDisposition. Abaixo está um detalhamento de como esses cenários são mapeados para valores para esse parâmetro e o que acontece quando eles são usados.

Durante a criação ou a abertura de um novo arquivo quando um arquivo com esse nome ainda não existe (dwCreationDisposition definido como CREATE_NEW, CREATE_ALWAYS ou OPEN_ALWAYS), a função CreateFile realizará as seguintes ações:

  • Combina os atributos de arquivo e sinalizadores especificados por dwFlagsAndAttributes com FILE_ATTRIBUTE_ARCHIVE.
  • Define o comprimento do arquivo como zero.
  • Copiará os atributos estendidos fornecidos pelo arquivo de modelo para o novo arquivo se o parâmetro hTemplateFile for especificado (isso substitui todos os identificadores FILE_ATTRIBUTE_* especificados anteriormente).
  • Define o sinalizador inherit especificado pelo membro bInheritHandle e o descritor de segurança especificado pelo membro lpSecurityDescriptor do parâmetro lpSecurityAttributes (estrutura SECURITY_ATTRIBUTES), se fornecido.

Durante a criação de um novo arquivo, mesmo que já exista um arquivo com o mesmo nome (dwCreationDisposition definido como CREATE_ALWAYS), a função CreateFile realiza as seguintes ações:

  • Verifica os atributos de arquivo atuais e as configurações de segurança para acesso de gravação, falhando se negado.
  • Combina os atributos de arquivo e sinalizadores especificados por dwFlagsAndAttributes com FILE_ATTRIBUTE_ARCHIVE e os atributos de arquivo existentes.
  • Define o comprimento do arquivo como zero (ou seja, todos os dados que estavam no arquivo não estão mais disponíveis e o arquivo está vazio).
  • Copiará os atributos estendidos fornecidos pelo arquivo de modelo para o novo arquivo se o parâmetro hTemplateFile for especificado (isso substitui todos os identificadores FILE_ATTRIBUTE_* especificados anteriormente).
  • Define o sinalizador inherit especificado pelo membro bInheritHandle do parâmetro lpSecurityAttributes (estrutura SECURITY_ATTRIBUTES) se fornecido, mas ignora o membro lpSecurityDescriptor da estrutura SECURITY_ATTRIBUTES.
  • Se for bem-sucedido (ou seja, CreateFile retorna um identificador válido), a chamada de GetLastError produzirá o código ERROR_ALREADY_EXISTS, mesmo que, para esse caso de uso específico, não seja realmente um erro como tal (se você pretendia criar um "novo" arquivo (vazio) no lugar do existente).

Durante a abertura de um arquivo existente (dwCreationDisposition definido como OPEN_EXISTING, OPEN_ALWAYS ou TRUNCATE_EXISTING), a função CreateFile realiza as seguintes ações:

  • Verifica os atributos de arquivo atuais e as configurações de segurança para acesso solicitado, falhando se negado.
  • Combina os sinalizadores de arquivo (FILE_FLAG_*) especificados por dwFlagsAndAttributes com atributos de arquivo existentes, além de ignorar todos os atributos de arquivo (FILE_ATTRIBUTE_*) especificados por dwFlagsAndAttributes.
  • Definirá o comprimento do arquivo como zero somente se dwCreationDisposition estiver definido como TRUNCATE_EXISTING; do contrário, o comprimento do arquivo atual será mantido e o arquivo será aberto no estado em que se encontra.
  • Ignora o parâmetro hTemplateFile.
  • Define o sinalizador inherit especificado pelo membro bInheritHandle do parâmetro lpSecurityAttributes (estrutura SECURITY_ATTRIBUTES) se fornecido, mas ignora o membro lpSecurityDescriptor da estrutura SECURITY_ATTRIBUTES.

Atributos e diretórios de arquivos

Os atributos de arquivo fazem parte dos metadados associados a um arquivo ou diretório, cada um com a própria finalidade e regras sobre como ele pode ser definido e alterado. Alguns desses atributos só se aplicam a arquivos, e outros apenas a diretórios. Por exemplo, o atributo FILE_ATTRIBUTE_DIRECTORY só se aplica a diretórios: ele é usado pelo sistema de arquivos para determinar se um objeto no disco é um diretório, mas não pode ser alterado por um objeto do sistema de arquivos existente.

Alguns atributos de arquivo podem ser definidos para um diretório, mas têm significado apenas para arquivos criados nesse diretório, funcionando como atributos padrão. Por exemplo, FILE_ATTRIBUTE_COMPRESSED pode ser definido em um objeto do directory, mas como o objeto do directory propriamente dito não contém dados reais, ele não é realmente compactado; no entanto, os diretórios marcados com esse atributo informam ao sistema de arquivos para compactar todos os novos arquivos adicionados a esse diretório. Qualquer atributo de arquivo que possa ser definido em um diretório e também será definido para novos arquivos adicionados a esse diretório é chamado de atributo herdado.

A função CreateFile oferece um parâmetro para definir determinados atributos de arquivo quando um arquivo é criado. Em geral, esses atributos são os mais comuns para um aplicativo usar no momento da criação do arquivo, mas nem todos os atributos de arquivo possíveis estão disponíveis para CreateFile. Alguns atributos de arquivo exigem o uso de outras funções, como SetFileAttributes, DeviceIoControl, or DecryptFile depois que o arquivo já é existente. No caso de FILE_ATTRIBUTE_DIRECTORY, a função CreateDirectory é necessária no momento da criação porque CreateFile não consegue criar diretórios. Os outros atributos de arquivo que exigem tratamento especial são FILE_ATTRIBUTE_REPARSE_POINT and FILE_ATTRIBUTE_SPARSE_FILE, que exigem DeviceIoControl. Para obter mais informações, consulte SetFileAttributes.

Conforme dito anteriormente, a herança do atributo de arquivo ocorre quando um arquivo é criado com atributos de arquivo lidos a partir dos atributos de diretório em que o arquivo estará localizado. A tabela a seguir resume esses atributos herdados e como eles se relacionam com as capacidades CreateFile.

Estado de atributo do directory Capacidade de substituição da herança CreateFile para novos arquivos
FILE_ATTRIBUTE_COMPRESSED definido.
Sem controle. Use DeviceIoControl para apagar.
FILE_ATTRIBUTE_COMPRESSED não definido.
Sem controle. Use DeviceIoControl para definir.
FILE_ATTRIBUTE_ENCRYPTED definido.
Sem controle. Use DecryptFile.
FILE_ATTRIBUTE_ENCRYPTED não definido.
Pode ser definido usando CreateFile.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED definido.
Sem controle. Use SetFileAttributes para apagar.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED não definido.
Sem controle. Use SetFileAttributes para definir.

Controle de acesso

CreateFile

DeviceIoControl

Constantes de atributo de arquivo

Compressão e descompressão do arquivo

Criptografia do arquivo

Funções de gerenciamento de arquivo

Identificadores e objetos

Herança do identificador

Abrir um arquivo para leitura ou gravação

SetFileAttributes