* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / WinUi.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // WinUi.c\r
79 // Win32 用ユーザーインターフェースコード\r
80 \r
81 #ifdef  WIN32\r
82 \r
83 #define WINUI_C\r
84 \r
85 #define _WIN32_WINNT            0x0502\r
86 #define WINVER                          0x0502\r
87 #include <winsock2.h>\r
88 #include <windows.h>\r
89 #include <wincrypt.h>\r
90 #include <wininet.h>\r
91 #include <Iphlpapi.h>\r
92 #include <shlobj.h>\r
93 #include <commctrl.h>\r
94 #include <Dbghelp.h>\r
95 #include <stdio.h>\r
96 #include <stdlib.h>\r
97 #include <string.h>\r
98 #include <wchar.h>\r
99 #include <stdarg.h>\r
100 #include <time.h>\r
101 #include <errno.h>\r
102 #include <Mayaqua/Mayaqua.h>\r
103 #include <Cedar/Cedar.h>\r
104 #include "../PenCore/resource.h"\r
105 \r
106 char cached_pin_code[MAX_SIZE] = {0};\r
107 UINT64 cached_pin_code_expires = 0;\r
108 \r
109 static HINSTANCE hDll = NULL;\r
110 static wchar_t *title_bar = NULL;\r
111 static char *font_name = NULL;\r
112 static UINT font_size = 9;\r
113 static HIMAGELIST large_image_list = NULL, small_image_list = NULL;\r
114 static LIST *icon_list = NULL;\r
115 static HINSTANCE hMsHtml = NULL;\r
116 static UINT init_winui_counter = 0;\r
117 static bool new_style_mode = false;\r
118 \r
119 bool UseAlpha = false;\r
120 UINT AlphaValue = 100;\r
121 \r
122 static THREAD *led_thread = NULL;\r
123 static bool thread_stop = false;\r
124 static bool g_led_special = false;\r
125 static bool g_tcpip_topmost = false;\r
126 \r
127 typedef struct GDI_CACHE\r
128 {\r
129         bool IsInited;\r
130         COLORREF BackgroundColor;\r
131         COLORREF ForegroundColor;\r
132         COLORREF TextBoxBackgroundColor;\r
133         HBRUSH BlackBrush;\r
134         HBRUSH WhiteBrush;\r
135         HBRUSH BackgroundColorBrush;\r
136         HBRUSH ForegroundColorBrush;\r
137         HBRUSH TextBoxBackgroundColorBrush;\r
138 } GDI_CACHE;\r
139 \r
140 static GDI_CACHE gdi_cache = { false, };\r
141 \r
142 // スプラッシュウインドウデータ\r
143 typedef struct SPLASH\r
144 {\r
145         HWND hWnd;\r
146         HWND hWndParent;\r
147         WINBMP *Bmp;\r
148         void *Param;\r
149         UINT64 Ticks;\r
150         UINT64 StartTick;\r
151         char *Title;\r
152         wchar_t *Caption;\r
153         HPEN LinePen;\r
154         WINMEMDC *BackDC;\r
155 } SPLASH;\r
156 \r
157 // 画面がフルカラーモードかどうか取得\r
158 bool IsFullColor()\r
159 {\r
160         bool ret = false;\r
161         HDC hDC = CreateCompatibleDC(0);\r
162 \r
163         if (GetDeviceCaps(hDC, BITSPIXEL) >= 16)\r
164         {\r
165                 ret = true;\r
166         }\r
167 \r
168         DeleteDC(hDC);\r
169 \r
170         return ret;\r
171 }\r
172 \r
173 // リストビューの背景に画像を表示する\r
174 void LvSetBkImage(HWND hWnd, UINT id, char *bmp_file_name)\r
175 {\r
176         LVBKIMAGE t;\r
177         char *tmp;\r
178         // 引数チェック\r
179         if (hWnd == NULL || bmp_file_name == NULL)\r
180         {\r
181                 return;\r
182         }\r
183         if (IsFullColor() == false)\r
184         {\r
185                 // 256 色モードの場合は表示しない\r
186                 return;\r
187         }\r
188 \r
189         Zero(&t, sizeof(t));\r
190 \r
191         tmp = MsCreateTempFileNameByExt(".bmp");\r
192 \r
193         FileCopy(bmp_file_name, tmp);\r
194 \r
195         t.ulFlags = LVBKIF_SOURCE_URL | LVBKIF_STYLE_NORMAL;\r
196         t.pszImage = tmp;\r
197         t.xOffsetPercent = 100;\r
198         t.yOffsetPercent = 100;\r
199 \r
200         ListView_SetBkImage(DlgItem(hWnd, id), &t);\r
201 \r
202         Free(tmp);\r
203 }\r
204 \r
205 // メモリ DC を解放する\r
206 void FreeMemDC(WINMEMDC *m)\r
207 {\r
208         // 引数チェック\r
209         if (m == NULL)\r
210         {\r
211                 return;\r
212         }\r
213 \r
214         DeleteDC(m->hDC);\r
215         DeleteObject(m->hBitmap);\r
216 \r
217         Free(m);\r
218 }\r
219 \r
220 // メモリ DC を作成する\r
221 WINMEMDC *NewMemDC(UINT width, UINT height)\r
222 {\r
223         WINMEMDC *m = ZeroMalloc(sizeof(WINMEMDC));\r
224         BITMAPINFOHEADER h;\r
225         BITMAPINFO bi;\r
226 \r
227         m->Width = width;\r
228         m->Height = height;\r
229 \r
230         m->hDC = CreateCompatibleDC(0);\r
231 \r
232         Zero(&h, sizeof(h));\r
233         h.biSize = sizeof(h);\r
234         h.biWidth = width;\r
235         h.biHeight = height;\r
236         h.biPlanes = 1;\r
237         h.biBitCount = 24;\r
238         h.biXPelsPerMeter = 2834;\r
239         h.biYPelsPerMeter = 2834;\r
240 \r
241         Zero(&bi, sizeof(bi));\r
242         Copy(&bi.bmiHeader, &h, sizeof(BITMAPINFOHEADER));\r
243 \r
244         m->hBitmap = CreateDIBSection(m->hDC, &bi, DIB_RGB_COLORS,\r
245                 &m->Data, NULL, 0);\r
246 \r
247         SelectObject(m->hDC, m->hBitmap);\r
248 \r
249         return m;\r
250 }\r
251 \r
252 // スプラッシュ画面を表示する (毎回絵が変わる)\r
253 void ShowSplashEx(HWND hWndParent, char *software_name, UINT ticks, UINT line_color)\r
254 {\r
255         wchar_t tmp[MAX_SIZE];\r
256         wchar_t caption[MAX_SIZE];\r
257         UINT id = MsRegReadInt(REG_CURRENT_USER, SPLASH_BMP_REGKEY, SPLASH_BMP_REGVALUE);\r
258         id++;\r
259         if (id > 20)\r
260         {\r
261                 id = 1;\r
262         }\r
263         MsRegWriteInt(REG_CURRENT_USER, SPLASH_BMP_REGKEY, SPLASH_BMP_REGVALUE, id);\r
264 \r
265         UniFormat(tmp, sizeof(tmp), L"|Splash%02u.bmp", id);\r
266 \r
267         StrToUni(caption, sizeof(caption), software_name);\r
268 \r
269         ShowSplash(hWndParent, tmp, software_name, caption, ticks, line_color, NULL);\r
270 }\r
271 \r
272 // フォント描画\r
273 void DrawFont(HDC hDC, wchar_t *text, UINT x, UINT y, HFONT font, UINT fore_color,\r
274                           UINT back_color, UINT back_width)\r
275 {\r
276         int i, j;\r
277 \r
278         SelectObject(hDC, font);\r
279         SetBkMode(hDC, TRANSPARENT);\r
280 \r
281         // 背景の描画\r
282         SetTextColor(hDC, back_color);\r
283         for (i = -((int)back_width);i <= (int)back_width;i++)\r
284         {\r
285                 for (j = -((int)back_width); j <= (int)back_width;j++)\r
286                 {\r
287                         if (i != 0 || j != 0)\r
288                         {\r
289                                 TextOutW(hDC, (int)x + i, (int)y + j, text, UniStrLen(text));\r
290                         }\r
291                 }\r
292         }\r
293 \r
294         // 文字の描画\r
295         SetTextColor(hDC, fore_color);\r
296         TextOutW(hDC, x, y, text, UniStrLen(text));\r
297 }\r
298 \r
299 // スプラッシュウインドウを開く\r
300 LRESULT CALLBACK SplashProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
301 {\r
302         SPLASH *splash;\r
303         CREATESTRUCT *cs = (CREATESTRUCT *)lParam;\r
304         UINT64 now = Tick64();\r
305         UINT64 current_span = 0;\r
306         UINT a;\r
307         UINT fade = 8;\r
308 \r
309         if (msg == WM_CREATE)\r
310         {\r
311                 splash = (SPLASH *)cs->lpCreateParams;\r
312                 current_span = 0;\r
313         }\r
314         else\r
315         {\r
316                 splash = (SPLASH *)GetWindowLongPtrA(hWnd, GWLP_USERDATA);\r
317                 if (splash != NULL)\r
318                 {\r
319                         current_span = now - splash->StartTick;\r
320                 }\r
321         }\r
322 \r
323         switch (msg)\r
324         {\r
325         case WM_CREATE:\r
326                 SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)splash);\r
327 \r
328                 CenterParent(hWnd);\r
329 \r
330                 if (splash->Ticks != 0)\r
331                 {\r
332                         SetTimer(hWnd, 1, 1, NULL);\r
333 \r
334                         splash->StartTick = now;\r
335 \r
336                         SetAplha(hWnd, 0);\r
337 \r
338                         Top(hWnd);\r
339                 }\r
340 \r
341                 break;\r
342 \r
343         case WM_TIMER:\r
344                 switch (wParam)\r
345                 {\r
346                 case 1:\r
347                         KillTimer(hWnd, 1);\r
348 \r
349                         a = 0;\r
350 \r
351                         if (current_span < (splash->Ticks / fade))\r
352                         {\r
353                                 // フェードイン\r
354                                 a = (UINT)((double)current_span * 255.0 / (double)(splash->Ticks / fade));\r
355                         }\r
356                         else if (current_span < (splash->Ticks * (fade - 1) / fade))\r
357                         {\r
358                                 // 通常表示\r
359                                 a = 255;\r
360                         }\r
361                         else if (current_span < splash->Ticks)\r
362                         {\r
363                                 // フェードアウト\r
364                                 a = 255 - (UINT)(((double)(current_span - (splash->Ticks * (fade - 1) / fade))) * 255.0 / (double)(splash->Ticks / fade));\r
365                         }\r
366                         else\r
367                         {\r
368                                 // 閉じる\r
369                                 goto LABEL_CLOSE;\r
370                         }\r
371 \r
372                         SetAplha(hWnd, a);\r
373 \r
374                         SetTimer(hWnd, 1, 1, NULL);\r
375                         break;\r
376                 }\r
377                 break;\r
378 \r
379         case WM_PAINT:\r
380                 if (true)\r
381                 {\r
382                         PAINTSTRUCT ps;\r
383                         HDC hDC, hWndDC;\r
384 \r
385                         Zero(&ps, sizeof(ps));\r
386                         hWndDC = BeginPaint(hWnd, &ps);\r
387                         if (hWndDC != NULL)\r
388                         {\r
389                                 POINT points[5];\r
390                                 wchar_t tmp[MAX_SIZE];\r
391 \r
392                                 hDC = splash->BackDC->hDC;\r
393 \r
394                                 // ビットマップ画像\r
395                                 BitBlt(hDC, 0, 0, splash->Bmp->Width, splash->Bmp->Height,\r
396                                         splash->Bmp->hDC, 0, 0, SRCCOPY);\r
397 \r
398                                 // 線\r
399                                 Zero(points, sizeof(points));\r
400                                 points[0].x = 0; points[0].y = 0;\r
401                                 points[1].x = splash->Bmp->Width - 1; points[1].y = 0;\r
402                                 points[2].x = splash->Bmp->Width - 1; points[2].y = splash->Bmp->Height - 1;\r
403                                 points[3].x = 0; points[3].y = splash->Bmp->Height - 1;\r
404                                 points[4].x = 0; points[4].y = 0;\r
405 \r
406                                 SelectObject(hDC, splash->LinePen);\r
407                                 Polyline(hDC, points, 5);\r
408 \r
409                                 // ソフトウェアのタイトルの描画\r
410                                 DrawFont(hDC, splash->Caption, 114, 136,\r
411                                         GetFont("Arial", 36, true, false, false, false),\r
412                                         RGB(0, 0, 0),\r
413                                         RGB(255, 255, 255),\r
414                                         3);\r
415 \r
416                                 // ソフトウェアのバージョン情報の描画\r
417                                 UniFormat(tmp, sizeof(tmp),\r
418                                         L"Version %u.%02u Build %u, Compiled in %04u/%02u/%02u.",\r
419                                         CEDAR_VER / 100, CEDAR_VER - (CEDAR_VER / 100) * 100,\r
420                                         CEDAR_BUILD, BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D);\r
421                                 DrawFont(hDC, tmp, 200, 202,\r
422                                         GetFont("Arial", 8, true, false, false, false),\r
423                                         RGB(0, 0, 0),\r
424                                         RGB(255, 255, 255),\r
425                                         1);\r
426 \r
427                                 // 画面に描画\r
428                                 BitBlt(hWndDC, 0, 0, splash->Bmp->Width, splash->Bmp->Height,\r
429                                         hDC, 0, 0, SRCCOPY);\r
430 \r
431                                 EndPaint(hWnd, &ps);\r
432                         }\r
433                 }\r
434                 break;\r
435 \r
436         case WM_CLOSE:\r
437                 if (splash->Ticks != 0)\r
438                 {\r
439                         return 0;\r
440                 }\r
441 LABEL_CLOSE:\r
442                 if (splash->hWndParent != NULL)\r
443                 {\r
444                         Enable(splash->hWndParent, 0);\r
445                 }\r
446                 DestroyWindow(hWnd);\r
447                 return 0;\r
448 \r
449         case WM_KEYDOWN:\r
450                 switch (wParam)\r
451                 {\r
452                 case VK_ESCAPE:\r
453                 case VK_RETURN:\r
454                 case VK_SPACE:\r
455                         Close(hWnd);\r
456                         break;\r
457                 }\r
458                 break;\r
459 \r
460         case WM_LBUTTONUP:\r
461         case WM_RBUTTONUP:\r
462         case WM_MBUTTONUP:\r
463                 Close(hWnd);\r
464                 break;\r
465 \r
466         case WM_DESTROY:\r
467                 if (splash->hWndParent != NULL)\r
468                 {\r
469                         Enable(splash->hWndParent, 0);\r
470                 }\r
471                 PostQuitMessage(0);\r
472                 return 0;\r
473         }\r
474 \r
475         return DefWindowProc(hWnd, msg, wParam, lParam);\r
476 }\r
477 \r
478 // スプラッシュウインドウ\r
479 void ShowSplash(HWND hWndParent, wchar_t *bmp_file_name, char *title, wchar_t *caption, UINT ticks, UINT line_color, void *param)\r
480 {\r
481         SPLASH *p;\r
482         WNDCLASSA wc;\r
483         char wndclass_name[MAX_SIZE];\r
484         // 引数チェック\r
485         if (bmp_file_name == NULL)\r
486         {\r
487                 return;\r
488         }\r
489         if (IsEmptyStr(title))\r
490         {\r
491                 title = "Splash Window";\r
492         }\r
493 \r
494         p = ZeroMalloc(sizeof(SPLASH));\r
495 \r
496         p->Bmp = LoadBmpFromFileW(bmp_file_name);\r
497         if (p->Bmp == NULL)\r
498         {\r
499                 Free(p);\r
500                 return;\r
501         }\r
502 \r
503         p->BackDC = NewMemDC(p->Bmp->Width, p->Bmp->Height);\r
504 \r
505         p->LinePen = CreatePen(PS_SOLID, 1, line_color);\r
506 \r
507         p->hWndParent = hWndParent;\r
508 \r
509         p->Title = title;\r
510         p->Caption = caption;\r
511         p->Ticks = ticks;\r
512 \r
513         p->Param = param;\r
514 \r
515         Zero(&wc, sizeof(wc));\r
516         wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);\r
517         wc.hCursor = LoadCursor(NULL, ticks == 0 ? IDC_ARROW : IDC_APPSTARTING);\r
518         wc.hInstance = GetModuleHandleA(NULL);\r
519         wc.lpfnWndProc = SplashProc;\r
520 \r
521         Format(wndclass_name, sizeof(wndclass_name), "WINUI_SPLASH_CLASS_%I64u", Rand64());\r
522         wc.lpszClassName = wndclass_name;\r
523 \r
524         RegisterClassA(&wc);\r
525 \r
526         p->hWnd = CreateWindowA(wndclass_name, title,\r
527                 WS_POPUP, 0, 0,\r
528                 p->Bmp->Width, p->Bmp->Height,\r
529                 hWndParent, NULL, GetModuleHandleA(NULL), p);\r
530         if (p->hWnd == NULL)\r
531         {\r
532                 Debug("CreateWindowA Error: %u\n", GetLastError());\r
533         }\r
534 \r
535         if (hWndParent != NULL)\r
536         {\r
537                 Disable(hWndParent, 0);\r
538         }\r
539 \r
540         ShowWindow(p->hWnd, SW_SHOW);\r
541 \r
542         if (p->hWnd != NULL)\r
543         {\r
544                 MSG msg;\r
545 \r
546                 while (true)\r
547                 {\r
548                         Zero(&msg, sizeof(msg));\r
549 \r
550                         if (GetMessageA(&msg, NULL, 0, 0) == 0)\r
551                         {\r
552                                 break;\r
553                         }\r
554 \r
555                         TranslateMessage(&msg);\r
556                         DispatchMessageA(&msg);\r
557                 }\r
558         }\r
559 \r
560         if (hWndParent != NULL)\r
561         {\r
562                 Enable(hWndParent, 0);\r
563                 SetActiveWindow(hWndParent);\r
564                 BringWindowToTop(hWndParent);\r
565         }\r
566 \r
567         UnregisterClassA(wndclass_name, GetModuleHandleA(NULL));\r
568 \r
569         FreeMemDC(p->BackDC);\r
570 \r
571         FreeBmp(p->Bmp);\r
572 \r
573         DeleteObject(p->LinePen);\r
574 \r
575         Free(p);\r
576 }\r
577 \r
578 // GDI オブジェクトのキャッシュがまだ作成されていない場合は作成する\r
579 void InitGdiCache()\r
580 {\r
581         if (gdi_cache.IsInited)\r
582         {\r
583                 return;\r
584         }\r
585 \r
586         gdi_cache.BlackBrush = GetStockObject(BLACK_BRUSH);\r
587         gdi_cache.WhiteBrush = GetStockObject(WHITE_BRUSH);\r
588 \r
589         gdi_cache.BackgroundColor = RGB(247, 238, 255);\r
590         gdi_cache.BackgroundColorBrush = CreateSolidBrush(gdi_cache.BackgroundColor);\r
591 \r
592         gdi_cache.ForegroundColor = RGB(0, 0, 0);\r
593         gdi_cache.ForegroundColorBrush = CreateSolidBrush(gdi_cache.ForegroundColor);\r
594 \r
595         gdi_cache.TextBoxBackgroundColor = RGB(255, 255, 255);\r
596         gdi_cache.TextBoxBackgroundColorBrush = CreateSolidBrush(gdi_cache.TextBoxBackgroundColor);\r
597 \r
598         gdi_cache.IsInited = true;\r
599 }\r
600 \r
601 // ビットマップをリソースから読む\r
602 WINBMP *LoadBmpFromResource(UINT id)\r
603 {\r
604         HANDLE h;\r
605         // 引数チェック\r
606         if (id == 0)\r
607         {\r
608                 return NULL;\r
609         }\r
610 \r
611         h = LoadImageA(hDll, MAKEINTRESOURCEA(id), IMAGE_BITMAP, 0, 0,\r
612                 LR_CREATEDIBSECTION | LR_VGACOLOR);\r
613 \r
614         if (h == NULL)\r
615         {\r
616                 return NULL;\r
617         }\r
618 \r
619         return LoadBmpMain(h);\r
620 }\r
621 \r
622 // ビットマップをファイルから読む\r
623 WINBMP *LoadBmpFromFileW(wchar_t *filename)\r
624 {\r
625         wchar_t tmp[MAX_SIZE];\r
626         char *tmpa;\r
627         // 引数チェック\r
628         if (filename == NULL)\r
629         {\r
630                 return NULL;\r
631         }\r
632 \r
633         // 一時ファイルにコピー\r
634         tmpa = MsCreateTempFileNameByExt("bmp");\r
635 \r
636         StrToUni(tmp, sizeof(tmp), tmpa);\r
637 \r
638         Free(tmpa);\r
639 \r
640         if (FileCopyW(filename, tmp) == false)\r
641         {\r
642                 return NULL;\r
643         }\r
644 \r
645         return LoadBmpFromFileInnerW(tmp);\r
646 }\r
647 WINBMP *LoadBmpFromFileInnerW(wchar_t *filename)\r
648 {\r
649         HANDLE h;\r
650         // 引数チェック\r
651         if (filename == NULL)\r
652         {\r
653                 return NULL;\r
654         }\r
655 \r
656         if (MsIsNt())\r
657         {\r
658                 h = LoadImageW(NULL, filename, IMAGE_BITMAP, 0, 0,\r
659                         LR_CREATEDIBSECTION | LR_LOADFROMFILE | LR_VGACOLOR);\r
660         }\r
661         else\r
662         {\r
663                 char tmp[MAX_SIZE];\r
664 \r
665                 UniToStr(tmp, sizeof(tmp), filename);\r
666 \r
667                 h = LoadImageA(NULL, tmp, IMAGE_BITMAP, 0, 0,\r
668                         LR_CREATEDIBSECTION | LR_LOADFROMFILE | LR_VGACOLOR);\r
669         }\r
670 \r
671         if (h == NULL)\r
672         {\r
673                 return NULL;\r
674         }\r
675 \r
676         return LoadBmpMain(h);\r
677 }\r
678 WINBMP *LoadBmpFromFileA(char *filename)\r
679 {\r
680         wchar_t tmp[MAX_SIZE];\r
681         // 引数チェック\r
682         if (filename == NULL)\r
683         {\r
684                 return NULL;\r
685         }\r
686 \r
687         StrToUni(tmp, sizeof(tmp), filename);\r
688 \r
689         return LoadBmpFromFileW(tmp);\r
690 }\r
691 \r
692 // ビットマップ読み込みメイン\r
693 WINBMP *LoadBmpMain(void *hBitmap)\r
694 {\r
695         WINBMP *b;\r
696         BITMAP d;\r
697         HDC hDC;\r
698         // 引数チェック\r
699         if (hBitmap == NULL)\r
700         {\r
701                 return NULL;\r
702         }\r
703 \r
704         Zero(&d, sizeof(d));\r
705 \r
706         if (GetObject((HANDLE)hBitmap, sizeof(d), &d) == 0)\r
707         {\r
708                 DeleteObject((HANDLE)hBitmap);\r
709                 return NULL;\r
710         }\r
711 \r
712         b = ZeroMalloc(sizeof(WINBMP));\r
713         b->Bits = d.bmBitsPixel;\r
714         b->hBitmap = hBitmap;\r
715         b->Height = d.bmHeight;\r
716         b->Width = d.bmWidth;\r
717 \r
718         hDC = CreateCompatibleDC(0);\r
719 \r
720         SelectObject(hDC, hBitmap);\r
721 \r
722         b->hDC = hDC;\r
723 \r
724         return b;\r
725 }\r
726 \r
727 // ビットマップを解放する\r
728 void FreeBmp(WINBMP *b)\r
729 {\r
730         // 引数チェック\r
731         if (b == NULL)\r
732         {\r
733                 return;\r
734         }\r
735 \r
736         DeleteDC(b->hDC);\r
737         DeleteObject(b->hBitmap);\r
738 \r
739         Free(b);\r
740 }\r
741 \r
742 // 新しいスタイルを開始\r
743 void EnableNewStyleMode()\r
744 {\r
745         InitGdiCache();\r
746 \r
747         new_style_mode = true;\r
748 }\r
749 \r
750 // 新しいスタイルを終了\r
751 void DisableNewStyleMode()\r
752 {\r
753         new_style_mode = false;\r
754 }\r
755 \r
756 // 新しいスタイルが有効になっているかどうかチェック\r
757 bool IsNewStyleModeEnabled()\r
758 {\r
759         return new_style_mode;\r
760 }\r
761 \r
762 // NIC 情報ダイアログプロシージャ\r
763 UINT NicInfoProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
764 {\r
765         UI_NICINFO *info = (UI_NICINFO *)param;\r
766 \r
767         switch (msg)\r
768         {\r
769         case WM_INITDIALOG:\r
770                 NicInfoInit(hWnd, info);\r
771 \r
772                 SetTimer(hWnd, 1, 50, NULL);\r
773                 break;\r
774 \r
775         case WM_TIMER:\r
776                 switch (wParam)\r
777                 {\r
778                 case 1:\r
779                         KillTimer(hWnd, 1);\r
780 \r
781                         NicInfoOnTimer(hWnd, info);\r
782 \r
783                         SetTimer(hWnd, 1, 50, NULL);\r
784                         break;\r
785 \r
786                 case 2:\r
787                         KillTimer(hWnd, 2);\r
788                         Close(hWnd);\r
789                         break;\r
790                 }\r
791                 break;\r
792 \r
793         case WM_COMMAND:\r
794                 switch (wParam)\r
795                 {\r
796                 case IDOK:\r
797                 case IDCANCEL:\r
798                         Close(hWnd);\r
799                         break;\r
800                 }\r
801                 break;\r
802 \r
803         case WM_CLOSE:\r
804                 KillTimer(hWnd, 1);\r
805                 KillTimer(hWnd, 2);\r
806                 EndDialog(hWnd, 0);\r
807                 break;\r
808         }\r
809 \r
810         return 0;\r
811 }\r
812 void NicInfoCloseAfterTime(HWND hWnd, UI_NICINFO *info, UINT tick)\r
813 {\r
814         UINT64 now;\r
815         UINT64 closetime;\r
816         // 引数チェック\r
817         if (hWnd == NULL || info == NULL)\r
818         {\r
819                 return;\r
820         }\r
821 \r
822         now = Tick64();\r
823         closetime = now + (UINT64)tick;\r
824 \r
825         if (info->CloseAfterTime == 0 || info->CloseAfterTime >= closetime)\r
826         {\r
827                 info->CloseAfterTime = closetime;\r
828                 KillTimer(hWnd, 2);\r
829                 SetTimer(hWnd, 2, tick, NULL);\r
830         }\r
831 }\r
832 void NicInfoShowStatus(HWND hWnd, UI_NICINFO *info, wchar_t *msg1, wchar_t *msg2, UINT icon, bool animate)\r
833 {\r
834         // 引数チェック\r
835         if (hWnd == NULL || info == NULL)\r
836         {\r
837                 return;\r
838         }\r
839         if (icon == 0)\r
840         {\r
841                 icon = ICO_TEST;\r
842         }\r
843         if (msg1 == NULL)\r
844         {\r
845                 msg1 = L"";\r
846         }\r
847         if (msg2 == NULL)\r
848         {\r
849                 msg2 = L"";\r
850         }\r
851 \r
852         if (info->CurrentIcon != icon)\r
853         {\r
854                 SetIcon(hWnd, S_ICON, icon);\r
855                 info->CurrentIcon = icon;\r
856         }\r
857 \r
858         SetText(hWnd, S_STATUS1, msg1);\r
859         SetText(hWnd, S_STATUS2, msg2);\r
860 \r
861         SetShow(hWnd, P_BAR, animate && MsIsWinXPOrWinVista());\r
862 }\r
863 void NicInfoRefresh(HWND hWnd, UI_NICINFO *info)\r
864 {\r
865         MS_ADAPTER *a;\r
866         IP ip;\r
867         char ip_str[MAX_SIZE];\r
868         char title[MAX_SIZE];\r
869         UINT i;\r
870         wchar_t tmp[MAX_SIZE];\r
871         bool has_ip = false;\r
872         // 引数チェック\r
873         if (hWnd == NULL || info == NULL)\r
874         {\r
875                 return;\r
876         }\r
877 \r
878         Format(title, sizeof(title), VLAN_ADAPTER_NAME_TAG, info->NicName);\r
879 \r
880         a = MsGetAdapter(title);\r
881         if (a == NULL)\r
882         {\r
883                 Close(hWnd);\r
884                 return;\r
885         }\r
886 \r
887         // IP アドレスが割り当てら割れているかどうかチェック\r
888         Zero(&ip, sizeof(ip));\r
889         for (i = 0;i < MAX_MS_ADAPTER_IP_ADDRESS;i++)\r
890         {\r
891                 if (IsZeroIP(&a->IpAddresses[i]) == false)\r
892                 {\r
893                         Copy(&ip, &a->IpAddresses[i], sizeof(IP));\r
894 \r
895                         if (!(ip.addr[0] == 169 && ip.addr[1] == 254))\r
896                         {\r
897                                 has_ip = true;\r
898                         }\r
899                 }\r
900         }\r
901         IPToStr(ip_str, sizeof(ip_str), &ip);\r
902 \r
903         if (has_ip == false)\r
904         {\r
905                 if (a->UseDhcp)\r
906                 {\r
907                         NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_1"), ICO_NIC_OFFLINE, true);\r
908                 }\r
909                 else\r
910                 {\r
911                         NicInfoShowStatus(hWnd, info, _UU("NICINFO_1"), _UU("NICINFO_1_2"), ICO_NIC_OFFLINE, true);\r
912                 }\r
913         }\r
914         else\r
915         {\r
916                 if (a->UseDhcp)\r
917                 {\r
918                         UniFormat(tmp, sizeof(tmp), _UU("NICINFO_2_1"), ip_str);\r
919                         NicInfoShowStatus(hWnd, info, _UU("NICINFO_2"), tmp, ICO_NIC_ONLINE, false);\r
920                 }\r
921                 else\r
922                 {\r
923                         UniFormat(tmp, sizeof(tmp), _UU("NICINFO_3_1"), ip_str);\r
924                         NicInfoShowStatus(hWnd, info, _UU("NICINFO_3"), tmp, ICO_NIC_ONLINE, false);\r
925                 }\r
926 \r
927                 NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_2);\r
928         }\r
929 \r
930         MsFreeAdapter(a);\r
931 }\r
932 void NicInfoInit(HWND hWnd, UI_NICINFO *info)\r
933 {\r
934         // 引数チェック\r
935         if (hWnd == NULL || info == NULL)\r
936         {\r
937                 return;\r
938         }\r
939 \r
940         if (MsIsWinXPOrWinVista())\r
941         {\r
942                 // Windows XP 以降の場合はプログレスバーを表示する\r
943                 SendMsg(hWnd, P_BAR, PBM_SETMARQUEE, TRUE, 150);\r
944                 SetStyle(hWnd, P_BAR, PBS_MARQUEE);\r
945         }\r
946 \r
947         DlgFont(hWnd, S_STATUS1, 9, false);\r
948         DlgFont(hWnd, S_STATUS2, 11, false);\r
949 \r
950         SetIcon(hWnd, 0, ICO_NIC_ONLINE);\r
951 \r
952         FormatText(hWnd, 0, info->NicName);\r
953 \r
954         NicInfoRefresh(hWnd, info);\r
955 \r
956         NicInfoCloseAfterTime(hWnd, info, NICINFO_AUTOCLOSE_TIME_1);\r
957 }\r
958 void NicInfoOnTimer(HWND hWnd, UI_NICINFO *info)\r
959 {\r
960         // 引数チェック\r
961         if (hWnd == NULL || info == NULL)\r
962         {\r
963                 return;\r
964         }\r
965 \r
966         if (info->Halt)\r
967         {\r
968                 Close(hWnd);\r
969                 return;\r
970         }\r
971 \r
972         if (info->RouteChange != NULL &&\r
973                 IsRouteChanged(info->RouteChange) == false)\r
974         {\r
975                 return;\r
976         }\r
977 \r
978         NicInfoRefresh(hWnd, info);\r
979 }\r
980 \r
981 // NIC 情報ダイアログの表示\r
982 void NicInfo(UI_NICINFO *info)\r
983 {\r
984         // 引数チェック\r
985         if (info == NULL)\r
986         {\r
987                 return;\r
988         }\r
989 \r
990         info->RouteChange = NewRouteChange();\r
991 \r
992         DialogEx2(NULL, D_NICINFO, NicInfoProc, info, true, true);\r
993 \r
994         FreeRouteChange(info->RouteChange);\r
995         info->RouteChange = NULL;\r
996 }\r
997 \r
998 // TCP 接続スレッド\r
999 void WinConnectDlgThread(THREAD *thread, void *param)\r
1000 {\r
1001         SOCK *s;\r
1002         WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;\r
1003         // 引数チェック\r
1004         if (d == NULL || thread == NULL)\r
1005         {\r
1006                 return;\r
1007         }\r
1008 \r
1009         // ソケット接続\r
1010         s = ConnectEx2(d->hostname, d->port, d->timeout, &d->cancel);\r
1011 \r
1012         d->ret_sock = s;\r
1013 \r
1014         PostMessageA(d->hWnd, WM_APP + 68, 0, 0);\r
1015 }\r
1016 \r
1017 // TCP 接続ダイアログプロシージャ\r
1018 UINT WinConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
1019 {\r
1020         WINCONNECT_DLG_DATA *d = (WINCONNECT_DLG_DATA *)param;\r
1021         // 引数チェック\r
1022         if (hWnd == NULL || d == NULL)\r
1023         {\r
1024                 return 0;\r
1025         }\r
1026 \r
1027         switch (msg)\r
1028         {\r
1029         case WM_INITDIALOG:\r
1030                 // UI 設定\r
1031                 CenterParent(hWnd);\r
1032                 SetText(hWnd, 0, d->caption);\r
1033                 SetText(hWnd, S_INFO, d->info);\r
1034                 SetIcon(hWnd, S_ICON, d->icon_id);\r
1035                 d->hWnd = hWnd;\r
1036 \r
1037                 if (MsIsWinXPOrWinVista())\r
1038                 {\r
1039                         // Windows XP 以降の場合はプログレスバーを表示する\r
1040                         SendMsg(hWnd, IDC_PROGRESS1, PBM_SETMARQUEE, TRUE, 100);\r
1041                         SetStyle(hWnd, IDC_PROGRESS1, PBS_MARQUEE);\r
1042                 }\r
1043                 else\r
1044                 {\r
1045                         // Windows 2000 以前の場合はプログレスバーを非表示にする\r
1046                         Hide(hWnd, IDC_PROGRESS1);\r
1047                 }\r
1048 \r
1049                 // スレッドの作成\r
1050                 d->thread = NewThread(WinConnectDlgThread, d);\r
1051                 break;\r
1052 \r
1053         case WM_COMMAND:\r
1054                 switch (wParam)\r
1055                 {\r
1056                 case IDCANCEL:\r
1057                         Close(hWnd);\r
1058                         break;\r
1059                 }\r
1060                 break;\r
1061 \r
1062         case WM_APP + 68:\r
1063         case WM_CLOSE:\r
1064                 if (d->cancel == false)\r
1065                 {\r
1066                         d->cancel = true;\r
1067                         Disable(hWnd, IDCANCEL);\r
1068                         if (d->ret_sock == NULL)\r
1069                         {\r
1070                                 SetText(hWnd, S_INFO, _UU("CONNECTDLG_CANCELING"));\r
1071                         }\r
1072                         DoEvents(hWnd);\r
1073                         Refresh(hWnd);\r
1074                         WaitThread(d->thread, INFINITE);\r
1075                         ReleaseThread(d->thread);\r
1076                         EndDialog(hWnd, 0);\r
1077                 }\r
1078                 break;\r
1079         }\r
1080 \r
1081         return 0;\r
1082 }\r
1083 \r
1084 // TCP 接続を UI を表示しながら実施\r
1085 SOCK *WinConnectEx2(HWND hWnd, char *server, UINT port, UINT timeout, UINT icon_id, wchar_t *caption, wchar_t *info)\r
1086 {\r
1087         wchar_t tmp[MAX_SIZE];\r
1088         wchar_t tmp2[MAX_SIZE];\r
1089         WINCONNECT_DLG_DATA d;\r
1090         // 引数チェック\r
1091         if (server == NULL || port == 0)\r
1092         {\r
1093                 return NULL;\r
1094         }\r
1095         if (icon_id == 0)\r
1096         {\r
1097                 icon_id = ICO_USER_ADMIN;\r
1098         }\r
1099         if (caption == NULL)\r
1100         {\r
1101                 if (hWnd == NULL)\r
1102                 {\r
1103                         caption = _UU("CONNECTDLG_CAPTION");\r
1104                 }\r
1105                 else\r
1106                 {\r
1107                         GetTxt(hWnd, 0, tmp2, sizeof(tmp2));\r
1108                         caption = tmp2;\r
1109                 }\r
1110         }\r
1111         if (info == NULL)\r
1112         {\r
1113                 UniFormat(tmp, sizeof(tmp), _UU("CONNECTDLG_MESSAGE"), server, port);\r
1114 \r
1115                 info = tmp;\r
1116         }\r
1117 \r
1118         Zero(&d, sizeof(d));\r
1119 \r
1120         d.cancel = false;\r
1121         d.caption = caption;\r
1122         d.icon_id = icon_id;\r
1123         d.info = info;\r
1124         d.timeout = timeout;\r
1125         d.hostname = server;\r
1126         d.port = port;\r
1127 \r
1128         Dialog(hWnd, D_CONNECT, WinConnectDlgProc, &d);\r
1129 \r
1130         return d.ret_sock;\r
1131 }\r
1132 \r
1133 // Windows ネットワーク設定画面の表示\r
1134 bool ShowWindowsNetworkConnectionDialog()\r
1135 {\r
1136         wchar_t exe_name[MAX_SIZE];\r
1137         void *proc;\r
1138 \r
1139         CombinePathW(exe_name, sizeof(exe_name), MsGetSystem32DirW(), L"control.exe");\r
1140 \r
1141         proc = Win32RunEx2W(exe_name, L"netconnections", false, NULL);\r
1142 \r
1143         if (proc == NULL)\r
1144         {\r
1145                 return false;\r
1146         }\r
1147 \r
1148         Win32CloseProcess(proc);\r
1149 \r
1150         return true;\r
1151 }\r
1152 \r
1153 // メイリオフォントの取得\r
1154 HFONT GetMeiryoFont()\r
1155 {\r
1156         return GetMeiryoFontEx(0);\r
1157 }\r
1158 HFONT GetMeiryoFontEx(UINT font_size)\r
1159 {\r
1160         // 少し適当な処理。日本語版では Meiryo, 中文版では Microsoft YaHei を使用する。\r
1161         if (_GETLANG() == 0)\r
1162         {\r
1163                 return GetFont("Meiryo", font_size, false, false, false, false);\r
1164         }\r
1165         else if (_GETLANG() == 2)\r
1166         {\r
1167                 return GetFont("Microsoft YaHei", font_size, false, false, false, false);\r
1168         }\r
1169         else\r
1170         {\r
1171                 return GetFont(NULL, font_size, false, false, false, false);\r
1172         }\r
1173 }\r
1174 \r
1175 // メイリオフォントに設定\r
1176 void SetFontMeiryo(HWND hWnd, UINT id)\r
1177 {\r
1178         SetFont(hWnd, id, GetMeiryoFont());\r
1179 }\r
1180 \r
1181 // デフォルトフォントに設定\r
1182 void SetFontDefault(HWND hWnd, UINT id)\r
1183 {\r
1184         SetFont(hWnd, id, GetDialogDefaultFont());\r
1185 }\r
1186 \r
1187 // 悪いプロセスに関する警告メッセージの表示\r
1188 void ShowBadProcessWarning(HWND hWnd, BAD_PROCESS *bad)\r
1189 {\r
1190         wchar_t title[MAX_SIZE];\r
1191         wchar_t message[8192];\r
1192         // 引数チェック\r
1193         if (bad == NULL)\r
1194         {\r
1195                 return;\r
1196         }\r
1197 \r
1198         UniFormat(title, sizeof(title), _UU("BAD_PROCESS_TITLE"), bad->Title);\r
1199         UniFormat(message, sizeof(message), _UU("BAD_PROCESS_MESSAGE"),\r
1200                 bad->Title, bad->Title, bad->Title, bad->Title);\r
1201 \r
1202         OnceMsg(hWnd, title, message, true, ICO_WARNING);\r
1203 }\r
1204 \r
1205 // 競合するアンチウイルスソフトの一覧を検索し、該当するものがあれば表示する\r
1206 bool CheckBadProcesses(HWND hWnd)\r
1207 {\r
1208         bool ret = true;\r
1209         UINT i;\r
1210         LIST *o;\r
1211 \r
1212         o = MsGetProcessList();\r
1213 \r
1214         for (i = 0;i < LIST_NUM(o);i++)\r
1215         {\r
1216                 MS_PROCESS *p = LIST_DATA(o, i);\r
1217                 char exe[MAX_PATH];\r
1218                 BAD_PROCESS *bad;\r
1219 \r
1220                 GetFileNameFromFilePath(exe, sizeof(exe), p->ExeFilename);\r
1221 \r
1222                 bad = IsBadProcess(exe);\r
1223 \r
1224                 if (bad != NULL)\r
1225                 {\r
1226                         // 悪いプロセスを発見したのでメッセージを表示する\r
1227                         ret = false;\r
1228 \r
1229                         ShowBadProcessWarning(hWnd, bad);\r
1230                 }\r
1231         }\r
1232 \r
1233         MsFreeProcessList(o);\r
1234 \r
1235         return ret;\r
1236 }\r
1237 \r
1238 // 指定したプロセス名が悪いプロセスに該当するかどうか検索する\r
1239 BAD_PROCESS *IsBadProcess(char *exe)\r
1240 {\r
1241         UINT i;\r
1242         // 引数チェック\r
1243         if (exe == NULL)\r
1244         {\r
1245                 return NULL;\r
1246         }\r
1247 \r
1248         for (i = 0;i < num_bad_processes;i++)\r
1249         {\r
1250                 BAD_PROCESS *bad = &bad_processes[i];\r
1251 \r
1252                 if (StrCmpi(bad->ExeName, exe) == 0)\r
1253                 {\r
1254                         return bad;\r
1255                 }\r
1256         }\r
1257 \r
1258         return NULL;\r
1259 }\r
1260 \r
1261 // メッセージ表示プロシージャ\r
1262 UINT OnceMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
1263 {\r
1264         ONCEMSG_DLG *d = (ONCEMSG_DLG *)param;\r
1265         // 引数チェック\r
1266         if (hWnd == NULL)\r
1267         {\r
1268                 return 0;\r
1269         }\r
1270 \r
1271         switch (msg)\r
1272         {\r
1273         case WM_INITDIALOG:\r
1274                 SetText(hWnd, 0, d->Title);\r
1275                 SetText(hWnd, E_TEXT, d->Message);\r
1276                 SetShow(hWnd, C_DONTSHOWAGAIN, d->ShowCheckbox);\r
1277                 //DisableClose(hWnd);\r
1278                 Focus(hWnd, IDCANCEL);\r
1279                 if (d->Icon != 0)\r
1280                 {\r
1281                         SetIcon(hWnd, 0, d->Icon);\r
1282                 }\r
1283 \r
1284                 if (MsIsVista())\r
1285                 {\r
1286                         SetFont(hWnd, E_TEXT, GetMeiryoFont());\r
1287                 }\r
1288                 else\r
1289                 {\r
1290                         DlgFont(hWnd, E_TEXT, 11, false);\r
1291                 }\r
1292 \r
1293                 SetTimer(hWnd, 1, 50, NULL);\r
1294                 break;\r
1295 \r
1296         case WM_TIMER:\r
1297                 switch (wParam)\r
1298                 {\r
1299                 case 1:\r
1300                         if (*d->halt)\r
1301                         {\r
1302                                 Close(hWnd);\r
1303                         }\r
1304                         break;\r
1305                 }\r
1306                 break;\r
1307 \r
1308         case WM_COMMAND:\r
1309                 switch (wParam)\r
1310                 {\r
1311                 case IDOK:\r
1312                 case IDCANCEL:\r
1313                         Close(hWnd);\r
1314                         break;\r
1315                 }\r
1316                 break;\r
1317 \r
1318         case WM_CLOSE:\r
1319                 KillTimer(hWnd, 1);\r
1320                 d->Checked = IsChecked(hWnd, C_DONTSHOWAGAIN);\r
1321                 EndDialog(hWnd, 0);\r
1322                 break;\r
1323         }\r
1324 \r
1325         return 0;\r
1326 }\r
1327 \r
1328 // メッセージを表示する\r
1329 void OnceMsg(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon)\r
1330 {\r
1331         OnceMsgEx(hWnd, title, message, show_checkbox, icon, NULL);\r
1332 }\r
1333 void OnceMsgEx(HWND hWnd, wchar_t *title, wchar_t *message, bool show_checkbox, UINT icon, bool *halt)\r
1334 {\r
1335         ONCEMSG_DLG d;\r
1336         UINT hash;\r
1337         char valuename[MAX_PATH];\r
1338         bool b_dummy = false;\r
1339         // 引数チェック\r
1340         if (title == NULL)\r
1341         {\r
1342                 title = title_bar;\r
1343         }\r
1344         if (message == NULL)\r
1345         {\r
1346                 message = L"message";\r
1347         }\r
1348         if (halt == NULL)\r
1349         {\r
1350                 halt = &b_dummy;\r
1351         }\r
1352 \r
1353         Zero(&d, sizeof(d));\r
1354         d.Message = message;\r
1355         d.Title = title;\r
1356         d.ShowCheckbox = show_checkbox;\r
1357         d.Icon = icon;\r
1358         d.halt = halt;\r
1359 \r
1360         hash = GetOnceMsgHash(title, message);\r
1361         Format(valuename, sizeof(valuename), ONCE_MSG_REGVALUE, hash);\r
1362 \r
1363         if (MsRegReadInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename) == 0)\r
1364         {\r
1365                 switch (icon)\r
1366                 {\r
1367                 case ICO_WARNING:\r
1368                         MessageBeep(MB_ICONEXCLAMATION);\r
1369                         break;\r
1370 \r
1371                 case ICO_INFORMATION:\r
1372                         MessageBeep(MB_ICONASTERISK);\r
1373                         break;\r
1374                 }\r
1375 \r
1376                 Dialog(hWnd, D_ONCEMSG, OnceMsgProc, &d);\r
1377 \r
1378                 if (show_checkbox)\r
1379                 {\r
1380                         if (d.Checked)\r
1381                         {\r
1382                                 MsRegWriteInt(REG_CURRENT_USER, ONCE_MSG_REGKEY, valuename, 1);\r
1383                         }\r
1384                 }\r
1385         }\r
1386 }\r
1387 \r
1388 // メッセージハッシュの取得\r
1389 UINT GetOnceMsgHash(wchar_t *title, wchar_t *message)\r
1390 {\r
1391         BUF *b;\r
1392         UCHAR hash[SHA1_SIZE];\r
1393         UINT ret;\r
1394         // 引数チェック\r
1395         if (title == NULL)\r
1396         {\r
1397                 title = title_bar;\r
1398         }\r
1399         if (message == NULL)\r
1400         {\r
1401                 message = L"message";\r
1402         }\r
1403 \r
1404         b = NewBuf();\r
1405         WriteBuf(b, title, UniStrSize(title));\r
1406         WriteBuf(b, message, UniStrSize(message));\r
1407         HashSha1(hash, b->Buf, b->Size);\r
1408         FreeBuf(b);\r
1409 \r
1410         Copy(&ret, hash, sizeof(UINT));\r
1411 \r
1412         return ret;\r
1413 }\r
1414 \r
1415 // Windows Vista のテーマを設定する\r
1416 void InitVistaWindowTheme(HWND hWnd)\r
1417 {\r
1418         static HINSTANCE hInstDll = NULL;\r
1419         HRESULT (WINAPI *_SetWindowTheme)(HWND, LPCWSTR, LPCWSTR) = NULL;\r
1420 \r
1421         if (MsIsVista() == false)\r
1422         {\r
1423                 return;\r
1424         }\r
1425 \r
1426         if (hInstDll == NULL)\r
1427         {\r
1428                 hInstDll = LoadLibraryA("uxtheme.dll");\r
1429         }\r
1430 \r
1431         if (hInstDll == NULL)\r
1432         {\r
1433                 return;\r
1434         }\r
1435 \r
1436         if (_SetWindowTheme == NULL)\r
1437         {\r
1438                 _SetWindowTheme = (HRESULT (WINAPI *)(HWND,LPCWSTR,LPCWSTR))GetProcAddress(hInstDll, "SetWindowTheme");\r
1439         }\r
1440 \r
1441         if (_SetWindowTheme == NULL)\r
1442         {\r
1443                 return;\r
1444         }\r
1445 \r
1446         _SetWindowTheme(hWnd, L"explorer", NULL);\r
1447 }\r
1448 \r
1449 // 現在のディレクトリに存在する可能性のある Windows ファイアウォールに登録すべき\r
1450 // すべてのアプリケーションを登録する\r
1451 // Q. 行儀が悪いのではないか?\r
1452 // A. 確かに行儀が悪いが、Windows Firewall でブロックされていることが原因で\r
1453 //    VPN ソフトウェアが使用できないという苦情メールがよく来ていたので\r
1454 //    やむを得ずこのように行うことにした。\r
1455 //    なお、Microsoft 純正のサーバーソフトや他社のサーバーソフト等もこのように\r
1456 //    して対応しているようであるから、良いのではないか。\r
1457 void RegistWindowsFirewallAll()\r
1458 {\r
1459         MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "utvpnclient.exe");\r
1460         MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "utvpnclient_x64.exe");\r
1461         MsRegistWindowsFirewallEx2(CEDAR_CLIENT_STR, "utvpnclient_ia64.exe");\r
1462 \r
1463         MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "utvpncmgr.exe");\r
1464         MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "utvpncmgr_x64.exe");\r
1465         MsRegistWindowsFirewallEx2(CEDAR_CLIENT_MANAGER_STR, "utvpncmgr_ia64.exe");\r
1466 \r
1467         MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "utvpnserver.exe");\r
1468         MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "utvpnserver_x64.exe");\r
1469         MsRegistWindowsFirewallEx2(CEDAR_SERVER_STR, "utvpnserver_ia64.exe");\r
1470 \r
1471         MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "utvpncmd.exe");\r
1472         MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "utvpncmd_x64.exe");\r
1473         MsRegistWindowsFirewallEx2(CEDAR_CUI_STR, "utvpncmd_ia64.exe");\r
1474 \r
1475         MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "ham.exe");\r
1476         MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "ham_x64.exe");\r
1477         MsRegistWindowsFirewallEx2(CEDAR_PRODUCT_STR, "ham_ia64.exe");\r
1478 }\r
1479 \r
1480 // すでに通知サービスが動作しているかどうかチェックする\r
1481 bool Win32CnCheckAlreadyExists(bool lock)\r
1482 {\r
1483         char tmp[MAX_SIZE];\r
1484         HANDLE hMutex;\r
1485 \r
1486         HashInstanceNameLocal(tmp, sizeof(tmp), CLIENT_NOTIFY_SERVICE_INSTANCENAME);\r
1487 \r
1488         hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, tmp);\r
1489         if (hMutex != NULL)\r
1490         {\r
1491                 CloseHandle(hMutex);\r
1492                 return true;\r
1493         }\r
1494 \r
1495         if (lock == false)\r
1496         {\r
1497                 return false;\r
1498         }\r
1499 \r
1500         hMutex = CreateMutex(NULL, FALSE, tmp);\r
1501         if (hMutex == NULL)\r
1502         {\r
1503                 CloseHandle(hMutex);\r
1504                 return true;\r
1505         }\r
1506 \r
1507         return false;\r
1508 }\r
1509 \r
1510 // hamcore 内の EXE の実行\r
1511 bool ExecuteHamcoreExe(char *name)\r
1512 {\r
1513         BUF *b;\r
1514         wchar_t tmp[MAX_PATH];\r
1515         char tmp2[MAX_PATH];\r
1516         UCHAR hash[MD5_SIZE];\r
1517         // 引数チェック\r
1518         if (name == NULL)\r
1519         {\r
1520                 return false;\r
1521         }\r
1522 \r
1523         b = ReadDump(name);\r
1524         if (b == NULL)\r
1525         {\r
1526                 return false;\r
1527         }\r
1528 \r
1529         Hash(hash, name, StrLen(name), false);\r
1530         BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));\r
1531         UniFormat(tmp, sizeof(tmp), L"%s\\tmp_%S.exe", MsGetMyTempDirW(), tmp2);\r
1532         SeekBuf(b, 0, 0);\r
1533         DumpBufW(b, tmp);\r
1534 \r
1535         FreeBuf(b);\r
1536 \r
1537         return RunW(tmp, NULL, false, false);\r
1538 }\r
1539 \r
1540 // イースターエッグの表示\r
1541 void ShowEasterEgg(HWND hWnd)\r
1542 {\r
1543 }\r
1544 \r
1545 void KakushiThread(THREAD *thread, void *param)\r
1546 {\r
1547         KAKUSHI *k;\r
1548         // 引数チェック\r
1549         if (thread == NULL || param == NULL)\r
1550         {\r
1551                 return;\r
1552         }\r
1553 \r
1554         k = (KAKUSHI *)param;\r
1555 \r
1556         k->Thread = thread;\r
1557         AddRef(k->Thread->ref);\r
1558         NoticeThreadInit(thread);\r
1559 \r
1560         Dialog(NULL, D_CM_KAKUSHI, KakushiDlgProc, k);\r
1561         k->hWnd = NULL;\r
1562 }\r
1563 \r
1564 KAKUSHI *InitKakushi()\r
1565 {\r
1566         THREAD *t;\r
1567         KAKUSHI *k = ZeroMalloc(sizeof(KAKUSHI));\r
1568 \r
1569         t = NewThread(KakushiThread, k);\r
1570 \r
1571         WaitThreadInit(t);\r
1572         ReleaseThread(t);\r
1573 \r
1574         return k;\r
1575 }\r
1576 \r
1577 UINT KakushiDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
1578 {\r
1579         KAKUSHI *k = (KAKUSHI *)param;\r
1580         UINT64 now;\r
1581         bool b;\r
1582         if (hWnd == NULL)\r
1583         {\r
1584                 return 0;\r
1585         }\r
1586 \r
1587         switch (msg)\r
1588         {\r
1589         case WM_INITDIALOG:\r
1590                 SetText(hWnd, S_INFO, _UU("CM_VLAN_CREATING"));\r
1591 \r
1592                 b = false;\r
1593 \r
1594                 if (MsIsVista())\r
1595                 {\r
1596                         if (_GETLANG() == 0)\r
1597                         {\r
1598                                 SetFont(hWnd, S_INFO, GetFont("Meiryo", 11, false, false, false, false));\r
1599                                 b = true;\r
1600                         }\r
1601                         else if (_GETLANG() == 2)\r
1602                         {\r
1603                                 SetFont(hWnd, S_INFO, GetFont("Microsoft YaHei", 11, false, false, false, false));\r
1604                                 b = true;\r
1605                         }\r
1606                 }\r
1607 \r
1608                 if (b == false)\r
1609                 {\r
1610                         DlgFont(hWnd, S_INFO, 11, false);\r
1611                 }\r
1612 \r
1613                 SetTimer(hWnd, 1, 50, NULL);\r
1614                 k->hWnd = hWnd;\r
1615 \r
1616                 k->Span = 20 * 1000;\r
1617                 k->StartTick = Tick64();\r
1618 \r
1619                 SetRange(hWnd, P_PROGRESS, 0, (UINT)k->Span);\r
1620 \r
1621         case WM_APP + 9821:\r
1622                 now = Tick64();\r
1623 \r
1624                 if (((k->StartTick + k->Span) <= now) || k->Halt)\r
1625                 {\r
1626                         EndDialog(hWnd, 0);\r
1627                         break;\r
1628                 }\r
1629 \r
1630                 SetPos(hWnd, P_PROGRESS, (UINT)(now - k->StartTick));\r
1631                 break;\r
1632 \r
1633         case WM_TIMER:\r
1634                 switch (wParam)\r
1635                 {\r
1636                 case 1:\r
1637                         AllowSetForegroundWindow(ASFW_ANY);\r
1638                         SetForegroundWindow(hWnd);\r
1639                         SetActiveWindow(hWnd);\r
1640 \r
1641                         now = Tick64();\r
1642 \r
1643                         if (((k->StartTick + k->Span) <= now) || k->Halt)\r
1644                         {\r
1645                                 EndDialog(hWnd, 0);\r
1646                                 break;\r
1647                         }\r
1648 \r
1649                         SetPos(hWnd, P_PROGRESS, (UINT)(now - k->StartTick));\r
1650                         break;\r
1651                 }\r
1652                 break;\r
1653 \r
1654         case WM_CLOSE:\r
1655                 return 1;\r
1656         }\r
1657 \r
1658         return 0;\r
1659 }\r
1660 \r
1661 // 隠し画面解放\r
1662 void FreeKakushi(KAKUSHI *k)\r
1663 {\r
1664         // 引数チェック\r
1665         if (k == NULL)\r
1666         {\r
1667                 return;\r
1668         }\r
1669 \r
1670         k->Halt = true;\r
1671 \r
1672         if (k->hWnd != NULL)\r
1673         {\r
1674                 PostMessage(k->hWnd, WM_APP + 9821, 0, 0);\r
1675         }\r
1676 \r
1677         WaitThread(k->Thread, INFINITE);\r
1678         ReleaseThread(k->Thread);\r
1679 \r
1680         Free(k);\r
1681 }\r
1682 \r
1683 // TCP/IP 最適化選択ダイアログプロシージャ\r
1684 UINT TcpMsgDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
1685 {\r
1686         UINT ret;\r
1687         // 引数チェック\r
1688         if (hWnd == NULL)\r
1689         {\r
1690                 return 0;\r
1691         }\r
1692 \r
1693         switch (msg)\r
1694         {\r
1695         case WM_INITDIALOG:\r
1696                 SetIcon(hWnd, 0, ICO_SETUP);\r
1697                 //DlgFont(hWnd, R_OPTIMIZE, 0, true);\r
1698 \r
1699                 Check(hWnd, R_NO, true);\r
1700 \r
1701                 if (g_tcpip_topmost)\r
1702                 {\r
1703                         Top(hWnd);\r
1704                 }\r
1705 \r
1706                 break;\r
1707 \r
1708         case WM_COMMAND:\r
1709                 switch (wParam)\r
1710                 {\r
1711                 case IDOK:\r
1712                         ret = 1;\r
1713                         if (IsChecked(hWnd, R_MANUAL))\r
1714                         {\r
1715                                 ret = 2;\r
1716                         }\r
1717                         else if (IsChecked(hWnd, R_NO))\r
1718                         {\r
1719                                 ret = 0;\r
1720                         }\r
1721 \r
1722                         EndDialog(hWnd, ret);\r
1723                         break;\r
1724                 }\r
1725                 break;\r
1726 \r
1727         case WM_CLOSE:\r
1728                 return 1;\r
1729         }\r
1730 \r
1731         return 0;\r
1732 }\r
1733 \r
1734 // ダイアログ初期化\r
1735 void TcpIpDlgInit(HWND hWnd)\r
1736 {\r
1737         MS_TCP tcp;\r
1738 \r
1739         SetIcon(hWnd, 0, ICO_SETUP);\r
1740 \r
1741         MsGetTcpConfig(&tcp);\r
1742 \r
1743         Check(hWnd, R_RECV_DISABLE, tcp.RecvWindowSize == 0);\r
1744         Check(hWnd, R_RECV_ENABLE, tcp.RecvWindowSize != 0);\r
1745         SetInt(hWnd, E_RECV, tcp.RecvWindowSize != 0 ? tcp.RecvWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);\r
1746 \r
1747         Check(hWnd, R_SEND_DISABLE, tcp.SendWindowSize == 0);\r
1748         Check(hWnd, R_SEND_ENABLE, tcp.SendWindowSize != 0);\r
1749         SetInt(hWnd, E_SEND, tcp.SendWindowSize != 0 ? tcp.SendWindowSize : DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);\r
1750 \r
1751         TcpIpDlgUpdate(hWnd);\r
1752 }\r
1753 \r
1754 // ダイアログ更新\r
1755 void TcpIpDlgUpdate(HWND hWnd)\r
1756 {\r
1757         bool ok = true;\r
1758 \r
1759         SetEnable(hWnd, E_RECV, IsChecked(hWnd, R_RECV_ENABLE));\r
1760         SetEnable(hWnd, S_RECV, IsChecked(hWnd, R_RECV_ENABLE));\r
1761         SetEnable(hWnd, E_SEND, IsChecked(hWnd, R_SEND_ENABLE));\r
1762         SetEnable(hWnd, S_SEND, IsChecked(hWnd, R_SEND_ENABLE));\r
1763 \r
1764         if (IsChecked(hWnd, R_RECV_ENABLE) && GetInt(hWnd, E_RECV) < 1454)\r
1765         {\r
1766                 ok = false;\r
1767         }\r
1768 \r
1769         if (IsChecked(hWnd, R_SEND_ENABLE) && GetInt(hWnd, E_SEND) < 1454)\r
1770         {\r
1771                 ok = false;\r
1772         }\r
1773 \r
1774         SetEnable(hWnd, IDOK, ok);\r
1775 }\r
1776 \r
1777 // TCP/IP ダイアログプロシージャ\r
1778 UINT TcpIpDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
1779 {\r
1780         MS_TCP tcp, old;\r
1781         // 引数チェック\r
1782         if (hWnd == NULL)\r
1783         {\r
1784                 return 0;\r
1785         }\r
1786 \r
1787         switch (msg)\r
1788         {\r
1789         case WM_INITDIALOG:\r
1790                 TcpIpDlgInit(hWnd);\r
1791 \r
1792                 if (g_tcpip_topmost)\r
1793                 {\r
1794                         Top(hWnd);\r
1795                 }\r
1796 \r
1797                 break;\r
1798 \r
1799         case WM_COMMAND:\r
1800                 switch (LOWORD(wParam))\r
1801                 {\r
1802                 case R_RECV_DISABLE:\r
1803                 case R_RECV_ENABLE:\r
1804                 case R_SEND_DISABLE:\r
1805                 case R_SEND_ENABLE:\r
1806                 case E_RECV:\r
1807                 case E_SEND:\r
1808                         TcpIpDlgUpdate(hWnd);\r
1809                         break;\r
1810                 }\r
1811 \r
1812                 switch (wParam)\r
1813                 {\r
1814                 case IDOK:\r
1815                         Zero(&tcp, sizeof(tcp));\r
1816 \r
1817                         if (IsChecked(hWnd, R_RECV_ENABLE))\r
1818                         {\r
1819                                 tcp.RecvWindowSize = GetInt(hWnd, E_RECV);\r
1820                         }\r
1821 \r
1822                         if (IsChecked(hWnd, R_SEND_ENABLE))\r
1823                         {\r
1824                                 tcp.SendWindowSize = GetInt(hWnd, E_SEND);\r
1825                         }\r
1826 \r
1827                         MsGetTcpConfig(&old);\r
1828 \r
1829                         MsSetTcpConfig(&tcp);\r
1830                         MsSaveTcpConfigReg(&tcp);\r
1831 \r
1832                         EndDialog(hWnd, true);\r
1833                         break;\r
1834 \r
1835                 case IDCANCEL:\r
1836                         Close(hWnd);\r
1837                         break;\r
1838 \r
1839                 case R_RECV_ENABLE:\r
1840                         FocusEx(hWnd, E_RECV);\r
1841                         break;\r
1842 \r
1843                 case R_SEND_ENABLE:\r
1844                         FocusEx(hWnd, E_SEND);\r
1845                         break;\r
1846 \r
1847                 case B_RECV:\r
1848                         SetInt(hWnd, E_RECV, DEFAULT_TCP_MAX_WINDOW_SIZE_RECV);\r
1849                         Check(hWnd, R_RECV_DISABLE, false);\r
1850                         Check(hWnd, R_RECV_ENABLE, true);\r
1851                         TcpIpDlgUpdate(hWnd);\r
1852                         FocusEx(hWnd, E_RECV);\r
1853                         break;\r
1854 \r
1855                 case B_SEND:\r
1856                         SetInt(hWnd, E_SEND, DEFAULT_TCP_MAX_WINDOW_SIZE_SEND);\r
1857                         Check(hWnd, R_SEND_DISABLE, false);\r
1858                         Check(hWnd, R_SEND_ENABLE, true);\r
1859                         TcpIpDlgUpdate(hWnd);\r
1860                         FocusEx(hWnd, E_SEND);\r
1861                         break;\r
1862 \r
1863                 case B_DELETE:\r
1864                         Zero(&tcp, sizeof(tcp));\r
1865                         MsSetTcpConfig(&tcp);\r
1866                         MsDeleteTcpConfigReg();\r
1867                         EndDialog(hWnd, 0);\r
1868                         break;\r
1869                 }\r
1870                 break;\r
1871 \r
1872         case WM_CLOSE:\r
1873                 EndDialog(hWnd, false);\r
1874                 break;\r
1875         }\r
1876 \r
1877         return 0;\r
1878 }\r
1879 \r
1880 // 64 bit に関する警告ダイアログ\r
1881 UINT Cpu64DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
1882 {\r
1883         switch (msg)\r
1884         {\r
1885         case WM_INITDIALOG:\r
1886                 SetIcon(hWnd, 0, ICO_WARNING);\r
1887                 DlgFont(hWnd, S_BOLD, 9, true);\r
1888                 SetTimer(hWnd, 1, 30 * 1000, NULL);\r
1889                 break;\r
1890 \r
1891         case WM_TIMER:\r
1892                 switch (wParam)\r
1893                 {\r
1894                 case 1:\r
1895                         KillTimer(hWnd, 1);\r
1896                         Command(hWnd, IDOK);\r
1897                         break;\r
1898                 }\r
1899 \r
1900                 break;\r
1901 \r
1902         case WM_COMMAND:\r
1903                 switch (wParam)\r
1904                 {\r
1905                 case IDOK:\r
1906                 case IDCANCEL:\r
1907                         Close(hWnd);\r
1908                         break;\r
1909                 }\r
1910                 break;\r
1911 \r
1912         case WM_CLOSE:\r
1913                 EndDialog(hWnd, 0);\r
1914                 break;\r
1915         }\r
1916 \r
1917         return 0;\r
1918 }\r
1919 \r
1920 // 64 bit に関する警告ダイアログの表示\r
1921 void ShowCpu64Warning()\r
1922 {\r
1923         Dialog(NULL, D_CPU64_WARNING, Cpu64DlgProc, NULL);\r
1924 }\r
1925 \r
1926 // TCP/IP 設定ユーティリティの表示\r
1927 void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode)\r
1928 {\r
1929         if (MsIsTcpConfigSupported() == false)\r
1930         {\r
1931                 if (util_mode)\r
1932                 {\r
1933                         // 現在の OS ではサポートされていない旨のメッセージを表示\r
1934                         if (MsIsAdmin() == false)\r
1935                         {\r
1936                                 MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_ADMIN"));\r
1937                         }\r
1938                         else\r
1939                         {\r
1940                                 MsgBox(hWnd, MB_ICONINFORMATION, _UU("TCPOPT_NOT_SUPPORTED"));\r
1941                         }\r
1942                 }\r
1943                 return;\r
1944         }\r
1945 \r
1946         if (util_mode == false)\r
1947         {\r
1948                 // utvpncmd を起動してすぐに終了する\r
1949                 wchar_t tmp[MAX_PATH];\r
1950                 wchar_t exedir[MAX_PATH];\r
1951                 HANDLE h;\r
1952 \r
1953                 GetExeDirW(exedir, sizeof(exedir));\r
1954 \r
1955                 if (IsX64())\r
1956                 {\r
1957                         UniFormat(tmp, sizeof(tmp), L"%s\\utvpncmd_x64.exe", exedir);\r
1958                 }\r
1959                 else if (IsIA64())\r
1960                 {\r
1961                         UniFormat(tmp, sizeof(tmp), L"%s\\utvpncmd_ia64.exe", exedir);\r
1962                 }\r
1963                 else\r
1964                 {\r
1965                         UniFormat(tmp, sizeof(tmp), L"%s\\utvpncmd.exe", exedir);\r
1966                 }\r
1967 \r
1968                 if (IsFileW(tmp))\r
1969                 {\r
1970                         RunW(tmp, L"/tool /cmd:exit", true, false);\r
1971                 }\r
1972 \r
1973                 // netsh によるタスクオフローディングの無効化\r
1974                 if (MsIsVista())\r
1975                 {\r
1976                         char netsh_exe[MAX_SIZE];\r
1977                         DIRLIST *dl;\r
1978                         UINT i;\r
1979                         bool b = false;\r
1980 \r
1981                         dl = EnumDirW(exedir);\r
1982 \r
1983                         for (i = 0;i < dl->NumFiles;i++)\r
1984                         {\r
1985                                 if (UniInStr(dl->File[i]->FileNameW, L"utvpnbridge") || \r
1986                                         UniInStr(dl->File[i]->FileNameW, L"utvpnserver"))\r
1987                                 {\r
1988                                         b = true;\r
1989                                 }\r
1990                         }\r
1991 \r
1992                         FreeDir(dl);\r
1993 \r
1994                         if (b)\r
1995                         {\r
1996                                 CombinePath(netsh_exe, sizeof(netsh_exe), MsGetSystem32Dir(), "netsh.exe");\r
1997 \r
1998                                 Run(netsh_exe, "netsh int ipv6 set global taskoffload=disabled", true, false);\r
1999                                 Run(netsh_exe, "netsh int ipv4 set global taskoffload=disabled", true, false);\r
2000                         }\r
2001                 }\r
2002 \r
2003                 // Windows Firewall 登録\r
2004                 RegistWindowsFirewallAll();\r
2005 \r
2006                 SleepThread(1000);\r
2007 \r
2008                 // utvpnclient.exe /uihelp の起動\r
2009                 h = CmExecUiHelperMain();\r
2010                 if (h != NULL)\r
2011                 {\r
2012                         CloseHandle(h);\r
2013                 }\r
2014 \r
2015                 if (Is64() == false)\r
2016                 {\r
2017                         if (MsIs64BitWindows())\r
2018                         {\r
2019                                 // 32 bit 版を 64 bit Windows 上で使用している場合は\r
2020                                 // 警告メッセージを表示する\r
2021                                 ShowCpu64Warning();\r
2022                         }\r
2023                 }\r
2024 \r
2025                 if (MsIsAdmin())\r
2026                 {\r
2027                         if (MsIsVista())\r
2028                         {\r
2029                                 // Windows Vista でインストールする場合は\r
2030                                 // MMCSS のネットワーク制限を解除する\r
2031                                 if (MsIsMMCSSNetworkThrottlingEnabled())\r
2032                                 {\r
2033                                         MsSetMMCSSNetworkThrottlingEnable(false);\r
2034                                 }\r
2035                         }\r
2036                 }\r
2037         }\r
2038 \r
2039         if (util_mode == false && MsIsShouldShowTcpConfigApp() == false)\r
2040         {\r
2041                 return;\r
2042         }\r
2043 \r
2044         if (util_mode == false)\r
2045         {\r
2046                 // 2006.07.04 nobori\r
2047                 // インストーラ上では TCP/IP 最適化ユーティリティは表示しないことにした\r
2048                 return;\r
2049         }\r
2050 \r
2051         g_tcpip_topmost = util_mode ? false : true;\r
2052 \r
2053         if (util_mode == false)\r
2054         {\r
2055                 UINT ret = Dialog(hWnd, D_TCP_MSG, TcpMsgDlgProc, NULL);\r
2056 \r
2057                 if (ret == 0)\r
2058                 {\r
2059                         MS_TCP tcp;\r
2060 \r
2061                         Zero(&tcp, sizeof(tcp));\r
2062                         MsGetTcpConfig(&tcp);\r
2063                         MsSaveTcpConfigReg(&tcp);\r
2064                         return;\r
2065                 }\r
2066                 else if (ret == 1)\r
2067                 {\r
2068                         MS_TCP tcp;\r
2069 \r
2070                         Zero(&tcp, sizeof(tcp));\r
2071 \r
2072                         tcp.RecvWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_RECV;\r
2073                         tcp.SendWindowSize = DEFAULT_TCP_MAX_WINDOW_SIZE_SEND;\r
2074                         MsSetTcpConfig(&tcp);\r
2075                         MsSaveTcpConfigReg(&tcp);\r
2076 \r
2077                         return;\r
2078                 }\r
2079         }\r
2080 \r
2081         Dialog(hWnd, D_TCP, TcpIpDlgProc, NULL);\r
2082 }\r
2083 \r
2084 // メニューの国際化対応処理を行う (Unicode)\r
2085 void InitMenuInternationalUni(HMENU hMenu, char *prefix)\r
2086 {\r
2087         UINT i, num;\r
2088         // 引数チェック\r
2089         if (hMenu == NULL || prefix == NULL)\r
2090         {\r
2091                 return;\r
2092         }\r
2093 \r
2094         // メニューの項目数を取得する\r
2095         num = GetMenuItemCount(hMenu);\r
2096 \r
2097         // メニューを列挙する\r
2098         for (i = 0;i < num;i++)\r
2099         {\r
2100                 HMENU hSubMenu = GetSubMenu(hMenu, i);\r
2101                 MENUITEMINFOW info;\r
2102                 wchar_t tmp[MAX_SIZE];\r
2103 \r
2104                 if (hSubMenu != NULL)\r
2105                 {\r
2106                         // サブメニューがある場合再帰呼び出しする\r
2107                         InitMenuInternational(hSubMenu, prefix);\r
2108                 }\r
2109 \r
2110                 // メニュー項目を取得する\r
2111                 Zero(&info, sizeof(info));\r
2112                 info.cbSize = sizeof(info);\r
2113                 info.cch = sizeof(tmp);\r
2114                 info.dwTypeData = tmp;\r
2115                 info.fMask = MIIM_STRING;\r
2116                 Zero(tmp, sizeof(tmp));\r
2117 \r
2118                 if (GetMenuItemInfoW(hMenu, i, true, &info))\r
2119                 {\r
2120                         if (tmp[0] == L'@')\r
2121                         {\r
2122                                 char name[256];\r
2123                                 wchar_t *ret;\r
2124 \r
2125                                 Format(name, sizeof(name), "%s@%S", prefix, &tmp[1]);\r
2126 \r
2127                                 ret = _UU(name);\r
2128                                 if (UniIsEmptyStr(ret) == false)\r
2129                                 {\r
2130                                         UniStrCpy(tmp, sizeof(tmp), ret);\r
2131                                         info.cch = UniStrLen(tmp);\r
2132 \r
2133                                         SetMenuItemInfoW(hMenu, i, true, &info);\r
2134                                 }\r
2135                         }\r
2136                 }\r
2137         }\r
2138 }\r
2139 \r
2140 // メニューの国際化対応処理を行う\r
2141 void InitMenuInternational(HMENU hMenu, char *prefix)\r
2142 {\r
2143         UINT i, num;\r
2144         // 引数チェック\r
2145         if (hMenu == NULL || prefix == NULL)\r
2146         {\r
2147                 return;\r
2148         }\r
2149 \r
2150         if (MsIsNt())\r
2151         {\r
2152                 InitMenuInternationalUni(hMenu, prefix);\r
2153                 return;\r
2154         }\r
2155 \r
2156         // メニューの項目数を取得する\r
2157         num = GetMenuItemCount(hMenu);\r
2158 \r
2159         // メニューを列挙する\r
2160         for (i = 0;i < num;i++)\r
2161         {\r
2162                 HMENU hSubMenu = GetSubMenu(hMenu, i);\r
2163                 MENUITEMINFO info;\r
2164                 char tmp[MAX_SIZE];\r
2165 \r
2166                 if (hSubMenu != NULL)\r
2167                 {\r
2168                         // サブメニューがある場合再帰呼び出しする\r
2169                         InitMenuInternational(hSubMenu, prefix);\r
2170                 }\r
2171 \r
2172                 // メニュー項目を取得する\r
2173                 Zero(&info, sizeof(info));\r
2174                 info.cbSize = sizeof(info);\r
2175                 info.cch = sizeof(tmp);\r
2176                 info.dwTypeData = tmp;\r
2177                 info.fMask = MIIM_STRING;\r
2178                 Zero(tmp, sizeof(tmp));\r
2179 \r
2180                 if (GetMenuItemInfo(hMenu, i, true, &info))\r
2181                 {\r
2182                         if (tmp[0] == '@')\r
2183                         {\r
2184                                 char name[256];\r
2185                                 char *ret;\r
2186 \r
2187                                 Format(name, sizeof(name), "%s@%s", prefix, &tmp[1]);\r
2188 \r
2189                                 ret = _SS(name);\r
2190                                 if (IsEmptyStr(ret) == false)\r
2191                                 {\r
2192                                         StrCpy(tmp, sizeof(tmp), ret);\r
2193                                         info.cch = StrLen(tmp);\r
2194 \r
2195                                         SetMenuItemInfo(hMenu, i, true, &info);\r
2196                                 }\r
2197                         }\r
2198                 }\r
2199         }\r
2200 }\r
2201 \r
2202 // ダイアログボックス用のデフォルトのフォントを取得する\r
2203 HFONT GetDialogDefaultFont()\r
2204 {\r
2205         return GetDialogDefaultFontEx(false);\r
2206 }\r
2207 HFONT GetDialogDefaultFontEx(bool meiryo)\r
2208 {\r
2209         char *default_font_name = _SS("DEFAULT_FONT");\r
2210         UINT default_font_size = _II("DEFAULT_FONT_SIZE");\r
2211 \r
2212         if (meiryo)\r
2213         {\r
2214                 if (_GETLANG() == 2)\r
2215                 {\r
2216                         default_font_name = "Microsoft YaHei";\r
2217                 }\r
2218                 else\r
2219                 {\r
2220                         default_font_name = "Meiryo";\r
2221                 }\r
2222         }\r
2223 \r
2224         if (IsEmptyStr(default_font_name))\r
2225         {\r
2226                 default_font_name = font_name;\r
2227         }\r
2228 \r
2229         if (default_font_size == 0)\r
2230         {\r
2231                 default_font_size = 9;\r
2232         }\r
2233 \r
2234         return GetFont(default_font_name, default_font_size, false, false, false, false);\r
2235 }\r
2236 \r
2237 // ウインドウサイズとコントロールサイズを調整する\r
2238 void AdjustWindowAndControlSize(HWND hWnd)\r
2239 {\r
2240         HFONT hDlgFont;\r
2241         UINT dlgfont_x, dlgfont_y;\r
2242         RECT rect, rect2;\r
2243         LIST *o;\r
2244         UINT i;\r
2245         // 引数チェック\r
2246         if (hWnd == NULL)\r
2247         {\r
2248                 return;\r
2249         }\r
2250 \r
2251         // 現在のウインドウのフォントを取得する\r
2252         hDlgFont = (HFONT)SendMsg(hWnd, 0, WM_GETFONT, 0, 0);\r
2253 \r
2254         // 現在のウインドウのフォントの幅と高さを取得する\r
2255         CalcFontSize(hDlgFont, &dlgfont_x, &dlgfont_y);\r
2256 \r
2257         if ((dlgfont_x == WINUI_DEFAULT_DIALOG_UNIT_X) &&\r
2258                 (dlgfont_y == WINUI_DEFAULT_DIALOG_UNIT_Y))\r
2259         {\r
2260                 // 調整する必要が無い\r
2261                 return;\r
2262         }\r
2263 \r
2264         // ウインドウのサイズを調整する\r
2265         if (GetWindowRect(hWnd, &rect))\r
2266         {\r
2267                 if (GetClientRect(hWnd, &rect2))\r
2268                 {\r
2269                         UINT width = rect2.right - rect2.left;\r
2270                         UINT height = rect2.bottom - rect2.top;\r
2271 \r
2272                         AdjustDialogXY(&width, &height, dlgfont_x, dlgfont_y);\r
2273 \r
2274                         width += (rect.right - rect.left) - (rect2.right - rect2.left);\r
2275                         height += (rect.bottom - rect.top) - (rect2.bottom - rect2.top);\r
2276 \r
2277                         if (true)\r
2278                         {\r
2279                                 HWND hParent = GetParent(hWnd);\r
2280 \r
2281                                 if (hParent != NULL)\r
2282                                 {\r
2283                                         RECT r;\r
2284 \r
2285                                         Zero(&r, sizeof(r));\r
2286 \r
2287                                         if (GetWindowRect(hParent, &r))\r
2288                                         {\r
2289                                                 RECT r2;\r
2290 \r
2291                                                 rect.top = r.top + GetSystemMetrics(SM_CYCAPTION);\r
2292 \r
2293                                                 Zero(&r2, sizeof(r2));\r
2294                                                 if (SystemParametersInfo(SPI_GETWORKAREA, 0, &r2, 0))\r
2295                                                 {\r
2296                                                         if (r2.bottom < (rect.top + (int)height))\r
2297                                                         {\r
2298                                                                 rect.top -= (rect.top + (int)height) - r2.bottom;\r
2299 \r
2300                                                                 if (rect.top < 0)\r
2301                                                                 {\r
2302                                                                         rect.top = 0;\r
2303                                                                 }\r
2304                                                         }\r
2305                                                 }\r
2306                                         }\r
2307                                 }\r
2308                         }\r
2309 \r
2310                         MoveWindow(hWnd, rect.left, rect.top, width, height, false);\r
2311                 }\r
2312         }\r
2313 \r
2314         // 子ウインドウを列挙する\r
2315         o = EnumAllChildWindowEx(hWnd, false, true, true);\r
2316 \r
2317         for (i = 0;i < LIST_NUM(o);i++)\r
2318         {\r
2319                 // 子ウインドウのサイズを調整する\r
2320                 HWND h = *((HWND *)LIST_DATA(o, i));\r
2321                 HWND hWndParent = GetParent(h);\r
2322                 RECT current_rect;\r
2323                 char class_name[MAX_PATH];\r
2324                 bool is_image = false;\r
2325 \r
2326                 // クラス名を取得\r
2327                 Zero(class_name, sizeof(class_name));\r
2328                 GetClassNameA(h, class_name, sizeof(class_name));\r
2329 \r
2330                 if (StrCmpi(class_name, "static") == 0)\r
2331                 {\r
2332                         if (SendMsg(h, 0, STM_GETIMAGE, IMAGE_BITMAP, 0) != 0 ||\r
2333                                 SendMsg(h, 0, STM_GETIMAGE, IMAGE_ICON, 0) != 0 ||\r
2334                                 SendMsg(h, 0, STM_GETICON, 0, 0) != 0)\r
2335                         {\r
2336                                 is_image = true;\r
2337                         }\r
2338                 }\r
2339 \r
2340                 // 位置を取得\r
2341                 if (GetWindowRect(h, &current_rect))\r
2342                 {\r
2343                         // クライアント座標に変換\r
2344                         POINT p1, p2;\r
2345 \r
2346                         p1.x = current_rect.left;\r
2347                         p1.y = current_rect.top;\r
2348 \r
2349                         p2.x = current_rect.right;\r
2350                         p2.y = current_rect.bottom;\r
2351 \r
2352                         ScreenToClient(hWndParent, &p1);\r
2353                         ScreenToClient(hWndParent, &p2);\r
2354 \r
2355                         // 位置を調整\r
2356                         AdjustDialogXY(&p1.x, &p1.y, dlgfont_x, dlgfont_y);\r
2357                         AdjustDialogXY(&p2.x, &p2.y, dlgfont_x, dlgfont_y);\r
2358 \r
2359                         if (is_image)\r
2360                         {\r
2361                                 p2.x = p1.x + (current_rect.right - current_rect.left);\r
2362                                 p2.y = p1.y + (current_rect.bottom - current_rect.top);\r
2363                         }\r
2364 \r
2365                         // 移動\r
2366                         MoveWindow(h, p1.x, p1.y, p2.x - p1.x, p2.y - p1.y, false);\r
2367                 }\r
2368         }\r
2369 \r
2370         FreeWindowList(o);\r
2371 }\r
2372 \r
2373 // x と y の値をフォントに応じて調整する\r
2374 void AdjustDialogXY(UINT *x, UINT *y, UINT dlgfont_x, UINT dlgfont_y)\r
2375 {\r
2376         if (x != NULL)\r
2377         {\r
2378                 *x = (UINT)(((double)*x) * (double)WINUI_DEFAULT_DIALOG_UNIT_X / (double)dlgfont_x);\r
2379         }\r
2380 \r
2381         if (y != NULL)\r
2382         {\r
2383                 *y = (UINT)(((double)*y) * (double)WINUI_DEFAULT_DIALOG_UNIT_Y / (double)dlgfont_y);\r
2384         }\r
2385 }\r
2386 \r
2387 // ダイアログボックスの国際化対応処理を行う\r
2388 void InitDialogInternational(HWND hWnd, void *param)\r
2389 {\r
2390         LIST *o;\r
2391         UINT i;\r
2392         bool is_managed_dialog = false;\r
2393         char caption[MAX_PATH];\r
2394         char *dialog_name;\r
2395         // 引数チェック\r
2396         if (hWnd == NULL)\r
2397         {\r
2398                 return;\r
2399         }\r
2400 \r
2401         AdjustWindowAndControlSize(hWnd);\r
2402 \r
2403         GetTxtA(hWnd, 0, caption, sizeof(caption));\r
2404         if (caption[0] == '@')\r
2405         {\r
2406                 dialog_name = &caption[1];\r
2407 \r
2408                 is_managed_dialog = true;\r
2409         }\r
2410 \r
2411         // すべてのウインドウハンドルを列挙する\r
2412         o = EnumAllChildWindow(hWnd);\r
2413 \r
2414         for (i = 0;i < LIST_NUM(o);i++)\r
2415         {\r
2416                 HWND hControl = *((HWND *)LIST_DATA(o, i));\r
2417 \r
2418                 if (hControl != NULL)\r
2419                 {\r
2420                         HFONT hFont = GetDialogDefaultFontEx(param && ((DIALOG_PARAM *)param)->meiryo);\r
2421 \r
2422                         SetFont(hControl, 0, hFont);\r
2423 \r
2424                         if (MsIsVista())\r
2425                         {\r
2426                                 char classname[MAX_PATH];\r
2427                                 GetClassNameA(hControl, classname, sizeof(classname));\r
2428 \r
2429                                 if (StrCmpi(classname, "syslistview32") == 0)\r
2430                                 {\r
2431                                         InitVistaWindowTheme(hControl);\r
2432                                 }\r
2433                         }\r
2434 \r
2435                         if (is_managed_dialog)\r
2436                         {\r
2437                                 char str[MAX_PATH];\r
2438 \r
2439                                 GetTxtA(hControl, 0, str, sizeof(str));\r
2440                                 if (str[0] == '@')\r
2441                                 {\r
2442                                         char *control_name = &str[1];\r
2443                                         char tmp[MAX_PATH];\r
2444                                         wchar_t *ret;\r
2445 \r
2446                                         StrCpy(tmp, sizeof(tmp), dialog_name);\r
2447                                         StrCat(tmp, sizeof(tmp), "@");\r
2448 \r
2449                                         if (hWnd == hControl)\r
2450                                         {\r
2451                                                 StrCat(tmp, sizeof(tmp), "CAPTION");\r
2452                                         }\r
2453                                         else\r
2454                                         {\r
2455                                                 StrCat(tmp, sizeof(tmp), control_name);\r
2456                                         }\r
2457 \r
2458                                         ret = _UU(tmp);\r
2459 \r
2460                                         if (ret != NULL && UniIsEmptyStr(ret) == false)\r
2461                                         {\r
2462                                                 SetText(hControl, 0, ret);\r
2463                                         }\r
2464                                 }\r
2465                         }\r
2466                 }\r
2467         }\r
2468 \r
2469         FreeWindowList(o);\r
2470 }\r
2471 \r
2472 // 子ウインドウ列挙プロシージャ\r
2473 // ダイアログ初期化\r
2474 void StringDlgInit(HWND hWnd, STRING_DLG *s)\r
2475 {\r
2476         // 引数チェック\r
2477         if (hWnd == NULL || s == NULL)\r
2478         {\r
2479                 return;\r
2480         }\r
2481 \r
2482         SetText(hWnd, E_STRING, s->String);\r
2483 \r
2484         SetIcon(hWnd, S_ICON, s->Icon);\r
2485         SetText(hWnd, S_INFO, s->Info);\r
2486         SetText(hWnd, 0, s->Title);\r
2487 \r
2488         FocusEx(hWnd, E_STRING);\r
2489 \r
2490         StringDlgUpdate(hWnd, s);\r
2491 }\r
2492 \r
2493 // ダイアログコントロール更新\r
2494 void StringDlgUpdate(HWND hWnd, STRING_DLG *s)\r
2495 {\r
2496         wchar_t *tmp;\r
2497         bool b = true;\r
2498         // 引数チェック\r
2499         if (hWnd == NULL || s == NULL)\r
2500         {\r
2501                 return;\r
2502         }\r
2503 \r
2504         tmp = GetText(hWnd, E_STRING);\r
2505 \r
2506         if (tmp != NULL)\r
2507         {\r
2508                 if (s->AllowEmpty == false)\r
2509                 {\r
2510                         if (UniIsEmptyStr(tmp))\r
2511                         {\r
2512                                 b = false;\r
2513                         }\r
2514                 }\r
2515 \r
2516                 if (s->AllowUnsafe == false)\r
2517                 {\r
2518                         if (IsSafeUniStr(tmp) == false)\r
2519                         {\r
2520                                 b = false;\r
2521                         }\r
2522                 }\r
2523 \r
2524                 Free(tmp);\r
2525         }\r
2526 \r
2527         SetEnable(hWnd, IDOK, b);\r
2528 }\r
2529 \r
2530 // 文字列ダイアログプロシージャ\r
2531 UINT StringDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
2532 {\r
2533         STRING_DLG *s = (STRING_DLG *)param;\r
2534         // 引数チェック\r
2535         if (hWnd == NULL)\r
2536         {\r
2537                 return 0;\r
2538         }\r
2539 \r
2540         switch (msg)\r
2541         {\r
2542         case WM_INITDIALOG:\r
2543                 StringDlgInit(hWnd, s);\r
2544                 break;\r
2545 \r
2546         case WM_COMMAND:\r
2547                 switch (LOWORD(wParam))\r
2548                 {\r
2549                 case E_STRING:\r
2550                         StringDlgUpdate(hWnd, s);\r
2551                         break;\r
2552                 }\r
2553 \r
2554                 switch (wParam)\r
2555                 {\r
2556                 case IDOK:\r
2557                         GetTxt(hWnd, E_STRING, s->String, sizeof(s->String));\r
2558                         EndDialog(hWnd, true);\r
2559                         break;\r
2560 \r
2561                 case IDCANCEL:\r
2562                         Close(hWnd);\r
2563                         break;\r
2564                 }\r
2565                 break;\r
2566 \r
2567         case WM_CLOSE:\r
2568                 EndDialog(hWnd, false);\r
2569                 break;\r
2570         }\r
2571 \r
2572         return 0;\r
2573 }\r
2574 \r
2575 // 文字列ダイアログを表示する\r
2576 wchar_t *StringDlg(HWND hWnd, wchar_t *title, wchar_t *info, wchar_t *def, UINT icon, bool allow_empty, bool allow_unsafe)\r
2577 {\r
2578         STRING_DLG s;\r
2579         // 引数チェック\r
2580         if (title == NULL)\r
2581         {\r
2582                 title = _UU("DLG_STRING_DEFTITLE");\r
2583         }\r
2584         if (info == NULL)\r
2585         {\r
2586                 info = _UU("DLG_STRING_DEFINFO");\r
2587         }\r
2588         if (def == NULL)\r
2589         {\r
2590                 def = L"";\r
2591         }\r
2592         if (icon == 0)\r
2593         {\r
2594                 icon = ICO_NULL;\r
2595         }\r
2596 \r
2597         Zero(&s, sizeof(s));\r
2598         s.Icon = icon;\r
2599         s.Info = info;\r
2600         s.Title = title;\r
2601         s.Icon = icon;\r
2602         UniStrCpy(s.String, sizeof(s.String), def);\r
2603         s.AllowEmpty = allow_empty;\r
2604         s.AllowUnsafe = allow_unsafe;\r
2605 \r
2606         if (Dialog(hWnd, D_STRING, StringDlgProc, &s) == false)\r
2607         {\r
2608                 return NULL;\r
2609         }\r
2610         else\r
2611         {\r
2612                 return CopyUniStr(s.String);\r
2613         }\r
2614 }\r
2615 char *StringDlgA(HWND hWnd, wchar_t *title, wchar_t *info, char *def, UINT icon, bool allow_empty, bool allow_unsafe)\r
2616 {\r
2617         wchar_t unidef[MAX_SIZE];\r
2618         wchar_t *tmp;\r
2619         char *ret;\r
2620         if (def == NULL)\r
2621         {\r
2622                 def = "";\r
2623         }\r
2624 \r
2625         StrToUni(unidef, sizeof(unidef), def);\r
2626 \r
2627         tmp = StringDlg(hWnd, title, info, unidef, icon, allow_empty, allow_unsafe);\r
2628         if (tmp == NULL)\r
2629         {\r
2630                 return NULL;\r
2631         }\r
2632 \r
2633         ret = CopyUniToStr(tmp);\r
2634         Free(tmp);\r
2635 \r
2636         return ret;\r
2637 }\r
2638 \r
2639 // 再起動ダイアログ\r
2640 UINT Win9xRebootDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
2641 {\r
2642         WIN9X_REBOOT_DLG *d = (WIN9X_REBOOT_DLG *)param;\r
2643         UINT64 now;\r
2644         wchar_t tmp[MAX_PATH];\r
2645         // 引数チェック\r
2646         if (hWnd == NULL)\r
2647         {\r
2648                 return 0;\r
2649         }\r
2650 \r
2651         switch (msg)\r
2652         {\r
2653         case WM_INITDIALOG:\r
2654                 d->StartTime = Tick64();\r
2655                 SetRange(hWnd, P_PROGRESS, 0, d->TotalTime);\r
2656                 SetTimer(hWnd, 1, 100, NULL);\r
2657                 goto UPDATE;\r
2658 \r
2659         case WM_TIMER:\r
2660                 switch (wParam)\r
2661                 {\r
2662                 case 1:\r
2663 UPDATE:\r
2664                         now = Tick64();\r
2665                         if ((d->StartTime + (UINT64)d->TotalTime) <= now)\r
2666                         {\r
2667                                 KillTimer(hWnd, 1);\r
2668                                 UniStrCpy(tmp, sizeof(tmp), _UU("DLG_REBOOT_INFO_2"));\r
2669                                 SetText(hWnd, S_INFO, tmp);\r
2670                                 if (MsShutdown(true, false) == false)\r
2671                                 {\r
2672                                         MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_REBOOT_ERROR"));\r
2673                                 }\r
2674                                 EndDialog(hWnd, 0);\r
2675                         }\r
2676                         else\r
2677                         {\r
2678                                 SetPos(hWnd, P_PROGRESS, (UINT)(now - d->StartTime));\r
2679                                 UniFormat(tmp, sizeof(tmp), _UU("DLG_REBOOT_INFO"),\r
2680                                         (UINT)((UINT64)d->TotalTime - (now - d->StartTime)) / 1000 + 1);\r
2681                                 SetText(hWnd, S_INFO, tmp);\r
2682                         }\r
2683 \r
2684                         break;\r
2685                 }\r
2686                 break;\r
2687         }\r
2688         return 0;\r
2689 }\r
2690 \r
2691 // 再起動用スレッド\r
2692 void Win9xRebootThread(THREAD *t, void *p)\r
2693 {\r
2694         // 引数チェック\r
2695         if (t == NULL)\r
2696         {\r
2697                 return;\r
2698         }\r
2699 \r
2700         Win9xReboot(NULL);\r
2701 }\r
2702 \r
2703 // 自動的に再起動する\r
2704 void Win9xReboot(HWND hWnd)\r
2705 {\r
2706         WIN9X_REBOOT_DLG d;\r
2707 \r
2708         Zero(&d, sizeof(d));\r
2709         d.TotalTime = 10 * 1000;\r
2710 \r
2711         Dialog(hWnd, D_WIN9X_REBOOT, Win9xRebootDlgProc, &d);\r
2712 }\r
2713 \r
2714 // バージョン情報の初期化\r
2715 void AboutDlgInit(HWND hWnd, WINUI_ABOUT *a)\r
2716 {\r
2717         wchar_t tmp[MAX_SIZE];\r
2718         // 引数チェック\r
2719         if (hWnd == NULL || a == NULL)\r
2720         {\r
2721                 return;\r
2722         }\r
2723 \r
2724         UniFormat(tmp, sizeof(tmp), _UU("ABOUT_CAPTION"), a->ProductName);\r
2725         SetText(hWnd, 0, tmp);\r
2726 \r
2727         SetFont(hWnd, S_VERSION, GetFont(NULL, 15, true, false, false, false));\r
2728 \r
2729         SetTextA(hWnd, S_VERSION, a->ProductName);\r
2730 \r
2731         SetFont(hWnd, S_VERSION2, GetFont("Verdana", 13, false, false, false, false));\r
2732         UniFormat(tmp, sizeof(tmp),\r
2733                 L"Version %u.%02u Build %u ",\r
2734                 a->Cedar->Version / 100, a->Cedar->Version % 100,\r
2735                 a->Cedar->Build);\r
2736         SetText(hWnd, S_VERSION2, tmp);\r
2737 \r
2738         SetFont(hWnd, S_BUILD, GetFont("Verdana", 11, false, false, true, false));\r
2739         SetTextA(hWnd, S_BUILD, a->Cedar->BuildInfo);\r
2740 \r
2741         SendMsg(hWnd, S_LOGO, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)LoadBitmap(hDll, MAKEINTRESOURCE(a->Bitmap)));\r
2742 }\r
2743 \r
2744 // バージョン情報プロシージャ\r
2745 UINT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
2746 {\r
2747         WINUI_ABOUT *a = (WINUI_ABOUT *)param;\r
2748         // 引数チェック\r
2749         if (hWnd == NULL)\r
2750         {\r
2751                 return 0;\r
2752         }\r
2753 \r
2754         switch (msg)\r
2755         {\r
2756         case WM_INITDIALOG:\r
2757                 AboutDlgInit(hWnd, a);\r
2758                 break;\r
2759 \r
2760         case WM_COMMAND:\r
2761                 switch (wParam)\r
2762                 {\r
2763                 case IDOK:\r
2764                 case IDCANCEL:\r
2765                         if ((GetKeyState(VK_SHIFT) & 0x8000) &&\r
2766                                 (GetKeyState(VK_CONTROL) & 0x8000) &&\r
2767                                 (GetKeyState(VK_MENU) & 0x8000))\r
2768                         {\r
2769                                 ShowEasterEgg(hWnd);\r
2770                         }\r
2771                         EndDialog(hWnd, true);\r
2772                         break;\r
2773                 case B_WEB:\r
2774                         ShellExecute(hWnd, "open", _SS("SE_COMPANY_URL"), NULL, NULL, SW_SHOW);\r
2775                         break;\r
2776                 }\r
2777                 break;\r
2778 \r
2779         case WM_CLOSE:\r
2780                 EndDialog(hWnd, false);\r
2781                 break;\r
2782         }\r
2783 \r
2784         return 0;\r
2785 }\r
2786 \r
2787 // バージョン情報 (古い形式)\r
2788 void About(HWND hWnd, CEDAR *cedar, char *product_name, UINT bitmap)\r
2789 {\r
2790         WINUI_ABOUT a;\r
2791         // 引数チェック\r
2792         if (cedar == NULL || product_name == NULL || bitmap == 0)\r
2793         {\r
2794                 return;\r
2795         }\r
2796 \r
2797         Zero(&a, sizeof(a));\r
2798         a.Bitmap = bitmap;\r
2799         a.Cedar = cedar;\r
2800         a.ProductName = product_name;\r
2801 \r
2802         Dialog(hWnd, D_ABOUT, AboutDlgProc, &a);\r
2803 }\r
2804 \r
2805 // テスト\r
2806 void UiTest()\r
2807 {\r
2808 }\r
2809 \r
2810 // IP アドレスが入力されているフィルード数を調べる\r
2811 UINT IpGetFilledNum(HWND hWnd, UINT id)\r
2812 {\r
2813         UINT ret;\r
2814         DWORD value;\r
2815         // 引数チェック\r
2816         if (hWnd == NULL)\r
2817         {\r
2818                 return 0;\r
2819         }\r
2820 \r
2821         ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);\r
2822 \r
2823         return ret;\r
2824 }\r
2825 \r
2826 // IP アドレスが入力されているかどうか調べる\r
2827 bool IpIsFilled(HWND hWnd, UINT id)\r
2828 {\r
2829         UINT ret;\r
2830         DWORD value;\r
2831         // 引数チェック\r
2832         if (hWnd == NULL)\r
2833         {\r
2834                 return 0;\r
2835         }\r
2836 \r
2837         ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);\r
2838 \r
2839         if (ret != 4)\r
2840         {\r
2841                 return false;\r
2842         }\r
2843         else\r
2844         {\r
2845                 return true;\r
2846         }\r
2847 }\r
2848 \r
2849 // IP アドレスのクリア\r
2850 void IpClear(HWND hWnd, UINT id)\r
2851 {\r
2852         // 引数チェック\r
2853         if (hWnd == NULL)\r
2854         {\r
2855                 return;\r
2856         }\r
2857 \r
2858         SendMsg(hWnd, id, IPM_CLEARADDRESS, 0, 0);\r
2859 }\r
2860 \r
2861 // IP アドレスの取得\r
2862 UINT IpGet(HWND hWnd, UINT id)\r
2863 {\r
2864         UINT ret;\r
2865         DWORD value;\r
2866         // 引数チェック\r
2867         if (hWnd == NULL)\r
2868         {\r
2869                 return 0;\r
2870         }\r
2871 \r
2872         ret = SendMsg(hWnd, id, IPM_GETADDRESS, 0, (LPARAM)&value);\r
2873 \r
2874         if (ret != 4)\r
2875         {\r
2876                 return 0;\r
2877         }\r
2878         else\r
2879         {\r
2880                 return Endian32((UINT)value);\r
2881         }\r
2882 }\r
2883 \r
2884 // IP アドレスのセット\r
2885 void IpSet(HWND hWnd, UINT id, UINT ip)\r
2886 {\r
2887         // 引数チェック\r
2888         if (hWnd == NULL)\r
2889         {\r
2890                 return;\r
2891         }\r
2892 \r
2893         SendMsg(hWnd, id, IPM_SETADDRESS, 0, Endian32(ip));\r
2894 }\r
2895 \r
2896 // レジストリに候補を書き込む\r
2897 void WriteCandidateToReg(UINT root, char *key, LIST *o, char *name)\r
2898 {\r
2899         BUF *b;\r
2900         // 引数チェック\r
2901         if (key == NULL || o == NULL || name == NULL)\r
2902         {\r
2903                 return;\r
2904         }\r
2905 \r
2906         b = CandidateToBuf(o);\r
2907         if (b == NULL)\r
2908         {\r
2909                 return;\r
2910         }\r
2911 \r
2912         MsRegWriteBin(root, key, name, b->Buf, b->Size);\r
2913 \r
2914         FreeBuf(b);\r
2915 }\r
2916 \r
2917 // レジストリから候補を読み込む\r
2918 LIST *ReadCandidateFromReg(UINT root, char *key, char *name)\r
2919 {\r
2920         BUF *b;\r
2921         // 引数チェック\r
2922         if (key == NULL || name == NULL)\r
2923         {\r
2924                 return NULL;\r
2925         }\r
2926 \r
2927         b = MsRegReadBin(root, key, name);\r
2928         if (b == NULL)\r
2929         {\r
2930                 return NewCandidateList();\r
2931         }\r
2932         else\r
2933         {\r
2934                 LIST *o = BufToCandidate(b);\r
2935                 FreeBuf(b);\r
2936 \r
2937                 return o;\r
2938         }\r
2939 }\r
2940 \r
2941 // リモート接続ダイアログ初期化\r
2942 void RemoteDlgInit(HWND hWnd, WINUI_REMOTE *r)\r
2943 {\r
2944         LIST *o;\r
2945         UINT i;\r
2946         // 引数チェック\r
2947         if (hWnd == NULL || r == NULL)\r
2948         {\r
2949                 return;\r
2950         }\r
2951 \r
2952         SetIcon(hWnd, 0, r->Icon);\r
2953 \r
2954         SetText(hWnd, 0, r->Caption);\r
2955         SetText(hWnd, S_TITLE, r->Title);\r
2956         SetIcon(hWnd, S_ICON, r->Icon);\r
2957 \r
2958         // 候補を読み込む\r
2959         o = ReadCandidateFromReg(REG_CURRENT_USER, r->RegKeyName, "RemoteHostCandidate");\r
2960         r->CandidateList = o;\r
2961 \r
2962         // 候補を表示する\r
2963         for (i = 0;i < LIST_NUM(o);i++)\r
2964         {\r
2965                 CANDIDATE *c = LIST_DATA(o, i);\r
2966                 CbAddStr(hWnd, C_HOSTNAME, c->Str, 0);\r
2967         }\r
2968 \r
2969         if (r->DefaultHostname != NULL)\r
2970         {\r
2971                 SetTextA(hWnd, C_HOSTNAME, r->DefaultHostname);\r
2972         }\r
2973 \r
2974         FocusEx(hWnd, C_HOSTNAME);\r
2975 \r
2976         RemoteDlgRefresh(hWnd, r);\r
2977 }\r
2978 \r
2979 // リモート接続ダイアログ更新\r
2980 void RemoteDlgRefresh(HWND hWnd, WINUI_REMOTE *r)\r
2981 {\r
2982         char *s;\r
2983         bool ok = true;\r
2984         bool localhost_mode = false;\r
2985         // 引数チェック\r
2986         if (hWnd == NULL || r == NULL)\r
2987         {\r
2988                 return;\r
2989         }\r
2990 \r
2991         s = GetTextA(hWnd, C_HOSTNAME);\r
2992         if (s != NULL)\r
2993         {\r
2994                 Trim(s);\r
2995                 if (StrCmpi(s, "localhost") == 0 || StartWith(s, "127."))\r
2996                 {\r
2997                         localhost_mode = true;\r
2998                 }\r
2999                 Free(s);\r
3000         }\r
3001 \r
3002         if (localhost_mode == false)\r
3003         {\r
3004                 Enable(hWnd, C_HOSTNAME);\r
3005                 Enable(hWnd, S_HOSTNAME);\r
3006                 Check(hWnd, R_LOCAL, false);\r
3007         }\r
3008         else\r
3009         {\r
3010                 if (r->Title != _UU("NM_CONNECT_TITLE"))\r
3011                 {\r
3012                         Disable(hWnd, C_HOSTNAME);\r
3013                         Disable(hWnd, S_HOSTNAME);\r
3014                 }\r
3015                 Check(hWnd, R_LOCAL, true);\r
3016                 SetTextA(hWnd, C_HOSTNAME, "localhost");\r
3017 \r
3018                 if (r->flag1 == false)\r
3019                 {\r
3020                         Focus(hWnd, IDOK);\r
3021                 }\r
3022         }\r
3023 \r
3024         if (IsEmpty(hWnd, C_HOSTNAME))\r
3025         {\r
3026                 ok = false;\r
3027         }\r
3028 \r
3029         SetEnable(hWnd, IDOK, ok);\r
3030 \r
3031         r->flag1 = true;\r
3032 }\r
3033 \r
3034 // リモート接続ダイアログ OK ボタン\r
3035 void RemoteDlgOnOk(HWND hWnd, WINUI_REMOTE *r)\r
3036 {\r
3037         char *hostname;\r
3038         wchar_t *s;\r
3039         LIST *o;\r
3040         // 引数チェック\r
3041         if (hWnd == NULL || r == NULL)\r
3042         {\r
3043                 return;\r
3044         }\r
3045 \r
3046         // 入力されているホスト名を取得\r
3047         hostname = GetTextA(hWnd, C_HOSTNAME);\r
3048         if (hostname == NULL)\r
3049         {\r
3050                 return;\r
3051         }\r
3052         Trim(hostname);\r
3053 \r
3054         // 候補を追加\r
3055         o = r->CandidateList;\r
3056         s = CopyStrToUni(hostname);\r
3057         AddCandidate(o, s, 64);\r
3058         Free(s);\r
3059 \r
3060         // 候補を書き込む\r
3061         WriteCandidateToReg(REG_CURRENT_USER, r->RegKeyName, o, "RemoteHostCandidate");\r
3062         FreeCandidateList(o);\r
3063 \r
3064         r->Hostname = hostname;\r
3065 \r
3066         EndDialog(hWnd, true);\r
3067 }\r
3068 \r
3069 // リモート接続ダイアログプロシージャ\r
3070 UINT RemoteDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
3071 {\r
3072         WINUI_REMOTE *r = (WINUI_REMOTE *)param;\r
3073         // 引数チェック\r
3074         if (hWnd == NULL)\r
3075         {\r
3076                 return 0;\r
3077         }\r
3078 \r
3079         switch (msg)\r
3080         {\r
3081         case WM_INITDIALOG:\r
3082                 RemoteDlgInit(hWnd, r);\r
3083                 SetTimer(hWnd, 1, 100, NULL);\r
3084                 break;\r
3085         case WM_TIMER:\r
3086                 switch (wParam)\r
3087                 {\r
3088                 case 1:\r
3089                         KillTimer(hWnd, 1);\r
3090                         RemoteDlgRefresh(hWnd, r);\r
3091                         SetTimer(hWnd, 1, 100, NULL);\r
3092                         break;\r
3093                 }\r
3094                 break;\r
3095         case WM_COMMAND:\r
3096                 switch (wParam)\r
3097                 {\r
3098                 case R_LOCAL:\r
3099                         if (IsChecked(hWnd, R_LOCAL) == false)\r
3100                         {\r
3101                                 SetTextA(hWnd, C_HOSTNAME, "");\r
3102                                 RemoteDlgRefresh(hWnd, r);\r
3103                                 FocusEx(hWnd, C_HOSTNAME);\r
3104                         }\r
3105                         else\r
3106                         {\r
3107                                 SetTextA(hWnd, C_HOSTNAME, "localhost");\r
3108                                 RemoteDlgRefresh(hWnd, r);\r
3109                                 Focus(hWnd, IDOK);\r
3110                         }\r
3111                         break;\r
3112                 case IDCANCEL:\r
3113                         Close(hWnd);\r
3114                         break;\r
3115                 case IDOK:\r
3116                         RemoteDlgOnOk(hWnd, r);\r
3117                         break;\r
3118                 }\r
3119                 switch (LOWORD(wParam))\r
3120                 {\r
3121                 case R_LOCAL:\r
3122                 case C_HOSTNAME:\r
3123                         RemoteDlgRefresh(hWnd, r);\r
3124                         break;\r
3125                 }\r
3126                 break;\r
3127         case WM_CLOSE:\r
3128                 FreeCandidateList(r->CandidateList);\r
3129                 EndDialog(hWnd, false);\r
3130                 break;\r
3131         }\r
3132 \r
3133         return 0;\r
3134 }\r
3135 \r
3136 // リモート接続ダイアログ\r
3137 char *RemoteDlg(HWND hWnd, char *regkey, UINT icon, wchar_t *caption, wchar_t *title, char *default_host)\r
3138 {\r
3139         WINUI_REMOTE r;\r
3140         // 引数チェック\r
3141         if (regkey == NULL)\r
3142         {\r
3143                 regkey = "Software\\SoftEther Corporation\\SoftEther UT-VPN\\WinUI Common Module";\r
3144         }\r
3145         if (caption == NULL)\r
3146         {\r
3147                 caption = _UU("REMOTE_DEF_CAPTION");\r
3148         }\r
3149         if (title == NULL)\r
3150         {\r
3151                 title = _UU("REMOTE_DEF_TITLE");\r
3152         }\r
3153         if (icon == 0)\r
3154         {\r
3155                 icon = ICO_INTERNET;\r
3156         }\r
3157 \r
3158         Zero(&r, sizeof(r));\r
3159         r.RegKeyName = regkey;\r
3160         r.Caption = caption;\r
3161         r.Title = title;\r
3162         r.Icon = icon;\r
3163         r.DefaultHostname = default_host;\r
3164 \r
3165         if (Dialog(hWnd, D_REMOTE, RemoteDlgProc, &r) == false)\r
3166         {\r
3167                 return NULL;\r
3168         }\r
3169 \r
3170         return r.Hostname;\r
3171 }\r
3172 \r
3173 // ウインドウの検索プロシージャ\r
3174 bool CALLBACK SearchWindowEnumProc(HWND hWnd, LPARAM lParam)\r
3175 {\r
3176         if (hWnd != NULL && lParam != 0)\r
3177         {\r
3178                 wchar_t *s = GetText(hWnd, 0);\r
3179                 SEARCH_WINDOW_PARAM *p = (SEARCH_WINDOW_PARAM *)lParam;\r
3180                 if (s != NULL)\r
3181                 {\r
3182                         if (UniStrCmpi(p->caption, s) == 0)\r
3183                         {\r
3184                                 p->hWndFound = hWnd;\r
3185                         }\r
3186                         Free(s);\r
3187                 }\r
3188         }\r
3189         return true;\r
3190 }\r
3191 \r
3192 // ウインドウの検索\r
3193 HWND SearchWindow(wchar_t *caption)\r
3194 {\r
3195         SEARCH_WINDOW_PARAM p;\r
3196         // 引数チェック\r
3197         if (caption == NULL)\r
3198         {\r
3199                 return NULL;\r
3200         }\r
3201 \r
3202         Zero(&p, sizeof(p));\r
3203         p.caption = caption;\r
3204         p.hWndFound = NULL;\r
3205 \r
3206         EnumWindows(SearchWindowEnumProc, (LPARAM)&p);\r
3207 \r
3208         return p.hWndFound;\r
3209 }\r
3210 \r
3211 // 指定したプロセスにフォアグラウンドウインドウになることを許可\r
3212 void AllowFGWindow(UINT process_id)\r
3213 {\r
3214         if (process_id == 0)\r
3215         {\r
3216                 return;\r
3217         }\r
3218 \r
3219         if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) &&\r
3220                 GET_KETA(GetOsInfo()->OsType, 100) >= 2)\r
3221         {\r
3222                 AllowSetForegroundWindow(process_id);\r
3223         }\r
3224 }\r
3225 \r
3226 // アイテムのリネーム\r
3227 void LvRename(HWND hWnd, UINT id, UINT pos)\r
3228 {\r
3229         // 引数チェック\r
3230         if (hWnd == NULL || pos == INFINITE)\r
3231         {\r
3232                 return;\r
3233         }\r
3234 \r
3235         ListView_EditLabel(DlgItem(hWnd, id), pos);\r
3236 }\r
3237 \r
3238 // メニューを表示する\r
3239 void PrintMenu(HWND hWnd, HMENU hMenu)\r
3240 {\r
3241         POINT p;\r
3242         // 引数チェック\r
3243         if (hMenu == NULL || hWnd == NULL)\r
3244         {\r
3245                 return;\r
3246         }\r
3247 \r
3248         GetCursorPos(&p);\r
3249 \r
3250         TrackPopupMenu(hMenu, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);\r
3251 }\r
3252 \r
3253 // メニューからショートカット文字列を削除する\r
3254 void RemoveShortcutKeyStrFromMenu(HMENU hMenu)\r
3255 {\r
3256         UINT i, num;\r
3257         // 引数チェック\r
3258         if (hMenu == NULL)\r
3259         {\r
3260                 return;\r
3261         }\r
3262 \r
3263         num = GetMenuNum(hMenu);\r
3264         for (i = 0;i < num;i++)\r
3265         {\r
3266                 wchar_t *str = GetMenuStr(hMenu, i);\r
3267                 if (str != NULL)\r
3268                 {\r
3269                         UINT j, len;\r
3270                         len = UniStrLen(str);\r
3271                         for (j = 0;j < len;j++)\r
3272                         {\r
3273                                 if (str[j] == L'\t')\r
3274                                 {\r
3275                                         str[j] = 0;\r
3276                                 }\r
3277                         }\r
3278                         SetMenuStr(hMenu, i, str);\r
3279                         Free(str);\r
3280                 }\r
3281         }\r
3282 }\r
3283 \r
3284 // メニュー内の項目数を取得する\r
3285 UINT GetMenuNum(HMENU hMenu)\r
3286 {\r
3287         UINT ret;\r
3288         // 引数チェック\r
3289         if (hMenu == NULL)\r
3290         {\r
3291                 return 0;\r
3292         }\r
3293 \r
3294         ret = GetMenuItemCount(hMenu);\r
3295         if (ret == INFINITE)\r
3296         {\r
3297                 return 0;\r
3298         }\r
3299         else\r
3300         {\r
3301                 return ret;\r
3302         }\r
3303 }\r
3304 \r
3305 // メニュー内の文字列を設定する\r
3306 void SetMenuStr(HMENU hMenu, UINT pos, wchar_t *str)\r
3307 {\r
3308         MENUITEMINFOW info;\r
3309         // 引数チェック\r
3310         if (hMenu == NULL || pos == INFINITE || str == NULL)\r
3311         {\r
3312                 return;\r
3313         }\r
3314 \r
3315         if (MsIsNt() == false)\r
3316         {\r
3317                 char *s = CopyUniToStr(str);\r
3318                 SetMenuStrA(hMenu, pos, s);\r
3319                 Free(s);\r
3320                 return;\r
3321         }\r
3322 \r
3323         Zero(&info, sizeof(info));\r
3324         info.cbSize = sizeof(info);\r
3325         info.fMask = MIIM_STRING;\r
3326         info.dwTypeData = str;\r
3327         SetMenuItemInfoW(hMenu, pos, true, &info);\r
3328 }\r
3329 void SetMenuStrA(HMENU hMenu, UINT pos, char *str)\r
3330 {\r
3331         MENUITEMINFOA info;\r
3332         // 引数チェック\r
3333         if (hMenu == NULL || pos == INFINITE || str == NULL)\r
3334         {\r
3335                 return;\r
3336         }\r
3337 \r
3338         Zero(&info, sizeof(info));\r
3339         info.cbSize = sizeof(info);\r
3340         info.fMask = MIIM_STRING;\r
3341         info.dwTypeData = str;\r
3342         SetMenuItemInfoA(hMenu, pos, true, &info);\r
3343 }\r
3344 \r
3345 // メニュー内の文字列を取得する\r
3346 wchar_t *GetMenuStr(HMENU hMenu, UINT pos)\r
3347 {\r
3348         wchar_t tmp[MAX_SIZE];\r
3349         // 引数チェック\r
3350         if (hMenu == NULL || pos == INFINITE)\r
3351         {\r
3352                 return NULL;\r
3353         }\r
3354         if (MsIsNt() == false)\r
3355         {\r
3356                 char *s = GetMenuStrA(hMenu, pos);\r
3357                 if (s == NULL)\r
3358                 {\r
3359                         return NULL;\r
3360                 }\r
3361                 else\r
3362                 {\r
3363                         wchar_t *ret = CopyStrToUni(s);\r
3364                         Free(s);\r
3365                         return ret;\r
3366                 }\r
3367         }\r
3368 \r
3369         if (GetMenuStringW(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)\r
3370         {\r
3371                 return NULL;\r
3372         }\r
3373 \r
3374         return UniCopyStr(tmp);\r
3375 }\r
3376 char *GetMenuStrA(HMENU hMenu, UINT pos)\r
3377 {\r
3378         char tmp[MAX_SIZE];\r
3379         // 引数チェック\r
3380         if (hMenu == NULL || pos == INFINITE)\r
3381         {\r
3382                 return NULL;\r
3383         }\r
3384 \r
3385         if (GetMenuString(hMenu, pos, tmp, sizeof(tmp), MF_BYPOSITION) == 0)\r
3386         {\r
3387                 return NULL;\r
3388         }\r
3389 \r
3390         return CopyStr(tmp);\r
3391 }\r
3392 \r
3393 // メニュー項目を太字にする\r
3394 void SetMenuItemBold(HMENU hMenu, UINT pos, bool bold)\r
3395 {\r
3396         MENUITEMINFO info;\r
3397         // 引数チェック\r
3398         if (hMenu == NULL || pos == INFINITE)\r
3399         {\r
3400                 return;\r
3401         }\r
3402 \r
3403         Zero(&info, sizeof(info));\r
3404         info.cbSize = sizeof(info);\r
3405         info.fMask = MIIM_STATE;\r
3406 \r
3407         if (GetMenuItemInfo(hMenu, pos, true, &info) == false)\r
3408         {\r
3409                 return;\r
3410         }\r
3411 \r
3412         if (bold)\r
3413         {\r
3414                 info.fState |= MFS_DEFAULT;\r
3415         }\r
3416         else\r
3417         {\r
3418                 info.fState = info.fState & ~MFS_DEFAULT;\r
3419         }\r
3420 \r
3421         SetMenuItemInfo(hMenu, pos, true, &info);\r
3422 }\r
3423 \r
3424 // メニュー項目を有効 / 無効にする\r
3425 void SetMenuItemEnable(HMENU hMenu, UINT pos, bool enable)\r
3426 {\r
3427         MENUITEMINFO info;\r
3428         // 引数チェック\r
3429         if (hMenu == NULL || pos == INFINITE)\r
3430         {\r
3431                 return;\r
3432         }\r
3433 \r
3434         Zero(&info, sizeof(info));\r
3435         info.cbSize = sizeof(info);\r
3436         info.fMask = MIIM_STATE;\r
3437 \r
3438         if (GetMenuItemInfo(hMenu, pos, true, &info) == false)\r
3439         {\r
3440                 return;\r
3441         }\r
3442 \r
3443         if (enable)\r
3444         {\r
3445                 info.fState |= MFS_ENABLED;\r
3446                 info.fState = info.fState & ~MFS_DISABLED;\r
3447         }\r
3448         else\r
3449         {\r
3450                 info.fState |= MFS_DISABLED;\r
3451                 info.fState = info.fState & ~MFS_ENABLED;\r
3452         }\r
3453 \r
3454         SetMenuItemInfo(hMenu, pos, true, &info);\r
3455 }\r
3456 \r
3457 // メニュー項目を削除する\r
3458 void DeleteMenuItem(HMENU hMenu, UINT pos)\r
3459 {\r
3460         // 引数チェック\r
3461         if (hMenu == NULL || pos == INFINITE)\r
3462         {\r
3463                 return;\r
3464         }\r
3465 \r
3466         DeleteMenu(hMenu, pos, MF_BYPOSITION);\r
3467 }\r
3468 \r
3469 // メニュー内の ID から位置を取得する\r
3470 UINT GetMenuItemPos(HMENU hMenu, UINT id)\r
3471 {\r
3472         UINT num, i;\r
3473         // 引数チェック\r
3474         if (hMenu == NULL)\r
3475         {\r
3476                 return INFINITE;\r
3477         }\r
3478 \r
3479         num = GetMenuItemCount(hMenu);\r
3480         if (num == INFINITE)\r
3481         {\r
3482                 return INFINITE;\r
3483         }\r
3484 \r
3485         for (i = 0;i < num;i++)\r
3486         {\r
3487                 if (GetMenuItemID(hMenu, i) == id)\r
3488                 {\r
3489                         return i;\r
3490                 }\r
3491         }\r
3492 \r
3493         return INFINITE;\r
3494 }\r
3495 \r
3496 // サブメニューを取得\r
3497 HMENU LoadSubMenu(UINT menu_id, UINT pos, HMENU *parent_menu)\r
3498 {\r
3499         HMENU h = LoadMenu(hDll, MAKEINTRESOURCE(menu_id));\r
3500         HMENU ret;\r
3501         if (h == NULL)\r
3502         {\r
3503                 return NULL;\r
3504         }\r
3505 \r
3506         ret = GetSubMenu(h, pos);\r
3507 \r
3508         if (parent_menu != NULL)\r
3509         {\r
3510                 *parent_menu = h;\r
3511         }\r
3512 \r
3513         return ret;\r
3514 }\r
3515 \r
3516 // ユーザーインターフェイスの DLL を取得\r
3517 HINSTANCE GetUiDll()\r
3518 {\r
3519         return hDll;\r
3520 }\r
3521 \r
3522 // 接続エラーダイアログプロシージャ\r
3523 UINT ConnectErrorDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
3524 {\r
3525         UI_CONNECTERROR_DLG *p = (UI_CONNECTERROR_DLG *)param;\r
3526         wchar_t tmp[1024];\r
3527         // 引数チェック\r
3528         if (hWnd == NULL)\r
3529         {\r
3530                 return 0;\r
3531         }\r
3532 \r
3533         switch (msg)\r
3534         {\r
3535         case WM_INITDIALOG:\r
3536                 if (p->Err == ERR_DISCONNECTED || p->Err == ERR_SESSION_TIMEOUT)\r
3537                 {\r
3538                         // 接続が切断された旨のメッセージ\r
3539                         SetText(hWnd, S_TITLE, _UU("ERRDLG_DISCONNECTED_MSG"));\r
3540                 }\r
3541                 if (p->HideWindow)\r
3542                 {\r
3543                         Hide(hWnd, R_HIDE);\r
3544                 }\r
3545                 FormatText(hWnd, 0, p->AccountName);\r
3546                 FormatText(hWnd, S_TITLE, p->ServerName);\r
3547                 UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_ERRMSG"), p->Err, _E(p->Err));\r
3548                 SetText(hWnd, E_ERROR, tmp);\r
3549 \r
3550                 SetIcon(hWnd, 0, ICO_SERVER_OFFLINE);\r
3551 \r
3552                 if (p->RetryIntervalSec == 0)\r
3553                 {\r
3554                         SetText(hWnd, S_COUNTDOWN, _UU("ERRDLG_INFORMATION"));\r
3555                         Hide(hWnd, P_PROGRESS);\r
3556                         Hide(hWnd, S_RETRYINFO);\r
3557                 }\r
3558                 else\r
3559                 {\r
3560                         if (p->RetryLimit != INFINITE)\r
3561                         {\r
3562                                 UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_1"), p->CurrentRetryCount, p->RetryLimit);\r
3563                         }\r
3564                         else\r
3565                         {\r
3566                                 UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRY_INFO_2"), p->CurrentRetryCount);\r
3567                         }\r
3568                         SetText(hWnd, S_RETRYINFO, tmp);\r
3569                         SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec);\r
3570                         SetPos(hWnd, P_PROGRESS, 0);\r
3571                         SetTimer(hWnd, 1, 10, NULL);\r
3572                         p->StartTick = Tick64();\r
3573                 }\r
3574                 SetTimer(hWnd, 2, 10, NULL);\r
3575                 Focus(hWnd, IDOK);\r
3576                 break;\r
3577         case WM_TIMER:\r
3578                 switch (wParam)\r
3579                 {\r
3580                 case 1:\r
3581                         if (p->RetryIntervalSec != 0)\r
3582                         {\r
3583                                 UINT64 start, end, now;\r
3584                                 now = Tick64();\r
3585                                 start = p->StartTick;\r
3586                                 end = start + (UINT64)p->RetryIntervalSec;\r
3587 \r
3588                                 if (end > now)\r
3589                                 {\r
3590                                         SetPos(hWnd, P_PROGRESS, (UINT)(now - start));\r
3591                                         UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_RETRYCOUNT"), ((UINT)(end - now)) / 1000);\r
3592                                         SetText(hWnd, S_COUNTDOWN, tmp);\r
3593                                 }\r
3594                                 else\r
3595                                 {\r
3596                                         Command(hWnd, IDOK);\r
3597                                 }\r
3598                         }\r
3599                         break;\r
3600                 case 2:\r
3601                         if (p->CancelEvent != NULL)\r
3602                         {\r
3603                                 if (WaitForSingleObject((HANDLE)p->CancelEvent->pData, 0) != WAIT_TIMEOUT)\r
3604                                 {\r
3605                                         // 強制キャンセル\r
3606                                         Close(hWnd);\r
3607                                 }\r
3608                         }\r
3609                         break;\r
3610                 }\r
3611                 break;\r
3612         case WM_COMMAND:\r
3613                 switch (LOWORD(wParam))\r
3614                 {\r
3615                 case R_HIDE:\r
3616                         p->HideWindow = IsChecked(hWnd, R_HIDE);\r
3617                         break;\r
3618                 }\r
3619                 switch (wParam)\r
3620                 {\r
3621                 case IDOK:\r
3622                         EndDialog(hWnd, true);\r
3623                         break;\r
3624                 case IDCANCEL:\r
3625                         Close(hWnd);\r
3626                         break;\r
3627                 }\r
3628                 break;\r
3629         case WM_CLOSE:\r
3630                 EndDialog(hWnd, false);\r
3631                 break;\r
3632         }\r
3633 \r
3634         return 0;\r
3635 }\r
3636 \r
3637 // 接続エラーダイアログを表示\r
3638 bool ConnectErrorDlg(UI_CONNECTERROR_DLG *p)\r
3639 {\r
3640         // 引数チェック\r
3641         if (p == NULL)\r
3642         {\r
3643                 return false;\r
3644         }\r
3645 \r
3646         return DialogEx2(NULL, D_CONNECTERROR, ConnectErrorDlgProc, p, true, true);\r
3647 }\r
3648 \r
3649 // 証明書の内容を表示する\r
3650 void PrintCheckCertInfo(HWND hWnd, UI_CHECKCERT *p)\r
3651 {\r
3652         wchar_t tmp[MAX_SIZE];\r
3653         char tmp2[MAX_SIZE];\r
3654         UCHAR md5[MD5_SIZE];\r
3655         UCHAR sha1[SHA1_SIZE];\r
3656         X *x;\r
3657         // 引数チェック\r
3658         if (hWnd == NULL || p == NULL)\r
3659         {\r
3660                 return;\r
3661         }\r
3662 \r
3663         x = p->x;\r
3664 \r
3665         GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);\r
3666         SetText(hWnd, E_SUBJECT, tmp);\r
3667 \r
3668         GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);\r
3669         SetText(hWnd, E_ISSUER, tmp);\r
3670 \r
3671         GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);\r
3672         SetText(hWnd, E_EXPIRES, tmp);\r
3673 \r
3674         GetXDigest(x, md5, false);\r
3675         BinToStr(tmp2, sizeof(tmp2), md5, sizeof(md5));\r
3676         SetTextA(hWnd, E_MD5, tmp2);\r
3677 \r
3678         GetXDigest(x, sha1, true);\r
3679         BinToStr(tmp2, sizeof(tmp2), sha1, sizeof(sha1));\r
3680         SetTextA(hWnd, E_SHA1, tmp2);\r
3681 \r
3682         SetFont(hWnd, E_MD5, GetFont("Arial", 8, false, false, false, false));\r
3683         SetFont(hWnd, E_SHA1, GetFont("Arial", 8, false, false, false, false));\r
3684 }\r
3685 \r
3686 // 証明書が相違する旨を警告する\r
3687 void ShowDlgDiffWarning(HWND hWnd, UI_CHECKCERT *p)\r
3688 {\r
3689         UCHAR sha1_new[SHA1_SIZE], sha1_old[SHA1_SIZE];\r
3690         UCHAR md5_new[MD5_SIZE], md5_old[MD5_SIZE];\r
3691         char sha1_new_str[MAX_SIZE], sha1_old_str[MAX_SIZE];\r
3692         char md5_new_str[MAX_SIZE], md5_old_str[MAX_SIZE];\r
3693         // 引数チェック\r
3694         if (hWnd == NULL || p == NULL || p->x == NULL || p->old_x == NULL)\r
3695         {\r
3696                 return;\r
3697         }\r
3698 \r
3699         GetXDigest(p->x, sha1_new, true);\r
3700         GetXDigest(p->x, md5_new, false);\r
3701 \r
3702         GetXDigest(p->old_x, sha1_old, true);\r
3703         GetXDigest(p->old_x, md5_old, false);\r
3704 \r
3705         BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));\r
3706         BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));\r
3707         BinToStrEx(sha1_old_str, sizeof(sha1_old_str), sha1_old, sizeof(sha1_old));\r
3708         BinToStrEx(md5_old_str, sizeof(md5_old_str), md5_old, sizeof(md5_old));\r
3709 \r
3710         MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("CC_DANGEROUS_MSG"),\r
3711                 p->ServerName, md5_old_str, sha1_old_str, md5_new_str, sha1_new_str);\r
3712 }\r
3713 \r
3714 // [OK] ボタンが押された\r
3715 void CheckCertDialogOnOk(HWND hWnd, UI_CHECKCERT *p)\r
3716 {\r
3717         UCHAR sha1_new[SHA1_SIZE];\r
3718         UCHAR md5_new[MD5_SIZE];\r
3719         char sha1_new_str[MAX_SIZE];\r
3720         char md5_new_str[MAX_SIZE];\r
3721         UINT ret;\r
3722         // 引数チェック\r
3723         if (hWnd == NULL || p == NULL)\r
3724         {\r
3725                 return;\r
3726         }\r
3727 \r
3728         GetXDigest(p->x, sha1_new, true);\r
3729         GetXDigest(p->x, md5_new, false);\r
3730         BinToStrEx(sha1_new_str, sizeof(sha1_new_str), sha1_new, sizeof(sha1_new));\r
3731         BinToStrEx(md5_new_str, sizeof(md5_new_str), md5_new, sizeof(md5_new));\r
3732 \r
3733         ret = MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON2,\r
3734                 _UU("CC_WARNING_MSG"),\r
3735                 p->AccountName, sha1_new_str, md5_new_str);\r
3736 \r
3737         if (ret == IDYES)\r
3738         {\r
3739                 p->SaveServerCert = true;\r
3740         }\r
3741 \r
3742         if (ret == IDCANCEL)\r
3743         {\r
3744                 return;\r
3745         }\r
3746 \r
3747         p->Ok = true;\r
3748         EndDialog(hWnd, true);\r
3749 }\r
3750 \r
3751 // 証明書ダイアログプロシージャ\r
3752 UINT CheckCertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
3753 {\r
3754         UI_CHECKCERT *p = (UI_CHECKCERT *)param;\r
3755         // 引数チェック\r
3756         if (hWnd == NULL || param == NULL)\r
3757         {\r
3758                 return 0;\r
3759         }\r
3760 \r
3761         switch (msg)\r
3762         {\r
3763         case WM_INITDIALOG:\r
3764                 FormatText(hWnd, 0, p->AccountName);\r
3765                 FormatText(hWnd, S_TITLE, p->ServerName);\r
3766                 FormatText(hWnd, S_MSG1, p->ServerName);\r
3767 \r
3768                 PrintCheckCertInfo(hWnd, p);\r
3769 \r
3770                 Focus(hWnd, IDCANCEL);\r
3771 \r
3772                 SetIcon(hWnd, 0, ICO_WARNING);\r
3773 \r
3774                 if (p->DiffWarning)\r
3775                 {\r
3776                         SetTimer(hWnd, 1, 1, NULL);\r
3777                 }\r
3778 \r
3779                 SetTimer(hWnd, 2, 100, NULL);\r
3780 \r
3781                 break;\r
3782         case WM_TIMER:\r
3783                 switch (wParam)\r
3784                 {\r
3785                 case 1:\r
3786                         KillTimer(hWnd, 1);\r
3787                         ShowDlgDiffWarning(hWnd, p);\r
3788                         break;\r
3789                 case 2:\r
3790                         if ((p->Session != NULL && p->Session->Halt) ||\r
3791                                 (p->Halt))\r
3792                         {\r
3793                                 p->Ok = false;\r
3794                                 EndDialog(hWnd, false);\r
3795                         }\r
3796                         break;\r
3797                 }\r
3798                 break;\r
3799         case WM_COMMAND:\r
3800                 switch (wParam)\r
3801                 {\r
3802                 case B_SHOW:\r
3803                         CertDlg(hWnd, p->x, p->parent_x, false);\r
3804                         break;\r
3805                 case IDOK:\r
3806                         CheckCertDialogOnOk(hWnd, p);\r
3807                         break;\r
3808                 case IDCANCEL:\r
3809                         Close(hWnd);\r
3810                         break;\r
3811                 }\r
3812                 break;\r
3813         case WM_CLOSE:\r
3814                 p->Ok = false;\r
3815                 EndDialog(hWnd, false);\r
3816                 break;\r
3817         }\r
3818 \r
3819         return 0;\r
3820 }\r
3821 \r
3822 // 証明書のチェックダイアログ\r
3823 void CheckCertDlg(UI_CHECKCERT *p)\r
3824 {\r
3825         // 引数チェック\r
3826         if (p == NULL)\r
3827         {\r
3828                 return;\r
3829         }\r
3830 \r
3831         Dialog(NULL, D_CHECKCERT, CheckCertDlgProc, p);\r
3832 }\r
3833 \r
3834 // アイコン ID からイメージリスト ID を取得する\r
3835 UINT GetIcon(UINT icon_id)\r
3836 {\r
3837         IMAGELIST_ICON *c, t;\r
3838         t.id = icon_id;\r
3839 \r
3840         c = Search(icon_list, &t);\r
3841         if (c == NULL)\r
3842         {\r
3843                 if (icon_id != ICO_NULL)\r
3844                 {\r
3845                         return GetIcon(ICO_NULL);\r
3846                 }\r
3847                 else\r
3848                 {\r
3849                         return INFINITE;\r
3850                 }\r
3851         }\r
3852         else\r
3853         {\r
3854                 return c->Index;\r
3855         }\r
3856 }\r
3857 \r
3858 // イメージリスト用にアイコンをロードする\r
3859 IMAGELIST_ICON *LoadIconForImageList(UINT id)\r
3860 {\r
3861         IMAGELIST_ICON *ret = ZeroMalloc(sizeof(IMAGELIST_ICON));\r
3862         HICON small_icon, large_icon;\r
3863 \r
3864         ret->id = id;\r
3865 \r
3866         large_icon = LoadLargeIcon(id);\r
3867         if (large_icon == NULL)\r
3868         {\r
3869                 large_icon = LoadSmallIcon(id);\r
3870         }\r
3871 \r
3872         small_icon = LoadSmallIcon(id);\r
3873         if (small_icon == NULL)\r
3874         {\r
3875                 small_icon = LoadLargeIcon(id);\r
3876         }\r
3877 \r
3878         ret->hSmallImage = small_icon;\r
3879         ret->hLargeImage = large_icon;\r
3880         ret->Index = ImageList_AddIcon(large_image_list, large_icon);\r
3881         ImageList_AddIcon(small_image_list, small_icon);\r
3882 \r
3883         return ret;\r
3884 }\r
3885 \r
3886 // イメージリストアイコンの比較\r
3887 int CompareImageListIcon(void *p1, void *p2)\r
3888 {\r
3889         IMAGELIST_ICON *c1, *c2;\r
3890         if (p1 == NULL || p2 == NULL)\r
3891         {\r
3892                 return 0;\r
3893         }\r
3894         c1 = *(IMAGELIST_ICON **)p1;\r
3895         c2 = *(IMAGELIST_ICON **)p2;\r
3896         if (c1 == NULL || c2 == NULL)\r
3897         {\r
3898                 return 0;\r
3899         }\r
3900 \r
3901         if (c1->id > c2->id)\r
3902         {\r
3903                 return 1;\r
3904         }\r
3905         else if (c1->id < c2->id)\r
3906         {\r
3907                 return -1;\r
3908         }\r
3909         else\r
3910         {\r
3911                 return 0;\r
3912         }\r
3913 }\r
3914 \r
3915 // イメージリストの初期化\r
3916 void InitImageList()\r
3917 {\r
3918         large_image_list = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 1, 0);\r
3919         ImageList_SetBkColor(large_image_list, RGB(255, 255, 255));\r
3920         small_image_list = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 0);\r
3921         ImageList_SetBkColor(small_image_list, RGB(255, 255, 255));\r
3922         icon_list = NewList(CompareImageListIcon);\r
3923 \r
3924         // 列挙\r
3925         EnumResourceNames(hDll, RT_GROUP_ICON, EnumResNameProc, 0);\r
3926 }\r
3927 \r
3928 // アイコンリソース列挙プロシージャ\r
3929 BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)\r
3930 {\r
3931         if (IS_INTRESOURCE(lpszName))\r
3932         {\r
3933                 UINT icon_id = (UINT)lpszName;\r
3934                 IMAGELIST_ICON *img = LoadIconForImageList(icon_id);\r
3935 \r
3936                 Add(icon_list, img);\r
3937         }\r
3938 \r
3939         return TRUE;\r
3940 }\r
3941 \r
3942 // イメージリストの解放\r
3943 void FreeImageList()\r
3944 {\r
3945         UINT i;\r
3946         ImageList_Destroy(large_image_list);\r
3947         ImageList_Destroy(small_image_list);\r
3948         large_image_list = small_image_list = NULL;\r
3949 \r
3950         for (i = 0;i < LIST_NUM(icon_list);i++)\r
3951         {\r
3952                 IMAGELIST_ICON *c = LIST_DATA(icon_list, i);\r
3953                 Free(c);\r
3954         }\r
3955 \r
3956         ReleaseList(icon_list);\r
3957         icon_list = NULL;\r
3958 }\r
3959 \r
3960 // カラムの横幅の取得\r
3961 UINT LvGetColumnWidth(HWND hWnd, UINT id, UINT index)\r
3962 {\r
3963         return ListView_GetColumnWidth(DlgItem(hWnd, id), index);\r
3964 }\r
3965 \r
3966 // カラムの挿入\r
3967 void LvInsertColumn(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT width)\r
3968 {\r
3969         LVCOLUMNW c;\r
3970         // 引数チェック\r
3971         if (hWnd == NULL || str == NULL)\r
3972         {\r
3973                 return;\r
3974         }\r
3975 \r
3976         Zero(&c, sizeof(c));\r
3977         c.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;\r
3978 \r
3979         c.pszText = str;\r
3980         c.iSubItem = index;\r
3981         c.cx = width;\r
3982 \r
3983         SendMsg(hWnd, id, LVM_INSERTCOLUMNW, index, (LPARAM)&c);\r
3984 }\r
3985 \r
3986 // すべてのアイテムを削除\r
3987 void LvReset(HWND hWnd, UINT id)\r
3988 {\r
3989         // 引数チェック\r
3990         if (hWnd == NULL)\r
3991         {\r
3992                 return;\r
3993         }\r
3994 \r
3995         ListView_DeleteAllItems(DlgItem(hWnd, id));\r
3996 }\r
3997 \r
3998 // リストビューを初期化\r
3999 void LvInitEx(HWND hWnd, UINT id, bool no_image)\r
4000 {\r
4001         LvInitEx2(hWnd, id, no_image, false);\r
4002 }\r
4003 void LvInitEx2(HWND hWnd, UINT id, bool no_image, bool large_icon)\r
4004 {\r
4005         // 引数チェック\r
4006         if (hWnd == NULL)\r
4007         {\r
4008                 return;\r
4009         }\r
4010 \r
4011         ListView_SetUnicodeFormat(DlgItem(hWnd, id), true);\r
4012 \r
4013         if (no_image == false)\r
4014         {\r
4015                 ListView_SetImageList(DlgItem(hWnd, id), large_image_list, LVSIL_NORMAL);\r
4016                 ListView_SetImageList(DlgItem(hWnd, id), large_icon ? large_image_list : small_image_list, LVSIL_SMALL);\r
4017         }\r
4018 \r
4019         ListView_SetExtendedListViewStyle(DlgItem(hWnd, id), LVS_EX_FULLROWSELECT);\r
4020 \r
4021         if (MsIsVista())\r
4022         {\r
4023                 LvSetStyle(hWnd, id, LVS_EX_DOUBLEBUFFER);\r
4024         }\r
4025 }\r
4026 void LvInit(HWND hWnd, UINT id)\r
4027 {\r
4028         LvInitEx(hWnd, id, false);\r
4029 }\r
4030 \r
4031 // バッチ追加処理完了 (高速)\r
4032 void LvInsertEnd(LVB *b, HWND hWnd, UINT id)\r
4033 {\r
4034         LvInsertEndEx(b, hWnd, id, false);\r
4035 }\r
4036 void LvInsertEndEx(LVB *b, HWND hWnd, UINT id, bool force_reset)\r
4037 {\r
4038         UINT i, num;\r
4039         LIST *new_list, *exist_list;\r
4040         wchar_t *last_selected = NULL;\r
4041         // 引数チェック\r
4042         if (b == NULL || hWnd == NULL)\r
4043         {\r
4044                 return;\r
4045         }\r
4046 \r
4047         new_list = NewListFast(CompareUniStr);\r
4048 \r
4049         for (i = 0;i < LIST_NUM(b->ItemList);i++)\r
4050         {\r
4051                 LVB_ITEM *t = LIST_DATA(b->ItemList, i);\r
4052                 Add(new_list, t->Strings[0]);\r
4053         }\r
4054 \r
4055         Sort(new_list);\r
4056 \r
4057         if ((LIST_NUM(b->ItemList) >= LV_INSERT_RESET_ALL_ITEM_MIN) || force_reset)\r
4058         {\r
4059                 last_selected = LvGetFocusedStr(hWnd, id, 0);\r
4060                 LvReset(hWnd, id);\r
4061         }\r
4062 \r
4063         exist_list = NewListFast(CompareUniStr);\r
4064 \r
4065         num = LvNum(hWnd, id);\r
4066 \r
4067         // 既存項目のうちバッチリスト内に存在していない項目を削除する\r
4068         for (i = 0;i < num;i++)\r
4069         {\r
4070                 bool exists = false;\r
4071                 wchar_t *s = LvGetStr(hWnd, id, i, 0);\r
4072                 if (Search(new_list, s) != NULL)\r
4073                 {\r
4074                         exists = true;\r
4075                 }\r
4076                 if (exists == false)\r
4077                 {\r
4078                         // 追加予定バッチリスト内に存在しない項目はリストビューから削除する\r
4079                         LvDeleteItem(hWnd, id, i);\r
4080                         num = LvNum(hWnd, id);\r
4081                         i--;\r
4082                         Free(s);\r
4083                 }\r
4084                 else\r
4085                 {\r
4086                         Add(exist_list, s);\r
4087                 }\r
4088         }\r
4089 \r
4090         Sort(exist_list);\r
4091 \r
4092         // バッチ内の項目を 1 つずつ追加していく\r
4093         for (i = 0;i < LIST_NUM(b->ItemList);i++)\r
4094         {\r
4095                 LVB_ITEM *t = LIST_DATA(b->ItemList, i);\r
4096                 UINT index;\r
4097                 UINT j;\r
4098                 bool exists = false;\r
4099 \r
4100                 if (Search(exist_list, t->Strings[0]) != NULL)\r
4101                 {\r
4102                         index = LvSearchStr(hWnd, id, 0, t->Strings[0]);\r
4103                 }\r
4104                 else\r
4105                 {\r
4106                         index = INFINITE;\r
4107                 }\r
4108 \r
4109                 if (index != INFINITE)\r
4110                 {\r
4111                         UINT j;\r
4112                         // 追加しようとする項目と同じ文字列の項目がすでに存在する場合は\r
4113                         // 追加ではなく更新を行う\r
4114                         for (j = 0;j < t->NumStrings;j++)\r
4115                         {\r
4116                                 LvSetItem(hWnd, id, index, j, t->Strings[j]);\r
4117                         }\r
4118                         LvSetItemImageByImageListId(hWnd, id, index, t->Image);\r
4119                         LvSetItemParam(hWnd, id, index, t->Param);\r
4120                 }\r
4121                 else\r
4122                 {\r
4123                         // 新しく追加を行う\r
4124                         UINT index = INFINITE;\r
4125                         UINT j;\r
4126                         for (j = 0;j < t->NumStrings;j++)\r
4127                         {\r
4128                                 if (j == 0)\r
4129                                 {\r
4130                                         index = LvInsertItemByImageListId(hWnd, id, t->Image, t->Param, t->Strings[j]);\r
4131                                 }\r
4132                                 else\r
4133                                 {\r
4134                                         LvSetItem(hWnd, id, index, j, t->Strings[j]);\r
4135                                 }\r
4136                         }\r
4137                 }\r
4138 \r
4139                 // メモリを解放する\r
4140                 for (j = 0;j < t->NumStrings;j++)\r
4141                 {\r
4142                         Free(t->Strings[j]);\r
4143                 }\r
4144                 Free(t->Strings);\r
4145                 Free(t);\r
4146         }\r
4147 \r
4148         // リストを解放する\r
4149         ReleaseList(b->ItemList);\r
4150 \r
4151         // メモリを解放する\r
4152         Free(b);\r
4153 \r
4154         ReleaseList(new_list);\r
4155 \r
4156         for (i = 0;i < LIST_NUM(exist_list);i++)\r
4157         {\r
4158                 Free(LIST_DATA(exist_list, i));\r
4159         }\r
4160         ReleaseList(exist_list);\r
4161 \r
4162         if (last_selected != NULL)\r
4163         {\r
4164                 UINT pos = LvSearchStr(hWnd, id, 0, last_selected);\r
4165 \r
4166                 if (pos != INFINITE)\r
4167                 {\r
4168                         LvSelect(hWnd, id, pos);\r
4169                 }\r
4170 \r
4171                 Free(last_selected);\r
4172         }\r
4173 }\r
4174 \r
4175 // カラム数の取得\r
4176 UINT LvGetColumnNum(HWND hWnd, UINT id)\r
4177 {\r
4178         UINT i;\r
4179         LVCOLUMN c;\r
4180         if (hWnd == NULL)\r
4181         {\r
4182                 return 0;\r
4183         }\r
4184 \r
4185         for (i = 0;;i++)\r
4186         {\r
4187                 Zero(&c, sizeof(c));\r
4188                 c.mask = LVCF_SUBITEM;\r
4189                 if (ListView_GetColumn(DlgItem(hWnd, id), i, &c) == false)\r
4190                 {\r
4191                         break;\r
4192                 }\r
4193         }\r
4194 \r
4195         return i;\r
4196 }\r
4197 \r
4198 // ソート関数\r
4199 int CALLBACK LvSortProc(LPARAM param1, LPARAM param2, LPARAM sort_param)\r
4200 {\r
4201         WINUI_LV_SORT *sort = (WINUI_LV_SORT *)sort_param;\r
4202         HWND hWnd;\r
4203         UINT id;\r
4204         UINT i1, i2;\r
4205         int ret = 0;\r
4206         wchar_t *s1, *s2;\r
4207         if (sort == NULL)\r
4208         {\r
4209                 return 0;\r
4210         }\r
4211 \r
4212         hWnd = sort->hWnd;\r
4213         id = sort->id;\r
4214 \r
4215         if (hWnd == NULL)\r
4216         {\r
4217                 return 0;\r
4218         }\r
4219 \r
4220         i1 = (UINT)param1;\r
4221         i2 = (UINT)param2;\r
4222 \r
4223         s1 = LvGetStr(hWnd, id, i1, sort->subitem);\r
4224         if (s1 == NULL)\r
4225         {\r
4226                 return 0;\r
4227         }\r
4228 \r
4229         s2 = LvGetStr(hWnd, id, i2, sort->subitem);\r
4230         if (s2 == NULL)\r
4231         {\r
4232                 Free(s1);\r
4233                 return 0;\r
4234         }\r
4235 \r
4236         if (sort->numeric == false)\r
4237         {\r
4238                 if (UniStrCmpi(s1, _UU("CM_NEW_ICON")) == 0)\r
4239                 {\r
4240                         ret = -1;\r
4241                 }\r
4242                 else if (UniStrCmpi(s1, _UU("CM_ASP")) == 0)\r
4243                 {\r
4244                         ret = -1;\r
4245                 }\r
4246                 else if (UniStrCmpi(s2, _UU("CM_NEW_ICON")) == 0)\r
4247                 {\r
4248                         ret = 1;\r
4249                 }\r
4250                 else if (UniStrCmpi(s2, _UU("CM_ASP")) == 0)\r
4251                 {\r
4252                         return 1;\r
4253                 }\r
4254                 else\r
4255                 {\r
4256                         ret = UniStrCmpi(s1, s2);\r
4257                 }\r
4258         }\r
4259         else\r
4260         {\r
4261                 UINT64 v1, v2;\r
4262                 v1 = UniToInt64(s1);\r
4263                 v2 = UniToInt64(s2);\r
4264                 if (v1 > v2)\r
4265                 {\r
4266                         ret = 1;\r
4267                 }\r
4268                 else if (v1 < v2)\r
4269                 {\r
4270                         ret = -1;\r
4271                 }\r
4272                 else\r
4273                 {\r
4274                         ret = 0;\r
4275                 }\r
4276         }\r
4277 \r
4278         Free(s1);\r
4279         Free(s2);\r
4280 \r
4281         if (sort->desc)\r
4282         {\r
4283                 ret = -ret;\r
4284         }\r
4285 \r
4286         return ret;\r
4287 }\r
4288 \r
4289 // 標準的なハンドラ\r
4290 void LvStandardHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)\r
4291 {\r
4292         NMHDR *n;\r
4293         NMLVKEYDOWN *key;\r
4294         // 引数チェック\r
4295         if (hWnd == NULL)\r
4296         {\r
4297                 return;\r
4298         }\r
4299 \r
4300         LvSortHander(hWnd, msg, wParam, lParam, id);\r
4301 \r
4302         switch (msg)\r
4303         {\r
4304         case WM_NOTIFY:\r
4305                 n = (NMHDR *)lParam;\r
4306                 if (n->idFrom == id)\r
4307                 {\r
4308                         switch (n->code)\r
4309                         {\r
4310                         case NM_DBLCLK:\r
4311                                 Command(hWnd, IDOK);\r
4312                                 break;\r
4313                         case LVN_KEYDOWN:\r
4314                                 key = (NMLVKEYDOWN *)n;\r
4315                                 if (key != NULL)\r
4316                                 {\r
4317                                         UINT code = key->wVKey;\r
4318                                         switch (code)\r
4319                                         {\r
4320                                         case VK_DELETE:\r
4321                                                 Command(hWnd, B_DELETE);\r
4322                                                 break;\r
4323 \r
4324                                         case VK_RETURN:\r
4325                                                 Command(hWnd, IDOK);\r
4326                                                 break;\r
4327 \r
4328                                         case VK_F5:\r
4329                                                 Command(hWnd, B_REFRESH);\r
4330                                                 break;\r
4331                                         }\r
4332                                 }\r
4333                                 break;\r
4334                         }\r
4335                 }\r
4336                 break;\r
4337         }\r
4338 }\r
4339 \r
4340 // ソートヘッダハンドラ\r
4341 void LvSortHander(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT id)\r
4342 {\r
4343         NMHDR *nmhdr;\r
4344         UINT subitem;\r
4345         bool desc;\r
4346         // 引数チェック\r
4347         if (hWnd == NULL)\r
4348         {\r
4349                 return;\r
4350         }\r
4351 \r
4352         switch (msg)\r
4353         {\r
4354         case WM_NOTIFY:\r
4355                 nmhdr = (NMHDR *)lParam;\r
4356 \r
4357                 if (nmhdr != NULL)\r
4358                 {\r
4359                         if (nmhdr->idFrom == id)\r
4360                         {\r
4361                                 NMLISTVIEW *v;\r
4362                                 switch (nmhdr->code)\r
4363                                 {\r
4364                                 case LVN_COLUMNCLICK:\r
4365                                         desc = false;\r
4366                                         v = (NMLISTVIEW *)lParam;\r
4367                                         subitem = v->iSubItem;\r
4368 \r
4369                                         if ((GetStyle(hWnd, id) & LVS_SORTDESCENDING) == 0)\r
4370                                         {\r
4371                                                 desc = true;\r
4372                                                 SetStyle(hWnd, id, LVS_SORTDESCENDING);\r
4373                                                 RemoveStyle(hWnd, id, LVS_SORTASCENDING);\r
4374                                         }\r
4375                                         else\r
4376                                         {\r
4377                                                 SetStyle(hWnd, id, LVS_SORTASCENDING);\r
4378                                                 RemoveStyle(hWnd, id, LVS_SORTDESCENDING);\r
4379                                         }\r
4380 \r
4381                                         LvSort(hWnd, id, subitem, desc);\r
4382                                         break;\r
4383                                 }\r
4384                         }\r
4385                 }\r
4386                 break;\r
4387         }\r
4388 }\r
4389 \r
4390 // ソートを行う\r
4391 void LvSort(HWND hWnd, UINT id, UINT subitem, bool desc)\r
4392 {\r
4393         UINT i, num;\r
4394         bool numeric = true;\r
4395         // 引数チェック\r
4396         if (hWnd == NULL)\r
4397         {\r
4398                 return;\r
4399         }\r
4400 \r
4401         num = LvNum(hWnd, id);\r
4402         for (i = 0;i < num;i++)\r
4403         {\r
4404                 wchar_t *s = LvGetStr(hWnd, id, i, subitem);\r
4405                 if (s != NULL)\r
4406                 {\r
4407                         if (UniIsNum(s) == false)\r
4408                         {\r
4409                                 numeric = false;\r
4410                                 Free(s);\r
4411                                 break;\r
4412                         }\r
4413                         Free(s);\r
4414                 }\r
4415                 else\r
4416                 {\r
4417                         numeric = false;\r
4418                         break;\r
4419                 }\r
4420         }\r
4421 \r
4422         LvSortEx(hWnd, id, subitem, desc, numeric);\r
4423 }\r
4424 \r
4425 void LvSortEx(HWND hWnd, UINT id, UINT subitem, bool desc, bool numeric)\r
4426 {\r
4427         WINUI_LV_SORT s;\r
4428         // 引数チェック\r
4429         if (hWnd == NULL)\r
4430         {\r
4431                 return;\r
4432         }\r
4433         if (subitem >= LvGetColumnNum(hWnd, id))\r
4434         {\r
4435                 return;\r
4436         }\r
4437 \r
4438         Zero(&s, sizeof(s));\r
4439         s.desc = desc;\r
4440         s.numeric = numeric;\r
4441         s.id = id;\r
4442         s.hWnd = hWnd;\r
4443         s.subitem = subitem;\r
4444 \r
4445         ListView_SortItemsEx(DlgItem(hWnd, id), LvSortProc, (LPARAM)&s);\r
4446 }\r
4447 \r
4448 // 項目追加バッチへの追加\r
4449 void LvInsertAdd(LVB *b, UINT icon, void *param, UINT num_str, ...)\r
4450 {\r
4451         UINT i;\r
4452         va_list va;\r
4453         UINT index = 0;\r
4454         LVB_ITEM *t;\r
4455         // 引数チェック\r
4456         if (b == NULL || num_str == 0)\r
4457         {\r
4458                 return;\r
4459         }\r
4460 \r
4461         t = ZeroMalloc(sizeof(LVB_ITEM));\r
4462 \r
4463         va_start(va, num_str);\r
4464 \r
4465         t->Strings = (wchar_t **)ZeroMalloc(sizeof(wchar_t *) * num_str);\r
4466         t->NumStrings = num_str;\r
4467 \r
4468         for (i = 0;i < num_str;i++)\r
4469         {\r
4470                 wchar_t *s = va_arg(va, wchar_t *);\r
4471 \r
4472                 t->Strings[i] = UniCopyStr(s);\r
4473         }\r
4474 \r
4475         t->Param = param;\r
4476         t->Image = GetIcon(icon);\r
4477 \r
4478         Add(b->ItemList, t);\r
4479 \r
4480         va_end(va);\r
4481 }\r
4482 \r
4483 // 項目追加バッチの開始\r
4484 LVB *LvInsertStart()\r
4485 {\r
4486         LVB *b = ZeroMalloc(sizeof(LVB));\r
4487         b->ItemList = NewListFast(NULL);\r
4488 \r
4489         return b;\r
4490 }\r
4491 \r
4492 // リストビューに項目を追加する\r
4493 void LvInsert(HWND hWnd, UINT id, UINT icon, void *param, UINT num_str, ...)\r
4494 {\r
4495         UINT i;\r
4496         va_list va;\r
4497         UINT index = 0;\r
4498         // 引数チェック\r
4499         if (hWnd == NULL)\r
4500         {\r
4501                 return;\r
4502         }\r
4503 \r
4504         va_start(va, num_str);\r
4505 \r
4506         for (i = 0;i < num_str;i++)\r
4507         {\r
4508                 wchar_t *s = va_arg(va, wchar_t *);\r
4509                 if (i == 0)\r
4510                 {\r
4511                         index = LvInsertItem(hWnd, id, icon, param, s);\r
4512                 }\r
4513                 else\r
4514                 {\r
4515                         LvSetItem(hWnd, id, index, i, s);\r
4516                 }\r
4517         }\r
4518 \r
4519         va_end(va);\r
4520 }\r
4521 \r
4522 // アイテムのサイズを自動調整する\r
4523 void LvAutoSize(HWND hWnd, UINT id)\r
4524 {\r
4525         UINT i;\r
4526         // 引数チェック\r
4527         if (hWnd == NULL)\r
4528         {\r
4529                 return;\r
4530         }\r
4531 \r
4532         i = 0;\r
4533         while (true)\r
4534         {\r
4535                 if (ListView_SetColumnWidth(DlgItem(hWnd, id), i, LVSCW_AUTOSIZE) == false)\r
4536                 {\r
4537                         break;\r
4538                 }\r
4539                 i++;\r
4540         }\r
4541 }\r
4542 \r
4543 // アイテムを追加する\r
4544 UINT LvInsertItem(HWND hWnd, UINT id, UINT icon, void *param, wchar_t *str)\r
4545 {\r
4546         return LvInsertItemByImageListId(hWnd, id, GetIcon(icon), param, str);\r
4547 }\r
4548 UINT LvInsertItemByImageListId(HWND hWnd, UINT id, UINT image, void *param, wchar_t *str)\r
4549 {\r
4550         LVITEMW t;\r
4551         // 引数チェック\r
4552         if (hWnd == NULL || str == NULL)\r
4553         {\r
4554                 return INFINITE;\r
4555         }\r
4556         if (MsIsNt() == false)\r
4557         {\r
4558                 char *s = CopyUniToStr(str);\r
4559                 UINT ret;\r
4560                 ret = LvInsertItemByImageListIdA(hWnd, id, image, param, s);\r
4561                 Free(s);\r
4562                 return ret;\r
4563         }\r
4564 \r
4565         Zero(&t, sizeof(t));\r
4566         t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;\r
4567         t.pszText = str;\r
4568         t.iImage = image;\r
4569         t.lParam = (LPARAM)param;\r
4570         t.iItem = LvNum(hWnd, id);\r
4571 \r
4572         return SendMsg(hWnd, id, LVM_INSERTITEMW, 0, (LPARAM)&t);\r
4573 }\r
4574 UINT LvInsertItemByImageListIdA(HWND hWnd, UINT id, UINT image, void *param, char *str)\r
4575 {\r
4576         LVITEM t;\r
4577         // 引数チェック\r
4578         if (hWnd == NULL || str == NULL)\r
4579         {\r
4580                 return INFINITE;\r
4581         }\r
4582 \r
4583         Zero(&t, sizeof(t));\r
4584         t.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;\r
4585         t.pszText = str;\r
4586         t.iImage = image;\r
4587         t.lParam = (LPARAM)param;\r
4588         t.iItem = LvNum(hWnd, id);\r
4589 \r
4590         return SendMsg(hWnd, id, LVM_INSERTITEM, 0, (LPARAM)&t);\r
4591 }\r
4592 \r
4593 // イメージを変更する\r
4594 void LvSetItemImage(HWND hWnd, UINT id, UINT index, UINT icon)\r
4595 {\r
4596         LvSetItemImageByImageListId(hWnd, id, index, GetIcon(icon));\r
4597 }\r
4598 void LvSetItemImageByImageListId(HWND hWnd, UINT id, UINT index, UINT image)\r
4599 {\r
4600         LVITEM t;\r
4601         // 引数チェック\r
4602         if (hWnd == NULL)\r
4603         {\r
4604                 return;\r
4605         }\r
4606 \r
4607         Zero(&t, sizeof(t));\r
4608         t.mask = LVIF_IMAGE;\r
4609         t.iImage = image;\r
4610         t.iItem = index;\r
4611 \r
4612         SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);\r
4613 }\r
4614 \r
4615 // アイテムのパラメータを設定する\r
4616 void LvSetItemParam(HWND hWnd, UINT id, UINT index, void *param)\r
4617 {\r
4618         LvSetItemParamEx(hWnd, id, index, 0, param);\r
4619 }\r
4620 void LvSetItemParamEx(HWND hWnd, UINT id, UINT index, UINT subitem, void *param)\r
4621 {\r
4622         LVITEM t;\r
4623         // 引数チェック\r
4624         if (hWnd == NULL)\r
4625         {\r
4626                 return;\r
4627         }\r
4628 \r
4629         Zero(&t, sizeof(t));\r
4630         t.mask = LVIF_PARAM;\r
4631         t.iItem = index;\r
4632         t.iSubItem = subitem;\r
4633         t.lParam = (LPARAM)param;\r
4634 \r
4635         SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);\r
4636 }\r
4637 \r
4638 // アイテムを設定する\r
4639 void LvSetItem(HWND hWnd, UINT id, UINT index, UINT pos, wchar_t *str)\r
4640 {\r
4641         LVITEMW t;\r
4642         wchar_t *old_str;\r
4643         // 引数チェック\r
4644         if (hWnd == NULL || str == NULL)\r
4645         {\r
4646                 return;\r
4647         }\r
4648         if (MsIsNt() == false)\r
4649         {\r
4650                 char *s = CopyUniToStr(str);\r
4651                 LvSetItemA(hWnd, id, index, pos, s);\r
4652                 Free(s);\r
4653                 return;\r
4654         }\r
4655 \r
4656         Zero(&t, sizeof(t));\r
4657         t.mask = LVIF_TEXT;\r
4658         t.pszText = str;\r
4659         t.iItem = index;\r
4660         t.iSubItem = pos;\r
4661 \r
4662         old_str = LvGetStr(hWnd, id, index, pos);\r
4663 \r
4664         if (UniStrCmp(old_str, str) != 0)\r
4665         {\r
4666                 SendMsg(hWnd, id, LVM_SETITEMW, 0, (LPARAM)&t);\r
4667         }\r
4668 \r
4669         Free(old_str);\r
4670 }\r
4671 void LvSetItemA(HWND hWnd, UINT id, UINT index, UINT pos, char *str)\r
4672 {\r
4673         LVITEM t;\r
4674         wchar_t *old_str;\r
4675         char *old_str_2;\r
4676         // 引数チェック\r
4677         if (hWnd == NULL || str == NULL)\r
4678         {\r
4679                 return;\r
4680         }\r
4681 \r
4682         Zero(&t, sizeof(t));\r
4683         t.mask = LVIF_TEXT;\r
4684         t.pszText = str;\r
4685         t.iItem = index;\r
4686         t.iSubItem = pos;\r
4687 \r
4688         old_str = LvGetStr(hWnd, id, index, pos);\r
4689         old_str_2 = CopyUniToStr(old_str);\r
4690 \r
4691         if (StrCmp(old_str_2, str) != 0)\r
4692         {\r
4693                 SendMsg(hWnd, id, LVM_SETITEM, 0, (LPARAM)&t);\r
4694         }\r
4695 \r
4696         Free(old_str_2);\r
4697         Free(old_str);\r
4698 }\r
4699 \r
4700 // リストボックスのビューを設定\r
4701 void LvSetView(HWND hWnd, UINT id, bool details)\r
4702 {\r
4703         // 引数チェック\r
4704         if (hWnd == NULL)\r
4705         {\r
4706                 return;\r
4707         }\r
4708 \r
4709         if (details)\r
4710         {\r
4711                 RemoveStyle(hWnd, id, LVS_ICON);\r
4712                 SetStyle(hWnd, id, LVS_REPORT);\r
4713         }\r
4714         else\r
4715         {\r
4716                 RemoveStyle(hWnd, id, LVS_REPORT);\r
4717                 SetStyle(hWnd, id, LVS_ICON);\r
4718         }\r
4719 }\r
4720 \r
4721 // 指定したアイテムが必ず表示されるようにする\r
4722 void LvShow(HWND hWnd, UINT id, UINT index)\r
4723 {\r
4724         // 引数チェック\r
4725         if (hWnd == NULL)\r
4726         {\r
4727                 return;\r
4728         }\r
4729 \r
4730         ListView_EnsureVisible(DlgItem(hWnd, id), index, false);\r
4731 }\r
4732 \r
4733 // 現在選択されている項目が存在するかどうかを取得する\r
4734 bool LvIsSelected(HWND hWnd, UINT id)\r
4735 {\r
4736         // 引数チェック\r
4737         if (hWnd == NULL)\r
4738         {\r
4739                 return false;\r
4740         }\r
4741 \r
4742         if (LvGetSelected(hWnd, id) == INFINITE)\r
4743         {\r
4744                 return false;\r
4745         }\r
4746 \r
4747         return true;\r
4748 }\r
4749 \r
4750 // 現在選択されている項目を取得する\r
4751 UINT LvGetFocused(HWND hWnd, UINT id)\r
4752 {\r
4753         // 引数チェック\r
4754         if (hWnd == NULL)\r
4755         {\r
4756                 return INFINITE;\r
4757         }\r
4758 \r
4759         return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED);\r
4760 }\r
4761 \r
4762 // 現在選択されている文字列を取得する\r
4763 wchar_t *LvGetFocusedStr(HWND hWnd, UINT id, UINT pos)\r
4764 {\r
4765         UINT i;\r
4766         // 引数チェック\r
4767         if (hWnd == NULL)\r
4768         {\r
4769                 return NULL;\r
4770         }\r
4771 \r
4772         i = LvGetFocused(hWnd, id);\r
4773         if (i == INFINITE)\r
4774         {\r
4775                 return NULL;\r
4776         }\r
4777 \r
4778         return LvGetStr(hWnd, id, i, pos);\r
4779 }\r
4780 \r
4781 // 現在選択されている項目を取得する\r
4782 UINT LvGetSelected(HWND hWnd, UINT id)\r
4783 {\r
4784         // 引数チェック\r
4785         if (hWnd == NULL)\r
4786         {\r
4787                 return INFINITE;\r
4788         }\r
4789 \r
4790         return ListView_GetNextItem(DlgItem(hWnd, id), -1, LVNI_FOCUSED | LVNI_SELECTED);\r
4791 }\r
4792 \r
4793 // 現在選択されている文字列を取得する\r
4794 wchar_t *LvGetSelectedStr(HWND hWnd, UINT id, UINT pos)\r
4795 {\r
4796         UINT i;\r
4797         // 引数チェック\r
4798         if (hWnd == NULL)\r
4799         {\r
4800                 return NULL;\r
4801         }\r
4802 \r
4803         i = LvGetSelected(hWnd, id);\r
4804         if (i == INFINITE)\r
4805         {\r
4806                 return NULL;\r
4807         }\r
4808 \r
4809         return LvGetStr(hWnd, id, i, pos);\r
4810 }\r
4811 char *LvGetSelectedStrA(HWND hWnd, UINT id, UINT pos)\r
4812 {\r
4813         char *ret;\r
4814         wchar_t *tmp = LvGetSelectedStr(hWnd, id, pos);\r
4815         if (tmp == NULL)\r
4816         {\r
4817                 return NULL;\r
4818         }\r
4819         ret = CopyUniToStr(tmp);\r
4820         Free(tmp);\r
4821         return ret;\r
4822 }\r
4823 \r
4824 // 2 つ以上の項目がマスクされているかどうかを取得する\r
4825 bool LvIsMultiMasked(HWND hWnd, UINT id)\r
4826 {\r
4827         UINT i;\r
4828         // 引数チェック\r
4829         if (hWnd == NULL)\r
4830         {\r
4831                 return false;\r
4832         }\r
4833 \r
4834         i = INFINITE;\r
4835         i = LvGetNextMasked(hWnd, id, i);\r
4836         if (i != INFINITE)\r
4837         {\r
4838                 if (LvGetNextMasked(hWnd, id, i) != INFINITE)\r
4839                 {\r
4840                         return true;\r
4841                 }\r
4842         }\r
4843 \r
4844         return false;\r
4845 }\r
4846 \r
4847 // ただ 1 つの項目だけが選択されているかどうか調べる\r
4848 bool LvIsSingleSelected(HWND hWnd, UINT id)\r
4849 {\r
4850         return LvIsSelected(hWnd, id) && (LvIsMultiMasked(hWnd, id) == false);\r
4851 }\r
4852 \r
4853 // 現在マスクされている項目が存在するかどうかを取得する\r
4854 bool LvIsMasked(HWND hWnd, UINT id)\r
4855 {\r
4856         // 引数チェック\r
4857         if (hWnd == NULL)\r
4858         {\r
4859                 return false;\r
4860         }\r
4861 \r
4862         if (LvGetNextMasked(hWnd, id, INFINITE) == INFINITE)\r
4863         {\r
4864                 return false;\r
4865         }\r
4866 \r
4867         return true;\r
4868 }\r
4869 \r
4870 // 現在マスクされている項目数を取得する\r
4871 UINT LvGetMaskedNum(HWND hWnd, UINT id)\r
4872 {\r
4873         UINT i = INFINITE;\r
4874         UINT num = 0;\r
4875         // 引数チェック\r
4876         if (hWnd == NULL)\r
4877         {\r
4878                 return 0;\r
4879         }\r
4880 \r
4881         while (true)\r
4882         {\r
4883                 i = LvGetNextMasked(hWnd, id, i);\r
4884                 if (i == INFINITE)\r
4885                 {\r
4886                         break;\r
4887                 }\r
4888 \r
4889                 num++;\r
4890         }\r
4891 \r
4892         return num;\r
4893 }\r
4894 \r
4895 // 現在マスクされている項目を取得する\r
4896 UINT LvGetNextMasked(HWND hWnd, UINT id, UINT start)\r
4897 {\r
4898         // 引数チェック\r
4899         if (hWnd == NULL)\r
4900         {\r
4901                 return INFINITE;\r
4902         }\r
4903 \r
4904         return ListView_GetNextItem(DlgItem(hWnd, id), start, LVNI_SELECTED);\r
4905 }\r
4906 \r
4907 // 指定した文字列を持つ項目を検索する\r
4908 UINT LvSearchStr_(HWND hWnd, UINT id, UINT pos, wchar_t *str)\r
4909 {\r
4910         UINT ret;\r
4911         LVFINDINFOW t;\r
4912         // 引数チェック\r
4913         if (hWnd == NULL || str == NULL)\r
4914         {\r
4915                 return INFINITE;\r
4916         }\r
4917 \r
4918         Zero(&t, sizeof(t));\r
4919         t.flags = LVFI_STRING;\r
4920         t.psz = str;\r
4921         t.vkDirection = VK_DOWN;\r
4922 \r
4923         ret = SendMsg(hWnd, id, LVM_FINDITEMW, -1, (LPARAM)&t);\r
4924 \r
4925         return ret;\r
4926 }\r
4927 \r
4928 // 指定した文字列を持つ項目を検索する\r
4929 UINT LvSearchStr(HWND hWnd, UINT id, UINT pos, wchar_t *str)\r
4930 {\r
4931         UINT i, num;\r
4932         // 引数チェック\r
4933         if (hWnd == NULL || str == NULL)\r
4934         {\r
4935                 return INFINITE;\r
4936         }\r
4937 \r
4938         num = LvNum(hWnd, id);\r
4939 \r
4940         for (i = 0;i < num;i++)\r
4941         {\r
4942                 wchar_t *s = LvGetStr(hWnd, id, i, pos);\r
4943                 if (s != NULL)\r
4944                 {\r
4945                         if (UniStrCmpi(s, str) == 0)\r
4946                         {\r
4947                                 Free(s);\r
4948                                 return i;\r
4949                         }\r
4950                         else\r
4951                         {\r
4952                                 Free(s);\r
4953                         }\r
4954                 }\r
4955         }\r
4956 \r
4957         return INFINITE;\r
4958 }\r
4959 UINT LvSearchStrA(HWND hWnd, UINT id, UINT pos, char *str)\r
4960 {\r
4961         wchar_t *tmp = CopyStrToUni(str);\r
4962         UINT ret = LvSearchStr(hWnd, id, pos, tmp);\r
4963         Free(tmp);\r
4964         return ret;\r
4965 }\r
4966 \r
4967 // 指定した param を持つ項目を検索する\r
4968 UINT LvSearchParam(HWND hWnd, UINT id, void *param)\r
4969 {\r
4970         UINT i, num;\r
4971         // 引数チェック\r
4972         if (hWnd == NULL)\r
4973         {\r
4974                 return INFINITE;\r
4975         }\r
4976 \r
4977         num = LvNum(hWnd, id);\r
4978 \r
4979         for (i = 0;i < num;i++)\r
4980         {\r
4981                 if (LvGetParam(hWnd, id, i) == param)\r
4982                 {\r
4983                         return i;\r
4984                 }\r
4985         }\r
4986 \r
4987         return INFINITE;\r
4988 }\r
4989 \r
4990 // 項目数を取得する\r
4991 UINT LvNum(HWND hWnd, UINT id)\r
4992 {\r
4993         // 引数チェック\r
4994         if (hWnd == NULL)\r
4995         {\r
4996                 return 0;\r
4997         }\r
4998 \r
4999         return ListView_GetItemCount(DlgItem(hWnd, id));\r
5000 }\r
5001 \r
5002 // 項目を削除する\r
5003 void LvDeleteItem(HWND hWnd, UINT id, UINT index)\r
5004 {\r
5005         UINT i;\r
5006         // 引数チェック\r
5007         if (hWnd == NULL)\r
5008         {\r
5009                 return;\r
5010         }\r
5011 \r
5012         ListView_DeleteItem(DlgItem(hWnd, id), index);\r
5013 \r
5014         i = LvGetSelected(hWnd, id);\r
5015         if (i != INFINITE)\r
5016         {\r
5017                 LvSelect(hWnd, id, i);\r
5018         }\r
5019 }\r
5020 \r
5021 // 項目からデータを取得する\r
5022 void *LvGetParam(HWND hWnd, UINT id, UINT index)\r
5023 {\r
5024         return LvGetParamEx(hWnd, id, index, 0);\r
5025 }\r
5026 void *LvGetParamEx(HWND hWnd, UINT id, UINT index, UINT subitem)\r
5027 {\r
5028         LVITEM t;\r
5029         // 引数チェック\r
5030         if (hWnd == NULL)\r
5031         {\r
5032                 return NULL;\r
5033         }\r
5034         if (index == INFINITE)\r
5035         {\r
5036                 return NULL;\r
5037         }\r
5038 \r
5039         Zero(&t, sizeof(t));\r
5040         t.mask = LVIF_PARAM;\r
5041         t.iItem = index;\r
5042         t.iSubItem = subitem;\r
5043 \r
5044         if (ListView_GetItem(DlgItem(hWnd, id), &t) == false)\r
5045         {\r
5046                 return NULL;\r
5047         }\r
5048 \r
5049         return (void *)t.lParam;\r
5050 }\r
5051 \r
5052 // 項目の文字列を取得する\r
5053 wchar_t *LvGetStr(HWND hWnd, UINT id, UINT index, UINT pos)\r
5054 {\r
5055         wchar_t *tmp;\r
5056         UINT size;\r
5057         LVITEMW t;\r
5058         // 引数チェック\r
5059         if (hWnd == NULL)\r
5060         {\r
5061                 return NULL;\r
5062         }\r
5063         if (MsIsNt() == false)\r
5064         {\r
5065                 char *s = LvGetStrA(hWnd, id, index, pos);\r
5066                 if (s == NULL)\r
5067                 {\r
5068                         return NULL;\r
5069                 }\r
5070                 else\r
5071                 {\r
5072                         wchar_t *ret = CopyStrToUni(s);\r
5073                         Free(s);\r
5074 \r
5075                         return ret;\r
5076                 }\r
5077         }\r
5078 \r
5079         size = 65536;\r
5080         tmp = Malloc(size);\r
5081 \r
5082         Zero(&t, sizeof(t));\r
5083         t.mask = LVIF_TEXT;\r
5084         t.iItem = index;\r
5085         t.iSubItem = pos;\r
5086         t.pszText = tmp;\r
5087         t.cchTextMax = size;\r
5088 \r
5089         if (SendMsg(hWnd, id, LVM_GETITEMTEXTW, index, (LPARAM)&t) <= 0)\r
5090         {\r
5091                 Free(tmp);\r
5092                 return UniCopyStr(L"");\r
5093         }\r
5094         else\r
5095         {\r
5096                 wchar_t *ret = UniCopyStr(tmp);\r
5097                 Free(tmp);\r
5098                 return ret;\r
5099         }\r
5100 }\r
5101 char *LvGetStrA(HWND hWnd, UINT id, UINT index, UINT pos)\r
5102 {\r
5103         char *tmp;\r
5104         UINT size;\r
5105         LVITEM t;\r
5106         // 引数チェック\r
5107         if (hWnd == NULL)\r
5108         {\r
5109                 return NULL;\r
5110         }\r
5111 \r
5112         size = 65536;\r
5113         tmp = Malloc(size);\r
5114 \r
5115         Zero(&t, sizeof(t));\r
5116         t.mask = LVIF_TEXT;\r
5117         t.iItem = index;\r
5118         t.iSubItem = pos;\r
5119         t.pszText = tmp;\r
5120         t.cchTextMax = size;\r
5121 \r
5122         if (SendMsg(hWnd, id, LVM_GETITEMTEXT, index, (LPARAM)&t) <= 0)\r
5123         {\r
5124                 Free(tmp);\r
5125                 return CopyStr("");\r
5126         }\r
5127         else\r
5128         {\r
5129                 char *ret = CopyStr(tmp);\r
5130                 Free(tmp);\r
5131                 return ret;\r
5132         }\r
5133 }\r
5134 \r
5135 // スタイルを設定する\r
5136 void LvSetStyle(HWND hWnd, UINT id, UINT style)\r
5137 {\r
5138         // 引数チェック\r
5139         if (hWnd == NULL)\r
5140         {\r
5141                 return;\r
5142         }\r
5143 \r
5144         if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) == 0)\r
5145         {\r
5146                 ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, style);\r
5147         }\r
5148 }\r
5149 \r
5150 // スタイルを削除する\r
5151 void LvRemoveStyle(HWND hWnd, UINT id, UINT style)\r
5152 {\r
5153         // 引数チェック\r
5154         if (hWnd == NULL)\r
5155         {\r
5156                 return;\r
5157         }\r
5158 \r
5159         if ((ListView_GetExtendedListViewStyle(DlgItem(hWnd, id)) & style) != 0)\r
5160         {\r
5161                 ListView_SetExtendedListViewStyleEx(DlgItem(hWnd, id), style, 0);\r
5162         }\r
5163 }\r
5164 \r
5165 // 項目の選択を反転する\r
5166 void LvSwitchSelect(HWND hWnd, UINT id)\r
5167 {\r
5168         UINT i, num;\r
5169         bool *states;\r
5170         // 引数チェック\r
5171         if (hWnd == NULL)\r
5172         {\r
5173                 return;\r
5174         }\r
5175 \r
5176         num = LvNum(hWnd, id);\r
5177         states = ZeroMalloc(sizeof(bool) * num);\r
5178 \r
5179         i = INFINITE;\r
5180         while (true)\r
5181         {\r
5182                 i = LvGetNextMasked(hWnd, id, i);\r
5183                 if (i == INFINITE)\r
5184                 {\r
5185                         break;\r
5186                 }\r
5187 \r
5188                 states[i] = true;\r
5189         }\r
5190 \r
5191         for (i = 0;i < num;i++)\r
5192         {\r
5193                 if (states[i] == false)\r
5194                 {\r
5195                         ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);\r
5196                 }\r
5197                 else\r
5198                 {\r
5199                         ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);\r
5200                 }\r
5201         }\r
5202 \r
5203         Free(states);\r
5204 }\r
5205 \r
5206 // すべての項目を選択する\r
5207 void LvSelectAll(HWND hWnd, UINT id)\r
5208 {\r
5209         UINT i, num;\r
5210         // 引数チェック\r
5211         if (hWnd == NULL)\r
5212         {\r
5213                 return;\r
5214         }\r
5215 \r
5216         num = LvNum(hWnd, id);\r
5217         for (i = 0;i < num;i++)\r
5218         {\r
5219                 ListView_SetItemState(DlgItem(hWnd, id), i, LVIS_SELECTED, LVIS_SELECTED);\r
5220         }\r
5221 }\r
5222 \r
5223 // 項目を選択する\r
5224 void LvSelect(HWND hWnd, UINT id, UINT index)\r
5225 {\r
5226         // 引数チェック\r
5227         if (hWnd == NULL)\r
5228         {\r
5229                 return;\r
5230         }\r
5231 \r
5232         if (index == INFINITE)\r
5233         {\r
5234                 UINT i, num;\r
5235                 // すべて選択解除する\r
5236                 num = LvNum(hWnd, id);\r
5237                 for (i = 0;i < num;i++)\r
5238                 {\r
5239                         ListView_SetItemState(DlgItem(hWnd, id), i, 0, LVIS_SELECTED);\r
5240                 }\r
5241         }\r
5242         else\r
5243         {\r
5244                 // 選択する\r
5245                 ListView_SetItemState(DlgItem(hWnd, id), index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);\r
5246                 ListView_EnsureVisible(DlgItem(hWnd, id), index, true);\r
5247         }\r
5248 }\r
5249 \r
5250 // 証明書情報を表示する\r
5251 void PrintCertInfo(HWND hWnd, CERT_DLG *p)\r
5252 {\r
5253         X *x;\r
5254         char *serial_tmp;\r
5255         UINT serial_size;\r
5256         wchar_t *wchar_tmp;\r
5257         wchar_t tmp[1024 * 5];\r
5258         UCHAR md5[MD5_SIZE];\r
5259         UCHAR sha1[SHA1_SIZE];\r
5260         char *s_tmp;\r
5261         K *k;\r
5262         // 引数チェック\r
5263         if (p == NULL || hWnd == NULL)\r
5264         {\r
5265                 return;\r
5266         }\r
5267 \r
5268         x = p->x;\r
5269 \r
5270         // シリアル番号\r
5271         if (x->serial != NULL)\r
5272         {\r
5273                 serial_size = x->serial->size * 3 + 1;\r
5274                 serial_tmp = ZeroMalloc(serial_size);\r
5275                 BinToStrEx(serial_tmp, serial_size, x->serial->data, x->serial->size);\r
5276                 wchar_tmp = CopyStrToUni(serial_tmp);\r
5277                 Free(serial_tmp);\r
5278         }\r
5279         else\r
5280         {\r
5281                 wchar_tmp = CopyUniStr(_UU("CERT_NO_SERIAL"));\r
5282         }\r
5283         LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SERIAL"), wchar_tmp);\r
5284 \r
5285         // 発行者\r
5286         GetAllNameFromName(tmp, sizeof(tmp), x->issuer_name);\r
5287         LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_ISSUER"), tmp);\r
5288 \r
5289         // サブジェクト\r
5290         GetAllNameFromName(tmp, sizeof(tmp), x->subject_name);\r
5291         LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_SUBJECT"), tmp);\r
5292 \r
5293         // 有効期限の開始\r
5294         GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notBefore), NULL);\r
5295         LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_BEFORE"), tmp);\r
5296 \r
5297         // 有効期限の終了\r
5298         GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);\r
5299         LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_NOT_AFTER"), tmp);\r
5300 \r
5301         // ビット数\r
5302         if (x->is_compatible_bit)\r
5303         {\r
5304                 UniFormat(tmp, sizeof(tmp), _UU("CERT_BITS_FORMAT"), x->bits);\r
5305                 LvInsert(hWnd, L_CERTINFO, ICO_CERT, NULL, 2, _UU("CERT_BITS"), tmp);\r
5306         }\r
5307 \r
5308         // 公開鍵\r
5309         k = GetKFromX(x);\r
5310         if (k != NULL)\r
5311         {\r
5312                 BUF *b = KToBuf(k, false, NULL);\r
5313                 s_tmp = CopyBinToStrEx(b->Buf, b->Size);\r
5314                 StrToUni(tmp, sizeof(tmp), s_tmp);\r
5315                 Free(s_tmp);\r
5316                 LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_PUBLIC_KEY"), tmp);\r
5317                 FreeBuf(b);\r
5318         }\r
5319         FreeK(k);\r
5320 \r
5321         GetXDigest(x, md5, false);\r
5322         GetXDigest(x, sha1, true);\r
5323 \r
5324         // ダイジェスト (MD5)\r
5325         s_tmp = CopyBinToStrEx(md5, sizeof(md5));\r
5326         StrToUni(tmp, sizeof(tmp), s_tmp);\r
5327         Free(s_tmp);\r
5328         LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_MD5"), tmp);\r
5329 \r
5330         // ダイジェスト (SHA-1)\r
5331         s_tmp = CopyBinToStrEx(sha1, sizeof(sha1));\r
5332         StrToUni(tmp, sizeof(tmp), s_tmp);\r
5333         Free(s_tmp);\r
5334         LvInsert(hWnd, L_CERTINFO, ICO_KEY, NULL, 2, _UU("CERT_DIGEST_SHA1"), tmp);\r
5335 \r
5336         Free(wchar_tmp);\r
5337 \r
5338         LvSelect(hWnd, L_CERTINFO, 0);\r
5339 }\r
5340 \r
5341 // 表示の更新\r
5342 void CertDlgUpdate(HWND hWnd, CERT_DLG *p)\r
5343 {\r
5344         // 引数チェック\r
5345         if (hWnd == NULL || p == NULL)\r
5346         {\r
5347                 return;\r
5348         }\r
5349 \r
5350         if (LvIsSelected(hWnd, L_CERTINFO) == false)\r
5351         {\r
5352                 SetText(hWnd, E_DETAIL, L"");\r
5353         }\r
5354         else\r
5355         {\r
5356                 UINT i = LvGetSelected(hWnd, L_CERTINFO);\r
5357                 wchar_t *tmp = LvGetStr(hWnd, L_CERTINFO, i, 1);\r
5358                 SetText(hWnd, E_DETAIL, tmp);\r
5359                 Free(tmp);\r
5360         }\r
5361 }\r
5362 \r
5363 // 証明書の保存\r
5364 void CertDlgSave(HWND hWnd, CERT_DLG *p)\r
5365 {\r
5366         wchar_t *name;\r
5367         X *x;\r
5368         // 引数チェック\r
5369         if (hWnd == NULL || p == NULL)\r
5370         {\r
5371                 return;\r
5372         }\r
5373 \r
5374         // 保存\r
5375         name = SaveDlg(hWnd, _UU("DLG_CERT_FILES"), _UU("DLG_SAVE_CERT"), NULL, L".cer");\r
5376         x = p->x;\r
5377         if (name != NULL)\r
5378         {\r
5379                 char str[MAX_SIZE];\r
5380                 UniToStr(str, sizeof(str), name);\r
5381                 if (XToFile(x, str, true))\r
5382                 {\r
5383                         MsgBox(hWnd, MB_ICONINFORMATION, _UU("DLG_CERT_SAVE_OK"));\r
5384                 }\r
5385                 else\r
5386                 {\r
5387                         MsgBox(hWnd, MB_ICONSTOP, _UU("DLG_CERT_SAVE_ERROR"));\r
5388                 }\r
5389                 Free(name);\r
5390         }\r
5391 }\r
5392 \r
5393 // 証明書表示ダイアログプロシージャ\r
5394 UINT CertDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
5395 {\r
5396         CERT_DLG *p = (CERT_DLG *)param;\r
5397         X *x;\r
5398         wchar_t tmp[MAX_SIZE];\r
5399         NMHDR *n;\r
5400         // 引数チェック\r
5401         if (hWnd == NULL)\r
5402         {\r
5403                 return 0;\r
5404         }\r
5405 \r
5406         switch (msg)\r
5407         {\r
5408         case WM_INITDIALOG:\r
5409                 SetIcon(hWnd, 0, ICO_CERT);\r
5410                 x = p->x;\r
5411                 GetAllNameFromNameEx(tmp, sizeof(tmp), x->subject_name);\r
5412                 SetText(hWnd, E_SUBJECT, tmp);\r
5413                 GetAllNameFromNameEx(tmp, sizeof(tmp), x->issuer_name);\r
5414                 SetText(hWnd, E_ISSUER, tmp);\r
5415                 GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(x->notAfter), NULL);\r
5416                 SetText(hWnd, E_EXPIRES, tmp);\r
5417                 SetFont(hWnd, E_SUBJECT, Font(0, 1));\r
5418                 SetFont(hWnd, E_ISSUER, Font(0, 1));\r
5419                 SetFont(hWnd, E_EXPIRES, Font(0, 1));\r
5420                 SetIcon(hWnd, B_PARENT, ICO_CERT);\r
5421                 if (x->root_cert)\r
5422                 {\r
5423                         // ルート証明書\r
5424                         Hide(hWnd, S_WARNING_ICON);\r
5425                         SetText(hWnd, S_PARENT, _UU("CERT_ROOT"));\r
5426                         Hide(hWnd, B_PARENT);\r
5427                         Hide(hWnd, S_PARENT_BUTTON_STR);\r
5428                 }\r
5429                 else if (p->issuer_x != NULL)\r
5430                 {\r
5431                         // 親証明書がある\r
5432                         Hide(hWnd, S_WARNING_ICON);\r
5433                 }\r
5434                 else\r
5435                 {\r
5436                         // 親証明書が無い\r
5437                         Hide(hWnd, S_CERT_ICON);\r
5438                         Hide(hWnd, B_PARENT);\r
5439                         Hide(hWnd, S_PARENT_BUTTON_STR);\r
5440                         SetText(hWnd, S_PARENT, _UU("CERT_NOT_FOUND"));\r
5441                         if (p->ManagerMode)\r
5442                         {\r
5443                                 Hide(hWnd, IDC_STATIC1);\r
5444                                 Hide(hWnd, S_PARENT);\r
5445                                 Hide(hWnd, S_WARNING_ICON);\r
5446                                 Hide(hWnd, S_CERT_ICON);\r
5447                                 Hide(hWnd, B_PARENT);\r
5448                                 Hide(hWnd, S_PARENT_BUTTON_STR);\r
5449                         }\r
5450                 }\r
5451 \r
5452 \r
5453                 LvInit(hWnd, L_CERTINFO);\r
5454                 LvInsertColumn(hWnd, L_CERTINFO, 0, _UU("CERT_LV_C1"), 130);\r
5455                 LvInsertColumn(hWnd, L_CERTINFO, 1, _UU("CERT_LV_C2"), 250);\r
5456 \r
5457                 PrintCertInfo(hWnd, p);\r
5458                 Focus(hWnd, L_CERTINFO);\r
5459 \r
5460                 CertDlgUpdate(hWnd, p);\r
5461 \r
5462                 if (p->ManagerMode)\r
5463                 {\r
5464                         Show(hWnd, B_SAVE);\r
5465                 }\r
5466                 else\r
5467                 {\r
5468                         // セキュリティのため非表示にする\r
5469                         Hide(hWnd, B_SAVE);\r
5470                 }\r
5471 \r
5472                 break;\r
5473         case WM_COMMAND:\r
5474                 switch (wParam)\r
5475                 {\r
5476                 case IDOK:\r
5477                 case IDCANCEL:\r
5478                         Close(hWnd);\r
5479                         break;\r
5480                 case B_PARENT:\r
5481                         CertDlg(hWnd, p->issuer_x, NULL, p->ManagerMode);\r
5482                         break;\r
5483                 case B_SAVE:\r
5484                         // ファイルに保存\r
5485                         CertDlgSave(hWnd, p);\r
5486                         break;\r
5487                 }\r
5488                 break;\r
5489         case WM_CLOSE:\r
5490                 EndDialog(hWnd, false);\r
5491                 break;\r
5492         case WM_NOTIFY:\r
5493                 n = (NMHDR *)lParam;\r
5494                 switch (n->idFrom)\r
5495                 {\r
5496                 case L_CERTINFO:\r
5497                         switch (n->code)\r
5498                         {\r
5499                         case LVN_ITEMCHANGED:\r
5500                                 CertDlgUpdate(hWnd, p);\r
5501                                 break;\r
5502                         }\r
5503                         break;\r
5504                 }\r
5505                 break;\r
5506         }\r
5507 \r
5508         LvSortHander(hWnd, msg, wParam, lParam, L_CERTINFO);\r
5509 \r
5510         return 0;\r
5511 }\r
5512 \r
5513 // 証明書表示ダイアログ\r
5514 void CertDlg(HWND hWnd, X *x, X *issuer_x, bool manager)\r
5515 {\r
5516         CERT_DLG p;\r
5517         // 引数チェック\r
5518         if (x == NULL)\r
5519         {\r
5520                 return;\r
5521         }\r
5522 \r
5523         Zero(&p, sizeof(p));\r
5524         p.x = x;\r
5525         if (CompareX(x, issuer_x) == false)\r
5526         {\r
5527                 p.issuer_x = issuer_x;\r
5528         }\r
5529         p.ManagerMode = manager;\r
5530         Dialog(hWnd, D_CERT, CertDlgProc, &p);\r
5531 }\r
5532 \r
5533 // ステータスウインドウダイアログ\r
5534 UINT StatusPrinterWindowDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
5535 {\r
5536         STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;\r
5537         PACK *pack;\r
5538         // 引数チェック\r
5539         if (hWnd == NULL)\r
5540         {\r
5541                 return 0;\r
5542         }\r
5543 \r
5544         switch (msg)\r
5545         {\r
5546         case WM_INITDIALOG:\r
5547                 // 初期化\r
5548                 SetIcon(hWnd, 0, ICO_SERVER_ONLINE);\r
5549                 RemoveExStyle(hWnd, 0, WS_EX_APPWINDOW);\r
5550                 p->hWnd = hWnd;\r
5551                 NoticeThreadInit(p->Thread);\r
5552                 FormatText(hWnd, 0, p->AccountName);\r
5553                 break;\r
5554 \r
5555         case WM_COMMAND:\r
5556                 switch (wParam)\r
5557                 {\r
5558                 case IDOK:\r
5559                 case IDCANCEL:\r
5560                         // キャンセルボタン\r
5561                         Close(hWnd);\r
5562                         break;\r
5563                 }\r
5564 \r
5565                 break;\r
5566 \r
5567         case WM_APP + 1:\r
5568                 // 文字列を設定\r
5569                 SetText(hWnd, S_STATUS, (wchar_t *)lParam);\r
5570                 break;\r
5571 \r
5572         case WM_APP + 2:\r
5573                 // このウインドウを閉じる\r
5574                 EndDialog(hWnd, false);\r
5575                 break;\r
5576 \r
5577         case WM_CLOSE:\r
5578                 // セッションを終了する\r
5579                 pack = NewPack();\r
5580                 SendPack(p->Sock, pack);\r
5581                 EndDialog(hWnd, false);\r
5582                 break;\r
5583         }\r
5584 \r
5585         return 0;\r
5586 }\r
5587 \r
5588 // ステータスウインドウ制御用スレッド\r
5589 void StatusPrinterWindowThread(THREAD *thread, void *param)\r
5590 {\r
5591         STATUS_WINDOW_PARAM *p = (STATUS_WINDOW_PARAM *)param;\r
5592         // 引数チェック\r
5593         if (thread == NULL || param == NULL)\r
5594         {\r
5595                 return;\r
5596         }\r
5597 \r
5598         p->Thread = thread;\r
5599         DialogEx2(NULL, D_STATUS, StatusPrinterWindowDlg, p, true, true);\r
5600 \r
5601         Free(p);\r
5602 }\r
5603 \r
5604 // ステータスウインドウにメッセージを表示する\r
5605 void StatusPrinterWindowPrint(STATUS_WINDOW *sw, wchar_t *str)\r
5606 {\r
5607         // 引数チェック\r
5608         if (sw == NULL)\r
5609         {\r
5610                 return;\r
5611         }\r
5612 \r
5613         SendMessage(sw->hWnd, WM_APP + 1, 0, (LPARAM)str);\r
5614 }\r
5615 \r
5616 // ステータスウインドウの終了と解放\r
5617 void StatusPrinterWindowStop(STATUS_WINDOW *sw)\r
5618 {\r
5619         // 引数チェック\r
5620         if (sw == NULL)\r
5621         {\r
5622                 return;\r
5623         }\r
5624 \r
5625         // 停止メッセージを送信\r
5626         SendMessage(sw->hWnd, WM_APP + 2, 0, 0);\r
5627 \r
5628         // スレッド停止まで待機\r
5629         WaitThread(sw->Thread, INFINITE);\r
5630 \r
5631         // メモリ解放\r
5632         ReleaseThread(sw->Thread);\r
5633         Free(sw);\r
5634 }\r
5635 \r
5636 // ステータスウインドウの初期化\r
5637 STATUS_WINDOW *StatusPrinterWindowStart(SOCK *s, wchar_t *account_name)\r
5638 {\r
5639         STATUS_WINDOW_PARAM *p;\r
5640         STATUS_WINDOW *sw;\r
5641         THREAD *t;\r
5642         // 引数チェック\r
5643         if (s == NULL || account_name == NULL)\r
5644         {\r
5645                 return NULL;\r
5646         }\r
5647 \r
5648         p = ZeroMalloc(sizeof(STATUS_WINDOW_PARAM));\r
5649         p->Sock = s;\r
5650         UniStrCpy(p->AccountName, sizeof(p->AccountName), account_name);\r
5651 \r
5652         // スレッド作成\r
5653         t = NewThread(StatusPrinterWindowThread, p);\r
5654         WaitThreadInit(t);\r
5655 \r
5656         sw = ZeroMalloc(sizeof(STATUS_WINDOW));\r
5657         sw->hWnd = p->hWnd;\r
5658         sw->Thread = t;\r
5659 \r
5660         return sw;\r
5661 }\r
5662 \r
5663 // 文字列を取得\r
5664 wchar_t *LbGetStr(HWND hWnd, UINT id)\r
5665 {\r
5666         // 引数チェック\r
5667         if (hWnd == NULL)\r
5668         {\r
5669                 return NULL;\r
5670         }\r
5671 \r
5672         return GetText(hWnd, id);\r
5673 }\r
5674 \r
5675 // 文字列検索\r
5676 UINT LbFindStr(HWND hWnd, UINT id, wchar_t *str)\r
5677 {\r
5678         UINT ret;\r
5679         // 引数チェック\r
5680         if (hWnd == NULL || str == NULL)\r
5681         {\r
5682                 return INFINITE;\r
5683         }\r
5684 \r
5685         ret = SendMsg(hWnd, id, LB_FINDSTRING, -1, (LPARAM)str);\r
5686 \r
5687         return ret;\r
5688 }\r
5689 \r
5690 // 項目数を取得\r
5691 UINT LbNum(HWND hWnd, UINT id)\r
5692 {\r
5693         // 引数チェック\r
5694         if (hWnd == NULL)\r
5695         {\r
5696                 return INFINITE;\r
5697         }\r
5698 \r
5699         return SendMsg(hWnd, id, LB_GETCOUNT, 0, 0);\r
5700 }\r
5701 \r
5702 // 文字列追加\r
5703 UINT LbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data)\r
5704 {\r
5705         UINT ret;\r
5706 \r
5707         if (MsIsNt() == false)\r
5708         {\r
5709                 char *s = CopyUniToStr(str);\r
5710                 ret = LbAddStrA(hWnd, id, s, data);\r
5711                 Free(s);\r
5712                 return ret;\r
5713         }\r
5714 \r
5715         // 引数チェック\r
5716         if (hWnd == NULL || str == NULL)\r
5717         {\r
5718                 return INFINITE;\r
5719         }\r
5720 \r
5721         ret = SendMsg(hWnd, id, LB_ADDSTRING, 0, (LPARAM)str);\r
5722         SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);\r
5723 \r
5724         if (LbNum(hWnd, id) == 1)\r
5725         {\r
5726                 LbSelectIndex(hWnd, id, 0);\r
5727         }\r
5728 \r
5729         return ret;\r
5730 }\r
5731 UINT LbAddStrA(HWND hWnd, UINT id, char *str, UINT data)\r
5732 {\r
5733         UINT ret;\r
5734         // 引数チェック\r
5735         if (hWnd == NULL || str == NULL)\r
5736         {\r
5737                 return INFINITE;\r
5738         }\r
5739 \r
5740         ret = SendMsg(hWnd, id, LB_ADDSTRING, 0, (LPARAM)str);\r
5741         SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);\r
5742 \r
5743         if (LbNum(hWnd, id) == 1)\r
5744         {\r
5745                 LbSelectIndex(hWnd, id, 0);\r
5746         }\r
5747 \r
5748         return ret;\r
5749 }\r
5750 \r
5751 // 文字列挿入\r
5752 UINT LbInsertStr(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT data)\r
5753 {\r
5754         UINT ret;\r
5755 \r
5756         if (MsIsNt() == false)\r
5757         {\r
5758                 char *s = CopyUniToStr(str);\r
5759                 ret = LbInsertStrA(hWnd, id, index, s, data);\r
5760                 Free(s);\r
5761                 return ret;\r
5762         }\r
5763 \r
5764         // 引数チェック\r
5765         if (hWnd == NULL || str == NULL)\r
5766         {\r
5767                 return INFINITE;\r
5768         }\r
5769 \r
5770         ret = SendMsg(hWnd, id, LB_INSERTSTRING, index, (LPARAM)str);\r
5771         SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);\r
5772 \r
5773         if (LbNum(hWnd, id) == 1)\r
5774         {\r
5775                 LbSelect(hWnd, id, 0);\r
5776         }\r
5777 \r
5778         return ret;\r
5779 }\r
5780 UINT LbInsertStrA(HWND hWnd, UINT id, UINT index, char *str, UINT data)\r
5781 {\r
5782         UINT ret;\r
5783         // 引数チェック\r
5784         if (hWnd == NULL || str == NULL)\r
5785         {\r
5786                 return INFINITE;\r
5787         }\r
5788 \r
5789         ret = SendMsg(hWnd, id, LB_INSERTSTRING, index, (LPARAM)str);\r
5790         SendMsg(hWnd, id, LB_SETITEMDATA, ret, (LPARAM)data);\r
5791 \r
5792         if (LbNum(hWnd, id) == 1)\r
5793         {\r
5794                 LbSelect(hWnd, id, 0);\r
5795         }\r
5796 \r
5797         return ret;\r
5798 }\r
5799 \r
5800 // すべて削除\r
5801 void LbReset(HWND hWnd, UINT id)\r
5802 {\r
5803         // 引数チェック\r
5804         if (hWnd == NULL)\r
5805         {\r
5806                 return;\r
5807         }\r
5808 \r
5809         SendMsg(hWnd, id, LB_RESETCONTENT, 0, 0);\r
5810 }\r
5811 \r
5812 // インデックスを指定して選択\r
5813 void LbSelectIndex(HWND hWnd, UINT id, UINT index)\r
5814 {\r
5815         // 引数チェック\r
5816         if (hWnd == NULL)\r
5817         {\r
5818                 return;\r
5819         }\r
5820 \r
5821         SendMsg(hWnd, id, LB_SETCURSEL, index, 0);\r
5822 }\r
5823 \r
5824 // データを取得\r
5825 UINT LbGetData(HWND hWnd, UINT id, UINT index)\r
5826 {\r
5827         // 引数チェック\r
5828         if (hWnd == NULL || index == INFINITE)\r
5829         {\r
5830                 return INFINITE;\r
5831         }\r
5832 \r
5833         return SendMsg(hWnd, id, LB_GETITEMDATA, index, 0);\r
5834 }\r
5835 \r
5836 // データを検索\r
5837 UINT LbFindData(HWND hWnd, UINT id, UINT data)\r
5838 {\r
5839         UINT i, num;\r
5840         // 引数チェック\r
5841         if (hWnd == NULL)\r
5842         {\r
5843                 return INFINITE;\r
5844         }\r
5845 \r
5846         num = LbNum(hWnd, id);\r
5847         if (num == INFINITE)\r
5848         {\r
5849                 return INFINITE;\r
5850         }\r
5851 \r
5852         for (i = 0;i < num;i++)\r
5853         {\r
5854                 if (LbGetData(hWnd, id, i) == data)\r
5855                 {\r
5856                         return i;\r
5857                 }\r
5858         }\r
5859 \r
5860         return INFINITE;\r
5861 }\r
5862 \r
5863 // アイテムの高さを設定\r
5864 void LbSetHeight(HWND hWnd, UINT id, UINT value)\r
5865 {\r
5866         // 引数チェック\r
5867         if (hWnd == NULL)\r
5868         {\r
5869                 return;\r
5870         }\r
5871 \r
5872         SendMsg(hWnd, id, LB_SETITEMHEIGHT, 0, value);\r
5873 }\r
5874 \r
5875 // データを指定して検索\r
5876 void LbSelect(HWND hWnd, UINT id, int data)\r
5877 {\r
5878         UINT index;\r
5879         // 引数チェック\r
5880         if (hWnd == NULL)\r
5881         {\r
5882                 return;\r
5883         }\r
5884 \r
5885         if (data == INFINITE)\r
5886         {\r
5887                 // 最初の項目を取得\r
5888                 LbSelectIndex(hWnd, id, 0);\r
5889                 return;\r
5890         }\r
5891 \r
5892         index = LbFindData(hWnd, id, data);\r
5893         if (index == INFINITE)\r
5894         {\r
5895                 // 発見できなかった\r
5896                 return;\r
5897         }\r
5898 \r
5899         // 選択する\r
5900         LbSelectIndex(hWnd, id, index);\r
5901 }\r
5902 \r
5903 // 現在選択されている項目を取得\r
5904 UINT LbGetSelectIndex(HWND hWnd, UINT id)\r
5905 {\r
5906         // 引数チェック\r
5907         if (hWnd == NULL)\r
5908         {\r
5909                 return INFINITE;\r
5910         }\r
5911 \r
5912         return SendMsg(hWnd, id, LB_GETCURSEL, 0, 0);\r
5913 }\r
5914 \r
5915 // 現在選択されている値を取得\r
5916 UINT LbGetSelect(HWND hWnd, UINT id)\r
5917 {\r
5918         UINT index;\r
5919         // 引数チェック\r
5920         if (hWnd == NULL)\r
5921         {\r
5922                 return INFINITE;\r
5923         }\r
5924 \r
5925         index = LbGetSelectIndex(hWnd, id);\r
5926         if (index == INFINITE)\r
5927         {\r
5928                 return INFINITE;\r
5929         }\r
5930 \r
5931         return LbGetData(hWnd, id, index);\r
5932 }\r
5933 \r
5934 // パスワード入力ダイアログ状態変化\r
5935 void PasswordDlgProcChange(HWND hWnd, UI_PASSWORD_DLG *p)\r
5936 {\r
5937         bool b;\r
5938         // 引数チェック\r
5939         if (hWnd == NULL || p == NULL)\r
5940         {\r
5941                 return;\r
5942         }\r
5943 \r
5944         b = true;\r
5945         if (IsEmpty(hWnd, E_USERNAME))\r
5946         {\r
5947                 b = false;\r
5948         }\r
5949 \r
5950         SetEnable(hWnd, IDOK, b);\r
5951 \r
5952         p->StartTick = Tick64();\r
5953         if (p->RetryIntervalSec)\r
5954         {\r
5955                 KillTimer(hWnd, 1);\r
5956                 Hide(hWnd, P_PROGRESS);\r
5957                 Hide(hWnd, S_COUNTDOWN);\r
5958         }\r
5959 }\r
5960 \r
5961 // 文字列を取得\r
5962 wchar_t *CbGetStr(HWND hWnd, UINT id)\r
5963 {\r
5964         // 引数チェック\r
5965         if (hWnd == NULL)\r
5966         {\r
5967                 return NULL;\r
5968         }\r
5969 \r
5970         return GetText(hWnd, id);\r
5971 }\r
5972 \r
5973 // 文字列検索\r
5974 UINT CbFindStr(HWND hWnd, UINT id, wchar_t *str)\r
5975 {\r
5976         UINT ret;\r
5977         if (MsIsNt() == false)\r
5978         {\r
5979                 char *tmp = CopyUniToStr(str);\r
5980                 ret = CbFindStr9xA(hWnd, id, tmp);\r
5981                 Free(tmp);\r
5982                 return ret;\r
5983         }\r
5984         // 引数チェック\r
5985         if (hWnd == NULL || str == NULL)\r
5986         {\r
5987                 return INFINITE;\r
5988         }\r
5989 \r
5990         ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);\r
5991 \r
5992         return ret;\r
5993 }\r
5994 UINT CbFindStr9xA(HWND hWnd, UINT id, char *str)\r
5995 {\r
5996         UINT ret;\r
5997         // 引数チェック\r
5998         if (hWnd == NULL || str == NULL)\r
5999         {\r
6000                 return INFINITE;\r
6001         }\r
6002 \r
6003         ret = SendMsg(hWnd, id, CB_FINDSTRINGEXACT, -1, (LPARAM)str);\r
6004 \r
6005         return ret;\r
6006 }\r
6007 \r
6008 // 項目数を取得\r
6009 UINT CbNum(HWND hWnd, UINT id)\r
6010 {\r
6011         // 引数チェック\r
6012         if (hWnd == NULL)\r
6013         {\r
6014                 return INFINITE;\r
6015         }\r
6016 \r
6017         return SendMsg(hWnd, id, CB_GETCOUNT, 0, 0);\r
6018 }\r
6019 \r
6020 // 文字列追加\r
6021 UINT CbAddStrA(HWND hWnd, UINT id, char *str, UINT data)\r
6022 {\r
6023         wchar_t *tmp;\r
6024         UINT ret;\r
6025         // 引く数チェック\r
6026         if (hWnd == NULL || str == NULL)\r
6027         {\r
6028                 return INFINITE;\r
6029         }\r
6030         tmp = CopyStrToUni(str);\r
6031         ret = CbAddStr(hWnd, id, tmp, data);\r
6032         Free(tmp);\r
6033         return ret;\r
6034 }\r
6035 UINT CbAddStr(HWND hWnd, UINT id, wchar_t *str, UINT data)\r
6036 {\r
6037         UINT ret;\r
6038         if (MsIsNt() == false)\r
6039         {\r
6040                 char *s = CopyUniToStr(str);\r
6041                 ret = CbAddStr9xA(hWnd, id, s, data);\r
6042                 Free(s);\r
6043                 return ret;\r
6044         }\r
6045         // 引数チェック\r
6046         if (hWnd == NULL || str == NULL)\r
6047         {\r
6048                 return INFINITE;\r
6049         }\r
6050 \r
6051         ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);\r
6052         SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);\r
6053 \r
6054         if (CbNum(hWnd, id) == 1)\r
6055         {\r
6056                 wchar_t tmp[MAX_SIZE];\r
6057                 GetTxt(hWnd, id, tmp, sizeof(tmp));\r
6058                 if (UniStrLen(tmp) == 0)\r
6059                 {\r
6060                         CbSelectIndex(hWnd, id, 0);\r
6061                 }\r
6062         }\r
6063 \r
6064         return ret;\r
6065 }\r
6066 UINT CbAddStr9xA(HWND hWnd, UINT id, char *str, UINT data)\r
6067 {\r
6068         UINT ret;\r
6069         // 引数チェック\r
6070         if (hWnd == NULL || str == NULL)\r
6071         {\r
6072                 return INFINITE;\r
6073         }\r
6074 \r
6075         ret = SendMsg(hWnd, id, CB_ADDSTRING, 0, (LPARAM)str);\r
6076         SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);\r
6077 \r
6078         if (CbNum(hWnd, id) == 1)\r
6079         {\r
6080                 wchar_t tmp[MAX_SIZE];\r
6081                 GetTxt(hWnd, id, tmp, sizeof(tmp));\r
6082                 if (UniStrLen(tmp) == 0)\r
6083                 {\r
6084                         CbSelectIndex(hWnd, id, 0);\r
6085                 }\r
6086         }\r
6087 \r
6088         return ret;\r
6089 }\r
6090 \r
6091 // 文字列挿入\r
6092 UINT CbInsertStrA(HWND hWnd, UINT id, UINT index, char *str, UINT data)\r
6093 {\r
6094         wchar_t *tmp;\r
6095         UINT ret;\r
6096         // 引数チェック\r
6097         if (hWnd == NULL || str == NULL)\r
6098         {\r
6099                 return INFINITE;\r
6100         }\r
6101         tmp = CopyStrToUni(str);\r
6102         ret = CbInsertStr(hWnd, id, index, tmp, data);\r
6103         Free(tmp);\r
6104         return ret;\r
6105 }\r
6106 UINT CbInsertStr(HWND hWnd, UINT id, UINT index, wchar_t *str, UINT data)\r
6107 {\r
6108         UINT ret;\r
6109         // 引数チェック\r
6110         if (hWnd == NULL || str == NULL)\r
6111         {\r
6112                 return INFINITE;\r
6113         }\r
6114 \r
6115         if (MsIsNt() == false)\r
6116         {\r
6117                 char *s = CopyUniToStr(str);\r
6118                 ret = CbInsertStr9xA(hWnd, id, index, s, data);\r
6119                 Free(s);\r
6120                 return ret;\r
6121         }\r
6122 \r
6123         ret = SendMsg(hWnd, id, CB_INSERTSTRING, index, (LPARAM)str);\r
6124         SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);\r
6125 \r
6126         if (CbNum(hWnd, id) == 1)\r
6127         {\r
6128                 CbSelect(hWnd, id, 0);\r
6129         }\r
6130 \r
6131         return ret;\r
6132 }\r
6133 UINT CbInsertStr9xA(HWND hWnd, UINT id, UINT index, char *str, UINT data)\r
6134 {\r
6135         UINT ret;\r
6136         // 引数チェック\r
6137         if (hWnd == NULL || str == NULL)\r
6138         {\r
6139                 return INFINITE;\r
6140         }\r
6141 \r
6142         ret = SendMsg(hWnd, id, CB_INSERTSTRING, index, (LPARAM)str);\r
6143         SendMsg(hWnd, id, CB_SETITEMDATA, ret, (LPARAM)data);\r
6144 \r
6145         if (CbNum(hWnd, id) == 1)\r
6146         {\r
6147                 CbSelect(hWnd, id, 0);\r
6148         }\r
6149 \r
6150         return ret;\r
6151 }\r
6152 \r
6153 // すべて削除\r
6154 void CbReset(HWND hWnd, UINT id)\r
6155 {\r
6156         wchar_t *s;\r
6157         // 引数チェック\r
6158         if (hWnd == NULL)\r
6159         {\r
6160                 return;\r
6161         }\r
6162 \r
6163         s = GetText(hWnd, id);\r
6164 \r
6165         SendMsg(hWnd, id, CB_RESETCONTENT, 0, 0);\r
6166 \r
6167         if (s != NULL)\r
6168         {\r
6169                 SetText(hWnd, id, s);\r
6170                 Free(s);\r
6171         }\r
6172 }\r
6173 \r
6174 // インデックスを指定して選択\r
6175 void CbSelectIndex(HWND hWnd, UINT id, UINT index)\r
6176 {\r
6177         // 引数チェック\r
6178         if (hWnd == NULL)\r
6179         {\r
6180                 return;\r
6181         }\r
6182 \r
6183         SendMsg(hWnd, id, CB_SETCURSEL, index, 0);\r
6184 }\r
6185 \r
6186 // データを取得\r
6187 UINT CbGetData(HWND hWnd, UINT id, UINT index)\r
6188 {\r
6189         // 引数チェック\r
6190         if (hWnd == NULL || index == INFINITE)\r
6191         {\r
6192                 return INFINITE;\r
6193         }\r
6194 \r
6195         return SendMsg(hWnd, id, CB_GETITEMDATA, index, 0);\r
6196 }\r
6197 \r
6198 // データを検索\r
6199 UINT CbFindData(HWND hWnd, UINT id, UINT data)\r
6200 {\r
6201         UINT i, num;\r
6202         // 引数チェック\r
6203         if (hWnd == NULL)\r
6204         {\r
6205                 return INFINITE;\r
6206         }\r
6207 \r
6208         num = CbNum(hWnd, id);\r
6209         if (num == INFINITE)\r
6210         {\r
6211                 return INFINITE;\r
6212         }\r
6213 \r
6214         for (i = 0;i < num;i++)\r
6215         {\r
6216                 if (CbGetData(hWnd, id, i) == data)\r
6217                 {\r
6218                         return i;\r
6219                 }\r
6220         }\r
6221 \r
6222         return INFINITE;\r
6223 }\r
6224 \r
6225 // アイテムの高さを設定\r
6226 void CbSetHeight(HWND hWnd, UINT id, UINT value)\r
6227 {\r
6228         // 引数チェック\r
6229         if (hWnd == NULL)\r
6230         {\r
6231                 return;\r
6232         }\r
6233 \r
6234         SendMsg(hWnd, id, CB_SETITEMHEIGHT, 0, value);\r
6235 }\r
6236 \r
6237 // データを指定して検索\r
6238 void CbSelect(HWND hWnd, UINT id, int data)\r
6239 {\r
6240         UINT index;\r
6241         // 引数チェック\r
6242         if (hWnd == NULL)\r
6243         {\r
6244                 return;\r
6245         }\r
6246 \r
6247         if (data == INFINITE)\r
6248         {\r
6249                 // 最初の項目を取得\r
6250                 CbSelectIndex(hWnd, id, 0);\r
6251                 return;\r
6252         }\r
6253 \r
6254         index = CbFindData(hWnd, id, data);\r
6255         if (index == INFINITE)\r
6256         {\r
6257                 // 発見できなかった\r
6258                 return;\r
6259         }\r
6260 \r
6261         // 選択する\r
6262         CbSelectIndex(hWnd, id, index);\r
6263 }\r
6264 \r
6265 // 現在選択されている項目を取得\r
6266 UINT CbGetSelectIndex(HWND hWnd, UINT id)\r
6267 {\r
6268         // 引数チェック\r
6269         if (hWnd == NULL)\r
6270         {\r
6271                 return INFINITE;\r
6272         }\r
6273 \r
6274         return SendMsg(hWnd, id, CB_GETCURSEL, 0, 0);\r
6275 }\r
6276 \r
6277 // 現在選択されている値を取得\r
6278 UINT CbGetSelect(HWND hWnd, UINT id)\r
6279 {\r
6280         UINT index;\r
6281         // 引数チェック\r
6282         if (hWnd == NULL)\r
6283         {\r
6284                 return INFINITE;\r
6285         }\r
6286 \r
6287         index = CbGetSelectIndex(hWnd, id);\r
6288         if (index == INFINITE)\r
6289         {\r
6290                 return INFINITE;\r
6291         }\r
6292 \r
6293         return CbGetData(hWnd, id, index);\r
6294 }\r
6295 \r
6296 // OK ボタンが押された\r
6297 void PasswordDlgOnOk(HWND hWnd, UI_PASSWORD_DLG *p)\r
6298 {\r
6299         // 引数チェック\r
6300         if (hWnd == NULL || p == NULL)\r
6301         {\r
6302                 return;\r
6303         }\r
6304 \r
6305         GetTxtA(hWnd, E_USERNAME, p->Username, sizeof(p->Username));\r
6306         GetTxtA(hWnd, E_PASSWORD, p->Password, sizeof(p->Password));\r
6307         p->Type = CbGetSelect(hWnd, C_TYPE);\r
6308 \r
6309         if (p->ShowNoSavePassword)\r
6310         {\r
6311                 p->NoSavePassword = IsChecked(hWnd, R_NO_SAVE_PASSWORD);\r
6312         }\r
6313 \r
6314         EndDialog(hWnd, true);\r
6315 }\r
6316 \r
6317 // パスワード入力ダイアログプロシージャ\r
6318 UINT PasswordDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
6319 {\r
6320         UI_PASSWORD_DLG *p = (UI_PASSWORD_DLG *)param;\r
6321         // 引数チェック\r
6322         if (hWnd == NULL)\r
6323         {\r
6324                 return 0;\r
6325         }\r
6326 \r
6327         switch (msg)\r
6328         {\r
6329         case WM_INITDIALOG:\r
6330                 SetIcon(hWnd, 0, ICO_KEY);\r
6331                 CbSetHeight(hWnd, C_TYPE, 18);\r
6332                 if (p->ServerName != NULL)\r
6333                 {\r
6334                         FormatText(hWnd, 0, p->ServerName);\r
6335                 }\r
6336                 else\r
6337                 {\r
6338                         SetText(hWnd, 0, _UU("PW_LOGIN_DLG_TITLE"));\r
6339                 }\r
6340 \r
6341                 if (p->ProxyServer == false)\r
6342                 {\r
6343                         FormatText(hWnd, S_TITLE, p->ServerName == NULL ? "" : p->ServerName);\r
6344                 }\r
6345                 else\r
6346                 {\r
6347                         wchar_t tmp[MAX_SIZE];\r
6348                         UniFormat(tmp, sizeof(tmp), _UU("PW_MSG_PROXY"), p->ServerName == NULL ? "" : p->ServerName);\r
6349                         SetText(hWnd, S_TITLE, tmp);\r
6350                 }\r
6351 \r
6352                 // 接続方法の列挙\r
6353                 SendMsg(hWnd, C_TYPE, CBEM_SETUNICODEFORMAT, true, 0);\r
6354 \r
6355                 if (StrCmpi(p->Username, WINUI_PASSWORD_NULL_USERNAME) != 0)\r
6356                 {\r
6357                         SetTextA(hWnd, E_USERNAME, p->Username);\r
6358                         SetTextA(hWnd, E_PASSWORD, p->Password);\r
6359                 }\r
6360                 else\r
6361                 {\r
6362                         p->RetryIntervalSec = 0;\r
6363                         SetTextA(hWnd, E_USERNAME, "");\r
6364                         SetTextA(hWnd, E_PASSWORD, "");\r
6365                 }\r
6366 \r
6367                 if (p->AdminMode == false)\r
6368                 {\r
6369                         if (p->ProxyServer == false)\r
6370                         {\r
6371                                 CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_1"), CLIENT_AUTHTYPE_PASSWORD);\r
6372                                 CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_2"), CLIENT_AUTHTYPE_PLAIN_PASSWORD);\r
6373                         }\r
6374                         else\r
6375                         {\r
6376                                 CbAddStr(hWnd, C_TYPE, _UU("PW_TYPE_PROXY"), 0);\r
6377                                 Disable(hWnd, C_TYPE);\r
6378                         }\r
6379 \r
6380                         CbSelect(hWnd, C_TYPE, p->Type);\r
6381                 }\r
6382                 else\r
6383                 {\r
6384                         CbAddStr(hWnd, C_TYPE, _UU("SM_PASSWORD_TYPE_STR"), 0);\r
6385                         Disable(hWnd, C_TYPE);\r
6386                         SetTextA(hWnd, E_USERNAME, "Administrator");\r
6387                         Disable(hWnd, E_USERNAME);\r
6388                 }\r
6389 \r
6390                 if (IsEmpty(hWnd, E_USERNAME))\r
6391                 {\r
6392                         FocusEx(hWnd, E_USERNAME);\r
6393                 }\r
6394                 else\r
6395                 {\r
6396                         FocusEx(hWnd, E_PASSWORD);\r
6397                 }\r
6398                 LimitText(hWnd, E_USERNAME, MAX_USERNAME_LEN);\r
6399                 LimitText(hWnd, E_PASSWORD, MAX_PASSWORD_LEN);\r
6400 \r
6401                 PasswordDlgProcChange(hWnd, p);\r
6402 \r
6403                 if (p->RetryIntervalSec != 0)\r
6404                 {\r
6405                         SetTimer(hWnd, 1, 50, NULL);\r
6406                         FormatText(hWnd, S_COUNTDOWN, p->RetryIntervalSec);\r
6407                         Show(hWnd, S_COUNTDOWN);\r
6408                         Show(hWnd, P_PROGRESS);\r
6409                         SetRange(hWnd, P_PROGRESS, 0, p->RetryIntervalSec * 1000);\r
6410                 }\r
6411                 else\r
6412                 {\r
6413                         Hide(hWnd, S_COUNTDOWN);\r
6414                         Hide(hWnd, P_PROGRESS);\r
6415                 }\r
6416 \r
6417                 if (p->ShowNoSavePassword)\r
6418                 {\r
6419                         Show(hWnd, R_NO_SAVE_PASSWORD);\r
6420                         Check(hWnd, R_NO_SAVE_PASSWORD, p->NoSavePassword);\r
6421                 }\r
6422                 else\r
6423                 {\r
6424                         Hide(hWnd, R_NO_SAVE_PASSWORD);\r
6425                 }\r
6426 \r
6427                 p->StartTick = Tick64();\r
6428 \r
6429                 if (p->CancelEvent != NULL)\r
6430                 {\r
6431                         SetTimer(hWnd, 2, 50, NULL);\r
6432                 }\r
6433 \r
6434                 break;\r
6435 \r
6436         case WM_CLOSE:\r
6437                 EndDialog(hWnd, false);\r
6438                 break;\r
6439 \r
6440         case WM_TIMER:\r
6441                 switch (wParam)\r
6442                 {\r
6443                 case 1:\r
6444                         if (p->RetryIntervalSec != 0)\r
6445                         {\r
6446                                 wchar_t tmp[MAX_SIZE];\r
6447                                 UINT64 end, now, start;\r
6448                                 start = p->StartTick;\r
6449                                 end = p->StartTick + (UINT64)(p->RetryIntervalSec * 1000);\r
6450                                 now = Tick64();\r
6451 \r
6452                                 if (now <= end)\r
6453                                 {\r
6454                                         UniFormat(tmp, sizeof(tmp), _UU("PW_RETRYCOUNT"), (UINT)((end - now) / 1000));\r
6455                                         SetText(hWnd, S_COUNTDOWN, tmp);\r
6456                                         SetPos(hWnd, P_PROGRESS, (UINT)(now - start));\r
6457                                 }\r
6458                                 else\r
6459                                 {\r
6460                                         EndDialog(hWnd, true);\r
6461                                 }\r
6462                         }\r
6463                         break;\r
6464 \r
6465                 case 2:\r
6466                         if (p->CancelEvent != NULL)\r
6467                         {\r
6468                                 // 終了イベントを待機する\r
6469                                 HANDLE hEvent = (HANDLE)p->CancelEvent->pData;\r
6470                                 UINT ret = WaitForSingleObject(hEvent, 0);\r
6471                                 if (ret != WAIT_TIMEOUT)\r
6472                                 {\r
6473                                         // 強制終了イベントがセットされた\r
6474                                         Close(hWnd);\r
6475                                 }\r
6476                         }\r
6477                         break;\r
6478                 }\r
6479                 break;\r
6480 \r
6481         case WM_COMMAND:\r
6482                 switch (wParam)\r
6483                 {\r
6484                 case IDOK:\r
6485                         PasswordDlgOnOk(hWnd, p);\r
6486                         break;\r
6487                 case IDCANCEL:\r
6488                         Close(hWnd);\r
6489                         break;\r
6490                 }\r
6491                 switch (HIWORD(wParam))\r
6492                 {\r
6493                 case EN_CHANGE:\r
6494                         switch (LOWORD(wParam))\r
6495                         {\r
6496                         case E_USERNAME:\r
6497                         case E_PASSWORD:\r
6498                                 PasswordDlgProcChange(hWnd, p);\r
6499                                 break;\r
6500                         }\r
6501                         break;\r
6502                 case CBN_SELCHANGE:\r
6503                         switch (LOWORD(wParam))\r
6504                         {\r
6505                         case C_TYPE:\r
6506                                 PasswordDlgProcChange(hWnd, p);\r
6507                                 if (IsEmpty(hWnd, E_USERNAME))\r
6508                                 {\r
6509                                         FocusEx(hWnd, E_USERNAME);\r
6510                                 }\r
6511                                 else\r
6512                                 {\r
6513                                         FocusEx(hWnd, E_PASSWORD);\r
6514                                 }\r
6515                                 break;\r
6516                         }\r
6517                         break;\r
6518                 }\r
6519                 break;\r
6520         }\r
6521 \r
6522         return 0;\r
6523 }\r
6524 \r
6525 // プログレスバーの位置を設定\r
6526 void SetPos(HWND hWnd, UINT id, UINT pos)\r
6527 {\r
6528         // 引数チェック\r
6529         if (hWnd == NULL)\r
6530         {\r
6531                 return;\r
6532         }\r
6533 \r
6534         SendMsg(hWnd, id, PBM_SETPOS, pos, 0);\r
6535 }\r
6536 \r
6537 // プログレスバーの範囲を設定\r
6538 void SetRange(HWND hWnd, UINT id, UINT start, UINT end)\r
6539 {\r
6540         // 引数チェック\r
6541         if (hWnd == NULL)\r
6542         {\r
6543                 return;\r
6544         }\r
6545 \r
6546         SendMsg(hWnd, id, PBM_SETRANGE32, start, end);\r
6547 }\r
6548 \r
6549 // パスワード入力ダイアログ\r
6550 bool PasswordDlg(HWND hWnd, UI_PASSWORD_DLG *p)\r
6551 {\r
6552         // 引数チェック\r
6553         if (p == NULL)\r
6554         {\r
6555                 return false;\r
6556         }\r
6557 \r
6558         p->StartTick = Tick64();\r
6559 \r
6560         return Dialog(hWnd, D_PASSWORD, PasswordDlgProc, p);\r
6561 }\r
6562 \r
6563 // パスフレーズ入力ダイアログ\r
6564 bool PassphraseDlg(HWND hWnd, char *pass, UINT pass_size, BUF *buf, bool p12)\r
6565 {\r
6566         PASSPHRASE_DLG p;\r
6567         // 引数チェック\r
6568         if (pass == NULL || buf == NULL)\r
6569         {\r
6570                 return false;\r
6571         }\r
6572 \r
6573         Zero(&p, sizeof(PASSPHRASE_DLG));\r
6574 \r
6575         p.buf = buf;\r
6576         p.p12 = p12;\r
6577 \r
6578         // まず暗号化されているかどうかを調べる\r
6579         if (p12 == false)\r
6580         {\r
6581                 // 秘密鍵\r
6582                 if (IsEncryptedK(buf, true) == false)\r
6583                 {\r
6584                         // 暗号化されていない\r
6585                         StrCpy(pass, pass_size, "");\r
6586                         return true;\r
6587                 }\r
6588         }\r
6589         else\r
6590         {\r
6591                 // PKCS#12\r
6592                 P12 *p12 = BufToP12(buf);\r
6593                 if (p12 == NULL)\r
6594                 {\r
6595                         // 不明な形式だが暗号化されていない\r
6596                         StrCpy(pass, pass_size, "");\r
6597                         return true;\r
6598                 }\r
6599 \r
6600                 if (IsEncryptedP12(p12) == false)\r
6601                 {\r
6602                         // 暗号化されていない\r
6603                         StrCpy(pass, pass_size, "");\r
6604                         FreeP12(p12);\r
6605                         return true;\r
6606                 }\r
6607                 FreeP12(p12);\r
6608         }\r
6609 \r
6610         // ダイアログ表示\r
6611         if (Dialog(hWnd, D_PASSPHRASE, PassphraseDlgProc, &p) == false)\r
6612         {\r
6613                 // キャンセル\r
6614                 return false;\r
6615         }\r
6616 \r
6617         StrCpy(pass, pass_size, p.pass);\r
6618 \r
6619         return true;\r
6620 }\r
6621 \r
6622 // WM_COMMAND ハンドラ\r
6623 void PassphraseDlgProcCommand(HWND hWnd, PASSPHRASE_DLG *p)\r
6624 {\r
6625         char *pass;\r
6626         bool ok;\r
6627         // 引数チェック\r
6628         if (hWnd == NULL || p == NULL)\r
6629         {\r
6630                 return;\r
6631         }\r
6632 \r
6633         pass = GetTextA(hWnd, E_PASSPHRASE);\r
6634         if (pass == NULL)\r
6635         {\r
6636                 return;\r
6637         }\r
6638 \r
6639         ok = false;\r
6640 \r
6641         if (p->p12 == false)\r
6642         {\r
6643                 K *k;\r
6644                 k = BufToK(p->buf, true, true, pass);\r
6645                 if (k != NULL)\r
6646                 {\r
6647                         ok = true;\r
6648                         FreeK(k);\r
6649                 }\r
6650         }\r
6651         else\r
6652         {\r
6653                 X *x;\r
6654                 K *k;\r
6655                 P12 *p12;\r
6656                 p12 = BufToP12(p->buf);\r
6657                 if (p12 != NULL)\r
6658                 {\r
6659                         if (ParseP12(p12, &x, &k, pass))\r
6660                         {\r
6661                                 FreeX(x);\r
6662                                 FreeK(k);\r
6663                                 ok = true;\r
6664                         }\r
6665                         FreeP12(p12);\r
6666                 }\r
6667         }\r
6668 \r
6669         Free(pass);\r
6670 \r
6671         SetEnable(hWnd, IDOK, ok);\r
6672 }\r
6673 \r
6674 // パスフレーズ入力ダイアログプロシージャ\r
6675 UINT PassphraseDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
6676 {\r
6677         PASSPHRASE_DLG *p = (PASSPHRASE_DLG *)param;\r
6678         // 引数チェック\r
6679         if (hWnd == NULL)\r
6680         {\r
6681                 return 0;\r
6682         }\r
6683 \r
6684         switch (msg)\r
6685         {\r
6686         case WM_INITDIALOG:\r
6687                 PassphraseDlgProcCommand(hWnd, p);\r
6688                 break;\r
6689 \r
6690         case WM_COMMAND:\r
6691                 switch (wParam)\r
6692                 {\r
6693                 case IDOK:\r
6694                         GetTxtA(hWnd, E_PASSPHRASE, p->pass, sizeof(p->pass));\r
6695                         EndDialog(hWnd, true);\r
6696                         break;\r
6697 \r
6698                 case IDCANCEL:\r
6699                         Close(hWnd);\r
6700                         break;\r
6701                 }\r
6702 \r
6703                 switch (LOWORD(wParam))\r
6704                 {\r
6705                 case E_PASSPHRASE:\r
6706                         PassphraseDlgProcCommand(hWnd, p);\r
6707                         break;\r
6708                 }\r
6709                 break;\r
6710 \r
6711         case WM_CLOSE:\r
6712                 EndDialog(hWnd, false);\r
6713                 break;\r
6714         }\r
6715 \r
6716         return 0;\r
6717 }\r
6718 \r
6719 // PKCS ユーティリティ\r
6720 void PkcsUtil()\r
6721 {\r
6722         InitWinUi(_UU("PKCS_UTIL_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));\r
6723         Dialog(NULL, D_PKCSUTIL, PkcsUtilProc, NULL);\r
6724         FreeWinUi();\r
6725 }\r
6726 \r
6727 // PKCS 書き込み\r
6728 void PkcsUtilWrite(HWND hWnd)\r
6729 {\r
6730         wchar_t *filename;\r
6731         BUF *in_buf;\r
6732         char filename_ansi[MAX_SIZE];\r
6733         char pass[MAX_SIZE];\r
6734         // 引数チェック\r
6735         if (hWnd == NULL)\r
6736         {\r
6737                 return;\r
6738         }\r
6739 \r
6740         filename = OpenDlg(hWnd, _UU("DLG_PKCS12_FILTER"), _UU("PKCS_UTIL_SAVEDLG_TITLE"));\r
6741         if (filename == NULL)\r
6742         {\r
6743                 return;\r
6744         }\r
6745 \r
6746         UniToStr(filename_ansi, sizeof(filename_ansi), filename);\r
6747 \r
6748         in_buf = ReadDump(filename_ansi);\r
6749 \r
6750         if (in_buf == NULL)\r
6751         {\r
6752                 MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("PKCS_UTIL_READ_ERROR"), filename);\r
6753         }\r
6754         else\r
6755         {\r
6756                 if (PassphraseDlg(hWnd, pass, sizeof(pass), in_buf, true))\r
6757                 {\r
6758                         P12 *p12 = BufToP12(in_buf);\r
6759                         if (p12 == NULL)\r
6760                         {\r
6761                                 MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("PKCS_UTIL_BAD_FILE"));\r
6762                         }\r
6763                         else\r
6764                         {\r
6765                                 X *x = NULL;\r
6766                                 K *k = NULL;\r
6767                                 BUF *b;\r
6768                                 ParseP12(p12, &x, &k, pass);\r
6769                                 FreeP12(p12);\r
6770                                 p12 = NewP12(x, k, NULL);\r
6771                                 FreeX(x);\r
6772                                 FreeK(k);\r
6773                                 b = P12ToBuf(p12);\r
6774                                 FreeP12(p12);\r
6775                                 if (b != NULL)\r
6776                                 {\r
6777                                         // バッチ処理\r
6778                                         WINUI_SECURE_BATCH batch[] =\r
6779                                         {\r
6780                                                 {WINUI_SECURE_WRITE_DATA, _SS("PKCS_UTIL_SECA_FILENAME"), false,\r
6781                                                         b, NULL, NULL, NULL, NULL, NULL},\r
6782                                         };\r
6783 \r
6784                                         if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), 2, 0))\r
6785                                         {\r
6786                                                 MsgBoxEx(hWnd, MB_ICONINFORMATION, _UU("PKCS_UTIL_WRITE_OK_MSG"), filename);\r
6787                                         }\r
6788                                 }\r
6789                                 FreeBuf(b);\r
6790                         }\r
6791                 }\r
6792 \r
6793                 FreeBuf(in_buf);\r
6794         }\r
6795 \r
6796         Free(filename);\r
6797 }\r
6798 \r
6799 // PKCS 消去\r
6800 void PkcsUtilErase(HWND hWnd)\r
6801 {\r
6802         // 引数チェック\r
6803         if (hWnd == NULL)\r
6804         {\r
6805                 return;\r
6806         }\r
6807 \r
6808         if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,\r
6809                 _UU("PKCS_MAKE_SURE")) == IDYES)\r
6810         {\r
6811                 // バッチ処理\r
6812                 WINUI_SECURE_BATCH batch[] =\r
6813                 {\r
6814                         {WINUI_SECURE_DELETE_OBJECT, _SS("PKCS_UTIL_SECA_FILENAME"), false,\r
6815                                 NULL, NULL, NULL, NULL, NULL, NULL},\r
6816                 };\r
6817 \r
6818                 if (SecureDeviceWindow(hWnd, batch, sizeof(batch) / sizeof(batch[0]), 2, 0))\r
6819                 {\r
6820                         MsgBox(hWnd, MB_ICONINFORMATION, _UU("PKCS_UTIL_DELETE_OK_MSG"));\r
6821                 }\r
6822         }\r
6823 }\r
6824 \r
6825 // PKCS ユーティリティ ダイアログ\r
6826 UINT PkcsUtilProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
6827 {\r
6828         // 引数チェック\r
6829         if (hWnd == NULL)\r
6830         {\r
6831                 return 0;\r
6832         }\r
6833 \r
6834         switch (msg)\r
6835         {\r
6836         case WM_INITDIALOG:\r
6837                 DlgFont(hWnd, S_TITLE, 12, true);\r
6838                 SetIcon(hWnd, 0, ICO_CERT);\r
6839                 SetFont(hWnd, S_COPYRIGHT, GetFont("Arial", 8, false, false, false, false));\r
6840                 break;\r
6841 \r
6842         case WM_COMMAND:\r
6843                 switch (wParam)\r
6844                 {\r
6845                 case B_WRITE:\r
6846                         PkcsUtilWrite(hWnd);\r
6847                         break;\r
6848 \r
6849                 case B_ERASE:\r
6850                         PkcsUtilErase(hWnd);\r
6851                         break;\r
6852 \r
6853                 case IDCANCEL:\r
6854                         Close(hWnd);\r
6855                         break;\r
6856                 }\r
6857 \r
6858                 break;\r
6859 \r
6860         case WM_CLOSE:\r
6861                 EndDialog(hWnd, 0);\r
6862                 break;\r
6863         }\r
6864 \r
6865         return 0;\r
6866 }\r
6867 \r
6868 // [ファイルを保存する] ダイアログ\r
6869 wchar_t *SaveDlg(HWND hWnd, wchar_t *filter, wchar_t *title, wchar_t *default_name, wchar_t *default_ext)\r
6870 {\r
6871         wchar_t *filter_str;\r
6872         wchar_t tmp[MAX_SIZE];\r
6873         OPENFILENAMEW o;\r
6874 \r
6875         if (MsIsNt() == false)\r
6876         {\r
6877                 char *ret, *s1, *s2, *s3, *s4;\r
6878                 wchar_t *wr;\r
6879                 s1 = CopyUniToStr(filter);\r
6880                 s2 = CopyUniToStr(title);\r
6881                 s3 = CopyUniToStr(default_name);\r
6882                 s4 = CopyUniToStr(default_ext);\r
6883                 ret = SaveDlgA(hWnd, s1, s2, s3, s4);\r
6884                 Free(s1);\r
6885                 Free(s2);\r
6886                 Free(s3);\r
6887                 Free(s4);\r
6888                 wr = CopyStrToUni(ret);\r
6889                 Free(ret);\r
6890                 return wr;\r
6891         }\r
6892 \r
6893         // 引数チェック\r
6894         if (filter == NULL)\r
6895         {\r
6896                 filter = _UU("DLG_ALL_FILES");\r
6897         }\r
6898 \r
6899         filter_str = MakeFilter(filter);\r
6900 \r
6901         Zero(&o, sizeof(o));\r
6902         Zero(tmp, sizeof(tmp));\r
6903 \r
6904         if (default_name != NULL)\r
6905         {\r
6906                 UniStrCpy(tmp, sizeof(tmp), default_name);\r
6907         }\r
6908 \r
6909         o.lStructSize = sizeof(o);\r
6910         \r
6911         if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))\r
6912         {\r
6913                 o.lStructSize = OPENFILENAME_SIZE_VERSION_400W;\r
6914         }\r
6915 \r
6916         o.hwndOwner = hWnd;\r
6917         o.hInstance = GetModuleHandleA(NULL);\r
6918         o.lpstrFile = tmp;\r
6919         o.lpstrTitle = title;\r
6920         o.lpstrFilter = filter_str;\r
6921         o.nMaxFile = sizeof(tmp);\r
6922         o.Flags = OFN_OVERWRITEPROMPT;\r
6923         o.lpstrDefExt = default_ext;\r
6924 \r
6925         if (GetSaveFileNameW(&o) == false)\r
6926         {\r
6927                 Free(filter_str);\r
6928                 return NULL;\r
6929         }\r
6930 \r
6931         Free(filter_str);\r
6932 \r
6933         return UniCopyStr(tmp);\r
6934 }\r
6935 char *SaveDlgA(HWND hWnd, char *filter, char *title, char *default_name, char *default_ext)\r
6936 {\r
6937         char *filter_str;\r
6938         char tmp[MAX_SIZE];\r
6939         OPENFILENAME o;\r
6940         // 引数チェック\r
6941         if (filter == NULL)\r
6942         {\r
6943                 filter = _SS("DLG_ALL_FILES");\r
6944         }\r
6945 \r
6946         filter_str = MakeFilterA(filter);\r
6947 \r
6948         Zero(&o, sizeof(o));\r
6949         Zero(tmp, sizeof(tmp));\r
6950 \r
6951         if (default_name != NULL)\r
6952         {\r
6953                 StrCpy(tmp, sizeof(tmp), default_name);\r
6954         }\r
6955 \r
6956         o.lStructSize = sizeof(o);\r
6957         \r
6958         if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))\r
6959         {\r
6960                 o.lStructSize = OPENFILENAME_SIZE_VERSION_400A;\r
6961         }\r
6962 \r
6963         o.hwndOwner = hWnd;\r
6964         o.hInstance = GetModuleHandleA(NULL);\r
6965         o.lpstrFile = tmp;\r
6966         o.lpstrTitle = title;\r
6967         o.lpstrFilter = filter_str;\r
6968         o.nMaxFile = sizeof(tmp);\r
6969         o.Flags = OFN_OVERWRITEPROMPT;\r
6970         o.lpstrDefExt = default_ext;\r
6971 \r
6972         if (GetSaveFileName(&o) == false)\r
6973         {\r
6974                 Free(filter_str);\r
6975                 return NULL;\r
6976         }\r
6977 \r
6978         Free(filter_str);\r
6979 \r
6980         return CopyStr(tmp);\r
6981 }\r
6982 \r
6983 // [ファイルを開く] ダイアログ\r
6984 wchar_t *OpenDlg(HWND hWnd, wchar_t *filter, wchar_t *title)\r
6985 {\r
6986         wchar_t *filter_str;\r
6987         wchar_t tmp[MAX_SIZE];\r
6988         OPENFILENAMEW o;\r
6989 \r
6990         if (MsIsNt() == false)\r
6991         {\r
6992                 char *ret;\r
6993                 char *filter_a;\r
6994                 char *title_a;\r
6995                 wchar_t *w;\r
6996                 filter_a = CopyUniToStr(filter);\r
6997                 title_a = CopyUniToStr(title);\r
6998                 ret = OpenDlgA(hWnd, filter_a, title_a);\r
6999                 Free(filter_a);\r
7000                 Free(title_a);\r
7001                 w = CopyStrToUni(ret);\r
7002                 Free(ret);\r
7003                 return w;\r
7004         }\r
7005 \r
7006         // 引数チェック\r
7007         if (filter == NULL)\r
7008         {\r
7009                 filter = _UU("DLG_ALL_FILES");\r
7010         }\r
7011 \r
7012         filter_str = MakeFilter(filter);\r
7013 \r
7014         Zero(&o, sizeof(OPENFILENAMEW));\r
7015         Zero(tmp, sizeof(tmp));\r
7016 \r
7017         o.lStructSize = sizeof(o);\r
7018 \r
7019 \r
7020         if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))\r
7021         {\r
7022                 o.lStructSize = OPENFILENAME_SIZE_VERSION_400W;\r
7023         }\r
7024 \r
7025 \r
7026         o.hwndOwner = hWnd;\r
7027         o.hInstance = GetModuleHandleA(NULL);\r
7028         o.lpstrFilter = filter_str;\r
7029         o.lpstrFile = tmp;\r
7030         o.nMaxFile = sizeof(tmp);\r
7031         o.lpstrTitle = title;\r
7032         o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;\r
7033 \r
7034         if (GetOpenFileNameW(&o) == false)\r
7035         {\r
7036                 Free(filter_str);\r
7037                 return NULL;\r
7038         }\r
7039 \r
7040         Free(filter_str);\r
7041 \r
7042         return UniCopyStr(tmp);\r
7043 }\r
7044 char *OpenDlgA(HWND hWnd, char *filter, char *title)\r
7045 {\r
7046         char *filter_str;\r
7047         char tmp[MAX_SIZE];\r
7048         OPENFILENAME o;\r
7049         // 引数チェック\r
7050         if (filter == NULL)\r
7051         {\r
7052                 filter = _SS("DLG_ALL_FILES");\r
7053         }\r
7054 \r
7055         filter_str = MakeFilterA(filter);\r
7056 \r
7057         Zero(&o, sizeof(OPENFILENAME));\r
7058         Zero(tmp, sizeof(tmp));\r
7059 \r
7060         o.lStructSize = sizeof(o);\r
7061 \r
7062         if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType) || (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) && GET_KETA(GetOsInfo()->OsType, 100) <= 1))\r
7063         {\r
7064                 o.lStructSize = OPENFILENAME_SIZE_VERSION_400A;\r
7065         }\r
7066 \r
7067         o.hwndOwner = hWnd;\r
7068         o.hInstance = GetModuleHandleA(NULL);\r
7069         o.lpstrFilter = filter_str;\r
7070         o.lpstrFile = tmp;\r
7071         o.nMaxFile = sizeof(tmp);\r
7072         o.lpstrTitle = title;\r
7073         o.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;\r
7074 \r
7075         if (GetOpenFileName(&o) == false)\r
7076         {\r
7077                 Free(filter_str);\r
7078                 return NULL;\r
7079         }\r
7080 \r
7081         Free(filter_str);\r
7082 \r
7083         return CopyStr(tmp);\r
7084 }\r
7085 \r
7086 // フィルタ文字列の生成\r
7087 wchar_t *MakeFilter(wchar_t *str)\r
7088 {\r
7089         UINT i;\r
7090         wchar_t *ret;\r
7091         // 引数チェック\r
7092         if (str == NULL)\r
7093         {\r
7094                 return NULL;\r
7095         }\r
7096 \r
7097         ret = ZeroMalloc(UniStrSize(str) + 32);\r
7098 \r
7099         for (i = 0;i < UniStrLen(str);i++)\r
7100         {\r
7101                 if (str[i] == L'|')\r
7102                 {\r
7103                         ret[i] = L'\0';\r
7104                 }\r
7105                 else\r
7106                 {\r
7107                         ret[i] = str[i];\r
7108                 }\r
7109         }\r
7110 \r
7111         return ret;\r
7112 }\r
7113 char *MakeFilterA(char *str)\r
7114 {\r
7115         UINT i;\r
7116         char *ret;\r
7117         // 引数チェック\r
7118         if (str == NULL)\r
7119         {\r
7120                 return NULL;\r
7121         }\r
7122 \r
7123         ret = ZeroMalloc(StrSize(str) + 32);\r
7124 \r
7125         for (i = 0;i < StrLen(str);i++)\r
7126         {\r
7127                 if (str[i] == '|')\r
7128                 {\r
7129                         ret[i] = '\0';\r
7130                 }\r
7131                 else\r
7132                 {\r
7133                         ret[i] = str[i];\r
7134                 }\r
7135         }\r
7136 \r
7137         return ret;\r
7138 }\r
7139 \r
7140 // バッチの実行\r
7141 bool ExecuteSecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev, WINUI_SECURE_BATCH *batch)\r
7142 {\r
7143         LIST *o;\r
7144         void *buf;\r
7145         UINT size = 10 * 1024;          // データの最大サイズ\r
7146         UINT type = INFINITE;\r
7147         // 引数チェック\r
7148         if (hWnd == NULL || p == NULL || dev == NULL || batch == NULL || sec == NULL)\r
7149         {\r
7150                 return false;\r
7151         }\r
7152 \r
7153         switch (batch->Type)\r
7154         {\r
7155         case WINUI_SECURE_DELETE_CERT:\r
7156                 type = SEC_X;\r
7157                 goto DELETE_OBJECT;\r
7158 \r
7159         case WINUI_SECURE_DELETE_KEY:\r
7160                 type = SEC_K;\r
7161                 goto DELETE_OBJECT;\r
7162 \r
7163         case WINUI_SECURE_DELETE_DATA:\r
7164                 type = SEC_DATA;\r
7165                 goto DELETE_OBJECT;\r
7166 \r
7167         case WINUI_SECURE_DELETE_OBJECT:\r
7168                 // オブジェクトの削除\r
7169 DELETE_OBJECT:\r
7170                 SetText(hWnd, S_STATUS, _UU("SEC_DELETE"));\r
7171                 if (DeleteSecObjectByName(sec, batch->Name, type) == false)\r
7172                 {\r
7173                         p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_DELETE"));\r
7174                         return false;\r
7175                 }\r
7176                 break;\r
7177 \r
7178         case WINUI_SECURE_ENUM_OBJECTS:\r
7179                 // オブジェクトの列挙\r
7180                 SetText(hWnd, S_STATUS, _UU("SEC_ENUM"));\r
7181                 o = EnumSecObject(sec);\r
7182                 if (o == NULL)\r
7183                 {\r
7184                         p->ErrorMessage = UniCopyStr(_UU("SEC_ERROR_ENUM"));\r
7185                         return false;\r
7186                 }\r
7187 \r
7188                 batch->EnumList = o;\r
7189                 break;\r
7190 \r
7191         case WINUI_SECURE_WRITE_DATA:\r
7192                 // データの書き込み\r
7193                 SetText(hWnd, S_STATUS, _UU("SEC_WRITE_DATA"));\r
7194                 if (WriteSecData(sec, batch->Private, batch->Name, batch->InputData->Buf, batch->InputData->Size) == false)\r
7195                 {\r
7196                         p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?\r
7197                                 _UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));\r
7198                         return false;\r
7199                 }\r
7200                 break;\r
7201 \r
7202         case WINUI_SECURE_READ_DATA:\r
7203                 // データの読み込み\r
7204                 SetText(hWnd, S_STATUS, _UU("SEC_READ_DATA"));\r
7205                 buf = MallocEx(size, true);\r
7206                 size = ReadSecData(sec, batch->Name, buf, size);\r
7207                 if (size == 0)\r
7208                 {\r
7209                         Free(buf);\r
7210                         p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?\r
7211                                 _UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));\r
7212                         return false;\r
7213                 }\r
7214                 batch->OutputData = NewBuf();\r
7215                 WriteBuf(batch->OutputData, buf, size);\r
7216                 SeekBuf(batch->OutputData, 0, 0);\r
7217                 Free(buf);\r
7218                 break;\r
7219 \r
7220         case WINUI_SECURE_WRITE_CERT:\r
7221                 // 証明書の書き込み\r
7222                 SetText(hWnd, S_STATUS, _UU("SEC_WRITE_CERT"));\r
7223                 if (WriteSecCert(sec, batch->Private, batch->Name, batch->InputX) == false)\r
7224                 {\r
7225                         p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?\r
7226                                 _UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));\r
7227                         return false;\r
7228                 }\r
7229                 break;\r
7230 \r
7231         case WINUI_SECURE_READ_CERT:\r
7232                 // 証明書の読み込み\r
7233                 SetText(hWnd, S_STATUS, _UU("SEC_READ_CERT"));\r
7234                 batch->OutputX = ReadSecCert(sec, batch->Name);\r
7235                 if (batch->OutputX == NULL)\r
7236                 {\r
7237                         p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?\r
7238                                 _UU("SEC_ERROR_NOT_FOUND_1") : _UU("SEC_ERROR_NOT_FOUND_2"));\r
7239                         return false;\r
7240                 }\r
7241                 break;\r
7242 \r
7243         case WINUI_SECURE_WRITE_KEY:\r
7244                 // 秘密鍵の書き込み\r
7245                 SetText(hWnd, S_STATUS, _UU("SEC_WRITE_KEY"));\r
7246                 if (WriteSecKey(sec, batch->Private, batch->Name, batch->InputK) == false)\r
7247                 {\r
7248                         p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?\r
7249                                 _UU("SEC_ERROR_WRITE_1") : _UU("SEC_ERROR_WRITE_2"));\r
7250                         return false;\r
7251                 }\r
7252                 break;\r
7253 \r
7254         case WINUI_SECURE_SIGN_WITH_KEY:\r
7255                 // 署名\r
7256                 SetText(hWnd, S_STATUS, _UU("SEC_SIGN"));\r
7257                 if (SignSec(sec, batch->Name, batch->OutputSign, batch->InputData->Buf, batch->InputData->Size) == false)\r
7258                 {\r
7259                         p->ErrorMessage = UniCopyStr(dev->Type != SECURE_USB_TOKEN ?\r
7260                                 _UU("SEC_ERROR_SIGN_1") : _UU("SEC_ERROR_SIGN_2"));\r
7261                         return false;\r
7262                 }\r
7263                 break;\r
7264         }\r
7265 \r
7266         return true;\r
7267 }\r
7268 \r
7269 // セキュアデバイス操作をバッチ処理で実行する\r
7270 void SecureDeviceBatch(HWND hWnd, SECURE *sec, SECURE_DEVICE_THREAD *p, SECURE_DEVICE *dev)\r
7271 {\r
7272         UINT i;\r
7273         // 引数チェック\r
7274         if (hWnd == NULL || p == NULL || dev == NULL || sec == NULL)\r
7275         {\r
7276                 return;\r
7277         }\r
7278 \r
7279         // 逐次処理を行う\r
7280         for (i = 0;i < p->w->num_batch;i++)\r
7281         {\r
7282                 WINUI_SECURE_BATCH *batch = &p->w->batch[i];\r
7283 \r
7284                 if (ExecuteSecureDeviceBatch(hWnd, sec, p, dev, batch) == false)\r
7285                 {\r
7286                         // 1 つでも失敗したら直ちに中断する\r
7287                         return;\r
7288                 }\r
7289         }\r
7290 \r
7291         // すべてのバッチ処理が成功した\r
7292         p->Succeed = true;\r
7293 }\r
7294 \r
7295 // セキュアデバイス操作を行うスレッド\r
7296 void SecureDeviceThread(THREAD *t, void *param)\r
7297 {\r
7298         SECURE *sec;\r
7299         SECURE_DEVICE_THREAD *p = (SECURE_DEVICE_THREAD *)param;\r
7300         SECURE_DEVICE *dev;\r
7301         HWND hWnd;\r
7302         // 引数チェック\r
7303         if (t == NULL || param == NULL)\r
7304         {\r
7305                 return;\r
7306         }\r
7307 \r
7308         p->Succeed = false;\r
7309         p->ErrorMessage = NULL;\r
7310 \r
7311         hWnd = p->hWnd;\r
7312 \r
7313         // デバイスを開く\r
7314         dev = GetSecureDevice(p->w->device_id);\r
7315         SetText(hWnd, S_STATUS, _UU("SEC_OPENING"));\r
7316         sec = OpenSec(p->w->device_id);\r
7317         if (sec == NULL)\r
7318         {\r
7319                 // デバイスオープン失敗\r
7320                 if (p->w->device_id != 9)\r
7321                 {\r
7322                         p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICE"), dev->DeviceName);\r
7323                 }\r
7324                 else\r
7325                 {\r
7326                         p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_DEVICEEX"), dev->DeviceName);\r
7327                 }\r
7328         }\r
7329         else\r
7330         {\r
7331                 // セッションを開く\r
7332                 SetText(hWnd, S_STATUS, _UU("SEC_OPEN_SESSION"));\r
7333                 if (OpenSecSession(sec, 0) == false)\r
7334                 {\r
7335                         // セッション初期化失敗\r
7336                         p->ErrorMessage = CopyUniFormat(_UU("SEC_ERROR_OPEN_SESSION"), dev->DeviceName);\r
7337                 }\r
7338                 else\r
7339                 {\r
7340                         // ログイン\r
7341                         SetText(hWnd, S_STATUS, _UU("SEC_LOGIN"));\r
7342                         if (LoginSec(sec, p->pin) == false)\r
7343                         {\r
7344                                 // ログイン失敗\r
7345                                 p->ErrorMessage =UniCopyStr(_UU("SEC_ERROR_LOGIN"));\r
7346                         }\r
7347                         else\r
7348                         {\r
7349                                 // バッチ処理メイン\r
7350                                 SetText(hWnd, S_STATUS, _UU("SEC_INIT_BATCH"));\r
7351                                 SecureDeviceBatch(hWnd, sec, p, dev);\r
7352 \r
7353                                 // ログアウト\r
7354                                 SetText(hWnd, S_STATUS, _UU("SEC_LOGOUT"));\r
7355                                 LogoutSec(sec);\r
7356                         }\r
7357 \r
7358                         // セッションを閉じる\r
7359                         SetText(hWnd, S_STATUS, _UU("SEC_CLOSE_SESSION"));\r
7360                         CloseSecSession(sec);\r
7361                 }\r
7362 \r
7363                 // デバイスを閉じる\r
7364                 SetText(hWnd, S_STATUS, _UU("SEC_CLOSING"));\r
7365                 CloseSec(sec);\r
7366         }\r
7367 \r
7368         if (p->Succeed)\r
7369         {\r
7370                 // 成功した場合は 150ms メッセージを表示する (サービス)\r
7371                 SetText(hWnd, S_STATUS, _UU("SEC_FINISHED"));\r
7372                 SleepThread(150);\r
7373         }\r
7374 \r
7375         SendMessage(p->hWnd, WM_APP + 1, 0, 0);\r
7376 }\r
7377 \r
7378 // セキュアデバイス操作を開始する\r
7379 void StartSecureDevice(HWND hWnd, SECURE_DEVICE_WINDOW *w)\r
7380 {\r
7381         SECURE_DEVICE_THREAD *p;\r
7382         // 引数チェック\r
7383         if (hWnd == NULL || w == NULL)\r
7384         {\r
7385                 return;\r
7386         }\r
7387 \r
7388         // コントロールを無効にする\r
7389         EnableSecureDeviceWindowControls(hWnd, false);\r
7390 \r
7391         // スレッドを開始する\r
7392         p = ZeroMalloc(sizeof(SECURE_DEVICE_THREAD));\r
7393         p->w = w;\r
7394         p->hWnd = hWnd;\r
7395         w->p = p;\r
7396         p->pin = GetTextA(hWnd, E_PIN);\r
7397         ReleaseThread(NewThread(SecureDeviceThread, p));\r
7398 }\r
7399 \r
7400 // セキュアデバイス操作用ウインドウのコントロールを有効・無効化する\r
7401 void EnableSecureDeviceWindowControls(HWND hWnd, bool enable)\r
7402 {\r
7403         // 引数チェック\r
7404         if (hWnd == NULL)\r
7405         {\r
7406                 return;\r
7407         }\r
7408 \r
7409         if (enable)\r
7410         {\r
7411                 Show(hWnd, S_PIN_CODE);\r
7412                 Show(hWnd, E_PIN);\r
7413                 Show(hWnd, S_WARNING);\r
7414         }\r
7415         else\r
7416         {\r
7417                 Hide(hWnd, S_PIN_CODE);\r
7418                 Hide(hWnd, E_PIN);\r
7419                 Hide(hWnd, S_WARNING);\r
7420         }\r
7421 \r
7422         SetEnable(hWnd, IDOK, enable);\r
7423         SetEnable(hWnd, IDCANCEL, enable);\r
7424         SetEnable(hWnd, S_TITLE, enable);\r
7425         SetEnable(hWnd, S_DEVICE_INFO, enable);\r
7426         SetEnable(hWnd, S_INSERT_SECURE, enable);\r
7427 \r
7428         if (enable == false)\r
7429         {\r
7430                 DisableClose(hWnd);\r
7431                 SetText(hWnd, S_STATUS, L"");\r
7432                 Show(hWnd, S_STATUS);\r
7433                 PlayAvi(hWnd, A_PROGRESS, true);\r
7434         }\r
7435         else\r
7436         {\r
7437                 EnableClose(hWnd);\r
7438                 SetText(hWnd, S_STATUS, L"");\r
7439                 Hide(hWnd, S_STATUS);\r
7440                 StopAvi(hWnd, A_PROGRESS);\r
7441         }\r
7442 }\r
7443 \r
7444 // セキュアデバイス操作用ウインドウプロシージャ\r
7445 UINT SecureDeviceWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
7446 {\r
7447         SECURE_DEVICE_WINDOW *w = (SECURE_DEVICE_WINDOW *)param;\r
7448         SECURE_DEVICE *dev = GetSecureDevice(w->device_id);\r
7449 \r
7450         switch (msg)\r
7451         {\r
7452         case WM_INITDIALOG:\r
7453                 if (dev == NULL)\r
7454                 {\r
7455                         MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SEC_ERROR_INVALID_ID"), w->device_id);\r
7456                         EndDialog(hWnd, 0);\r
7457                         break;\r
7458                 }\r
7459 \r
7460                 if (IsJPKI(dev->Id))\r
7461                 {\r
7462                         // 住基カード\r
7463                         Hide(hWnd, S_IMAGE);\r
7464                         Show(hWnd, S_IMAGE2);\r
7465                         Hide(hWnd, S_IMAGE_TSUKUBA);\r
7466                 }\r
7467                 else\r
7468                 {\r
7469                         // 普通のカード\r
7470                         Hide(hWnd, S_IMAGE2);\r
7471 \r
7472                         if (w->BitmapId != 0)\r
7473                         {\r
7474                                 // 筑波大学用\r
7475                                 Hide(hWnd, S_IMAGE);\r
7476                                 Show(hWnd, S_IMAGE_TSUKUBA);\r
7477                         }\r
7478                         else\r
7479                         {\r
7480                                 // 一般用\r
7481                                 Show(hWnd, S_IMAGE);\r
7482                                 Hide(hWnd, S_IMAGE_TSUKUBA);\r
7483                         }\r
7484                 }\r
7485 \r
7486                 FormatText(hWnd, 0, dev->Type != SECURE_USB_TOKEN ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN"),\r
7487                         dev->DeviceName);\r
7488                 FormatText(hWnd, S_TITLE, dev->DeviceName);\r
7489                 FormatText(hWnd, S_INSERT_SECURE,\r
7490                         dev->Type != SECURE_USB_TOKEN ? _UU("SEC_INIT_MSG_1") : _UU("SEC_INIT_MSG_2"));\r
7491                 FormatText(hWnd, S_DEVICE_INFO,\r
7492                         dev->DeviceName, dev->Manufacturer, dev->ModuleName);\r
7493 \r
7494                 DlgFont(hWnd, S_SOFTWARE_TITLE, 11, 0);\r
7495                 SetText(hWnd, S_SOFTWARE_TITLE, title_bar);\r
7496 \r
7497                 DlgFont(hWnd, S_TITLE, 14, true);\r
7498                 DlgFont(hWnd, S_DEVICE_INFO, 11, false);\r
7499                 DlgFont(hWnd, S_STATUS, 13, true);\r
7500                 EnableSecureDeviceWindowControls(hWnd, true);\r
7501                 OpenAvi(hWnd, A_PROGRESS, AVI_PROGRESS);\r
7502 \r
7503                 SetIcon(hWnd, 0, ICO_KEY);\r
7504 \r
7505                 // 初期 PIN\r
7506                 if ((w->default_pin != NULL && StrLen(w->default_pin) != 0) || (cached_pin_code_expires >= Tick64()))\r
7507                 {\r
7508                         if (w->default_pin != NULL && StrLen(w->default_pin) != 0)\r
7509                         {\r
7510                                 SetTextA(hWnd, E_PIN, w->default_pin);\r
7511                         }\r
7512                         else\r
7513                         {\r
7514                                 SetTextA(hWnd, E_PIN, cached_pin_code);\r
7515                         }\r
7516                         SetTimer(hWnd, 1, 1, NULL);\r
7517                 }\r
7518 \r
7519                 break;\r
7520 \r
7521         case WM_TIMER:\r
7522                 switch (wParam)\r
7523                 {\r
7524                 case 1:\r
7525                         KillTimer(hWnd, 1);\r
7526                         Command(hWnd, IDOK);\r
7527                         break;\r
7528                 }\r
7529                 break;\r
7530 \r
7531         case WM_COMMAND:\r
7532                 switch (wParam)\r
7533                 {\r
7534                 case IDOK:\r
7535                         StartSecureDevice(hWnd, w);\r
7536                         break;\r
7537 \r
7538                 case IDCANCEL:\r
7539                         Close(hWnd);\r
7540                         break;\r
7541                 }\r
7542                 break;\r
7543 \r
7544         case WM_CLOSE:\r
7545                 if (IsEnable(hWnd, IDCANCEL))\r
7546                 {\r
7547                         CloseAvi(hWnd, A_PROGRESS);\r
7548                         EndDialog(hWnd, false);\r
7549                 }\r
7550                 break;\r
7551 \r
7552         case WM_APP + 1:\r
7553                 // スレッドから応答があった\r
7554                 if (w->p != NULL)\r
7555                 {\r
7556                         if (w->p->Succeed)\r
7557                         {\r
7558                                 // 成功\r
7559                                 if (w->default_pin != NULL)\r
7560                                 {\r
7561                                         StrCpy(w->default_pin, 128, w->p->pin);\r
7562                                 }\r
7563                                 StrCpy(cached_pin_code, sizeof(cached_pin_code), w->p->pin);\r
7564                                 cached_pin_code_expires = Tick64() + (UINT64)WINUI_SECUREDEVICE_PIN_CACHE_TIME;\r
7565                                 Free(w->p->pin);\r
7566                                 Free(w->p);\r
7567                                 EndDialog(hWnd, true);\r
7568                         }\r
7569                         else\r
7570                         {\r
7571                                 // 失敗\r
7572                                 cached_pin_code_expires = 0;\r
7573                                 EnableSecureDeviceWindowControls(hWnd, true);\r
7574                                 FocusEx(hWnd, E_PIN);\r
7575                                 MsgBox(hWnd, MB_ICONEXCLAMATION, w->p->ErrorMessage);\r
7576                                 Free(w->p->pin);\r
7577                                 Free(w->p->ErrorMessage);\r
7578                                 Free(w->p);\r
7579                         }\r
7580                 }\r
7581                 break;\r
7582         }\r
7583 \r
7584         return 0;\r
7585 }\r
7586 \r
7587 // WM_COMMAND を送信する\r
7588 void Command(HWND hWnd, UINT id)\r
7589 {\r
7590         SendMessage(hWnd, WM_COMMAND, id, 0);\r
7591 }\r
7592 \r
7593 // セキュアデバイスウインドウを表示する\r
7594 bool SecureDeviceWindow(HWND hWnd, WINUI_SECURE_BATCH *batch, UINT num_batch, UINT device_id, UINT bitmap_id)\r
7595 {\r
7596         SECURE_DEVICE_WINDOW w;\r
7597         UINT i;\r
7598         // 引数チェック\r
7599         if (batch == NULL || num_batch == 0 || device_id == 0)\r
7600         {\r
7601                 return false;\r
7602         }\r
7603 \r
7604         // 成功フラグを初期化\r
7605         for (i = 0;i < num_batch;i++)\r
7606         {\r
7607                 batch[i].Succeed = false;\r
7608         }\r
7609 \r
7610         Zero(&w, sizeof(w));\r
7611         w.batch = batch;\r
7612         w.device_id = device_id;\r
7613         w.num_batch = num_batch;\r
7614         w.BitmapId = bitmap_id;\r
7615 \r
7616         // ダイアログを開く\r
7617         return (bool)Dialog(hWnd, D_SECURE, SecureDeviceWindowProc, &w);\r
7618 }\r
7619 \r
7620 // AVI を停止する\r
7621 void StopAvi(HWND hWnd, UINT id)\r
7622 {\r
7623         // 引数チェック\r
7624         if (hWnd == NULL)\r
7625         {\r
7626                 return;\r
7627         }\r
7628 \r
7629         Animate_Stop(DlgItem(hWnd, id));\r
7630         Hide(hWnd, id);\r
7631 }\r
7632 \r
7633 // AVI を再生する\r
7634 void PlayAvi(HWND hWnd, UINT id, bool repeat)\r
7635 {\r
7636         // 引数チェック\r
7637         if (hWnd == NULL)\r
7638         {\r
7639                 return;\r
7640         }\r
7641 \r
7642         Show(hWnd, id);\r
7643         Animate_Play(DlgItem(hWnd, id), 0, -1, (repeat ? -1 : 0));\r
7644 }\r
7645 \r
7646 // AVI ファイルを閉じる\r
7647 void CloseAvi(HWND hWnd, UINT id)\r
7648 {\r
7649         // 引数チェック\r
7650         if (hWnd == NULL)\r
7651         {\r
7652                 return;\r
7653         }\r
7654 \r
7655         StopAvi(hWnd, id);\r
7656         Animate_Close(DlgItem(hWnd, id));\r
7657 }\r
7658 \r
7659 // AVI ファイルを開く\r
7660 void OpenAvi(HWND hWnd, UINT id, UINT avi_id)\r
7661 {\r
7662         // 引数チェック\r
7663         if (hWnd == NULL || avi_id == 0)\r
7664         {\r
7665                 return;\r
7666         }\r
7667 \r
7668         Hide(hWnd, id);\r
7669         Animate_OpenEx(DlgItem(hWnd, id), hDll, MAKEINTRESOURCE(avi_id));\r
7670 }\r
7671 \r
7672 // フォントをコントロールに設定する\r
7673 void DlgFont(HWND hWnd, UINT id, UINT size, UINT bold)\r
7674 {\r
7675         DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);\r
7676 \r
7677         if (param == NULL || param->meiryo == false)\r
7678         {\r
7679                 SetFont(hWnd, id, Font(size, bold));\r
7680         }\r
7681         else\r
7682         {\r
7683                 SetFont(hWnd, id, GetFont((_GETLANG() == 2 ? "Microsoft YaHei" : "Meiryo"), size, bold, false, false, false));\r
7684         }\r
7685 }\r
7686 \r
7687 // 標準的なフォントを生成する\r
7688 HFONT Font(UINT size, UINT bold)\r
7689 {\r
7690         return GetFont(NULL, size, bold, false, false, false);\r
7691 }\r
7692 \r
7693 // 内部管理用ダイアログプロシージャ\r
7694 UINT CALLBACK InternalDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
7695 {\r
7696         DIALOG_PARAM *param = (DIALOG_PARAM *)GetParam(hWnd);\r
7697         void *app_param = NULL;\r
7698         bool white_flag = false;\r
7699         UINT ret;\r
7700         // 引数チェック\r
7701         if (hWnd == NULL)\r
7702         {\r
7703                 return 0;\r
7704         }\r
7705 \r
7706         if (msg == WM_INITDIALOG)\r
7707         {\r
7708                 DoEvents(hWnd);\r
7709         }\r
7710 \r
7711         if (param == NULL)\r
7712         {\r
7713                 if (msg == WM_INITDIALOG)\r
7714                 {\r
7715                         param = (void *)lParam;\r
7716                         InitDialogInternational(hWnd, param);\r
7717                 }\r
7718         }\r
7719         if (param != NULL)\r
7720         {\r
7721                 app_param = param->param;\r
7722                 white_flag = param->white;\r
7723         }\r
7724 \r
7725         ret = DlgProc(hWnd, msg, wParam, lParam, white_flag);\r
7726         if (ret != 0)\r
7727         {\r
7728                 return ret;\r
7729         }\r
7730 \r
7731         ret = 0;\r
7732 \r
7733         if (param != NULL)\r
7734         {\r
7735                 if (param->proc != NULL)\r
7736                 {\r
7737                         ret = param->proc(hWnd, msg, wParam, lParam, app_param);\r
7738                 }\r
7739                 else\r
7740                 {\r
7741                         if (msg == WM_CLOSE)\r
7742                         {\r
7743                                 EndDialog(hWnd, 0);\r
7744                         }\r
7745                         else if (msg == WM_COMMAND && (wParam == IDOK || wParam == IDCANCEL))\r
7746                         {\r
7747                                 Close(hWnd);\r
7748                         }\r
7749                 }\r
7750         }\r
7751 \r
7752         if (msg == WM_INITDIALOG)\r
7753         {\r
7754                 SetForegroundWindow(hWnd);\r
7755                 SetActiveWindow(hWnd);\r
7756         }\r
7757 \r
7758         return ret;\r
7759 }\r
7760 \r
7761 // ダイアログ ボックスを表示する\r
7762 UINT Dialog(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param)\r
7763 {\r
7764         bool white = true;\r
7765 \r
7766         return DialogEx(hWnd, id, proc, param, white);\r
7767 }\r
7768 UINT DialogEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white)\r
7769 {\r
7770         return DialogEx2(hWnd, id, proc, param, white, false);\r
7771 }\r
7772 UINT DialogEx2(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white, bool meiryo)\r
7773 {\r
7774         UINT ret;\r
7775         DIALOG_PARAM p;\r
7776         // 引数チェック\r
7777         if (id == 0)\r
7778         {\r
7779                 return 0;\r
7780         }\r
7781 \r
7782         Zero(&p, sizeof(p));\r
7783         p.param = param;\r
7784         p.white = white;\r
7785         p.proc = proc;\r
7786 \r
7787         if (MsIsVista())\r
7788         {\r
7789                 p.meiryo = meiryo;\r
7790         }\r
7791 \r
7792         ret = DialogInternal(hWnd, id, InternalDialogProc, &p);\r
7793 \r
7794         return ret;\r
7795 }\r
7796 \r
7797 // モードレスダイアログを作成する\r
7798 HWND DialogCreateEx(HWND hWnd, UINT id, WINUI_DIALOG_PROC *proc, void *param, bool white)\r
7799 {\r
7800         HWND ret = NULL;\r
7801         DIALOG_PARAM p;\r
7802         // 引数チェック\r
7803         if (id == 0)\r
7804         {\r
7805                 return 0;\r
7806         }\r
7807 \r
7808         Zero(&p, sizeof(p));\r
7809         p.param = param;\r
7810         p.white = white;\r
7811         p.proc = proc;\r
7812 \r
7813         if (MsIsNt() == false)\r
7814         {\r
7815                 // Win9x\r
7816                 ret = CreateDialogParamA(hDll, MAKEINTRESOURCEA(id), hWnd,\r
7817                         (DLGPROC)proc, (LPARAM)param);\r
7818         }\r
7819         else\r
7820         {\r
7821                 // WinNT\r
7822                 ret = CreateDialogParamW(hDll, MAKEINTRESOURCEW(id), hWnd,\r
7823                         (DLGPROC)proc, (LPARAM)param);\r
7824         }\r
7825 \r
7826         return ret;\r
7827 }\r
7828 \r
7829 // ビットマップをボタンに設定する\r
7830 void SetBitmap(HWND hWnd, UINT id, UINT bmp_id)\r
7831 {\r
7832         HBITMAP bmp;\r
7833         char *class_name;\r
7834         // 引数チェック\r
7835         if (hWnd == NULL)\r
7836         {\r
7837                 return;\r
7838         }\r
7839 \r
7840         bmp = LoadImage(hDll, MAKEINTRESOURCE(bmp_id), IMAGE_BITMAP, 0, 0, (MsIsNt() ? LR_SHARED : 0) | LR_VGACOLOR);\r
7841         if (bmp == NULL)\r
7842         {\r
7843                 return;\r
7844         }\r
7845 \r
7846         class_name = GetClassA(hWnd, id);\r
7847 \r
7848         if (StrCmpi(class_name, "Static") != 0)\r
7849         {\r
7850                 SendMsg(hWnd, id, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);\r
7851         }\r
7852         else\r
7853         {\r
7854                 SendMsg(hWnd, id, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);\r
7855         }\r
7856 \r
7857         Free(class_name);\r
7858 }\r
7859 \r
7860 // アイコンキャッシュの初期化\r
7861 void InitIconCache()\r
7862 {\r
7863         if (icon_cache_list != NULL)\r
7864         {\r
7865                 return;\r
7866         }\r
7867 \r
7868         icon_cache_list = NewList(NULL);\r
7869 }\r
7870 \r
7871 // アイコンキャッシュの解放\r
7872 void FreeIconCache()\r
7873 {\r
7874         UINT i;\r
7875         if (icon_cache_list == NULL)\r
7876         {\r
7877                 return;\r
7878         }\r
7879 \r
7880         for (i = 0;i < LIST_NUM(icon_cache_list);i++)\r
7881         {\r
7882                 ICON_CACHE *c = LIST_DATA(icon_cache_list, i);\r
7883                 DestroyIcon(c->hIcon);\r
7884                 Free(c);\r
7885         }\r
7886 \r
7887         ReleaseList(icon_cache_list);\r
7888         icon_cache_list = NULL;\r
7889 }\r
7890 \r
7891 // アイコン取得\r
7892 HICON LoadIconEx(UINT id, bool small_icon)\r
7893 {\r
7894         HICON h = NULL;\r
7895         UINT i;\r
7896         if (icon_cache_list == NULL)\r
7897         {\r
7898                 return small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);\r
7899         }\r
7900 \r
7901         LockList(icon_cache_list);\r
7902         {\r
7903                 for (i = 0;i < LIST_NUM(icon_cache_list);i++)\r
7904                 {\r
7905                         ICON_CACHE *c = LIST_DATA(icon_cache_list, i);\r
7906                         if (c->id == id && c->small_icon == small_icon)\r
7907                         {\r
7908                                 h = c->hIcon;\r
7909                                 break;\r
7910                         }\r
7911                 }\r
7912 \r
7913                 if (h == NULL)\r
7914                 {\r
7915                         h = small_icon == false ? LoadLargeIconInner(id) : LoadSmallIconInner(id);\r
7916                         if (h != NULL)\r
7917                         {\r
7918                                 ICON_CACHE *c = ZeroMalloc(sizeof(ICON_CACHE));\r
7919                                 c->hIcon = h;\r
7920                                 c->id = id;\r
7921                                 c->small_icon = small_icon;\r
7922                                 Add(icon_cache_list, c);\r
7923                         }\r
7924                 }\r
7925         }\r
7926         UnlockList(icon_cache_list);\r
7927 \r
7928         return h;\r
7929 }\r
7930 \r
7931 // 大きいアイコン取得\r
7932 HICON LoadLargeIcon(UINT id)\r
7933 {\r
7934         return LoadIconEx(id, false);\r
7935 }\r
7936 \r
7937 // 小さいアイコン取得\r
7938 HICON LoadSmallIcon(UINT id)\r
7939 {\r
7940         return LoadIconEx(id, true);\r
7941 }\r
7942 \r
7943 // 大きいアイコンを取得する\r
7944 HICON LoadLargeIconInner(UINT id)\r
7945 {\r
7946         HICON ret;\r
7947         ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, 0);\r
7948         if (ret == NULL)\r
7949         {\r
7950                 ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 32, 32, LR_VGACOLOR);\r
7951                 if (ret == NULL)\r
7952                 {\r
7953                         ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);\r
7954                         if (ret == NULL)\r
7955                         {\r
7956                                 ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);\r
7957                                 if (ret == NULL)\r
7958                                 {\r
7959                                         ret = LoadIcon(hDll, MAKEINTRESOURCE(id));\r
7960                                 }\r
7961                         }\r
7962                 }\r
7963         }\r
7964         return ret;\r
7965 }\r
7966 \r
7967 // 小さいアイコンを取得する\r
7968 HICON LoadSmallIconInner(UINT id)\r
7969 {\r
7970         HICON ret;\r
7971         ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, 0);\r
7972         if (ret == NULL)\r
7973         {\r
7974                 ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, LR_VGACOLOR);\r
7975                 if (ret == NULL)\r
7976                 {\r
7977                         ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, 0);\r
7978                         if (ret == NULL)\r
7979                         {\r
7980                                 ret = LoadImage(hDll, MAKEINTRESOURCE(id), IMAGE_ICON, 0, 0, LR_VGACOLOR);\r
7981                                 if (ret == NULL)\r
7982                                 {\r
7983                                         ret = LoadLargeIconInner(id);\r
7984                                 }\r
7985                         }\r
7986                 }\r
7987         }\r
7988         return ret;\r
7989 }\r
7990 \r
7991 // アイコンをウインドウまたはボタンに設定する\r
7992 void SetIcon(HWND hWnd, UINT id, UINT icon_id)\r
7993 {\r
7994         HICON icon1, icon2;\r
7995         // 引数チェック\r
7996         if (hWnd == NULL)\r
7997         {\r
7998                 return;\r
7999         }\r
8000 \r
8001         icon1 = LoadLargeIcon(icon_id);\r
8002         if (icon1 == NULL)\r
8003         {\r
8004                 return;\r
8005         }\r
8006 \r
8007         if (id == 0)\r
8008         {\r
8009                 SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon1);\r
8010                 icon2 = LoadSmallIcon(icon_id);\r
8011                 if (icon2 == NULL)\r
8012                 {\r
8013                         icon2 = icon1;\r
8014                 }\r
8015                 SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon2);\r
8016         }\r
8017         else\r
8018         {\r
8019                 bool is_btn = true;\r
8020                 wchar_t *s = GetClass(hWnd, id);\r
8021                 if (s != NULL)\r
8022                 {\r
8023                         if (UniStrCmpi(s, L"Static") == 0)\r
8024                         {\r
8025                                 is_btn = false;\r
8026                         }\r
8027                         Free(s);\r
8028                 }\r
8029 \r
8030                 if (is_btn)\r
8031                 {\r
8032                         SendMsg(hWnd, id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon1);\r
8033                 }\r
8034                 else\r
8035                 {\r
8036                         SendMsg(hWnd, id, STM_SETICON, (WPARAM)icon1, 0);\r
8037                 }\r
8038         }\r
8039 }\r
8040 \r
8041 // ラジオボタンがチェックされているか確認する\r
8042 bool IsChecked(HWND hWnd, UINT id)\r
8043 {\r
8044         // 引数チェック\r
8045         if (hWnd == NULL)\r
8046         {\r
8047                 return false;\r
8048         }\r
8049 \r
8050         return IsDlgButtonChecked(hWnd, id) == BST_CHECKED ? true : false;\r
8051 }\r
8052 \r
8053 // ラジオボタンをチェック\r
8054 void Check(HWND hWnd, UINT id, bool b)\r
8055 {\r
8056         // 引数チェック\r
8057         if (hWnd == NULL)\r
8058         {\r
8059                 return;\r
8060         }\r
8061 \r
8062         if ((!(!IsChecked(hWnd, id))) != (!(!b)))\r
8063         {\r
8064                 CheckDlgButton(hWnd, id, b ? BST_CHECKED : BST_UNCHECKED);\r
8065         }\r
8066 }\r
8067 \r
8068 // テキストボックスの文字サイズが指定されたサイズ以下であることを確認する\r
8069 bool CheckTextSize(HWND hWnd, UINT id, UINT size, bool unicode)\r
8070 {\r
8071         // 引数チェック\r
8072         if (hWnd == NULL)\r
8073         {\r
8074                 return false;\r
8075         }\r
8076 \r
8077         if (GetTextSize(hWnd, id, unicode) <= size)\r
8078         {\r
8079                 return true;\r
8080         }\r
8081         else\r
8082         {\r
8083                 return false;\r
8084         }\r
8085 }\r
8086 \r
8087 // テキストボックスに入っている文字列数が指定された文字列数以下であることを確認する\r
8088 bool CheckTextLen(HWND hWnd, UINT id, UINT len, bool unicode)\r
8089 {\r
8090         // 引数チェック\r
8091         if (hWnd == NULL)\r
8092         {\r
8093                 return false;\r
8094         }\r
8095 \r
8096         if (GetTextLen(hWnd, id, unicode) <= len)\r
8097         {\r
8098                 return true;\r
8099         }\r
8100         else\r
8101         {\r
8102                 return false;\r
8103         }\r
8104 }\r
8105 \r
8106 // テキストボックスに入力できる文字数を制限する\r
8107 void LimitText(HWND hWnd, UINT id, UINT count)\r
8108 {\r
8109         // 引数チェック\r
8110         if (hWnd == NULL)\r
8111         {\r
8112                 return;\r
8113         }\r
8114 \r
8115         SendMsg(hWnd, id, EM_LIMITTEXT, count, 0);\r
8116 }\r
8117 \r
8118 // フォントの設定\r
8119 void SetFont(HWND hWnd, UINT id, HFONT hFont)\r
8120 {\r
8121         // 引数チェック\r
8122         if (hWnd == NULL || hFont == NULL)\r
8123         {\r
8124                 return;\r
8125         }\r
8126 \r
8127         SendMessage(DlgItem(hWnd, id), WM_SETFONT, (WPARAM)hFont, true);\r
8128 }\r
8129 \r
8130 // フォントサイズの取得\r
8131 bool GetFontSize(HFONT hFont, UINT *x, UINT *y)\r
8132 {\r
8133         bool ret = false;\r
8134         UINT xx = 0;\r
8135         UINT yy = 0;\r
8136 \r
8137         // フォントハンドルを検索\r
8138         LockList(font_list);\r
8139         {\r
8140                 UINT i;\r
8141 \r
8142                 for (i = 0;i < LIST_NUM(font_list);i++)\r
8143                 {\r
8144                         FONT *f = LIST_DATA(font_list, i);\r
8145 \r
8146                         if (f->hFont == hFont)\r
8147                         {\r
8148                                 xx = f->x;\r
8149                                 yy = f->y;\r
8150 \r
8151                                 ret = true;\r
8152                                 break;\r
8153                         }\r
8154                 }\r
8155         }\r
8156         UnlockList(font_list);\r
8157 \r
8158         if (ret == false)\r
8159         {\r
8160                 ret = CalcFontSize(hFont, &xx, &yy);\r
8161         }\r
8162 \r
8163         if (xx == 0 || yy == 0)\r
8164         {\r
8165                 xx = 8;\r
8166                 yy = 16;\r
8167         }\r
8168 \r
8169         if (x != NULL)\r
8170         {\r
8171                 *x = xx;\r
8172         }\r
8173 \r
8174         if (y != NULL)\r
8175         {\r
8176                 *y = yy;\r
8177         }\r
8178 \r
8179         return ret;\r
8180 }\r
8181 \r
8182 // フォントサイズの計算\r
8183 bool CalcFontSize(HFONT hFont, UINT *x, UINT *y)\r
8184 {\r
8185         UINT xx = 0, yy = 0;\r
8186         TEXTMETRIC tm;\r
8187         SIZE sz;\r
8188         bool ret = false;\r
8189         HDC hDC;\r
8190 \r
8191         hDC = CreateCompatibleDC(NULL);\r
8192 \r
8193         SelectObject(hDC, hFont);\r
8194 \r
8195         Zero(&tm, sizeof(tm));\r
8196         Zero(&sz, sizeof(sz));\r
8197 \r
8198         if (GetTextMetrics(hDC, &tm))\r
8199         {\r
8200                 xx = tm.tmAveCharWidth;\r
8201                 yy = tm.tmHeight;\r
8202 \r
8203                 ret = true;\r
8204 \r
8205                 if (GetTextExtentPoint32(hDC,\r
8206                         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",\r
8207                         52, &sz))\r
8208                 {\r
8209                         xx = (sz.cx / 26 + 1) / 2;\r
8210                 }\r
8211         }\r
8212 \r
8213         if (x != NULL)\r
8214         {\r
8215                 *x = xx;\r
8216         }\r
8217 \r
8218         if (y != NULL)\r
8219         {\r
8220                 *y = yy;\r
8221         }\r
8222 \r
8223         DeleteDC(hDC);\r
8224 \r
8225         return ret;\r
8226 }\r
8227 \r
8228 // フォントの取得\r
8229 HFONT GetFont(char *name, UINT size, bool bold, bool italic, bool underline, bool strikeout)\r
8230 {\r
8231         HFONT hFont;\r
8232         HDC hDC;\r
8233         // 引数チェック\r
8234         if (name == NULL)\r
8235         {\r
8236                 name = font_name;\r
8237         }\r
8238         if (size == 0)\r
8239         {\r
8240                 size = font_size;\r
8241                 if (size == 0)\r
8242                 {\r
8243                         size = 9;\r
8244                 }\r
8245         }\r
8246 \r
8247         // 既存のフォントを探す\r
8248         LockList(font_list);\r
8249         {\r
8250                 FONT *f, t;\r
8251                 DWORD font_quality = ANTIALIASED_QUALITY;\r
8252                 OS_INFO *os = GetOsInfo();\r
8253                 UINT x = 0;\r
8254                 UINT y = 0;\r
8255                 int rotate = 0;\r
8256 \r
8257                 Zero(&t, sizeof(t));\r
8258                 t.Bold = bold;\r
8259                 t.Italic = italic;\r
8260                 t.Size = size;\r
8261                 t.StrikeOut = strikeout;\r
8262                 t.UnderLine = underline;\r
8263                 t.Name = CopyStr(name);\r
8264                 f = Search(font_list, &t);\r
8265                 Free(t.Name);\r
8266 \r
8267                 if (f != NULL)\r
8268                 {\r
8269                         // フォントを発見した\r
8270                         UnlockList(font_list);\r
8271                         return f->hFont;\r
8272                 }\r
8273 \r
8274                 // 新しいフォントを作成する\r
8275                 hDC = CreateCompatibleDC(NULL);\r
8276 \r
8277                 // Windows XP 以降では ClearType を指定する\r
8278                 if (OS_IS_WINDOWS_NT(os->OsType) && GET_KETA(os->OsType, 100) >= 3)\r
8279                 {\r
8280                         font_quality = CLEARTYPE_NATURAL_QUALITY;\r
8281                         rotate = 3600;\r
8282                 }\r
8283 \r
8284                 // フォント作成\r
8285                 hFont = CreateFontA(-MulDiv(size, GetDeviceCaps(hDC, LOGPIXELSY), 72),\r
8286                         0, rotate, rotate, (bold == false ? 500 : FW_BOLD),\r
8287                         italic, underline, strikeout, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,\r
8288                         CLIP_DEFAULT_PRECIS, font_quality, DEFAULT_PITCH, name);\r
8289 \r
8290                 if (hFont == NULL)\r
8291                 {\r
8292                         // 失敗\r
8293                         DeleteDC(hDC);\r
8294                         UnlockList(font_list);\r
8295 \r
8296                         return NULL;\r
8297                 }\r
8298 \r
8299                 CalcFontSize(hFont, &x, &y);\r
8300 \r
8301                 // テーブルに追加\r
8302                 f = ZeroMalloc(sizeof(FONT));\r
8303                 f->Bold = bold;\r
8304                 f->hFont = hFont;\r
8305                 f->Italic = italic;\r
8306                 f->Name = CopyStr(name);\r
8307                 f->Size = size;\r
8308                 f->StrikeOut = strikeout;\r
8309                 f->UnderLine = underline;\r
8310                 f->x = x;\r
8311                 f->y = y;\r
8312 \r
8313                 Insert(font_list, f);\r
8314 \r
8315                 DeleteDC(hDC);\r
8316         }\r
8317         UnlockList(font_list);\r
8318 \r
8319         return hFont;\r
8320 }\r
8321 \r
8322 // フォントの比較\r
8323 int CompareFont(void *p1, void *p2)\r
8324 {\r
8325         FONT *f1, *f2;\r
8326         UINT r;\r
8327         if (p1 == NULL || p2 == NULL)\r
8328         {\r
8329                 return 0;\r
8330         }\r
8331         f1 = *(FONT **)p1;\r
8332         f2 = *(FONT **)p2;\r
8333         if (f1 == NULL || f2 == NULL)\r
8334         {\r
8335                 return 0;\r
8336         }\r
8337         r = StrCmpi(f1->Name, f2->Name);\r
8338         if (r != 0)\r
8339         {\r
8340                 return r;\r
8341         }\r
8342         else\r
8343         {\r
8344                 if (f1->Bold > f2->Bold)\r
8345                 {\r
8346                         return 1;\r
8347                 }\r
8348                 else if (f1->Bold < f2->Bold)\r
8349                 {\r
8350                         return -1;\r
8351                 }\r
8352                 else if (f1->Italic > f2->Italic)\r
8353                 {\r
8354                         return 1;\r
8355                 }\r
8356                 else if (f1->Italic < f2->Italic)\r
8357                 {\r
8358                         return -1;\r
8359                 }\r
8360                 else if (f1->Size > f2->Size)\r
8361                 {\r
8362                         return 1;\r
8363                 }\r
8364                 else if (f1->Size < f2->Size)\r
8365                 {\r
8366                         return -1;\r
8367                 }\r
8368                 else if (f1->StrikeOut > f2->StrikeOut)\r
8369                 {\r
8370                         return 1;\r
8371                 }\r
8372                 else if (f1->StrikeOut < f2->StrikeOut)\r
8373                 {\r
8374                         return -1;\r
8375                 }\r
8376                 else if (f1->UnderLine > f2->UnderLine)\r
8377                 {\r
8378                         return 1;\r
8379                 }\r
8380                 else if (f1->UnderLine < f2->UnderLine)\r
8381                 {\r
8382                         return -1;\r
8383                 }\r
8384                 else\r
8385                 {\r
8386                         return 0;\r
8387                 }\r
8388         }\r
8389 }\r
8390 \r
8391 // フォントの初期化\r
8392 void InitFont()\r
8393 {\r
8394         if (font_list != NULL)\r
8395         {\r
8396                 return;\r
8397         }\r
8398         font_list = NewList(CompareFont);\r
8399 }\r
8400 \r
8401 // フォントの解放\r
8402 void FreeFont()\r
8403 {\r
8404         UINT i;\r
8405         if (font_list == NULL)\r
8406         {\r
8407                 return;\r
8408         }\r
8409         for (i = 0;i < LIST_NUM(font_list);i++)\r
8410         {\r
8411                 FONT *f = LIST_DATA(font_list, i);\r
8412                 Free(f->Name);\r
8413                 DeleteObject((HGDIOBJ)f->hFont);\r
8414                 Free(f);\r
8415         }\r
8416         ReleaseList(font_list);\r
8417         font_list = NULL;\r
8418 }\r
8419 \r
8420 // ウインドウを閉じるボタンを出す\r
8421 void EnableClose(HWND hWnd)\r
8422 {\r
8423         HMENU h;\r
8424         // 引数チェック\r
8425         if (hWnd == NULL)\r
8426         {\r
8427                 return;\r
8428         }\r
8429 \r
8430         h = GetSystemMenu(hWnd, false);\r
8431         EnableMenuItem(h, SC_CLOSE, MF_ENABLED);\r
8432         DrawMenuBar(hWnd);\r
8433 }\r
8434 \r
8435 // ウインドウを閉じるボタンを消す\r
8436 void DisableClose(HWND hWnd)\r
8437 {\r
8438         HMENU h;\r
8439         // 引数チェック\r
8440         if (hWnd == NULL)\r
8441         {\r
8442                 return;\r
8443         }\r
8444 \r
8445         h = GetSystemMenu(hWnd, false);\r
8446         EnableMenuItem(h, SC_CLOSE, MF_GRAYED);\r
8447         DrawMenuBar(hWnd);\r
8448 }\r
8449 \r
8450 // 親ウインドウの中央に移動する\r
8451 void CenterParent(HWND hWnd)\r
8452 {\r
8453         RECT rp;\r
8454         RECT r;\r
8455         HWND hWndParent = GetParent(hWnd);\r
8456         int win_x, win_y;\r
8457         int x, y;\r
8458 \r
8459         if (hWndParent == NULL || IsHide(hWndParent, 0) || IsIconic(hWndParent))\r
8460         {\r
8461                 Center(hWnd);\r
8462                 return;\r
8463         }\r
8464 \r
8465         if (GetWindowRect(hWndParent, &rp) == false)\r
8466         {\r
8467                 Center(hWnd);\r
8468                 return;\r
8469         }\r
8470 \r
8471         GetWindowRect(hWnd, &r);\r
8472 \r
8473         win_x = r.right - r.left;\r
8474         win_y = r.bottom - r.top;\r
8475 \r
8476         x = (rp.right - rp.left - win_x) / 2 + rp.left;\r
8477         y = (rp.bottom - rp.top - win_y) / 2 + rp.top;\r
8478 \r
8479         x = MAX(x, 0);\r
8480         y = MAX(y, 0);\r
8481 \r
8482         SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);\r
8483 }\r
8484 \r
8485 // ウインドウを中央に移動する\r
8486 void Center(HWND hWnd)\r
8487 {\r
8488         RECT screen;\r
8489         RECT win;\r
8490         UINT x, y;\r
8491         UINT win_x, win_y;\r
8492         // 引数チェック\r
8493         if (hWnd == NULL)\r
8494         {\r
8495                 return;\r
8496         }\r
8497 \r
8498         if (SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0) == false)\r
8499         {\r
8500                 return;\r
8501         }\r
8502 \r
8503         GetWindowRect(hWnd, &win);\r
8504         win_x = win.right - win.left;\r
8505         win_y = win.bottom - win.top;\r
8506 \r
8507         if (win_x < (UINT)(screen.right - screen.left))\r
8508         {\r
8509                 x = (screen.right - screen.left - win_x) / 2;\r
8510         }\r
8511         else\r
8512         {\r
8513                 x = 0;\r
8514         }\r
8515 \r
8516         if (win_y < (UINT)(screen.bottom - screen.top))\r
8517         {\r
8518                 y = (screen.bottom - screen.top - win_y) / 2;\r
8519         }\r
8520         else\r
8521         {\r
8522                 y = 0;\r
8523         }\r
8524 \r
8525         SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);\r
8526 }\r
8527 \r
8528 // ウインドウを中央に移動する 2\r
8529 void Center2(HWND hWnd)\r
8530 {\r
8531         RECT screen;\r
8532         RECT win;\r
8533         UINT x, y;\r
8534         UINT win_x, win_y;\r
8535         // 引数チェック\r
8536         if (hWnd == NULL)\r
8537         {\r
8538                 return;\r
8539         }\r
8540 \r
8541         if (SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0) == false)\r
8542         {\r
8543                 return;\r
8544         }\r
8545 \r
8546         GetWindowRect(hWnd, &win);\r
8547         win_x = win.right - win.left;\r
8548         win_y = win.bottom - win.top;\r
8549 \r
8550         if (win_x < (UINT)(screen.right - screen.left))\r
8551         {\r
8552                 x = (screen.right - screen.left - win_x) / 2;\r
8553         }\r
8554         else\r
8555         {\r
8556                 x = 0;\r
8557         }\r
8558 \r
8559         if (win_y < (UINT)(screen.bottom - screen.top))\r
8560         {\r
8561                 y = (screen.bottom - screen.top - win_y) / 4;\r
8562         }\r
8563         else\r
8564         {\r
8565                 y = 0;\r
8566         }\r
8567 \r
8568         SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);\r
8569 }\r
8570 \r
8571 // モニタのサイズを取得する\r
8572 void GetMonitorSize(UINT *width, UINT *height)\r
8573 {\r
8574         // 引数チェック\r
8575         if (width == NULL || height == NULL)\r
8576         {\r
8577                 return;\r
8578         }\r
8579 \r
8580         *width = GetSystemMetrics(SM_CXSCREEN);\r
8581         *height = GetSystemMetrics(SM_CYSCREEN);\r
8582 }\r
8583 \r
8584 // ウインドウ内の文字列をフォーマットする\r
8585 void FormatText(HWND hWnd, UINT id, ...)\r
8586 {\r
8587         va_list args;\r
8588         wchar_t *buf;\r
8589         UINT size;\r
8590         wchar_t *str;\r
8591         // 引数チェック\r
8592         if (hWnd == NULL)\r
8593         {\r
8594                 return;\r
8595         }\r
8596 \r
8597         str = GetText(hWnd, id);\r
8598         if (str == NULL)\r
8599         {\r
8600                 return;\r
8601         }\r
8602 \r
8603         size = MAX(UniStrSize(str) * 10, MAX_SIZE * 10);\r
8604         buf = MallocEx(size, true);\r
8605 \r
8606         va_start(args, id);\r
8607         UniFormatArgs(buf, size, str, args);\r
8608 \r
8609         SetText(hWnd, id, buf);\r
8610 \r
8611         Free(buf);\r
8612 \r
8613         Free(str);\r
8614         va_end(args);\r
8615 }\r
8616 void FormatTextA(HWND hWnd, UINT id, ...)\r
8617 {\r
8618         va_list args;\r
8619         char *buf;\r
8620         UINT size;\r
8621         char *str;\r
8622         // 引数チェック\r
8623         if (hWnd == NULL)\r
8624         {\r
8625                 return;\r
8626         }\r
8627 \r
8628         str = GetTextA(hWnd, id);\r
8629         if (str == NULL)\r
8630         {\r
8631                 return;\r
8632         }\r
8633 \r
8634         size = MAX(StrSize(str) * 10, MAX_SIZE * 10);\r
8635         buf = MallocEx(size, true);\r
8636 \r
8637         va_start(args, id);\r
8638         FormatArgs(buf, size, str, args);\r
8639 \r
8640         SetTextA(hWnd, id, buf);\r
8641 \r
8642         Free(buf);\r
8643 \r
8644         Free(str);\r
8645         va_end(args);\r
8646 }\r
8647 \r
8648 // 可変長引数の文字列をウインドウに設定\r
8649 void SetTextEx(HWND hWnd, UINT id, wchar_t *str, ...)\r
8650 {\r
8651         va_list args;\r
8652         wchar_t *buf;\r
8653         UINT size;\r
8654         // 引数チェック\r
8655         if (str == NULL || hWnd == NULL)\r
8656         {\r
8657                 return;\r
8658         }\r
8659 \r
8660         size = MAX(UniStrSize(str) * 10, MAX_SIZE * 10);\r
8661         buf = MallocEx(size, true);\r
8662 \r
8663         va_start(args, str);\r
8664         UniFormatArgs(buf, size, str, args);\r
8665 \r
8666         SetText(hWnd, id, buf);\r
8667 \r
8668         Free(buf);\r
8669         va_end(args);\r
8670 }\r
8671 void SetTextExA(HWND hWnd, UINT id, char *str, ...)\r
8672 {\r
8673         va_list args;\r
8674         char *buf;\r
8675         UINT size;\r
8676         // 引数チェック\r
8677         if (str == NULL || hWnd == NULL)\r
8678         {\r
8679                 return;\r
8680         }\r
8681 \r
8682         size = MAX(StrSize(str) * 10, MAX_SIZE * 10);\r
8683         buf = MallocEx(size, true);\r
8684 \r
8685         va_start(args, str);\r
8686         FormatArgs(buf, size, str, args);\r
8687 \r
8688         SetTextA(hWnd, id, buf);\r
8689 \r
8690         Free(buf);\r
8691         va_end(args);\r
8692 }\r
8693 \r
8694 // 可変長メッセージボックスの表示\r
8695 UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...)\r
8696 {\r
8697         va_list args;\r
8698         wchar_t *buf;\r
8699         UINT size;\r
8700         UINT ret;\r
8701         // 引数チェック\r
8702         if (msg == NULL)\r
8703         {\r
8704                 msg = L"MessageBox";\r
8705         }\r
8706 \r
8707         size = MAX(UniStrSize(msg) * 10, MAX_SIZE * 10);\r
8708         buf = MallocEx(size, true);\r
8709 \r
8710         va_start(args, msg);\r
8711         UniFormatArgs(buf, size, msg, args);\r
8712 \r
8713         ret = MsgBox(hWnd, flag, buf);\r
8714         Free(buf);\r
8715         va_end(args);\r
8716 \r
8717         return ret;\r
8718 }\r
8719 \r
8720 // メッセージボックスの表示\r
8721 UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg)\r
8722 {\r
8723         UINT ret;\r
8724         wchar_t *title;\r
8725         // 引数チェック\r
8726         if (msg == NULL)\r
8727         {\r
8728                 msg = L"MessageBox";\r
8729         }\r
8730 \r
8731         if (title_bar != NULL)\r
8732         {\r
8733                 title = CopyUniStr(title_bar);\r
8734         }\r
8735         else\r
8736         {\r
8737                 title = CopyStrToUni(CEDAR_PRODUCT_STR);\r
8738         }\r
8739 \r
8740         if (hWnd)\r
8741         {\r
8742                 // 親ウインドウが最上位ウインドウの場合はメッセージボックスも最上位にする\r
8743                 if (GetExStyle(hWnd, 0) & WS_EX_TOPMOST)\r
8744                 {\r
8745                         flag |= MB_SYSTEMMODAL;\r
8746                 }\r
8747         }\r
8748 \r
8749         ret = MessageBoxW(hWnd, msg, title, flag);\r
8750 \r
8751         Free(title);\r
8752 \r
8753         return ret;\r
8754 }\r
8755 \r
8756 // ダイアログの作成 (内部)\r
8757 UINT DialogInternal(HWND hWnd, UINT id, DIALOG_PROC *proc, void *param)\r
8758 {\r
8759         // 引数チェック\r
8760         if (proc == NULL)\r
8761         {\r
8762                 return 0;\r
8763         }\r
8764 \r
8765         if (MsIsNt() == false)\r
8766         {\r
8767                 // Win9x\r
8768                 return (UINT)DialogBoxParam(hDll, MAKEINTRESOURCE(id), hWnd, (DLGPROC)proc, (LPARAM)param);\r
8769         }\r
8770         else\r
8771         {\r
8772                 // WinNT\r
8773                 return (UINT)DialogBoxParamW(hDll, MAKEINTRESOURCEW(id), hWnd, (DLGPROC)proc, (LPARAM)param);\r
8774         }\r
8775 }\r
8776 \r
8777 // システム設定が更新されたことを通知する\r
8778 void NoticeSettingChange()\r
8779 {\r
8780         PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);\r
8781         DoEvents(NULL);\r
8782 }\r
8783 \r
8784 // ウインドウを半透明にする\r
8785 void SetAplha(HWND hWnd, UINT value0_255)\r
8786 {\r
8787         // 引数チェック\r
8788         if (hWnd == NULL)\r
8789         {\r
8790                 return;\r
8791         }\r
8792 \r
8793         value0_255 = MAKESURE(value0_255, 0, 255);\r
8794 \r
8795         if (true)\r
8796         {\r
8797                 UINT os_type = GetOsInfo()->OsType;\r
8798                 if (OS_IS_WINDOWS_NT(os_type) && GET_KETA(os_type, 100) >= 2)\r
8799                 {\r
8800                         bool (WINAPI *_SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD);\r
8801                         HINSTANCE hInst;\r
8802 \r
8803                         hInst = LoadLibrary("user32.dll");\r
8804 \r
8805                         _SetLayeredWindowAttributes =\r
8806                                 (bool (__stdcall *)(HWND,COLORREF,BYTE,DWORD))\r
8807                                 GetProcAddress(hInst, "SetLayeredWindowAttributes");\r
8808 \r
8809                         if (_SetLayeredWindowAttributes != NULL)\r
8810                         {\r
8811                                 // Windows 2000 以降でのみ対応\r
8812                                 SetExStyle(hWnd, 0, WS_EX_LAYERED);\r
8813                                 _SetLayeredWindowAttributes(hWnd, 0, value0_255, LWA_ALPHA);\r
8814                         }\r
8815 \r
8816                         FreeLibrary(hInst);\r
8817                 }\r
8818         }\r
8819 }\r
8820 \r
8821 // WinUi が管理するダイアログボックスプロシージャ\r
8822 UINT DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, bool white_color)\r
8823 {\r
8824         void *param;\r
8825         HWND hWndParent;\r
8826         // 引数チェック\r
8827         if (hWnd == NULL)\r
8828         {\r
8829                 return 0;\r
8830         }\r
8831 \r
8832         switch (msg)\r
8833         {\r
8834         case WM_INITDIALOG:\r
8835                 param = (void *)lParam;\r
8836                 SetParam(hWnd, param);\r
8837 \r
8838                 // 親ウインドウが存在するかどうか調べる\r
8839                 hWndParent = GetParent(hWnd);\r
8840                 if (hWndParent == NULL || IsShow(hWndParent, 0) == false)\r
8841                 {\r
8842                         // 存在しない場合は中央に配置する\r
8843                         Center(hWnd);\r
8844                 }\r
8845 \r
8846                 if (UseAlpha)\r
8847                 {\r
8848                         SetAplha(hWnd, AlphaValue * 255 / 100);\r
8849                 }\r
8850 \r
8851                 break;\r
8852         }\r
8853 \r
8854         if (white_color)\r
8855         {\r
8856                 if (IsNewStyleModeEnabled() == false)\r
8857                 {\r
8858                         switch (msg)\r
8859                         {\r
8860                         case WM_CTLCOLORBTN:\r
8861                         case WM_CTLCOLORDLG:\r
8862                         case WM_CTLCOLOREDIT:\r
8863                         case WM_CTLCOLORLISTBOX:\r
8864                         case WM_CTLCOLORMSGBOX:\r
8865                         case WM_CTLCOLORSCROLLBAR:\r
8866                         case WM_CTLCOLORSTATIC:\r
8867                                 return (UINT)GetStockObject(WHITE_BRUSH);\r
8868                         }\r
8869                 }\r
8870                 else\r
8871                 {\r
8872                         switch (msg)\r
8873                         {\r
8874                         case WM_CTLCOLORDLG:\r
8875                                 // ダイアログの背景色\r
8876                                 return (UINT)gdi_cache.BackgroundColorBrush;\r
8877 \r
8878                         case WM_CTLCOLORBTN:\r
8879                                 // ボタンの背景色\r
8880                                 SetTextColor((HDC)wParam, gdi_cache.ForegroundColor);\r
8881                                 SetBkColor((HDC)wParam, gdi_cache.BackgroundColor);\r
8882                                 return (UINT)gdi_cache.BackgroundColorBrush;\r
8883 \r
8884                         case WM_CTLCOLORSTATIC:\r
8885                                 // ラベルの色\r
8886                                 SetTextColor((HDC)wParam, gdi_cache.ForegroundColor);\r
8887                                 SetBkColor((HDC)wParam, gdi_cache.BackgroundColor);\r
8888                                 return (UINT)gdi_cache.BackgroundColorBrush;\r
8889 \r
8890                         case WM_CTLCOLOREDIT:\r
8891                                 // エディットコントロールの色\r
8892                                 return (UINT)gdi_cache.TextBoxBackgroundColorBrush;\r
8893                         }\r
8894                 }\r
8895         }\r
8896 \r
8897         return 0;\r
8898 }\r
8899 \r
8900 // ダイアログボックスのパラメータの設定\r
8901 void SetParam(HWND hWnd, void *param)\r
8902 {\r
8903         // 引数チェック\r
8904         if (hWnd == NULL)\r
8905         {\r
8906                 return;\r
8907         }\r
8908 \r
8909         SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)param);\r
8910 }\r
8911 \r
8912 // ダイアログボックスのパラメータの取得\r
8913 void *GetParam(HWND hWnd)\r
8914 {\r
8915         void *ret;\r
8916         // 引数チェック\r
8917         if (hWnd == NULL)\r
8918         {\r
8919                 return NULL;\r
8920         }\r
8921 \r
8922         ret = (void *)GetWindowLongPtr(hWnd, DWLP_USER);\r
8923         return ret;\r
8924 }\r
8925 \r
8926 // ウインドウを最前面でなくする\r
8927 void NoTop(HWND hWnd)\r
8928 {\r
8929         // 引数チェック\r
8930         if (hWnd == NULL)\r
8931         {\r
8932                 return;\r
8933         }\r
8934 \r
8935         SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\r
8936 }\r
8937 \r
8938 // ウインドウを最前面に表示する\r
8939 void Top(HWND hWnd)\r
8940 {\r
8941         // 引数チェック\r
8942         if (hWnd == NULL)\r
8943         {\r
8944                 return;\r
8945         }\r
8946 \r
8947         SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\r
8948 }\r
8949 \r
8950 // ウインドウを隠す\r
8951 void Hide(HWND hWnd, UINT id)\r
8952 {\r
8953         // 引数チェック\r
8954         if (hWnd == NULL)\r
8955         {\r
8956                 return;\r
8957         }\r
8958 \r
8959         if (IsShow(hWnd, id))\r
8960         {\r
8961                 ShowWindow(DlgItem(hWnd, id), SW_HIDE);\r
8962         }\r
8963 }\r
8964 \r
8965 // ウインドウを表示する\r
8966 void Show(HWND hWnd, UINT id)\r
8967 {\r
8968         // 引数チェック\r
8969         if (hWnd == NULL)\r
8970         {\r
8971                 return;\r
8972         }\r
8973 \r
8974         if (IsHide(hWnd, id))\r
8975         {\r
8976                 ShowWindow(DlgItem(hWnd, id), SW_SHOW);\r
8977         }\r
8978 }\r
8979 \r
8980 // 表示設定の変更\r
8981 void SetShow(HWND hWnd, UINT id, bool b)\r
8982 {\r
8983         // 引数チェック\r
8984         if (hWnd == NULL)\r
8985         {\r
8986                 return;\r
8987         }\r
8988 \r
8989         if (b)\r
8990         {\r
8991                 Show(hWnd, id);\r
8992         }\r
8993         else\r
8994         {\r
8995                 Hide(hWnd, id);\r
8996         }\r
8997 }\r
8998 \r
8999 // ウインドウが表示されているかどうか取得する\r
9000 bool IsShow(HWND hWnd, UINT id)\r
9001 {\r
9002         return IsHide(hWnd, id) ? false : true;\r
9003 }\r
9004 \r
9005 // ウインドウが隠れているかどうか取得する\r
9006 bool IsHide(HWND hWnd, UINT id)\r
9007 {\r
9008         // 引数チェック\r
9009         if (hWnd == NULL)\r
9010         {\r
9011                 return true;\r
9012         }\r
9013 \r
9014         if (GetStyle(hWnd, id) & WS_VISIBLE)\r
9015         {\r
9016                 return false;\r
9017         }\r
9018         else\r
9019         {\r
9020                 return true;\r
9021         }\r
9022 }\r
9023 \r
9024 // ウインドウスタイルを削除する\r
9025 void RemoveExStyle(HWND hWnd, UINT id, UINT style)\r
9026 {\r
9027         UINT old;\r
9028         // 引数チェック\r
9029         if (hWnd == NULL)\r
9030         {\r
9031                 return;\r
9032         }\r
9033 \r
9034         old = GetExStyle(hWnd, id);\r
9035         if ((old & style) == 0)\r
9036         {\r
9037                 return;\r
9038         }\r
9039 \r
9040         SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old & ~style);\r
9041         Refresh(DlgItem(hWnd, id));\r
9042 }\r
9043 \r
9044 // ウインドウスタイルを設定する\r
9045 void SetExStyle(HWND hWnd, UINT id, UINT style)\r
9046 {\r
9047         UINT old;\r
9048         // 引数チェック\r
9049         if (hWnd == NULL)\r
9050         {\r
9051                 return;\r
9052         }\r
9053 \r
9054         old = GetExStyle(hWnd, id);\r
9055         if (old & style)\r
9056         {\r
9057                 return;\r
9058         }\r
9059 \r
9060         SetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE, old | style);\r
9061         Refresh(DlgItem(hWnd, id));\r
9062 }\r
9063 \r
9064 // ウインドウスタイルを取得する\r
9065 UINT GetExStyle(HWND hWnd, UINT id)\r
9066 {\r
9067         // 引数チェック\r
9068         if (hWnd == NULL)\r
9069         {\r
9070                 return 0;\r
9071         }\r
9072 \r
9073         return GetWindowLong(DlgItem(hWnd, id), GWL_EXSTYLE);\r
9074 }\r
9075 \r
9076 // ウインドウスタイルを削除する\r
9077 void RemoveStyle(HWND hWnd, UINT id, UINT style)\r
9078 {\r
9079         UINT old;\r
9080         // 引数チェック\r
9081         if (hWnd == NULL)\r
9082         {\r
9083                 return;\r
9084         }\r
9085 \r
9086         old = GetStyle(hWnd, id);\r
9087         if ((old & style) == 0)\r
9088         {\r
9089                 return;\r
9090         }\r
9091 \r
9092         SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old & ~style);\r
9093         Refresh(DlgItem(hWnd, id));\r
9094 }\r
9095 \r
9096 // ウインドウスタイルを設定する\r
9097 void SetStyle(HWND hWnd, UINT id, UINT style)\r
9098 {\r
9099         UINT old;\r
9100         // 引数チェック\r
9101         if (hWnd == NULL)\r
9102         {\r
9103                 return;\r
9104         }\r
9105 \r
9106         old = GetStyle(hWnd, id);\r
9107         if (old & style)\r
9108         {\r
9109                 return;\r
9110         }\r
9111 \r
9112         SetWindowLong(DlgItem(hWnd, id), GWL_STYLE, old | style);\r
9113         Refresh(DlgItem(hWnd, id));\r
9114 }\r
9115 \r
9116 // ウインドウスタイルを取得する\r
9117 UINT GetStyle(HWND hWnd, UINT id)\r
9118 {\r
9119         // 引数チェック\r
9120         if (hWnd == NULL)\r
9121         {\r
9122                 return 0;\r
9123         }\r
9124 \r
9125         return GetWindowLong(DlgItem(hWnd, id), GWL_STYLE);\r
9126 }\r
9127 \r
9128 // テキストのバイト数を取得する\r
9129 UINT GetTextSize(HWND hWnd, UINT id, bool unicode)\r
9130 {\r
9131         UINT len;\r
9132         // 引数チェック\r
9133         if (hWnd == NULL)\r
9134         {\r
9135                 return 0;\r
9136         }\r
9137 \r
9138         len = GetTextLen(hWnd, id, unicode);\r
9139 \r
9140         return len + (unicode ? 2 : 1);\r
9141 }\r
9142 \r
9143 // テキストの文字数を取得する\r
9144 UINT GetTextLen(HWND hWnd, UINT id, bool unicode)\r
9145 {\r
9146         wchar_t *s;\r
9147         UINT ret;\r
9148         // 引数チェック\r
9149         if (hWnd == NULL)\r
9150         {\r
9151                 return 0;\r
9152         }\r
9153 \r
9154         s = GetText(hWnd, id);\r
9155         if (s == NULL)\r
9156         {\r
9157                 return 0;\r
9158         }\r
9159 \r
9160         if (unicode)\r
9161         {\r
9162                 ret = UniStrLen(s);\r
9163         }\r
9164         else\r
9165         {\r
9166                 char *tmp = CopyUniToStr(s);\r
9167                 ret = StrLen(tmp);\r
9168                 Free(tmp);\r
9169         }\r
9170 \r
9171         Free(s);\r
9172 \r
9173         return ret;\r
9174 }\r
9175 \r
9176 // テキストが空白かどうかチェックする\r
9177 bool IsEmpty(HWND hWnd, UINT id)\r
9178 {\r
9179         bool ret;\r
9180         wchar_t *s;\r
9181         // 引数チェック\r
9182         if (hWnd == NULL)\r
9183         {\r
9184                 return true;\r
9185         }\r
9186 \r
9187         s = GetText(hWnd, id);\r
9188 \r
9189         UniTrim(s);\r
9190         if (UniStrLen(s) == 0)\r
9191         {\r
9192                 ret = true;\r
9193         }\r
9194         else\r
9195         {\r
9196                 ret = false;\r
9197         }\r
9198 \r
9199         Free(s);\r
9200 \r
9201         return ret;\r
9202 }\r
9203 \r
9204 // ウインドウクラスを取得する\r
9205 wchar_t *GetClass(HWND hWnd, UINT id)\r
9206 {\r
9207         wchar_t tmp[MAX_SIZE];\r
9208 \r
9209         if (MsIsNt() == false)\r
9210         {\r
9211                 wchar_t *ret;\r
9212                 char *s;\r
9213                 s = GetClassA(hWnd, id);\r
9214                 ret = CopyStrToUni(s);\r
9215                 Free(s);\r
9216                 return ret;\r
9217         }\r
9218 \r
9219         // 引数チェック\r
9220         if (hWnd == NULL)\r
9221         {\r
9222                 return CopyUniStr(L"");\r
9223         }\r
9224 \r
9225         GetClassNameW(DlgItem(hWnd, id), tmp, sizeof(tmp));\r
9226 \r
9227         return UniCopyStr(tmp);\r
9228 }\r
9229 char *GetClassA(HWND hWnd, UINT id)\r
9230 {\r
9231         char tmp[MAX_SIZE];\r
9232         // 引数チェック\r
9233         if (hWnd == NULL)\r
9234         {\r
9235                 return CopyStr("");\r
9236         }\r
9237 \r
9238         GetClassName(DlgItem(hWnd, id), tmp, sizeof(tmp));\r
9239 \r
9240         return CopyStr(tmp);\r
9241 }\r
9242 \r
9243 // コントロールにメッセージを送信する\r
9244 UINT SendMsg(HWND hWnd, UINT id, UINT msg, WPARAM wParam, LPARAM lParam)\r
9245 {\r
9246         // 引数チェック\r
9247         if (hWnd == NULL)\r
9248         {\r
9249                 return 0;\r
9250         }\r
9251 \r
9252         if (MsIsNt())\r
9253         {\r
9254                 return (UINT)SendMessageW(DlgItem(hWnd, id), msg, wParam, lParam);\r
9255         }\r
9256         else\r
9257         {\r
9258                 return (UINT)SendMessageA(DlgItem(hWnd, id), msg, wParam, lParam);\r
9259         }\r
9260 }\r
9261 \r
9262 // EDIT のテキストをすべて選択する\r
9263 void SelectEdit(HWND hWnd, UINT id)\r
9264 {\r
9265         wchar_t *class_name;\r
9266 \r
9267         // 引数チェック\r
9268         if (hWnd == NULL)\r
9269         {\r
9270                 return;\r
9271         }\r
9272 \r
9273         class_name = GetClass(hWnd, id);\r
9274 \r
9275         if (class_name != NULL)\r
9276         {\r
9277                 if (UniStrCmpi(class_name, L"edit") == 0)\r
9278                 {\r
9279                         SendMsg(hWnd, id, EM_SETSEL, 0, -1);\r
9280                 }\r
9281                 Free(class_name);\r
9282         }\r
9283 }\r
9284 \r
9285 // EDIT のテキストの選択を解除する\r
9286 void UnselectEdit(HWND hWnd, UINT id)\r
9287 {\r
9288         wchar_t *class_name;\r
9289 \r
9290         // 引数チェック\r
9291         if (hWnd == NULL)\r
9292         {\r
9293                 return;\r
9294         }\r
9295 \r
9296         class_name = GetClass(hWnd, id);\r
9297 \r
9298         if (class_name != NULL)\r
9299         {\r
9300                 if (UniStrCmpi(class_name, L"edit") == 0)\r
9301                 {\r
9302                         SendMsg(hWnd, id, EM_SETSEL, -1, 0);\r
9303                 }\r
9304                 Free(class_name);\r
9305         }\r
9306 }\r
9307 \r
9308 // EDIT にフォーカスを設定してすべて選択する\r
9309 void FocusEx(HWND hWnd, UINT id)\r
9310 {\r
9311         // 引数チェック\r
9312         if (hWnd == NULL)\r
9313         {\r
9314                 return;\r
9315         }\r
9316 \r
9317         if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)\r
9318         {\r
9319                 return;\r
9320         }\r
9321 \r
9322         SelectEdit(hWnd, id);\r
9323 \r
9324         Focus(hWnd, id);\r
9325 }\r
9326 \r
9327 // 指定したウインドウがフォーカスを持っているかどうか取得する\r
9328 bool IsFocus(HWND hWnd, UINT id)\r
9329 {\r
9330         // 引数チェック\r
9331         if (hWnd == NULL)\r
9332         {\r
9333                 return false;\r
9334         }\r
9335 \r
9336         if (GetFocus() == DlgItem(hWnd, id))\r
9337         {\r
9338                 return true;\r
9339         }\r
9340 \r
9341         return false;\r
9342 }\r
9343 \r
9344 // フォーカスを設定する\r
9345 void Focus(HWND hWnd, UINT id)\r
9346 {\r
9347         // 引数チェック\r
9348         if (hWnd == NULL)\r
9349         {\r
9350                 return;\r
9351         }\r
9352 \r
9353         if (IsEnable(hWnd, id) == false || IsShow(hWnd, id) == false)\r
9354         {\r
9355                 return;\r
9356         }\r
9357 \r
9358         SetFocus(DlgItem(hWnd, id));\r
9359 }\r
9360 \r
9361 // int 型の値を設定する\r
9362 void SetInt(HWND hWnd, UINT id, UINT value)\r
9363 {\r
9364         wchar_t tmp[MAX_SIZE];\r
9365         // 引数チェック\r
9366         if (hWnd == NULL)\r
9367         {\r
9368                 return;\r
9369         }\r
9370 \r
9371         UniToStru(tmp, value);\r
9372         SetText(hWnd, id, tmp);\r
9373 }\r
9374 void SetIntEx(HWND hWnd, UINT id, UINT value)\r
9375 {\r
9376         // 引数チェック\r
9377         if (hWnd == NULL)\r
9378         {\r
9379                 return;\r
9380         }\r
9381 \r
9382         if (value == 0)\r
9383         {\r
9384                 // 0 の場合は空欄にする\r
9385                 SetText(hWnd, id, L"");\r
9386         }\r
9387         else\r
9388         {\r
9389                 SetInt(hWnd, id, value);\r
9390         }\r
9391 }\r
9392 \r
9393 // int 型の値を取得する\r
9394 UINT GetInt(HWND hWnd, UINT id)\r
9395 {\r
9396         wchar_t *s;\r
9397         UINT ret;\r
9398         // 引数チェック\r
9399         if (hWnd == NULL)\r
9400         {\r
9401                 return 0;\r
9402         }\r
9403 \r
9404         s = GetText(hWnd, id);\r
9405         if (s == NULL)\r
9406         {\r
9407                 return 0;\r
9408         }\r
9409 \r
9410         ret = UniToInt(s);\r
9411         Free(s);\r
9412 \r
9413         return ret;\r
9414 }\r
9415 \r
9416 // ウインドウ表示を更新する\r
9417 void Refresh(HWND hWnd)\r
9418 {\r
9419         HWND parent;\r
9420         // 引数チェック\r
9421         if (hWnd == NULL)\r
9422         {\r
9423                 return;\r
9424         }\r
9425 \r
9426         DoEvents(hWnd);\r
9427         UpdateWindow(hWnd);\r
9428         DoEvents(hWnd);\r
9429 \r
9430         parent = GetParent(hWnd);\r
9431         if (parent != NULL)\r
9432         {\r
9433                 Refresh(parent);\r
9434         }\r
9435 }\r
9436 \r
9437 // イベントを処理する\r
9438 void DoEvents(HWND hWnd)\r
9439 {\r
9440         MSG msg;\r
9441 \r
9442         if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))\r
9443         {\r
9444                 TranslateMessage(&msg);\r
9445                 DispatchMessage(&msg);\r
9446         }\r
9447         UpdateWindow(hWnd);\r
9448 \r
9449         if (hWnd)\r
9450         {\r
9451                 DoEvents(NULL);\r
9452         }\r
9453 }\r
9454 \r
9455 // ウインドウを閉じる\r
9456 void Close(HWND hWnd)\r
9457 {\r
9458         // 引数チェック\r
9459         if (hWnd == NULL)\r
9460         {\r
9461                 return;\r
9462         }\r
9463 \r
9464         SendMessage(hWnd, WM_CLOSE, 0, 0);\r
9465 }\r
9466 \r
9467 // ウインドウを無効にする\r
9468 void Disable(HWND hWnd, UINT id)\r
9469 {\r
9470         SetEnable(hWnd, id, false);\r
9471 }\r
9472 \r
9473 // ウインドウを有効にする\r
9474 void Enable(HWND hWnd, UINT id)\r
9475 {\r
9476         SetEnable(hWnd, id, true);\r
9477 }\r
9478 \r
9479 // ウインドウの有効状態を設定する\r
9480 void SetEnable(HWND hWnd, UINT id, bool b)\r
9481 {\r
9482         // 引数チェック\r
9483         if (hWnd == NULL)\r
9484         {\r
9485                 return;\r
9486         }\r
9487 \r
9488         if (b == false)\r
9489         {\r
9490                 if (IsEnable(hWnd, id))\r
9491                 {\r
9492                         if (id != 0 && IsFocus(hWnd, id))\r
9493                         {\r
9494                                 Focus(hWnd, IDCANCEL);\r
9495                                 Focus(hWnd, IDOK);\r
9496                         }\r
9497                         EnableWindow(DlgItem(hWnd, id), false);\r
9498                         Refresh(DlgItem(hWnd, id));\r
9499                 }\r
9500         }\r
9501         else\r
9502         {\r
9503                 if (IsDisable(hWnd, id))\r
9504                 {\r
9505                         EnableWindow(DlgItem(hWnd, id), true);\r
9506                         Refresh(DlgItem(hWnd, id));\r
9507                 }\r
9508         }\r
9509 }\r
9510 \r
9511 // ウインドウが無効かどうか調べる\r
9512 bool IsDisable(HWND hWnd, UINT id)\r
9513 {\r
9514         return IsEnable(hWnd, id) ? false : true;\r
9515 }\r
9516 \r
9517 // ウインドウが有効かどうか調べる\r
9518 bool IsEnable(HWND hWnd, UINT id)\r
9519 {\r
9520         // 引数チェック\r
9521         if (hWnd == NULL)\r
9522         {\r
9523                 return false;\r
9524         }\r
9525 \r
9526         return IsWindowEnabled(DlgItem(hWnd, id));\r
9527 }\r
9528 \r
9529 static LOCK *winui_debug_lock = NULL;\r
9530 \r
9531 // デバッグの初期化\r
9532 void WinUiDebugInit()\r
9533 {\r
9534         winui_debug_lock = NewLock();\r
9535 }\r
9536 \r
9537 // デバッグの解放\r
9538 void WinUiDebugFree()\r
9539 {\r
9540         DeleteLock(winui_debug_lock);\r
9541 }\r
9542 \r
9543 // デバッグファイルに文字列を書き込む\r
9544 void WinUiDebug(wchar_t *str)\r
9545 {\r
9546         wchar_t tmp[1024];\r
9547         char dtstr[256];\r
9548         char *buf;\r
9549         wchar_t exename[MAX_PATH];\r
9550         UINT tid;\r
9551         // 引数チェック\r
9552         if (str == NULL)\r
9553         {\r
9554                 return;\r
9555         }\r
9556 \r
9557         tid = GetCurrentThreadId();\r
9558 \r
9559         GetExeNameW(exename, sizeof(exename));\r
9560         GetFileNameFromFilePathW(exename, sizeof(exename), exename);\r
9561 \r
9562         GetDateTimeStrMilli64(dtstr, sizeof(dtstr), LocalTime64());\r
9563 \r
9564         UniFormat(tmp, sizeof(tmp), L"[%S] (%s:%u) %s\r\n", dtstr, exename, tid, str);\r
9565 \r
9566         buf = CopyUniToUtf(tmp);\r
9567 \r
9568         Lock(winui_debug_lock);\r
9569         {\r
9570                 IO *o = FileOpenEx(WINUI_DEBUG_TEXT, true, true);\r
9571                 if (o == NULL)\r
9572                 {\r
9573                         o = FileCreate(WINUI_DEBUG_TEXT);\r
9574                 }\r
9575 \r
9576                 if (o != NULL)\r
9577                 {\r
9578                         UINT size = FileSize(o);\r
9579 \r
9580                         FileSeek(o, FILE_BEGIN, size);\r
9581 \r
9582                         FileWrite(o, buf, StrLen(buf));\r
9583                         FileFlush(o);\r
9584 \r
9585                         FileClose(o);\r
9586                 }\r
9587         }\r
9588         Unlock(winui_debug_lock);\r
9589 \r
9590         Free(buf);\r
9591 }\r
9592 \r
9593 \r
9594 // テキスト文字列の設定\r
9595 void SetText(HWND hWnd, UINT id, wchar_t *str)\r
9596 {\r
9597         // 引数チェック\r
9598         if (hWnd == NULL || str == NULL)\r
9599         {\r
9600                 return;\r
9601         }\r
9602 \r
9603         SetTextInner(hWnd, id, str);\r
9604 }\r
9605 void SetTextInner(HWND hWnd, UINT id, wchar_t *str)\r
9606 {\r
9607         wchar_t *old;\r
9608         // 引数チェック\r
9609         if (hWnd == NULL || str == NULL)\r
9610         {\r
9611                 return;\r
9612         }\r
9613 \r
9614         // 古い文字列を取得\r
9615         old = GetText(hWnd, id);\r
9616         if (UniStrCmp(str, old) == 0)\r
9617         {\r
9618                 // 同一\r
9619                 Free(old);\r
9620                 return;\r
9621         }\r
9622 \r
9623         Free(old);\r
9624 \r
9625         if (MsIsNt())\r
9626         {\r
9627                 SetWindowTextW(DlgItem(hWnd, id), str);\r
9628         }\r
9629         else\r
9630         {\r
9631                 char *tmp = CopyUniToStr(str);\r
9632 \r
9633                 if (MsIsNt() == false && StrLen(tmp) >= 32000)\r
9634                 {\r
9635                         // 32k 以下にきりつめる\r
9636                         tmp[32000] = 0;\r
9637                 }\r
9638 \r
9639                 SetWindowTextA(DlgItem(hWnd, id), tmp);\r
9640                 Free(tmp);\r
9641         }\r
9642 \r
9643         if (id != 0)\r
9644         {\r
9645                 Refresh(DlgItem(hWnd, id));\r
9646         }\r
9647 }\r
9648 void SetTextA(HWND hWnd, UINT id, char *str)\r
9649 {\r
9650         wchar_t *s;\r
9651         // 引数チェック\r
9652         if (hWnd == NULL || str == NULL)\r
9653         {\r
9654                 return;\r
9655         }\r
9656 \r
9657         s = CopyStrToUni(str);\r
9658         if (s == NULL)\r
9659         {\r
9660                 return;\r
9661         }\r
9662 \r
9663         SetText(hWnd, id, s);\r
9664 \r
9665         Free(s);\r
9666 }\r
9667 \r
9668 // テキスト文字列をバッファへ取得\r
9669 bool GetTxt(HWND hWnd, UINT id, wchar_t *str, UINT size)\r
9670 {\r
9671         wchar_t *s;\r
9672         // 引数チェック\r
9673         if (hWnd == NULL || str == NULL)\r
9674         {\r
9675                 return false;\r
9676         }\r
9677 \r
9678         s = GetText(hWnd, id);\r
9679         if (s == NULL)\r
9680         {\r
9681                 UniStrCpy(str, size, L"");\r
9682                 return false;\r
9683         }\r
9684 \r
9685         UniStrCpy(str, size, s);\r
9686         Free(s);\r
9687 \r
9688         return true;\r
9689 }\r
9690 bool GetTxtA(HWND hWnd, UINT id, char *str, UINT size)\r
9691 {\r
9692         char *s;\r
9693         // 引数チェック\r
9694         if (hWnd == NULL || str == NULL)\r
9695         {\r
9696                 return false;\r
9697         }\r
9698 \r
9699         s = GetTextA(hWnd, id);\r
9700         if (s == NULL)\r
9701         {\r
9702                 StrCpy(str, size, "");\r
9703                 return false;\r
9704         }\r
9705 \r
9706         StrCpy(str, size, s);\r
9707         Free(s);\r
9708 \r
9709         return true;\r
9710 }\r
9711 \r
9712 // テキスト文字列の取得\r
9713 wchar_t *GetText(HWND hWnd, UINT id)\r
9714 {\r
9715         wchar_t *ret;\r
9716         UINT size, len;\r
9717         // 引数チェック\r
9718         if (hWnd == NULL)\r
9719         {\r
9720                 return NULL;\r
9721         }\r
9722 \r
9723         if (MsIsNt() == false)\r
9724         {\r
9725                 char *s = GetTextA(hWnd, id);\r
9726                 ret = CopyStrToUni(s);\r
9727                 Free(s);\r
9728 \r
9729                 return ret;\r
9730         }\r
9731 \r
9732         len = GetWindowTextLengthW(DlgItem(hWnd, id));\r
9733         if (len == 0)\r
9734         {\r
9735                 return CopyUniStr(L"");\r
9736         }\r
9737 \r
9738         size = (len + 1) * 2;\r
9739         ret = ZeroMallocEx(size, true);\r
9740 \r
9741         GetWindowTextW(DlgItem(hWnd, id), ret, size);\r
9742 \r
9743         return ret;\r
9744 }\r
9745 char *GetTextA(HWND hWnd, UINT id)\r
9746 {\r
9747         char *ret;\r
9748         UINT size, len;\r
9749         // 引数チェック\r
9750         if (hWnd == NULL)\r
9751         {\r
9752                 return NULL;\r
9753         }\r
9754 \r
9755         len = GetWindowTextLengthA(DlgItem(hWnd, id));\r
9756         if (len == 0)\r
9757         {\r
9758                 return CopyStr("");\r
9759         }\r
9760 \r
9761         size = len + 1;\r
9762         ret = ZeroMallocEx(size, true);\r
9763 \r
9764         GetWindowTextA(DlgItem(hWnd, id), ret, size);\r
9765 \r
9766         return ret;\r
9767 }\r
9768 \r
9769 // ダイアログ内のアイテムの取得\r
9770 HWND DlgItem(HWND hWnd, UINT id)\r
9771 {\r
9772         // 引数チェック\r
9773         if (hWnd == NULL)\r
9774         {\r
9775                 return NULL;\r
9776         }\r
9777 \r
9778         if (id == 0)\r
9779         {\r
9780                 return hWnd;\r
9781         }\r
9782         else\r
9783         {\r
9784                 return GetDlgItem(hWnd, id);\r
9785         }\r
9786 }\r
9787 \r
9788 // タイトルの設定\r
9789 void SetWinUiTitle(wchar_t *title)\r
9790 {\r
9791         // 引数チェック\r
9792         if (title == NULL)\r
9793         {\r
9794                 return;\r
9795         }\r
9796 \r
9797         Free(title_bar);\r
9798         title_bar = CopyUniStr(title);\r
9799 }\r
9800 \r
9801 // WinUi の初期化\r
9802 void InitWinUi(wchar_t *software_name, char *font, UINT fontsize)\r
9803 {\r
9804         if ((init_winui_counter++) != 0)\r
9805         {\r
9806                 return;\r
9807         }\r
9808 \r
9809         if (hDll != NULL)\r
9810         {\r
9811                 return;\r
9812         }\r
9813 \r
9814         WinUiDebugInit();\r
9815 \r
9816         if (MayaquaIsMinimalMode() == false)\r
9817         {\r
9818                 if (Is64())\r
9819                 {\r
9820                         hDll = MsLoadLibraryAsDataFile(MsGetPenCoreDllFileName());\r
9821                 }\r
9822                 else\r
9823                 {\r
9824                         hDll = MsLoadLibrary(MsGetPenCoreDllFileName());\r
9825                 }\r
9826 \r
9827                 if (hDll == NULL)\r
9828                 {\r
9829                         Alert(PENCORE_DLL_NAME " not found. SoftEther UT-VPN couldn't start.\r\n\r\n"\r
9830                                 "Please reinstall all files with SoftEther UT-VPN Installer.",\r
9831                                 NULL);\r
9832                         exit(0);\r
9833                 }\r
9834         }\r
9835         else\r
9836         {\r
9837                 hDll = LoadLibrary(MsGetExeFileName());\r
9838 \r
9839                 if (hDll == NULL)\r
9840                 {\r
9841                         Alert("MsLoadLibrary() Error.",\r
9842                                 NULL);\r
9843                         exit(0);\r
9844                 }\r
9845         }\r
9846 \r
9847         if (software_name != NULL)\r
9848         {\r
9849                 title_bar = CopyUniStr(software_name);\r
9850         }\r
9851         else\r
9852         {\r
9853                 title_bar = CopyUniStr(L"SoftEther UT-VPN");\r
9854         }\r
9855 \r
9856         if (font != NULL)\r
9857         {\r
9858                 font_name = CopyStr(font);\r
9859         }\r
9860         else\r
9861         {\r
9862                 font_name = CopyStr(_SS("DEFAULT_FONT"));\r
9863         }\r
9864 \r
9865         if (fontsize != 0)\r
9866         {\r
9867                 font_size = fontsize;\r
9868         }\r
9869         else\r
9870         {\r
9871                 font_size = _II("DEFAULT_FONT_SIZE");\r
9872                 if (font_size == 0)\r
9873                 {\r
9874                         font_size = 9;\r
9875                 }\r
9876         }\r
9877 \r
9878         InitIconCache();\r
9879 \r
9880         InitFont();\r
9881 \r
9882         InitImageList();\r
9883 \r
9884         InitGdiCache();\r
9885 \r
9886         EnableNewStyleMode();\r
9887 }\r
9888 \r
9889 // WinUi の解放\r
9890 void FreeWinUi()\r
9891 {\r
9892         if ((--init_winui_counter) != 0)\r
9893         {\r
9894                 return;\r
9895         }\r
9896 \r
9897         if (hDll == NULL)\r
9898         {\r
9899                 return;\r
9900         }\r
9901 \r
9902         FreeImageList();\r
9903 \r
9904         FreeFont();\r
9905 \r
9906         FreeIconCache();\r
9907 \r
9908         FreeLibrary(hDll);\r
9909         hDll = NULL;\r
9910 \r
9911         Free(title_bar);\r
9912         title_bar = NULL;\r
9913 \r
9914         Free(font_name);\r
9915         font_name = NULL;\r
9916 \r
9917         WinUiDebugFree();\r
9918 }\r
9919 \r
9920 #endif  // WIN32\r