検証用に任意の設定でファイルハンドルを取得できるツールが欲しいなと思い、シンプルなツールを作成してみました。
もくじ
ソースコード
#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 を実行することができます。
これにより、例えばすでに FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE でハンドルが取得されているファイルに対して FILE_SHARE_NONE で CreateFile を実行すると SHARING VIOLATION で失敗する、みたいな動作を簡単に検証できるようになります。
まとめ
Github Copilot の開発支援がインテリジェンスすぎてめちゃくちゃコード書くのが楽になりました。
あとこの記事も 10 分で書きました。