1 // FontSub by Katayama Hirofumi MZ
3 // To the extent possible under law, the person who associated CC0 with
4 // FontSub has waived all copyright and related or neighboring rights
7 // You should have received a copy of the CC0 legalcode along with this
8 // work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
15 #include <vector> // for std::vector
16 #include <set> // for std::set
17 #include <string> // for std::basic_string
18 #include <algorithm> // for std::sort
25 #define NAME_COLUMN_WIDTH 250
26 #define SUB_COLUMN_WIDTH 250
27 #define MAX_STRING 120
30 #define _countof(array) (sizeof(array) / sizeof(array[0]))
33 typedef std::wstring STRING
;
37 STRING m_Name
, m_Substitute
;
38 BYTE m_CharSet1
, m_CharSet2
;
39 ITEM(const STRING
& Name
, const STRING
& Substitute
,
40 BYTE CharSet1
, BYTE CharSet2
)
41 : m_Name(Name
), m_Substitute(Substitute
),
42 m_CharSet1(CharSet1
), m_CharSet2(CharSet2
) { }
45 /* global variables */
46 HINSTANCE g_hInstance
= NULL
;
47 HWND g_hMainWnd
= NULL
;
49 HWND g_hListView
= NULL
;
50 BOOL g_bModified
= FALSE
;
51 BOOL g_bNeedsReboot
= FALSE
;
54 LPCWSTR g_pszClassName
= L
"ReactOS Font Substitutes Editor";
55 LPCWSTR g_pszFileHeader
= L
"Windows Registry Editor Version 5.00";
57 WCHAR g_szTitle
[MAX_STRING
];
58 WCHAR g_szNameHead
[MAX_STRING
];
59 WCHAR g_szSubstituteHead
[MAX_STRING
];
61 INT g_iSortColumn
= 0;
62 BOOL g_bSortAscendant
= TRUE
;
65 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
67 typedef std::set
<STRING
> FONTNAMESET
;
68 typedef std::vector
<ITEM
> ITEMVECTOR
;
73 STRING g_strSubstitute
;
74 BYTE g_CharSet1
= DEFAULT_CHARSET
;
75 BYTE g_CharSet2
= DEFAULT_CHARSET
;
77 typedef struct CHARSET_ENTRY
83 CHARSET_ENTRY g_CharSetList
[] =
85 { DEFAULT_CHARSET
, L
"DEFAULT_CHARSET (1)" },
86 { ANSI_CHARSET
, L
"ANSI_CHARSET (0)" },
87 { SYMBOL_CHARSET
, L
"SYMBOL_CHARSET (2)" },
88 { SHIFTJIS_CHARSET
, L
"SHIFTJIS_CHARSET (128)" },
89 { HANGUL_CHARSET
, L
"HANGUL_CHARSET (129)" },
90 { GB2312_CHARSET
, L
"GB2312_CHARSET (134)" },
91 { CHINESEBIG5_CHARSET
, L
"CHINESEBIG5_CHARSET (136)" },
92 { OEM_CHARSET
, L
"OEM_CHARSET (255)" },
93 { JOHAB_CHARSET
, L
"JOHAB_CHARSET (130)" },
94 { HEBREW_CHARSET
, L
"HEBREW_CHARSET (177)" },
95 { ARABIC_CHARSET
, L
"ARABIC_CHARSET (178)" },
96 { GREEK_CHARSET
, L
"GREEK_CHARSET (161)" },
97 { TURKISH_CHARSET
, L
"TURKISH_CHARSET (162)" },
98 { VIETNAMESE_CHARSET
, L
"VIETNAMESE_CHARSET (163)" },
99 { THAI_CHARSET
, L
"THAI_CHARSET (222)" },
100 { EASTEUROPE_CHARSET
, L
"EASTEUROPE_CHARSET (238)" },
101 { RUSSIAN_CHARSET
, L
"RUSSIAN_CHARSET (204)" },
102 { MAC_CHARSET
, L
"MAC_CHARSET (77)" },
103 { BALTIC_CHARSET
, L
"BALTIC_CHARSET (186)" }
105 const WCHAR g_LongestName
[] = L
"CHINESEBIG5_CHARSET (136)";
107 static void trim(STRING
& str
)
109 static const WCHAR Spaces
[] = L
" \t\r\n";
110 size_t i
= str
.find_first_not_of(Spaces
);
111 size_t j
= str
.find_last_not_of(Spaces
);
112 if (i
== STRING::npos
|| j
== STRING::npos
)
118 str
= str
.substr(i
, j
- i
+ 1);
123 EnumFontFamExProc(const ENUMLOGFONTW
*pelf
,
124 const NEWTEXTMETRICW
*pntm
,
128 switch (pelf
->elfFullName
[0])
130 case UNICODE_NULL
: case L
'@':
133 g_Names
.insert((const WCHAR
*)pelf
->elfFullName
);
135 switch (pelf
->elfLogFont
.lfFaceName
[0])
137 case UNICODE_NULL
: case L
'@':
140 g_Names
.insert(pelf
->elfLogFont
.lfFaceName
);
145 BOOL
DoLoadNames(void)
150 ZeroMemory(&lf
, sizeof(lf
));
151 lf
.lfCharSet
= DEFAULT_CHARSET
;
153 HDC hDC
= CreateCompatibleDC(NULL
);
154 EnumFontFamiliesExW(hDC
, &lf
, (FONTENUMPROCW
)EnumFontFamExProc
, 0, 0);
157 return !g_Names
.empty();
160 inline bool ItemCompareByNameAscend(const ITEM
& Item1
, const ITEM
& Item2
)
162 return Item1
.m_Name
< Item2
.m_Name
;
165 inline bool ItemCompareByNameDescend(const ITEM
& Item1
, const ITEM
& Item2
)
167 return Item1
.m_Name
> Item2
.m_Name
;
170 inline bool ItemCompareBySubAscend(const ITEM
& Item1
, const ITEM
& Item2
)
172 return Item1
.m_Substitute
< Item2
.m_Substitute
;
175 inline bool ItemCompareBySubDescend(const ITEM
& Item1
, const ITEM
& Item2
)
177 return Item1
.m_Substitute
> Item2
.m_Substitute
;
180 void DoSort(INT iColumn
, BOOL bAscendant
= TRUE
)
183 ZeroMemory(&Column
, sizeof(Column
));
184 Column
.mask
= LVCF_IMAGE
| LVCF_SUBITEM
;
187 ListView_SetColumn(g_hListView
, 0, &Column
);
189 ListView_SetColumn(g_hListView
, 1, &Column
);
197 std::sort(g_Items
.begin(), g_Items
.end(),
198 ItemCompareByNameAscend
);
200 ListView_SetColumn(g_hListView
, 0, &Column
);
204 std::sort(g_Items
.begin(), g_Items
.end(),
205 ItemCompareByNameDescend
);
207 ListView_SetColumn(g_hListView
, 0, &Column
);
214 std::sort(g_Items
.begin(), g_Items
.end(),
215 ItemCompareBySubAscend
);
217 ListView_SetColumn(g_hListView
, 1, &Column
);
221 std::sort(g_Items
.begin(), g_Items
.end(),
222 ItemCompareBySubDescend
);
224 ListView_SetColumn(g_hListView
, 1, &Column
);
228 g_iSortColumn
= iColumn
;
229 g_bSortAscendant
= bAscendant
;
230 InvalidateRect(g_hListView
, NULL
, TRUE
);
233 void LV_AddItems(HWND hwnd
)
235 ListView_DeleteAllItems(hwnd
);
238 ZeroMemory(&Item
, sizeof(Item
));
239 Item
.mask
= LVIF_PARAM
;
241 const INT Count
= INT(g_Items
.size());
242 for (INT i
= 0; i
< Count
; ++i
)
247 ListView_InsertItem(hwnd
, &Item
);
252 ListView_InsertItem(hwnd
, &Item
);
256 BOOL
DoLoadItems(void)
261 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, g_pszKey
, 0, KEY_READ
, &hKey
);
265 WCHAR szName
[MAX_STRING
], szValue
[MAX_STRING
];
266 DWORD cbName
, cbValue
;
267 for (DWORD dwIndex
= 0; ; ++dwIndex
)
269 cbName
= sizeof(szName
);
270 cbValue
= sizeof(szValue
);
271 LONG Error
= RegEnumValueW(hKey
, dwIndex
, szName
, &cbName
,
272 NULL
, NULL
, (LPBYTE
)szValue
, &cbValue
);
273 if (Error
!= ERROR_SUCCESS
)
276 BYTE CharSet1
= DEFAULT_CHARSET
, CharSet2
= DEFAULT_CHARSET
;
279 pch
= wcsrchr(szName
, L
',');
283 CharSet1
= (BYTE
)_wtoi(pch
+ 1);
286 pch
= wcsrchr(szValue
, L
',');
290 CharSet2
= (BYTE
)_wtoi(pch
+ 1);
293 ITEM
Item(szName
, szValue
, CharSet1
, CharSet2
);
295 trim(Item
.m_Substitute
);
296 Items
.push_back(Item
);
302 LV_AddItems(g_hListView
);
305 g_bNeedsReboot
= FALSE
;
307 return !g_Items
.empty();
312 return DoLoadNames() && DoLoadItems();
315 void LV_InvalidateRow(HWND hwnd
, INT iRow
= -1)
318 iRow
= ListView_GetNextItem(hwnd
, -1, LVNI_SELECTED
);
323 LPRECT GccIsWhining
= &Rect
;
324 ListView_GetItemRect(hwnd
, iRow
, GccIsWhining
, LVIR_BOUNDS
);
325 InvalidateRect(hwnd
, &Rect
, FALSE
);
328 BOOL
LV_Init(HWND hwnd
)
330 ListView_SetExtendedListViewStyle(hwnd
,
331 LVS_EX_FULLROWSELECT
| LVS_EX_GRIDLINES
);
333 HIMAGELIST hImageList
;
334 hImageList
= ImageList_Create(12, 12, ILC_COLOR8
| ILC_MASK
, 2, 2);
337 hbm
= (HBITMAP
)LoadImage(g_hInstance
, MAKEINTRESOURCE(2), IMAGE_BITMAP
,
338 12, 12, LR_CREATEDIBSECTION
| LR_LOADMAP3DCOLORS
);
340 ImageList_AddMasked(hImageList
, hbm
, RGB(192, 192, 192));
343 hbm
= (HBITMAP
)LoadImage(g_hInstance
, MAKEINTRESOURCE(3), IMAGE_BITMAP
,
344 12, 12, LR_CREATEDIBSECTION
| LR_LOADMAP3DCOLORS
);
346 ImageList_AddMasked(hImageList
, hbm
, RGB(192, 192, 192));
349 hbm
= (HBITMAP
)LoadImage(g_hInstance
, MAKEINTRESOURCE(4), IMAGE_BITMAP
,
350 12, 12, LR_CREATEDIBSECTION
| LR_LOADMAP3DCOLORS
);
352 ImageList_AddMasked(hImageList
, hbm
, RGB(192, 192, 192));
355 ListView_SetImageList(hwnd
, hImageList
, LVSIL_SMALL
);
358 ZeroMemory(&Column
, sizeof(Column
));
359 Column
.mask
= LVCF_FMT
| LVCF_TEXT
| LVCF_SUBITEM
| LVCF_WIDTH
| LVCF_IMAGE
;
360 Column
.fmt
= LVCFMT_LEFT
;
362 Column
.cx
= NAME_COLUMN_WIDTH
;
363 Column
.pszText
= g_szNameHead
;
366 ListView_InsertColumn(hwnd
, 0, &Column
);
368 Column
.cx
= SUB_COLUMN_WIDTH
;
369 Column
.pszText
= g_szSubstituteHead
;
372 ListView_InsertColumn(hwnd
, 1, &Column
);
374 UINT State
= LVIS_SELECTED
| LVIS_FOCUSED
;
375 ListView_SetItemState(hwnd
, 0, State
, State
);
380 BOOL
EditDlg_OnInitDialog(HWND hwnd
, HWND hwndFocus
, LPARAM lParam
)
382 COMBOBOXEXITEMW Item
;
383 ZeroMemory(&Item
, sizeof(Item
));
384 Item
.mask
= CBEIF_TEXT
;
386 FONTNAMESET::iterator it
, end
= g_Names
.end();
387 for (it
= g_Names
.begin(); it
!= end
; ++it
)
389 Item
.pszText
= const_cast<LPWSTR
>(it
->c_str());
390 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb2
));
391 SendDlgItemMessageW(hwnd
, cmb2
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
393 SetDlgItemTextW(hwnd
, edt1
, g_strFontName
.c_str());
394 SetDlgItemTextW(hwnd
, cmb2
, g_strSubstitute
.c_str());
396 const INT Count
= _countof(g_CharSetList
);
397 for (INT i
= 0; i
< Count
; ++i
)
399 Item
.pszText
= const_cast<LPWSTR
>(g_CharSetList
[i
].DisplayName
);
400 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb3
));
401 SendDlgItemMessageW(hwnd
, cmb3
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
402 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb4
));
403 SendDlgItemMessageW(hwnd
, cmb4
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
406 SendDlgItemMessageW(hwnd
, cmb3
, CB_SETCURSEL
, 0, 0);
407 SendDlgItemMessageW(hwnd
, cmb4
, CB_SETCURSEL
, 0, 0);
408 for (INT i
= 0; i
< Count
; ++i
)
410 if (g_CharSet1
== g_CharSetList
[i
].CharSet
)
412 SendDlgItemMessageW(hwnd
, cmb3
, CB_SETCURSEL
, i
, 0);
414 if (g_CharSet2
== g_CharSetList
[i
].CharSet
)
416 SendDlgItemMessageW(hwnd
, cmb4
, CB_SETCURSEL
, i
, 0);
421 HDC hDC
= CreateCompatibleDC(NULL
);
422 SelectObject(hDC
, GetStockObject(DEFAULT_GUI_FONT
));
423 GetTextExtentPoint32W(hDC
, g_LongestName
, lstrlenW(g_LongestName
), &siz
);
426 SendDlgItemMessageW(hwnd
, cmb3
, CB_SETHORIZONTALEXTENT
, siz
.cx
+ 16, 0);
427 SendDlgItemMessageW(hwnd
, cmb4
, CB_SETHORIZONTALEXTENT
, siz
.cx
+ 16, 0);
429 EnableWindow(GetDlgItem(hwnd
, cmb3
), FALSE
);
434 void LV_OnDelete(HWND hwnd
, INT iRow
= -1)
437 iRow
= ListView_GetNextItem(hwnd
, -1, LVNI_SELECTED
);
441 UINT State
= LVIS_SELECTED
| LVIS_FOCUSED
;
442 ListView_SetItemState(g_hListView
, iRow
, State
, State
);
444 WCHAR sz
[MAX_STRING
];
445 LoadStringW(g_hInstance
, IDS_QUERYDELETE
, sz
, _countof(sz
));
446 if (IDYES
!= MessageBoxW(g_hMainWnd
, sz
, g_szTitle
,
447 MB_ICONINFORMATION
| MB_YESNO
))
452 ListView_DeleteItem(hwnd
, iRow
);
453 g_Items
.erase(g_Items
.begin() + iRow
);
456 ListView_SetItemState(g_hListView
, iRow
, State
, State
);
458 InvalidateRect(hwnd
, NULL
, TRUE
);
461 void EditDlg_OnCommand(HWND hwnd
, int id
, HWND hwndCtl
, UINT codeNotify
)
463 WCHAR szValue
[MAX_STRING
];
470 GetDlgItemTextW(hwnd
, cmb2
, szValue
, _countof(szValue
));
475 WCHAR sz
[MAX_STRING
];
476 SendDlgItemMessageW(hwnd
, cmb2
, CB_SETEDITSEL
, 0, MAKELPARAM(0, -1));
477 SetFocus(GetDlgItem(hwnd
, cmb2
));
478 LoadStringW(g_hInstance
, IDS_ENTERNAME2
, sz
, _countof(sz
));
479 MessageBoxW(hwnd
, sz
, NULL
, MB_ICONERROR
);
483 g_Items
[g_iItem
].m_CharSet2
= DEFAULT_CHARSET
;
484 i
= SendDlgItemMessageW(hwnd
, cmb4
, CB_GETCURSEL
, 0, 0);
487 g_Items
[g_iItem
].m_CharSet2
= g_CharSetList
[i
].CharSet
;
489 g_Items
[g_iItem
].m_Substitute
= str
;
492 EndDialog(hwnd
, IDOK
);
495 EndDialog(hwnd
, IDCANCEL
);
498 LV_OnDelete(g_hListView
, g_iItem
);
499 EndDialog(hwnd
, psh1
);
505 EditDlg_DlgProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
509 HANDLE_MSG(hwnd
, WM_INITDIALOG
, EditDlg_OnInitDialog
);
510 HANDLE_MSG(hwnd
, WM_COMMAND
, EditDlg_OnCommand
);
515 void LV_OnDblClk(HWND hwnd
)
517 g_iItem
= ListView_GetNextItem(hwnd
, -1, LVNI_SELECTED
);
521 g_strFontName
= g_Items
[g_iItem
].m_Name
;
522 g_strSubstitute
= g_Items
[g_iItem
].m_Substitute
;
523 g_CharSet1
= g_Items
[g_iItem
].m_CharSet1
;
524 g_CharSet2
= g_Items
[g_iItem
].m_CharSet2
;
526 DialogBox(g_hInstance
, MAKEINTRESOURCE(IDD_EDIT
), g_hMainWnd
,
528 InvalidateRect(g_hListView
, NULL
, TRUE
);
531 BOOL
MainWnd_OnCreate(HWND hwnd
, LPCREATESTRUCT lpCreateStruct
)
533 DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_VSCROLL
|
534 LVS_SINGLESEL
| LVS_REPORT
| LVS_OWNERDRAWFIXED
;
535 DWORD dwExStyle
= WS_EX_CLIENTEDGE
;
536 g_hListView
= CreateWindowEx(dwExStyle
, WC_LISTVIEW
, NULL
, dwStyle
,
538 hwnd
, (HMENU
)1, g_hInstance
, NULL
);
539 if (g_hListView
== NULL
)
542 if (!LV_Init(g_hListView
))
548 UINT State
= LVIS_SELECTED
| LVIS_FOCUSED
;
549 ListView_SetItemState(g_hListView
, 0, State
, State
);
550 SetFocus(g_hListView
);
554 BOOL
AddDlg_OnInitDialog(HWND hwnd
, HWND hwndFocus
, LPARAM lParam
)
556 COMBOBOXEXITEMW Item
;
557 ZeroMemory(&Item
, sizeof(Item
));
559 Item
.mask
= CBEIF_TEXT
;
561 FONTNAMESET::iterator it
, end
= g_Names
.end();
562 for (it
= g_Names
.begin(); it
!= end
; ++it
)
564 Item
.pszText
= const_cast<LPWSTR
>(it
->c_str());
565 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb1
));
566 SendDlgItemMessageW(hwnd
, cmb1
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
567 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb2
));
568 SendDlgItemMessageW(hwnd
, cmb2
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
570 WCHAR szEnterName
[MAX_STRING
];
571 LoadStringW(g_hInstance
, IDS_ENTERNAME
, szEnterName
, _countof(szEnterName
));
572 SetDlgItemTextW(hwnd
, cmb1
, szEnterName
);
573 SendDlgItemMessageW(hwnd
, cmb1
, CB_SETEDITSEL
, 0, MAKELPARAM(0, -1));
575 const INT Count
= _countof(g_CharSetList
);
576 for (INT i
= 0; i
< Count
; ++i
)
578 Item
.pszText
= const_cast<LPWSTR
>(g_CharSetList
[i
].DisplayName
);
579 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb3
));
580 SendDlgItemMessageW(hwnd
, cmb3
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
581 Item
.iItem
= ComboBox_GetCount(GetDlgItem(hwnd
, cmb4
));
582 SendDlgItemMessageW(hwnd
, cmb4
, CBEM_INSERTITEM
, 0, (LPARAM
)&Item
);
585 SendDlgItemMessageW(hwnd
, cmb3
, CB_SETCURSEL
, 0, 0);
586 SendDlgItemMessageW(hwnd
, cmb4
, CB_SETCURSEL
, 0, 0);
587 for (INT i
= 0; i
< Count
; ++i
)
589 if (g_CharSet1
== g_CharSetList
[i
].CharSet
)
591 SendDlgItemMessageW(hwnd
, cmb3
, CB_SETCURSEL
, i
, 0);
593 if (g_CharSet2
== g_CharSetList
[i
].CharSet
)
595 SendDlgItemMessageW(hwnd
, cmb4
, CB_SETCURSEL
, i
, 0);
600 HDC hDC
= CreateCompatibleDC(NULL
);
601 SelectObject(hDC
, GetStockObject(DEFAULT_GUI_FONT
));
602 GetTextExtentPoint32W(hDC
, g_LongestName
, lstrlenW(g_LongestName
), &siz
);
605 SendDlgItemMessageW(hwnd
, cmb3
, CB_SETHORIZONTALEXTENT
, siz
.cx
+ 16, 0);
606 SendDlgItemMessageW(hwnd
, cmb4
, CB_SETHORIZONTALEXTENT
, siz
.cx
+ 16, 0);
611 void AddDlg_OnCommand(HWND hwnd
, int id
, HWND hwndCtl
, UINT codeNotify
)
613 WCHAR szKey
[MAX_STRING
], szValue
[MAX_STRING
], sz
[MAX_STRING
];
614 INT i
, iCharSet1
, iCharSet2
;
615 BYTE CharSet1
, CharSet2
;
620 GetDlgItemTextW(hwnd
, cmb1
, szKey
, _countof(szKey
));
623 LoadStringW(g_hInstance
, IDS_ENTERNAME
, sz
, _countof(sz
));
624 if (key
.empty() || key
== sz
)
626 SendDlgItemMessageW(hwnd
, cmb1
, CB_SETEDITSEL
, 0, MAKELPARAM(0, -1));
627 SetFocus(GetDlgItem(hwnd
, cmb1
));
628 LoadStringW(g_hInstance
, IDS_ENTERNAME2
, sz
, _countof(sz
));
629 MessageBoxW(hwnd
, sz
, NULL
, MB_ICONERROR
);
633 GetDlgItemTextW(hwnd
, cmb2
, szValue
, _countof(szValue
));
638 SendDlgItemMessageW(hwnd
, cmb2
, CB_SETEDITSEL
, 0, MAKELPARAM(0, -1));
639 SetFocus(GetDlgItem(hwnd
, cmb2
));
640 LoadStringW(g_hInstance
, IDS_ENTERNAME2
, sz
, _countof(sz
));
641 MessageBoxW(hwnd
, sz
, NULL
, MB_ICONERROR
);
645 iCharSet1
= SendDlgItemMessageW(hwnd
, cmb3
, CB_GETCURSEL
, 0, 0);
646 if (iCharSet1
== CB_ERR
)
648 iCharSet2
= SendDlgItemMessageW(hwnd
, cmb4
, CB_GETCURSEL
, 0, 0);
649 if (iCharSet2
== CB_ERR
)
652 CharSet1
= g_CharSetList
[iCharSet1
].CharSet
;
653 CharSet2
= g_CharSetList
[iCharSet2
].CharSet
;
655 for (i
= 0; i
< (INT
)g_Items
.size(); ++i
)
657 if (g_Items
[i
].m_Name
== key
&&
658 g_Items
[i
].m_CharSet1
== CharSet1
)
660 WCHAR sz
[MAX_STRING
];
661 SendDlgItemMessageW(hwnd
, cmb1
, CB_SETEDITSEL
, 0, MAKELPARAM(0, -1));
662 SetFocus(GetDlgItem(hwnd
, cmb1
));
663 LoadStringW(g_hInstance
, IDS_ALREADYEXISTS
, sz
, _countof(sz
));
664 MessageBoxW(hwnd
, sz
, NULL
, MB_ICONERROR
);
669 ITEM
Item(key
, value
, CharSet1
, CharSet2
);
670 g_Items
.push_back(Item
);
673 i
= (INT
)g_Items
.size();
675 ZeroMemory(&LvItem
, sizeof(LvItem
));
676 LvItem
.mask
= LVIF_PARAM
;
681 ListView_InsertItem(g_hListView
, &LvItem
);
684 ListView_InsertItem(g_hListView
, &LvItem
);
687 EndDialog(hwnd
, IDOK
);
690 EndDialog(hwnd
, IDCANCEL
);
696 AddDlg_DlgProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
700 HANDLE_MSG(hwnd
, WM_INITDIALOG
, AddDlg_OnInitDialog
);
701 HANDLE_MSG(hwnd
, WM_COMMAND
, AddDlg_OnCommand
);
706 void MainWnd_OnNew(HWND hwnd
)
708 g_iItem
= ListView_GetNextItem(hwnd
, -1, LVNI_SELECTED
);
712 g_strFontName
= g_Items
[g_iItem
].m_Name
;
713 g_strSubstitute
= g_Items
[g_iItem
].m_Substitute
;
714 g_CharSet1
= g_Items
[g_iItem
].m_CharSet1
;
715 g_CharSet2
= g_Items
[g_iItem
].m_CharSet2
;
717 if (IDOK
== DialogBox(g_hInstance
, MAKEINTRESOURCE(IDD_ADD
), g_hMainWnd
,
720 INT i
= ListView_GetItemCount(g_hListView
) - 1;
721 UINT State
= LVIS_SELECTED
| LVIS_FOCUSED
;
722 ListView_SetItemState(g_hListView
, i
, State
, State
);
723 ListView_EnsureVisible(g_hListView
, i
, FALSE
);
727 BOOL
MainWnd_OnUpdateRegistry(HWND hwnd
)
731 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, g_pszKey
, 0, KEY_ALL_ACCESS
, &hKey
);
736 WCHAR szName
[MAX_STRING
], szValue
[MAX_STRING
];
737 DWORD cbName
, cbValue
;
740 cbName
= sizeof(szName
);
741 cbValue
= sizeof(szValue
);
742 LONG Error
= RegEnumValueW(hKey
, 0, szName
, &cbName
,
743 NULL
, NULL
, (LPBYTE
)szValue
, &cbValue
);
744 if (Error
!= ERROR_SUCCESS
)
747 RegDeleteValueW(hKey
, szName
);
751 size_t Count
= g_Items
.size();
752 for (size_t i
= 0; i
< Count
; ++i
)
754 DWORD cbData
= (g_Items
[i
].m_Substitute
.size() + 1) * sizeof(WCHAR
);
755 RegSetValueExW(hKey
, g_Items
[i
].m_Name
.c_str(), 0,
756 REG_SZ
, (LPBYTE
)g_Items
[i
].m_Substitute
.c_str(), cbData
);
763 g_bNeedsReboot
= TRUE
;
767 LPWSTR
SkipSpace(LPCWSTR pch
)
769 while (*pch
&& wcschr(L
" \t\r\n", *pch
) != NULL
)
773 return const_cast<LPWSTR
>(pch
);
776 LPWSTR
SkipQuoted(LPWSTR pch
)
795 void UnescapeHex(const STRING
& str
, size_t& i
, STRING
& Ret
, BOOL Unicode
)
800 if (iswxdigit(str
[i
]))
804 if (iswxdigit(str
[i
]))
810 if (iswxdigit(str
[i
]))
814 if (iswxdigit(str
[i
]))
825 Ret
+= (WCHAR
)wcstoul(&Num
[0], NULL
, 16);
829 void UnescapeOther(const STRING
& str
, size_t& i
, STRING
& Ret
)
834 if (L
'0' <= str
[i
] && str
[i
] < L
'8')
838 if (L
'0' <= str
[i
] && str
[i
] < L
'8')
842 if (L
'0' <= str
[i
] && str
[i
] < L
'8')
857 Ret
+= (WCHAR
)wcstoul(&Num
[0], NULL
, 8);
861 // process escape sequence
862 void UnescapeChar(const STRING
& str
, size_t& i
, STRING
& Ret
)
874 case L
'a': Ret
+= L
'\a'; ++i
; break;
875 case L
'b': Ret
+= L
'\b'; ++i
; break;
876 case L
'f': Ret
+= L
'\f'; ++i
; break;
877 case L
'n': Ret
+= L
'\n'; ++i
; break;
878 case L
'r': Ret
+= L
'\r'; ++i
; break;
879 case L
't': Ret
+= L
'\t'; ++i
; break;
880 case L
'v': Ret
+= L
'\v'; ++i
; break;
884 UnescapeHex(str
, i
, Ret
, FALSE
);
887 // Unicode hexidemical
889 UnescapeHex(str
, i
, Ret
, TRUE
);
893 UnescapeOther(str
, i
, Ret
);
898 STRING
Unquote(const STRING
& str
)
905 while (i
< str
.size())
907 if (str
[i
] == L
'"' || str
[i
] == UNICODE_NULL
)
910 UnescapeChar(str
, i
, Ret
);
915 BOOL
DoParseFile(LPVOID pvContents
, DWORD dwSize
)
919 LPWSTR pch
, pchSep
, pchStart
= (LPWSTR
)pvContents
;
921 pchStart
[dwSize
/ sizeof(WCHAR
)] = UNICODE_NULL
;
924 const DWORD cbHeader
= lstrlenW(g_pszFileHeader
) * sizeof(WCHAR
);
925 if (memcmp(pchStart
, g_pszFileHeader
, cbHeader
) != 0)
928 pchStart
+= cbHeader
/ sizeof(WCHAR
);
931 WCHAR szKey
[MAX_STRING
];
932 wsprintfW(szKey
, L
"[HKEY_LOCAL_MACHINE\\%s]", g_pszKey
);
933 pch
= wcsstr(pchStart
, szKey
);
937 pchStart
= pch
+ lstrlenW(szKey
);
941 pchStart
= SkipSpace(pchStart
);
942 if (*pchStart
== UNICODE_NULL
|| *pchStart
== L
'[')
945 pch
= wcschr(pchStart
, L
'\n');
949 pchSep
= SkipQuoted(pchStart
);
952 *pchSep
= UNICODE_NULL
;
954 STRING key
= pchStart
;
958 STRING value
= pchSep
+ 1;
960 value
= Unquote(value
);
962 BYTE CharSet1
= DEFAULT_CHARSET
, CharSet2
= DEFAULT_CHARSET
;
965 pos
= key
.find(L
',');
966 if (pos
!= STRING::npos
)
968 CharSet1
= (BYTE
)_wtoi(&key
[pos
+ 1]);
972 pos
= value
.find(L
',');
973 if (pos
!= STRING::npos
)
975 CharSet2
= (BYTE
)_wtoi(&value
[pos
+ 1]);
980 ITEM
Item(key
, value
, CharSet1
, CharSet2
);
981 Items
.push_back(Item
);
993 LV_AddItems(g_hListView
);
997 BOOL
DoImport(HWND hwnd
, LPCWSTR pszFile
)
999 HANDLE hFile
= CreateFileW(pszFile
, GENERIC_READ
,
1000 FILE_SHARE_READ
| FILE_SHARE_DELETE
, NULL
,
1001 OPEN_EXISTING
, FILE_FLAG_SEQUENTIAL_SCAN
, NULL
);
1002 if (hFile
== INVALID_HANDLE_VALUE
)
1005 BOOL bSuccess
= FALSE
;
1006 DWORD dwSize
= GetFileSize(hFile
, NULL
);
1007 if (dwSize
!= 0xFFFFFFFF)
1009 std::vector
<BYTE
> Contents(dwSize
+ 2);
1011 if (ReadFile(hFile
, &Contents
[0], dwSize
, &cbRead
, NULL
) &&
1015 if (memcmp(&Contents
[0], "\xFF\xFE", 2) == 0)
1017 bSuccess
= DoParseFile(&Contents
[2], dwSize
- 2);
1021 bSuccess
= DoParseFile(&Contents
[0], dwSize
);
1030 STRING
Escape(const STRING
& str
)
1033 for (size_t i
= 0; i
< str
.size(); ++i
)
1037 case L
'"': case L
'\\':
1048 BOOL
DoExport(HWND hwnd
, LPCWSTR pszFile
)
1050 HANDLE hFile
= CreateFileW(pszFile
, GENERIC_WRITE
, FILE_SHARE_READ
,
1051 NULL
, CREATE_ALWAYS
,
1052 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_WRITE_THROUGH
, NULL
);
1053 if (hFile
== INVALID_HANDLE_VALUE
)
1057 DWORD dwSize
, cbWritten
;
1058 WCHAR szCharSet1
[MAX_STRING
], szCharSet2
[MAX_STRING
];
1059 WCHAR szLine
[MAX_STRING
* 2 + 4];
1062 dwSize
= lstrlenW(g_pszFileHeader
) * sizeof(WCHAR
);
1064 WriteFile(hFile
, "\xFF\xFE", 2, &cbWritten
, NULL
) &&
1065 WriteFile(hFile
, g_pszFileHeader
, dwSize
, &cbWritten
, NULL
);
1068 wsprintfW(szLine
, L
"\r\n\r\n[HKEY_LOCAL_MACHINE\\%s]\r\n", g_pszKey
);
1069 dwSize
= lstrlenW(szLine
) * sizeof(WCHAR
);
1070 bSuccess
= WriteFile(hFile
, szLine
, dwSize
, &cbWritten
, NULL
);
1074 size_t i
, Count
= g_Items
.size();
1075 for (i
= 0; i
< Count
; ++i
)
1077 if (g_Items
[i
].m_CharSet1
!= DEFAULT_CHARSET
)
1078 wsprintfW(szCharSet1
, L
",%u", g_Items
[i
].m_CharSet1
);
1080 szCharSet1
[0] = UNICODE_NULL
;
1082 if (g_Items
[i
].m_CharSet2
!= DEFAULT_CHARSET
)
1083 wsprintfW(szCharSet2
, L
",%u", g_Items
[i
].m_CharSet2
);
1085 szCharSet2
[0] = UNICODE_NULL
;
1087 STRING Name
= Escape(g_Items
[i
].m_Name
);
1088 STRING Substitute
= Escape(g_Items
[i
].m_Substitute
);
1089 wsprintfW(szLine
, L
"\"%s%s\"=\"%s%s\"\r\n",
1090 Name
.c_str(), szCharSet1
,
1091 Substitute
.c_str(), szCharSet2
);
1093 dwSize
= lstrlenW(szLine
) * sizeof(WCHAR
);
1094 if (!WriteFile(hFile
, szLine
, dwSize
, &cbWritten
, NULL
))
1100 WriteFile(hFile
, L
"\r\n", 2 * sizeof(WCHAR
), &cbWritten
, NULL
);
1106 DeleteFileW(pszFile
);
1112 void MakeFilter(LPWSTR pszFilter
)
1116 if (*pszFilter
== L
'|')
1123 void MainWnd_OnImport(HWND hwnd
)
1125 OPENFILENAMEW ofn
= {0};
1126 WCHAR szFile
[MAX_PATH
] = L
"";
1127 WCHAR szImportTitle
[MAX_STRING
];
1128 WCHAR szCannotImport
[MAX_STRING
];
1129 WCHAR szImportFilter
[MAX_STRING
];
1130 LoadStringW(g_hInstance
, IDS_IMPORT
, szImportTitle
, _countof(szImportTitle
));
1131 LoadStringW(g_hInstance
, IDS_CANTIMPORT
, szCannotImport
, _countof(szCannotImport
));
1132 LoadStringW(g_hInstance
, IDS_INPFILTER
, szImportFilter
, _countof(szImportFilter
));
1133 MakeFilter(szImportFilter
);
1135 ofn
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1136 ofn
.hwndOwner
= hwnd
;
1137 ofn
.lpstrFilter
= szImportFilter
;
1138 ofn
.lpstrFile
= szFile
;
1139 ofn
.nMaxFile
= _countof(szFile
);
1140 ofn
.lpstrTitle
= szImportTitle
;
1141 ofn
.Flags
= OFN_DONTADDTORECENT
| OFN_ENABLESIZING
|
1142 OFN_EXPLORER
| OFN_FILEMUSTEXIST
|
1143 OFN_HIDEREADONLY
| OFN_LONGNAMES
|
1145 ofn
.lpstrDefExt
= L
"reg";
1146 if (GetOpenFileNameW(&ofn
))
1148 if (!DoImport(hwnd
, szFile
))
1150 MessageBoxW(hwnd
, szCannotImport
, g_szTitle
, MB_ICONERROR
);
1155 void MainWnd_OnExport(HWND hwnd
)
1157 OPENFILENAMEW ofn
= {0};
1158 WCHAR szFile
[MAX_PATH
] = L
"";
1159 WCHAR szExportTitle
[MAX_STRING
];
1160 WCHAR szCannotExport
[MAX_STRING
];
1161 WCHAR szExportFilter
[MAX_STRING
];
1162 LoadStringW(g_hInstance
, IDS_EXPORT
, szExportTitle
, _countof(szExportTitle
));
1163 LoadStringW(g_hInstance
, IDS_CANTEXPORT
, szCannotExport
, _countof(szCannotExport
));
1164 LoadStringW(g_hInstance
, IDS_OUTFILTER
, szExportFilter
, _countof(szExportFilter
));
1165 MakeFilter(szExportFilter
);
1167 ofn
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
1168 ofn
.hwndOwner
= hwnd
;
1169 ofn
.lpstrFilter
= szExportFilter
;
1170 ofn
.lpstrFile
= szFile
;
1171 ofn
.nMaxFile
= _countof(szFile
);
1172 ofn
.lpstrTitle
= szExportTitle
;
1173 ofn
.Flags
= OFN_DONTADDTORECENT
| OFN_ENABLESIZING
|
1174 OFN_EXPLORER
| OFN_HIDEREADONLY
| OFN_LONGNAMES
|
1175 OFN_PATHMUSTEXIST
| OFN_OVERWRITEPROMPT
;
1176 ofn
.lpstrDefExt
= L
"reg";
1177 if (GetSaveFileNameW(&ofn
))
1179 if (!DoExport(hwnd
, szFile
))
1181 MessageBoxW(hwnd
, szCannotExport
, g_szTitle
, MB_ICONERROR
);
1186 void MainWnd_OnReload(HWND hwnd
)
1191 void MainWnd_OnEdit(HWND hwnd
)
1193 LV_OnDblClk(g_hListView
);
1196 void MainWnd_OnDelete(HWND hwnd
)
1198 LV_OnDelete(g_hListView
);
1201 void MainWnd_OnOpenRegKey(HWND hwnd
)
1203 static const WCHAR s_szRegeditKey
[] =
1204 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit";
1205 WCHAR sz
[MAX_STRING
];
1209 LSTATUS Result
= RegCreateKeyExW(HKEY_CURRENT_USER
, s_szRegeditKey
, 0,
1210 NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
);
1211 if (Result
!= ERROR_SUCCESS
)
1213 LoadStringW(g_hInstance
, IDS_CANTOPENKEY
, sz
, _countof(sz
));
1214 MessageBoxW(hwnd
, sz
, NULL
, MB_ICONERROR
);
1218 // set LastKey value
1219 wsprintfW(sz
, L
"HKEY_LOCAL_MACHINE\\%s", g_pszKey
);
1220 DWORD dwSize
= sizeof(sz
);
1221 Result
= RegSetValueExW(hKey
, L
"LastKey", 0, REG_SZ
,
1222 (LPBYTE
)sz
, dwSize
);
1227 if (Result
!= ERROR_SUCCESS
)
1229 LoadStringW(g_hInstance
, IDS_CANTOPENKEY
, sz
, _countof(sz
));
1230 MessageBoxW(hwnd
, sz
, NULL
, MB_ICONERROR
);
1235 ShellExecuteW(hwnd
, NULL
, L
"regedit.exe", NULL
, NULL
, SW_SHOWNORMAL
);
1238 void MainWnd_OnAbout(HWND hwnd
)
1240 WCHAR szAbout
[MAX_PATH
];
1241 LoadStringW(g_hInstance
, IDS_ABOUT
, szAbout
, _countof(szAbout
));
1243 MSGBOXPARAMS Params
;
1244 ZeroMemory(&Params
, sizeof(Params
));
1245 Params
.cbSize
= sizeof(Params
);
1246 Params
.hwndOwner
= hwnd
;
1247 Params
.hInstance
= g_hInstance
;
1248 Params
.lpszText
= szAbout
;
1249 Params
.lpszCaption
= g_szTitle
;
1250 Params
.dwStyle
= MB_OK
| MB_USERICON
;
1251 Params
.lpszIcon
= MAKEINTRESOURCEW(1);
1252 Params
.dwLanguageId
= LANG_USER_DEFAULT
;
1253 MessageBoxIndirectW(&Params
);
1256 void MainWnd_OnCommand(HWND hwnd
, int id
, HWND hwndCtl
, UINT codeNotify
)
1261 MainWnd_OnNew(hwnd
);
1264 MainWnd_OnEdit(hwnd
);
1267 PostMessage(hwnd
, WM_CLOSE
, 0, 0);
1270 MainWnd_OnReload(hwnd
);
1272 case ID_UPDATE_REGISTRY
:
1273 MainWnd_OnUpdateRegistry(hwnd
);
1276 MainWnd_OnDelete(hwnd
);
1279 MainWnd_OnImport(hwnd
);
1282 MainWnd_OnExport(hwnd
);
1284 case ID_OPEN_REGKEY
:
1285 MainWnd_OnOpenRegKey(hwnd
);
1288 MainWnd_OnAbout(hwnd
);
1293 void MainWnd_OnDestroy(HWND hwnd
)
1298 void MainWnd_OnSize(HWND hwnd
, UINT state
, int cx
, int cy
)
1300 MoveWindow(g_hListView
, 0, 0, cx
, cy
, TRUE
);
1303 void MainWnd_OnDrawItem(HWND hwnd
, const DRAWITEMSTRUCT
*lpDrawItem
)
1305 if (lpDrawItem
->CtlType
!= ODT_LISTVIEW
)
1308 HDC hDC
= lpDrawItem
->hDC
;
1309 SetBkMode(hDC
, TRANSPARENT
);
1311 INT iColumn
= 0, x
, cx
;
1312 RECT rcItem
, rcSubItem
, rcText
;
1315 x
= -GetScrollPos(g_hListView
, SB_HORZ
);
1317 rcItem
= lpDrawItem
->rcItem
;
1318 if (lpDrawItem
->itemState
& ODS_SELECTED
)
1320 FillRect(hDC
, &rcItem
, (HBRUSH
)(COLOR_HIGHLIGHT
+ 1));
1321 SetTextColor(hDC
, GetSysColor(COLOR_HIGHLIGHTTEXT
));
1325 FillRect(hDC
, &rcItem
, (HBRUSH
)(COLOR_WINDOW
+ 1));
1326 SetTextColor(hDC
, GetSysColor(COLOR_WINDOWTEXT
));
1329 cx
= ListView_GetColumnWidth(g_hListView
, iColumn
);
1332 rcSubItem
.right
= x
+ cx
;
1334 WCHAR sz
[MAX_STRING
];
1337 InflateRect(&rcText
, -1, -1);
1338 Str
= g_Items
[lpDrawItem
->itemID
].m_Name
;
1339 BYTE CharSet1
= g_Items
[lpDrawItem
->itemID
].m_CharSet1
;
1340 if (CharSet1
!= DEFAULT_CHARSET
)
1341 wsprintfW(sz
, L
"%s,%u", Str
.c_str(), CharSet1
);
1343 wsprintfW(sz
, L
"%s", Str
.c_str());
1345 DrawTextW(hDC
, sz
, lstrlenW(sz
), &rcText
,
1346 DT_SINGLELINE
| DT_LEFT
| DT_VCENTER
| DT_END_ELLIPSIS
|
1352 cx
= ListView_GetColumnWidth(g_hListView
, iColumn
);
1355 rcSubItem
.right
= x
+ cx
;
1358 InflateRect(&rcText
, -1, -1);
1359 Str
= g_Items
[lpDrawItem
->itemID
].m_Substitute
;
1360 BYTE CharSet2
= g_Items
[lpDrawItem
->itemID
].m_CharSet2
;
1361 if (CharSet2
!= DEFAULT_CHARSET
)
1362 wsprintfW(sz
, L
"%s,%u", Str
.c_str(), CharSet2
);
1364 wsprintfW(sz
, L
"%s", Str
.c_str());
1366 DrawTextW(hDC
, sz
, lstrlenW(sz
), &rcText
,
1367 DT_SINGLELINE
| DT_LEFT
| DT_VCENTER
| DT_END_ELLIPSIS
|
1371 void MainWnd_OnMeasureItem(HWND hwnd
, MEASUREITEMSTRUCT
*lpMeasureItem
)
1373 if (lpMeasureItem
->CtlType
!= ODT_LISTVIEW
)
1377 HDC hDC
= GetDC(hwnd
);
1378 GetTextMetrics(hDC
, &tm
);
1379 ReleaseDC(hwnd
, hDC
);
1381 lpMeasureItem
->itemHeight
= tm
.tmHeight
* 4 / 3;
1384 LRESULT
MainWnd_OnNotify(HWND hwnd
, int idFrom
, NMHDR
*pnmhdr
)
1386 NM_LISTVIEW
*pNMLV
= (NM_LISTVIEW
*)pnmhdr
;
1387 LV_KEYDOWN
*pLVKD
= (LV_KEYDOWN
*)pnmhdr
;
1389 switch (pnmhdr
->code
)
1391 case LVN_COLUMNCLICK
:
1392 if (pNMLV
->iSubItem
== g_iSortColumn
)
1393 DoSort(pNMLV
->iSubItem
, !g_bSortAscendant
);
1395 DoSort(pNMLV
->iSubItem
, TRUE
);
1398 LV_OnDblClk(g_hListView
);
1401 if (pLVKD
->wVKey
== VK_RETURN
) // [Enter] key
1403 LV_OnDblClk(g_hListView
);
1405 if (pLVKD
->wVKey
== VK_DELETE
) // [Del] key
1407 LV_OnDelete(g_hListView
);
1414 LRESULT
MainWnd_OnContextMenu(HWND hwnd
, HWND hwndContext
, UINT xPos
, UINT yPos
)
1416 POINT pt
= {(INT
)xPos
, (INT
)yPos
};
1417 ScreenToClient(g_hListView
, &pt
);
1418 SendMessageW(g_hListView
, WM_LBUTTONDOWN
, 0, MAKELPARAM(pt
.x
, pt
.y
));
1420 HMENU hMenu
= LoadMenu(g_hInstance
, MAKEINTRESOURCE(2));
1424 HMENU hSubMenu
= GetSubMenu(hMenu
, 0);
1425 if (hSubMenu
== NULL
)
1428 SetForegroundWindow(hwnd
);
1429 TrackPopupMenu(hSubMenu
, TPM_LEFTALIGN
| TPM_RIGHTBUTTON
,
1430 xPos
, yPos
, 0, g_hMainWnd
, NULL
);
1431 PostMessage(g_hMainWnd
, WM_NULL
, 0, 0);
1435 void MainWnd_OnActivate(HWND hwnd
, UINT state
, HWND hwndActDeact
, BOOL fMinimized
)
1437 if (state
!= WA_INACTIVE
)
1439 SetFocus(g_hListView
);
1443 BOOL
EnableProcessPrivileges(LPCWSTR lpPrivilegeName
, BOOL bEnable
= TRUE
)
1447 TOKEN_PRIVILEGES tokenPrivileges
;
1450 Ret
= ::OpenProcessToken(::GetCurrentProcess(),
1451 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1454 return Ret
; // failure
1456 Ret
= ::LookupPrivilegeValueW(NULL
, lpPrivilegeName
, &luid
);
1459 tokenPrivileges
.PrivilegeCount
= 1;
1460 tokenPrivileges
.Privileges
[0].Luid
= luid
;
1461 tokenPrivileges
.Privileges
[0].Attributes
= bEnable
? SE_PRIVILEGE_ENABLED
: 0;
1463 Ret
= ::AdjustTokenPrivileges(hToken
, FALSE
, &tokenPrivileges
, 0, 0, 0);
1466 ::CloseHandle(hToken
);
1470 void MainWnd_OnClose(HWND hwnd
)
1472 if (!g_bNeedsReboot
&& !g_bModified
)
1474 DestroyWindow(hwnd
);
1480 WCHAR szUpdateNow
[MAX_STRING
];
1481 LoadStringW(g_hInstance
, IDS_QUERYUPDATE
, szUpdateNow
, _countof(szUpdateNow
));
1482 INT id
= MessageBoxW(hwnd
, szUpdateNow
, g_szTitle
,
1483 MB_ICONINFORMATION
| MB_YESNOCANCEL
);
1487 MainWnd_OnUpdateRegistry(hwnd
);
1498 WCHAR szRebootNow
[MAX_STRING
];
1499 LoadStringW(g_hInstance
, IDS_REBOOTNOW
, szRebootNow
, _countof(szRebootNow
));
1500 INT id
= MessageBoxW(hwnd
, szRebootNow
, g_szTitle
,
1501 MB_ICONINFORMATION
| MB_YESNOCANCEL
);
1505 EnableProcessPrivileges(SE_SHUTDOWN_NAME
, TRUE
);
1506 ::ExitWindowsEx(EWX_REBOOT
| EWX_FORCE
, 0);
1515 ::DestroyWindow(hwnd
);
1519 WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1523 HANDLE_MSG(hwnd
, WM_CREATE
, MainWnd_OnCreate
);
1524 HANDLE_MSG(hwnd
, WM_COMMAND
, MainWnd_OnCommand
);
1525 HANDLE_MSG(hwnd
, WM_DESTROY
, MainWnd_OnDestroy
);
1526 HANDLE_MSG(hwnd
, WM_SIZE
, MainWnd_OnSize
);
1527 HANDLE_MSG(hwnd
, WM_DRAWITEM
, MainWnd_OnDrawItem
);
1528 HANDLE_MSG(hwnd
, WM_MEASUREITEM
, MainWnd_OnMeasureItem
);
1529 HANDLE_MSG(hwnd
, WM_NOTIFY
, MainWnd_OnNotify
);
1530 HANDLE_MSG(hwnd
, WM_CONTEXTMENU
, MainWnd_OnContextMenu
);
1531 HANDLE_MSG(hwnd
, WM_ACTIVATE
, MainWnd_OnActivate
);
1532 HANDLE_MSG(hwnd
, WM_CLOSE
, MainWnd_OnClose
);
1534 return DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
1538 INT WINAPI
wWinMain(
1539 HINSTANCE hInstance
,
1540 HINSTANCE hPrevInstance
,
1544 g_hInstance
= hInstance
;
1545 InitCommonControls();
1547 HACCEL hAccel
= LoadAcceleratorsW(hInstance
, MAKEINTRESOURCEW(1));
1549 LoadStringW(hInstance
, IDS_TITLE
, g_szTitle
, _countof(g_szTitle
));
1550 LoadStringW(hInstance
, IDS_FONTNAME
, g_szNameHead
, _countof(g_szNameHead
));
1551 LoadStringW(hInstance
, IDS_SUBSTITUTE
, g_szSubstituteHead
, _countof(g_szSubstituteHead
));
1555 wc
.lpfnWndProc
= WindowProc
;
1556 wc
.hInstance
= hInstance
;
1557 g_hIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(1));
1559 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
1560 wc
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
1561 wc
.lpszMenuName
= MAKEINTRESOURCEW(1);
1562 wc
.lpszClassName
= g_pszClassName
;
1563 if (!RegisterClassW(&wc
))
1565 MessageBoxA(NULL
, "ERROR: RegisterClass failed.", NULL
, MB_ICONERROR
);
1569 const DWORD dwStyle
= WS_OVERLAPPEDWINDOW
;
1570 INT Width
= NAME_COLUMN_WIDTH
+ SUB_COLUMN_WIDTH
+
1571 GetSystemMetrics(SM_CXVSCROLL
) +
1572 GetSystemMetrics(SM_CXSIZEFRAME
);
1575 RECT Rect
= { 0, 0, Width
, Height
};
1576 AdjustWindowRect(&Rect
, dwStyle
, TRUE
);
1577 Width
= Rect
.right
- Rect
.left
;
1578 Height
= Rect
.bottom
- Rect
.top
;
1580 g_hMainWnd
= CreateWindowW(g_pszClassName
, g_szTitle
, dwStyle
,
1581 CW_USEDEFAULT
, CW_USEDEFAULT
, Width
, Height
,
1582 NULL
, NULL
, hInstance
, NULL
);
1583 if (g_hMainWnd
== NULL
)
1585 MessageBoxA(NULL
, "ERROR: CreateWindow failed.", NULL
, MB_ICONERROR
);
1589 ShowWindow(g_hMainWnd
, nCmdShow
);
1590 UpdateWindow(g_hMainWnd
);
1593 while (GetMessage(&msg
, NULL
, 0, 0))
1595 if (TranslateAccelerator(g_hMainWnd
, hAccel
, &msg
))
1598 TranslateMessage(&msg
);
1599 DispatchMessage(&msg
);
1602 return (INT
)msg
.wParam
;