All Articles

Windows で任意のフラグを使用してファイルハンドルを取得するためのツールを作成したメモ書き

検証用に任意の設定でファイルハンドルを取得できるツールが欲しいなと思い、シンプルなツールを作成してみました。

もくじ

ソースコード

#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;
}

動作確認

上記のコードをビルドしたツールを実行すると、以下のように使用する dwDesiredAccess と dwShareMode をオプションで指定して CreateFileW を実行することができます。

image-20251119181145247

これにより、例えばすでに FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE でハンドルが取得されているファイルに対して FILE_SHARE_NONE で CreateFile を実行すると SHARING VIOLATION で失敗する、みたいな動作を簡単に検証できるようになります。

image-20251119181320435

image-20251119181540699

まとめ

Github Copilot の開発支援がインテリジェンスすぎてめちゃくちゃコード書くのが楽になりました。

あとこの記事も 10 分で書きました。