Introduction to Creating Files on Windows using C

NTFS is Window’s go-to filesystem that supports encryption, fault tolerance, compression, and large files. In addition to NTFS, the FAT32 filesystem is often seen on memory sticks.

Unlike in *nix, the pathname separator is the backslash, although the forward slash can be used as well. In general, we should use backslashes just to be safe. Likewise, the full pathname of a file on disk starts with the drive name, such as C: or D:. Finally, filenames are case-insensitive. 

The CreateFile() function opens existing files and creates new ones. The CreateFile() function accepts seven arguments. The second, third, fifth and sixth arguments are of type DWORD; a WORD is an unsigned 16 bit integer, and a DWORD is double that, at 32 bits. Note that the a DWORD is always 32 bits long, even on current 64 bit machines.

The first argument is of type LPCTSTR, which is a const char pointer. LPCTSTR supports unicode (16-bit, rather than 8 bit) character strings as well as ASCII (8 bit) character strings. Pretty much any data type with STR in it represents a string.  Note that when using Visual Studio, we should change our project’s character properties to Not Set. The easiest way to do this is by pressing Alt-F7 and then setting Character Set under Project Defaults to Not Set. 

Essentially, the first argument of type LPCTSTR is a pointer to a null-terminated string representing the pathname, which is normally limited to 260 characters. The fourth argument is of type LPSECURITY_ATTRIBUTES, which is a data structure.

The second argument, which is a DWORD, an unsigned 32 bit integer, accepts either GENERIC_READ or GENERIC_WRITE. To open a file for read/write we can use the bitwise or operator |, as in GENERIC_READ | GENERIC_WRITE.

#include <Windows.h>
#include <stdio.h>

int main(void){

printf("GENERIC READ = 0x%x\n", GENERIC_READ);
printf("GENERIC WRITE = 0x%x\n", GENERIC_WRITE);
printf("READ + WRITE = 0x%x\n", GENERIC_READ | GENERIC_WRITE);

printf("Press any key to continue...");

getchar();

return 0;

}

The third argument is the share mode. If this is set to 0, no other processes, including the one making the call, can access the file. If we specify FILE_SHARE_READ, other processes can access the file for concurrent read access. FILE_SHARE_WRITE allows concurrent writing to the file.

#include <Windows.h>
#include <stdio.h>

int main(void){

//one, basically
printf("FILE_SHARE_READ = 0x%x\n", FILE_SHARE_READ);
//two, basically
printf("FILE_SHARE_WRITE = 0x%x\n", FILE_SHARE_WRITE);

printf("Press any key to continue...");

getchar();

return 0;

}

The SECURITY_ATTRIBUTES structure contains three members, one of which is a pointer to a SECURITY_DESCRIPTOR structure. For now, we will just pass NULL as the argument. 

The fifth argument specifies whether to create, overwrite, open, or truncate the file. If we use CREATE_NEW here, it will create a new file, and more importantly, it will fail if the file already exists. If we specify CREATE_ALWAYS, however, the system will instead overwrite any preexisting files. Likewise, OPEN_EXISTING will fail if the file doesn’t already exist, but OPEN_ALWAYS will go go ahead and create the file if it hasn’t been created already. 

The sixth argument is used to define file attributes and flags for the file. 

 

The CreateFile() function either returns a HANDLE to an open file object, or else an INVALID_HANDLE_VALUE in the event of failure. On current machines, a HANDLE is an unsigned 64 bit value. 

#include <stdio.h>

int main(void){

HANDLE ourHandle;


ourHandle = CreateFile("newfile.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);

if(ourHandle==INVALID_HANDLE_VALUE){
printf("Problem creating file.\n");
printf("Error %x\n", GetLastError());
} else {
printf("File created successfully.\n");
}

printf("Press any key to continue...");

getchar();

return 0;

}

Although Windows closes all open handles on exit, it’s a good idea to close handles no matter what using the CloseHandle() function. Note that the CloseHandle() function returns a Boolean value indicating success or failure.

#include <Windows.h>
#include <stdio.h>

int main(void){

HANDLE theHandle;
LPCTSTR filepath = "another.txt";
bool closed;

theHandle = CreateFile(filepath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if(theHandle!=INVALID_HANDLE_VALUE){
printf("%s created successfully\n", filepath);
}

closed = CloseHandle(theHandle);

if(closed){
printf("HANDLE to %s now closed.\n", filepath);
}

printf("Press any key to continue...");

getchar();

return 0;

}

The win32 CreateFile() function is a bit more complicated than the *nix open() function, which can take as little as two arguments, with the first argument being the pathname and the second argument being the flags for reading or writing the file or directory, and an optional third argument to specify file and directory permissions.

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s