-
Notifications
You must be signed in to change notification settings - Fork 0
/
CustomFileProtocolHandler.cpp
156 lines (137 loc) · 4.78 KB
/
CustomFileProtocolHandler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "framework.h"
#include "resource.h"
#include "CFileProtocolHandlerService.h"
#include <windowsx.h>
#include <string>
#include <algorithm>
using namespace std::string_literals;
#define MAX_LOADSTRING 100
#define MAX_PROTOCOLNAME 64
// グローバル変数:
HINSTANCE hInst; // 現在のインターフェイス
WCHAR szTitle[MAX_LOADSTRING]; // タイトル バーのテキスト
WCHAR szProtocolName[MAX_PROTOCOLNAME] = L"set-your-protocol-name";
static CFileProtocolHandlerService* s_app;
EXTERN_C INT_PTR CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
static void HresultErrorMessageBox(HWND hWnd, HRESULT hr, const std::wstring& baseMessage)
{
HLOCAL msg = nullptr;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&msg), 0, nullptr);
::MessageBox(hWnd, (baseMessage + L"\n理由: " + reinterpret_cast<LPCWSTR>(msg)).c_str(), szTitle, MB_OK | MB_ICONERROR);
::LocalFree(msg);
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE /*hPrevInstance*/,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
hInst = hInstance;
//::CoInitialize(nullptr);
// グローバル文字列を初期化する
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
{
auto const modulePath = getModulePath() + L".protocolname";
FILE* file = nullptr;
_wfopen_s(&file, modulePath.c_str(), L"r");
if (file)
{
fgetws(szProtocolName, _countof(szProtocolName), file);
using namespace std;
std::replace_if(begin(szProtocolName), end(szProtocolName),
[](auto c) { return iswspace(c) || iswcntrl(c); }, L'\0');
}
}
CFileProtocolHandlerService app{ szProtocolName };
if (lpCmdLine && wcslen(lpCmdLine) > 0)
{
auto hr = app.OpenFile(lpCmdLine);
if (FAILED(hr) && HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr)
{
HresultErrorMessageBox(nullptr, hr, L"ShellExecuteExに失敗しました。:");
}
else if (S_FALSE == hr)
{
::MessageBox(nullptr, (L"プログラム引数が不正です。:`"s + lpCmdLine + L"`").c_str(), szTitle, MB_OK | MB_ICONERROR);
}
return 0;
}
s_app = &app;
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_FILEPROTOCOLHANDLER_DIALOG), nullptr, DialogProc, reinterpret_cast<LPARAM>(&app));
return 0;
}
void SetDialogItem(HWND hDlg, CFileProtocolHandlerService* app)
{
auto regsiterd = app->IsRegistered();
::EnableWindow(::GetDlgItem(hDlg, IDC_BUTTON_UNREGISTER), regsiterd == S_OK && app->IsValidProtocolName());
::EnableWindow(::GetDlgItem(hDlg, IDC_BUTTON_REGISTER), regsiterd == S_FALSE);
}
INT_PTR OnCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, id);
return (INT_PTR)TRUE;
case IDC_BUTTON_UNREGISTER:
{
auto registerdPath = s_app->GetRegisteredPath();
if (FAILED(registerdPath.first))
{
HresultErrorMessageBox(hDlg, registerdPath.first, L"レジストリの読み書きに失敗しました。:");
return (INT_PTR)TRUE;
}
if (IDOK != ::MessageBox(hDlg, (L"下記のコマンドで登録されています。\n続行しますか?\n" + registerdPath.second).c_str(), szTitle,
MB_OKCANCEL | MB_ICONQUESTION | MB_DEFBUTTON2))
{
return (INT_PTR)TRUE;
}
auto const hr = s_app->Unregister();
if (FAILED(hr))
HresultErrorMessageBox(hDlg, hr, L"解除に失敗しました。");
SetDialogItem(hDlg, s_app);
return (INT_PTR)TRUE;
}
case IDC_BUTTON_REGISTER:
{
auto const hr = s_app->Register();
if (FAILED(hr))
HresultErrorMessageBox(hDlg, hr, L"登録に失敗しました。");
SetDialogItem(hDlg, s_app);
return (INT_PTR)TRUE;
}
}
return (INT_PTR)FALSE;
}
BOOL OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lParam)
{
auto hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_SMALL), IMAGE_ICON, 16, 16, 0);
SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
::SetDlgItemText(hDlg, IDC_EDIT1, s_app->ProtocolName().c_str());
if (!s_app->IsValidProtocolName())
{
::MessageBox(hDlg, (L"プロトコル名が不正です。:`" + s_app->ProtocolName() + L"`").c_str(), szTitle, MB_OK | MB_ICONERROR);
}
SetDialogItem(hDlg, s_app);
auto regsiterd = s_app->IsRegistered();
if (FAILED(regsiterd))
{
HresultErrorMessageBox(hDlg, regsiterd, L"レジストリの読み書きに失敗しました。:"s);
}
return TRUE;
}
// バージョン情報ボックスのメッセージ ハンドラーです。
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return HANDLE_WM_INITDIALOG(hDlg, wParam, lParam, OnInitDialog);
case WM_COMMAND:
return HANDLE_WM_COMMAND(hDlg, wParam, lParam, OnCommand);
}
return (INT_PTR)FALSE;
}