All Articles

Notes on Creating a Tool to Obtain File Handles with Arbitrary Flags on Windows

This page has been machine-translated from the original page.

I wanted a tool that could obtain file handles with arbitrary settings for testing, so I created a simple one.

Table of Contents

Source Code

#include <windows.h>
#include <iostream>
#include <string>

# define FILE_SHARE_NONE 0x00000000

int isEmpty(std::wstring text) {

    if (text.empty()) {
        std::wcerr << L"Input is empty. Using default path." << std::endl;
        return 1;
    }

    return 0;
}

std::wstring handleInput(std::wstring text) {
    while (!text.empty() && (text.back() == L'\n' || text.back() == L'\r' || text.back() == L' '))
        text.pop_back();

    return text;
}

HANDLE createFileHandle(const std::wstring& path, std::wstring& desiredAccess, std::wstring& shareMode) {
    
    DWORD dwDesiredAccess = 0;
    DWORD dwShareMode = 0;

    if (desiredAccess == L"1") {
        dwDesiredAccess = GENERIC_READ;
    }
    else if (desiredAccess == L"2") {
        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
    }
    else {
        std::wcerr << L"Invalid desired access input." << std::endl;
        return NULL;
}

    if (shareMode == L"1") {
        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
    }
    else if (shareMode == L"2") {
        dwShareMode = FILE_SHARE_READ;
    }
    else if (shareMode == L"3") {
        dwShareMode = FILE_SHARE_NONE;
    }
    else {
        std::wcerr << L"Invalid share mode input." << std::endl;
        return NULL;
    }

    HANDLE hFile = CreateFileW(
path.c_str(), // lpFileName
dwDesiredAccess, // dwDesiredAccess
dwShareMode, // dwShareMode
NULL, // lpSecurityAttributes
        OPEN_ALWAYS, // dwCreationDisposition
FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
NULL // hTemplateFile
    );

    if (hFile == INVALID_HANDLE_VALUE) {
        std::wcerr << L"Failed to open file. Error: " << GetLastError() << std::endl;
        return NULL;
    }
    std::wcout << L"File opened successfully." << std::endl;

    return hFile;

}

int wmain()
{
// Input target file path
    std::wcout << L"Input target file path(Default C:\\Windows\\Temp\\testfile.txt): ";
    std::wstring path;
    std::getline(std::wcin, path);

path = handleInput(path);
    if (isEmpty(path)) {
path = L"C:\\Windows\\Temp\\testfile.txt";
    }

// Input desired access
    std::wcout << L"\nWhat is desired access?\n1:\"GENERIC_READ\"\n2:\"GENERIC_READ | GENERIC_WRITE\" : ";
    std::wstring desiredAccess;
    std::getline(std::wcin, desiredAccess);

desiredAccess = handleInput(desiredAccess);
    if (isEmpty(desiredAccess))
return 1;
 
// Input share mode
    std::wcout << L"\nWhat is share mode?\n1:\"FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE\"\n2:\"FILE_SHARE_READ\"\n3:\"FILE_SHARE_NONE\" : ";
    std::wstring shareMode;
    std::getline(std::wcin, shareMode);

shareMode = handleInput(shareMode);
if (isEmpty(shareMode))
return 1;
    
HANDLE hFile = createFileHandle(path, desiredAccess, shareMode);

    std::wcout << L"\nPlease Enter key to close.";
    std::wstring tmp;
    std::getline(std::wcin, tmp);

    CloseHandle(hFile);

    return 0;
}

Operation Check

When you run the tool built from the code above, you can execute CreateFileW by specifying the dwDesiredAccess and dwShareMode options as shown below.

image-20251119181145247

This makes it easy to verify behaviors such as CreateFile failing with SHARING VIOLATION when you execute CreateFile with FILE_SHARE_NONE against a file whose handle has already been obtained with FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE.

image-20251119181320435

image-20251119181540699

Summary

GitHub Copilot’s development assistance is so intelligent that writing code has become incredibly easy.

I also wrote this article in 10 minutes.