2 * Copyright 2015 Mark Jansen
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 const GUID CLSID_CLayerUIPropPage
= { 0x513D916F, 0x2A8E, 0x4F51, { 0xAE, 0xAB, 0x0C, 0xBC, 0x76, 0xFB, 0x1A, 0xF8 } };
24 #define ACP_WNDPROP L"{513D916F-2A8E-4F51-AEAB-0CBC76FB1AF8}.Prop"
27 #define GPLK_MACHINE 2
28 #define MAX_LAYER_LENGTH 256
30 void ACDBG_FN(PCSTR FunctionName
, PCWSTR Format
, ...)
33 WCHAR
* Current
= Buffer
;
34 size_t Length
= _countof(Buffer
);
36 StringCchPrintfExW(Current
, Length
, &Current
, &Length
, STRSAFE_NULL_ON_FAILURE
, L
"[%-20S] ", FunctionName
);
38 va_start(ArgList
, Format
);
39 StringCchVPrintfExW(Current
, Length
, &Current
, &Length
, STRSAFE_NULL_ON_FAILURE
, Format
, ArgList
);
41 OutputDebugStringW(Buffer
);
44 #define ACDBG(fmt, ...) ACDBG_FN(__FUNCTION__, fmt, ##__VA_ARGS__ )
48 CLayerUIPropPage::CLayerUIPropPage()
50 , m_IsSfcProtected(FALSE
)
51 , m_AllowPermLayer(FALSE
)
52 , m_LayerQueryFlags(GPLK_USER
)
55 , m_RegistryEnabledLayers(0)
60 CLayerUIPropPage::~CLayerUIPropPage()
66 HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
67 WINXPSP3
256COLOR
640X480 DISABLETHEMES DISABLEDWM HIGHDPIAWARE RUNASADMIN
74 { L
"Windows 95", L
"WIN95" },
75 { L
"Windows 98/ME", L
"WIN98" },
76 { L
"Windows NT 4.0 (SP5)", L
"NT4SP5" },
77 { L
"Windows 2000", L
"WIN2000" },
78 { L
"Windows XP (SP2)", L
"WINXPSP2" },
79 { L
"Windows XP (SP3)", L
"WINXPSP3" },
80 { L
"Windows Server 2003 (SP1)", L
"WINSRV03SP1" },
82 { L
"Windows Server 2008 (SP1)", L
"WINSRV08SP1" },
83 { L
"Windows Vista", L
"VISTARTM" },
84 { L
"Windows Vista (SP1)", L
"VISTASP1" },
85 { L
"Windows Vista (SP2)", L
"VISTASP2" },
86 { L
"Windows 7", L
"WIN7RTM" },
96 { L
"256COLOR", IDC_CHKRUNIN256COLORS
, TRUE
},
97 { L
"640X480", IDC_CHKRUNIN640480RES
, TRUE
},
98 { L
"DISABLETHEMES", IDC_CHKDISABLEVISUALTHEMES
, TRUE
},
102 static const WCHAR
* g_AllowedExtensions
[] = {
111 HRESULT
CLayerUIPropPage::InitFile(PCWSTR Filename
)
113 PCWSTR pwszExt
= PathFindExtensionW(Filename
);
116 ACDBG(L
"Failed to find an extension: '%s'\r\n", Filename
);
119 if (!wcsicmp(pwszExt
, L
".lnk"))
121 WCHAR Buffer
[MAX_PATH
];
122 if (!GetExeFromLnk(Filename
, Buffer
, _countof(Buffer
)))
124 ACDBG(L
"Failed to read link target from: '%s'\r\n", Filename
);
127 if (!wcsicmp(Buffer
, Filename
))
129 ACDBG(L
"Link redirects to itself: '%s'\r\n", Filename
);
132 return InitFile(Buffer
);
134 for (size_t n
= 0; g_AllowedExtensions
[n
]; ++n
)
136 if (!wcsicmp(g_AllowedExtensions
[n
], pwszExt
))
138 m_Filename
= Filename
;
139 ACDBG(L
"Got: %s\r\n", Filename
);
140 m_IsSfcProtected
= SfcIsFileProtected(NULL
, m_Filename
);
141 m_AllowPermLayer
= AllowPermLayer(Filename
);
145 ACDBG(L
"Extension not included: '%s'\r\n", pwszExt
);
149 BOOL
GetLayerInfo(BSTR Filename
, DWORD QueryFlags
, PDWORD OSMode
, PDWORD Enabledlayers
)
151 *OSMode
= *Enabledlayers
= 0;
152 WCHAR wszLayers
[MAX_LAYER_LENGTH
] = { 0 };
153 DWORD dwBytes
= sizeof(wszLayers
);
154 if (!SdbGetPermLayerKeys(Filename
, wszLayers
, &dwBytes
, QueryFlags
))
157 for (PWCHAR Layer
= wcstok(wszLayers
, L
" "); Layer
; Layer
= wcstok(NULL
, L
" "))
160 for (n
= 0; g_Layers
[n
].Name
; ++n
)
162 if (g_Layers
[n
].Enabled
&& !wcsicmp(g_Layers
[n
].Name
, Layer
))
164 *Enabledlayers
|= (1<<n
);
168 if (!g_Layers
[n
].Name
)
170 for (n
= 0; g_CompatModes
[n
].Name
; ++n
)
172 if (!wcsicmp(g_CompatModes
[n
].Name
, Layer
))
183 void CLayerUIPropPage::OnRefresh(HWND hWnd
)
185 if (!GetLayerInfo(m_Filename
, m_LayerQueryFlags
, &m_RegistryOSMode
, &m_RegistryEnabledLayers
))
186 m_RegistryOSMode
= m_RegistryEnabledLayers
= 0;
188 for (size_t n
= 0; g_Layers
[n
].Name
; ++n
)
189 CheckDlgButton(hWnd
, g_Layers
[n
].Id
, (m_RegistryEnabledLayers
& (1<<n
)) ? BST_CHECKED
: BST_UNCHECKED
);
190 CheckDlgButton(hWnd
, IDC_CHKRUNCOMPATIBILITY
, m_RegistryOSMode
? BST_CHECKED
: BST_UNCHECKED
);
191 if (m_RegistryOSMode
)
192 ComboBox_SetCurSel(GetDlgItem(hWnd
, IDC_COMPATIBILITYMODE
), m_RegistryOSMode
-1);
193 UpdateControls(hWnd
);
196 void CLayerUIPropPage::OnApply(HWND hWnd
)
198 if (m_RegistryEnabledLayers
!= m_EnabledLayers
|| m_RegistryOSMode
!= m_OSMode
)
200 BOOL bMachine
= m_LayerQueryFlags
== GPLK_MACHINE
;
201 for (size_t n
= 0; g_CompatModes
[n
].Name
; ++n
)
202 SetPermLayerState(m_Filename
, g_CompatModes
[n
].Name
, 0, bMachine
, (n
+1) == m_OSMode
);
203 for (size_t n
= 0; g_Layers
[n
].Name
; ++n
)
205 if (g_Layers
[n
].Enabled
)
206 SetPermLayerState(m_Filename
, g_Layers
[n
].Name
, 0, bMachine
, ((1<<n
) & m_EnabledLayers
) != 0);
208 SHChangeNotify(SHCNE_UPDATEITEM
, SHCNF_PATHW
, (BSTR
)m_Filename
, NULL
);
212 INT_PTR
CLayerUIPropPage::InitDialog(HWND hWnd
)
214 HWND cboMode
= GetDlgItem(hWnd
, IDC_COMPATIBILITYMODE
);
215 for (size_t n
= 0; g_CompatModes
[n
].Display
; ++n
)
216 ComboBox_AddString(cboMode
, g_CompatModes
[n
].Display
);
217 ComboBox_SetCurSel(cboMode
, 5);
218 EnableWindow(GetDlgItem(hWnd
, IDC_EDITCOMPATIBILITYMODES
), 0);
220 CComBSTR explanation
;
221 if (!m_AllowPermLayer
)
223 explanation
.LoadString(g_hModule
, IDS_FAILED_NETWORK
);
224 DisableControls(hWnd
);
225 ACDBG(L
"AllowPermLayer returned FALSE\r\n");
227 else if (m_IsSfcProtected
)
229 explanation
.LoadString(g_hModule
, IDS_FAILED_PROTECTED
);
230 DisableControls(hWnd
);
231 ACDBG(L
"Protected OS file\r\n");
237 SetDlgItemTextW(hWnd
, IDC_EXPLANATION
, explanation
);
241 INT_PTR
CLayerUIPropPage::DisableControls(HWND hWnd
)
243 EnableWindow(GetDlgItem(hWnd
, IDC_COMPATIBILITYMODE
), 0);
244 EnableWindow(GetDlgItem(hWnd
, IDC_CHKRUNCOMPATIBILITY
), 0);
245 for (size_t n
= 0; g_Layers
[n
].Name
; ++n
)
246 EnableWindow(GetDlgItem(hWnd
, g_Layers
[n
].Id
), 0);
247 EnableWindow(GetDlgItem(hWnd
, IDC_EDITCOMPATIBILITYMODES
), 0);
251 void CLayerUIPropPage::UpdateControls(HWND hWnd
)
253 m_OSMode
= 0, m_EnabledLayers
= 0;
254 BOOL ModeEnabled
= IsDlgButtonChecked(hWnd
, IDC_CHKRUNCOMPATIBILITY
);
256 m_OSMode
= ComboBox_GetCurSel(GetDlgItem(hWnd
, IDC_COMPATIBILITYMODE
))+1;
257 EnableWindow(GetDlgItem(hWnd
, IDC_COMPATIBILITYMODE
), ModeEnabled
);
258 for (size_t n
= 0; g_Layers
[n
].Name
; ++n
)
260 if (g_Layers
[n
].Enabled
)
262 m_EnabledLayers
|= IsDlgButtonChecked(hWnd
, g_Layers
[n
].Id
) ? (1<<n
) : 0;
263 ShowWindow(GetDlgItem(hWnd
, g_Layers
[n
].Id
), SW_SHOW
);
267 ShowWindow(GetDlgItem(hWnd
, g_Layers
[n
].Id
), SW_HIDE
);
270 if (m_RegistryOSMode
!= m_OSMode
|| m_RegistryEnabledLayers
!= m_EnabledLayers
)
272 PropSheet_Changed(GetParent(hWnd
), hWnd
);
276 PropSheet_UnChanged(GetParent(hWnd
), hWnd
);
280 INT_PTR
CLayerUIPropPage::OnCommand(HWND hWnd
, WORD id
)
284 case IDC_CHKRUNCOMPATIBILITY
:
285 UpdateControls(hWnd
);
287 case IDC_COMPATIBILITYMODE
:
288 UpdateControls(hWnd
);
290 case IDC_CHKRUNIN256COLORS
:
291 case IDC_CHKRUNIN640480RES
:
292 case IDC_CHKDISABLEVISUALTHEMES
:
293 UpdateControls(hWnd
);
295 case IDC_EDITCOMPATIBILITYMODES
:
301 INT_PTR CALLBACK
CLayerUIPropPage::PropDlgProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
303 CLayerUIPropPage
* page
= NULL
;
308 page
= (CLayerUIPropPage
*)((LPPROPSHEETPAGE
)lParam
)->lParam
;
309 SetProp(hWnd
, ACP_WNDPROP
, page
);
310 return page
->InitDialog(hWnd
);
314 page
= (CLayerUIPropPage
*)GetProp(hWnd
, ACP_WNDPROP
);
315 RemoveProp(hWnd
, ACP_WNDPROP
);
320 page
= (CLayerUIPropPage
*)GetProp(hWnd
, ACP_WNDPROP
);
321 return page
->OnCommand(hWnd
, LOWORD(wParam
));
323 switch (((LPNMHDR
)lParam
)->code
)
326 if (((LPNMHDR
)lParam
)->hwndFrom
== GetParent(hWnd
))
328 page
= (CLayerUIPropPage
*)GetProp(hWnd
, ACP_WNDPROP
);
329 page
->OnRefresh(hWnd
);
333 if (((LPNMHDR
)lParam
)->hwndFrom
== GetParent(hWnd
))
335 page
= (CLayerUIPropPage
*)GetProp(hWnd
, ACP_WNDPROP
);
341 if (((LPNMHDR
)lParam
)->idFrom
== IDC_INFOLINK
)
343 ShellExecute(NULL
, L
"open", L
"https://www.reactos.org/forum/viewforum.php?f=4", NULL
, NULL
, SW_SHOW
);
355 STDMETHODIMP
CLayerUIPropPage::Initialize(LPCITEMIDLIST pidlFolder
, LPDATAOBJECT pDataObj
, HKEY hkeyProgID
)
357 FORMATETC etc
= { CF_HDROP
, NULL
, DVASPECT_CONTENT
, -1, TYMED_HGLOBAL
};
359 HRESULT hr
= pDataObj
->GetData(&etc
, &stg
);
362 ACDBG(L
"Failed to retrieve Data from pDataObj.\r\n");
366 HDROP hdrop
= (HDROP
)GlobalLock(stg
.hGlobal
);
369 UINT uNumFiles
= DragQueryFileW(hdrop
, 0xFFFFFFFF, NULL
, 0);
372 WCHAR szFile
[MAX_PATH
* 2];
373 if (DragQueryFileW(hdrop
, 0, szFile
, _countof(szFile
)))
376 hr
= InitFile(szFile
);
380 ACDBG(L
"Failed to query the file.\r\n");
385 ACDBG(L
"Invalid number of files: %d\r\n", uNumFiles
);
387 GlobalUnlock(stg
.hGlobal
);
391 ACDBG(L
"Could not lock stg.hGlobal\r\n");
393 ReleaseStgMedium(&stg
);
397 STDMETHODIMP
CLayerUIPropPage::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage
, LPARAM lParam
)
399 PROPSHEETPAGEW psp
= { 0 };
400 psp
.dwSize
= sizeof(psp
);
401 psp
.dwFlags
= PSP_USEREFPARENT
| PSP_USETITLE
;
402 psp
.hInstance
= g_hModule
;
403 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_ACPPAGESHEET
);
404 psp
.pszTitle
= MAKEINTRESOURCE(IDS_TABTITLE
);
405 psp
.pfnDlgProc
= PropDlgProc
;
406 psp
.lParam
= (LPARAM
)this;
407 psp
.pcRefParent
= (PUINT
)&g_ModuleRefCnt
;
408 HPROPSHEETPAGE hPage
= CreatePropertySheetPageW(&psp
);
409 if (hPage
&& !pfnAddPage(hPage
, lParam
))
410 DestroyPropertySheetPage(hPage
);