[ACPPAGE] Do not allow shims to be applied to files in System32/WinSxs.
[reactos.git] / reactos / dll / shellext / acppage / CLayerUIPropPage.cpp
1 /*
2 * Copyright 2015-2017 Mark Jansen (mark.jansen@reactos.org)
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "precomp.h"
20
21 #include <shlwapi.h>
22 #include <shellapi.h>
23 #include <shellutils.h>
24 #include <strsafe.h>
25 #include <apphelp.h>
26 #include <windowsx.h>
27 #include <sfc.h>
28
29 const GUID CLSID_CLayerUIPropPage = { 0x513D916F, 0x2A8E, 0x4F51, { 0xAE, 0xAB, 0x0C, 0xBC, 0x76, 0xFB, 0x1A, 0xF8 } };
30 #define ACP_WNDPROP L"{513D916F-2A8E-4F51-AEAB-0CBC76FB1AF8}.Prop"
31
32 #define GPLK_USER 1
33 #define GPLK_MACHINE 2
34 #define MAX_LAYER_LENGTH 256
35
36 static struct {
37 const PCWSTR Display;
38 const PCWSTR Name;
39 } g_CompatModes[] = {
40 { L"Windows 95", L"WIN95" },
41 { L"Windows 98/ME", L"WIN98" },
42 { L"Windows NT 4.0 (SP5)", L"NT4SP5" },
43 { L"Windows 2000", L"WIN2000" },
44 { L"Windows XP (SP2)", L"WINXPSP2" },
45 { L"Windows XP (SP3)", L"WINXPSP3" },
46 { L"Windows Server 2003 (SP1)", L"WINSRV03SP1" },
47 #if 0
48 { L"Windows Server 2008 (SP1)", L"WINSRV08SP1" },
49 { L"Windows Vista", L"VISTARTM" },
50 { L"Windows Vista (SP1)", L"VISTASP1" },
51 { L"Windows Vista (SP2)", L"VISTASP2" },
52 { L"Windows 7", L"WIN7RTM" },
53 #endif
54 { NULL, NULL }
55 };
56
57 static struct {
58 const PCWSTR Name;
59 DWORD Id;
60 } g_Layers[] = {
61 { L"256COLOR", IDC_CHKRUNIN256COLORS },
62 { L"640X480", IDC_CHKRUNIN640480RES },
63 { L"DISABLETHEMES", IDC_CHKDISABLEVISUALTHEMES },
64 #if 0
65 { L"DISABLEDWM", IDC_??, TRUE },
66 { L"HIGHDPIAWARE", IDC_??, TRUE },
67 { L"RUNASADMIN", IDC_??, TRUE },
68 #endif
69 { NULL, 0 }
70 };
71
72 static const WCHAR* g_AllowedExtensions[] = {
73 L".exe",
74 L".msi",
75 L".pif",
76 L".bat",
77 L".cmd",
78 0
79 };
80
81
82 void ACDBG_FN(PCSTR FunctionName, PCWSTR Format, ...)
83 {
84 WCHAR Buffer[512];
85 WCHAR* Current = Buffer;
86 size_t Length = _countof(Buffer);
87
88 StringCchPrintfExW(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, L"[%-20S] ", FunctionName);
89 va_list ArgList;
90 va_start(ArgList, Format);
91 StringCchVPrintfExW(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
92 va_end(ArgList);
93 OutputDebugStringW(Buffer);
94 }
95
96 #define ACDBG(fmt, ...) ACDBG_FN(__FUNCTION__, fmt, ##__VA_ARGS__ )
97
98
99
100 CLayerUIPropPage::CLayerUIPropPage()
101 : m_IsSfcProtected(FALSE)
102 , m_AllowPermLayer(FALSE)
103 , m_LayerQueryFlags(GPLK_USER) /* TODO: When do we read from HKLM? */
104 , m_RegistryOSMode(0)
105 , m_OSMode(0)
106 , m_RegistryEnabledLayers(0)
107 , m_EnabledLayers(0)
108 {
109 }
110
111 CLayerUIPropPage::~CLayerUIPropPage()
112 {
113 }
114
115 HRESULT CLayerUIPropPage::InitFile(PCWSTR Filename)
116 {
117 CString ExpandedFilename;
118 DWORD dwRequired = ExpandEnvironmentStringsW(Filename, NULL, 0);
119 if (dwRequired > 0)
120 {
121 LPWSTR Buffer = ExpandedFilename.GetBuffer(dwRequired);
122 DWORD dwReturned = ExpandEnvironmentStringsW(Filename, Buffer, dwRequired);
123 if (dwRequired == dwReturned)
124 {
125 ExpandedFilename.ReleaseBufferSetLength(dwReturned - 1);
126 ACDBG(L"Expanded '%s' => '%s'\r\n", Filename, (PCWSTR)ExpandedFilename);
127 }
128 else
129 {
130 ExpandedFilename.ReleaseBufferSetLength(0);
131 ExpandedFilename = Filename;
132 ACDBG(L"Failed during expansion '%s'\r\n", Filename);
133 }
134 }
135 else
136 {
137 ACDBG(L"Failed to expand '%s'\r\n", Filename);
138 ExpandedFilename = Filename;
139 }
140 PCWSTR pwszExt = PathFindExtensionW(ExpandedFilename);
141 if (!pwszExt)
142 {
143 ACDBG(L"Failed to find an extension: '%s'\r\n", (PCWSTR)ExpandedFilename);
144 return E_FAIL;
145 }
146 if (!wcsicmp(pwszExt, L".lnk"))
147 {
148 WCHAR Buffer[MAX_PATH];
149 if (!GetExeFromLnk(ExpandedFilename, Buffer, _countof(Buffer)))
150 {
151 ACDBG(L"Failed to read link target from: '%s'\r\n", (PCWSTR)ExpandedFilename);
152 return E_FAIL;
153 }
154 if (!wcsicmp(Buffer, ExpandedFilename))
155 {
156 ACDBG(L"Link redirects to itself: '%s'\r\n", (PCWSTR)ExpandedFilename);
157 return E_FAIL;
158 }
159 return InitFile(Buffer);
160 }
161
162 CString tmp;
163 if (tmp.GetEnvironmentVariable(L"SystemRoot"))
164 {
165 tmp += L"\\System32";
166 if (ExpandedFilename.GetLength() >= tmp.GetLength() &&
167 ExpandedFilename.Left(tmp.GetLength()).MakeLower() == tmp.MakeLower())
168 {
169 ACDBG(L"Ignoring System32: %s\r\n", (PCWSTR)ExpandedFilename);
170 return E_FAIL;
171 }
172 tmp.GetEnvironmentVariable(L"SystemRoot");
173 tmp += L"\\WinSxs";
174 if (ExpandedFilename.GetLength() >= tmp.GetLength() &&
175 ExpandedFilename.Left(tmp.GetLength()).MakeLower() == tmp.MakeLower())
176 {
177 ACDBG(L"Ignoring WinSxs: %s\r\n", (PCWSTR)ExpandedFilename);
178 return E_FAIL;
179 }
180 }
181
182 for (size_t n = 0; g_AllowedExtensions[n]; ++n)
183 {
184 if (!wcsicmp(g_AllowedExtensions[n], pwszExt))
185 {
186 m_Filename = ExpandedFilename;
187 ACDBG(L"Got: %s\r\n", (PCWSTR)ExpandedFilename);
188 m_IsSfcProtected = SfcIsFileProtected(NULL, m_Filename);
189 m_AllowPermLayer = AllowPermLayer(ExpandedFilename);
190 return S_OK;
191 }
192 }
193 ACDBG(L"Extension not included: '%s'\r\n", pwszExt);
194 return E_FAIL;
195 }
196
197 static BOOL GetLayerInfo(PCWSTR Filename, DWORD QueryFlags, PDWORD OSMode, PDWORD Enabledlayers, CSimpleArray<CString>& customLayers)
198 {
199 WCHAR wszLayers[MAX_LAYER_LENGTH] = { 0 };
200 DWORD dwBytes = sizeof(wszLayers);
201
202 *OSMode = *Enabledlayers = 0;
203 customLayers.RemoveAll();
204 if (!SdbGetPermLayerKeys(Filename, wszLayers, &dwBytes, QueryFlags))
205 return FALSE;
206
207 for (PWCHAR Layer = wcstok(wszLayers, L" "); Layer; Layer = wcstok(NULL, L" "))
208 {
209 size_t n;
210 for (n = 0; g_Layers[n].Name; ++n)
211 {
212 if (!wcsicmp(g_Layers[n].Name, Layer))
213 {
214 *Enabledlayers |= (1<<n);
215 break;
216 }
217 }
218 /* Did we find it? */
219 if (g_Layers[n].Name)
220 continue;
221
222 for (n = 0; g_CompatModes[n].Name; ++n)
223 {
224 if (!wcsicmp(g_CompatModes[n].Name, Layer))
225 {
226 *OSMode = n+1;
227 break;
228 }
229 }
230 /* Did we find it? */
231 if (g_CompatModes[n].Name)
232 continue;
233
234 /* Must be a 'custom' layer */
235 customLayers.Add(Layer);
236 }
237 return TRUE;
238 }
239
240 void CLayerUIPropPage::OnRefresh(HWND hWnd)
241 {
242 if (!GetLayerInfo(m_Filename, m_LayerQueryFlags, &m_RegistryOSMode, &m_RegistryEnabledLayers, m_RegistryCustomLayers))
243 m_RegistryOSMode = m_RegistryEnabledLayers = 0;
244
245 for (size_t n = 0; g_Layers[n].Name; ++n)
246 CheckDlgButton(hWnd, g_Layers[n].Id, (m_RegistryEnabledLayers & (1<<n)) ? BST_CHECKED : BST_UNCHECKED);
247
248 CheckDlgButton(hWnd, IDC_CHKRUNCOMPATIBILITY, m_RegistryOSMode ? BST_CHECKED : BST_UNCHECKED);
249
250 if (m_RegistryOSMode)
251 ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_COMPATIBILITYMODE), m_RegistryOSMode-1);
252
253 m_CustomLayers = m_RegistryCustomLayers;
254
255 /* TODO: visualize 'custom' layers! */
256
257 UpdateControls(hWnd);
258 }
259
260
261 static BOOL ArrayEquals(const CSimpleArray<CString>& lhs, const CSimpleArray<CString>& rhs)
262 {
263 if (lhs.GetSize() != rhs.GetSize())
264 return FALSE;
265
266 for (int n = 0; n < lhs.GetSize(); ++n)
267 {
268 if (lhs[n] != rhs[n])
269 return FALSE;
270 }
271 return TRUE;
272 }
273
274 BOOL CLayerUIPropPage::HasChanges() const
275 {
276 if (m_RegistryEnabledLayers != m_EnabledLayers)
277 return TRUE;
278
279 if (m_RegistryOSMode != m_OSMode)
280 return TRUE;
281
282 if (!ArrayEquals(m_RegistryCustomLayers, m_CustomLayers))
283 return TRUE;
284
285 return FALSE;
286 }
287
288 void CLayerUIPropPage::OnApply(HWND hWnd)
289 {
290 if (HasChanges())
291 {
292 BOOL bMachine = m_LayerQueryFlags == GPLK_MACHINE;
293
294 for (size_t n = 0; g_CompatModes[n].Name; ++n)
295 SetPermLayerState(m_Filename, g_CompatModes[n].Name, 0, bMachine, (n+1) == m_OSMode);
296
297 for (size_t n = 0; g_Layers[n].Name; ++n)
298 {
299 SetPermLayerState(m_Filename, g_Layers[n].Name, 0, bMachine, ((1<<n) & m_EnabledLayers) != 0);
300 }
301
302 /* Disable all old values */
303 for (int j = 0; j < m_RegistryCustomLayers.GetSize(); j++)
304 {
305 SetPermLayerState(m_Filename, m_RegistryCustomLayers[j].GetString(), 0, bMachine, FALSE);
306 }
307
308 /* Enable all new values */
309 for (int j = 0; j < m_CustomLayers.GetSize(); j++)
310 {
311 SetPermLayerState(m_Filename, m_CustomLayers[j].GetString(), 0, bMachine, TRUE);
312 }
313
314 SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATHW, (PCWSTR)m_Filename, NULL);
315 }
316 }
317
318 INT_PTR CLayerUIPropPage::InitDialog(HWND hWnd)
319 {
320 HWND cboMode = GetDlgItem(hWnd, IDC_COMPATIBILITYMODE);
321 for (size_t n = 0; g_CompatModes[n].Display; ++n)
322 ComboBox_AddString(cboMode, g_CompatModes[n].Display);
323 ComboBox_SetCurSel(cboMode, 5);
324
325 CComBSTR explanation;
326 if (!m_AllowPermLayer)
327 {
328 explanation.LoadString(g_hModule, IDS_FAILED_NETWORK);
329 DisableControls(hWnd);
330 ACDBG(L"AllowPermLayer returned FALSE\r\n");
331 }
332 else if (m_IsSfcProtected)
333 {
334 explanation.LoadString(g_hModule, IDS_FAILED_PROTECTED);
335 DisableControls(hWnd);
336 ACDBG(L"Protected OS file\r\n");
337 }
338 else
339 {
340 return TRUE;
341 }
342 SetDlgItemTextW(hWnd, IDC_EXPLANATION, explanation);
343 return TRUE;
344 }
345
346 INT_PTR CLayerUIPropPage::DisableControls(HWND hWnd)
347 {
348 EnableWindow(GetDlgItem(hWnd, IDC_COMPATIBILITYMODE), 0);
349 EnableWindow(GetDlgItem(hWnd, IDC_CHKRUNCOMPATIBILITY), 0);
350 for (size_t n = 0; g_Layers[n].Name; ++n)
351 EnableWindow(GetDlgItem(hWnd, g_Layers[n].Id), 0);
352 EnableWindow(GetDlgItem(hWnd, IDC_EDITCOMPATIBILITYMODES), 0);
353 return TRUE;
354 }
355
356 void CLayerUIPropPage::UpdateControls(HWND hWnd)
357 {
358 m_OSMode = 0, m_EnabledLayers = 0;
359 BOOL ModeEnabled = IsDlgButtonChecked(hWnd, IDC_CHKRUNCOMPATIBILITY);
360 if (ModeEnabled)
361 m_OSMode = ComboBox_GetCurSel(GetDlgItem(hWnd, IDC_COMPATIBILITYMODE))+1;
362 EnableWindow(GetDlgItem(hWnd, IDC_COMPATIBILITYMODE), ModeEnabled);
363
364 for (size_t n = 0; g_Layers[n].Name; ++n)
365 {
366 m_EnabledLayers |= IsDlgButtonChecked(hWnd, g_Layers[n].Id) ? (1<<n) : 0;
367 ShowWindow(GetDlgItem(hWnd, g_Layers[n].Id), SW_SHOW);
368 }
369
370 if (HasChanges())
371 {
372 PropSheet_Changed(GetParent(hWnd), hWnd);
373 }
374 else
375 {
376 PropSheet_UnChanged(GetParent(hWnd), hWnd);
377 }
378 }
379
380 INT_PTR CLayerUIPropPage::OnCommand(HWND hWnd, WORD id)
381 {
382 switch (id)
383 {
384 case IDC_CHKRUNCOMPATIBILITY:
385 UpdateControls(hWnd);
386 break;
387 case IDC_COMPATIBILITYMODE:
388 UpdateControls(hWnd);
389 break;
390 case IDC_CHKRUNIN256COLORS:
391 case IDC_CHKRUNIN640480RES:
392 case IDC_CHKDISABLEVISUALTHEMES:
393 UpdateControls(hWnd);
394 break;
395 case IDC_EDITCOMPATIBILITYMODES:
396 if (DialogBoxParam(g_hModule, MAKEINTRESOURCE(IDD_EDITCOMPATIBILITYMODES), hWnd, EditModesProc, (LPARAM)this) == IDOK)
397 {
398 UpdateControls(hWnd);
399 }
400 break;
401 }
402 return FALSE;
403 }
404
405 INT_PTR CALLBACK CLayerUIPropPage::PropDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
406 {
407 CLayerUIPropPage* page = NULL;
408
409 switch (uMsg)
410 {
411 case WM_INITDIALOG:
412 page = (CLayerUIPropPage*)((LPPROPSHEETPAGE)lParam)->lParam;
413 SetProp(hWnd, ACP_WNDPROP, page);
414 return page->InitDialog(hWnd);
415
416 case WM_ENDSESSION:
417 case WM_DESTROY:
418 page = (CLayerUIPropPage*)GetProp(hWnd, ACP_WNDPROP);
419 RemoveProp(hWnd, ACP_WNDPROP);
420 page->Release();
421 break;
422
423 case WM_COMMAND:
424 page = (CLayerUIPropPage*)GetProp(hWnd, ACP_WNDPROP);
425 return page->OnCommand(hWnd, LOWORD(wParam));
426 case WM_NOTIFY:
427 switch (((LPNMHDR)lParam)->code)
428 {
429 case PSN_SETACTIVE:
430 if (((LPNMHDR)lParam)->hwndFrom == GetParent(hWnd))
431 {
432 page = (CLayerUIPropPage*)GetProp(hWnd, ACP_WNDPROP);
433 page->OnRefresh(hWnd);
434 }
435 break;
436 case PSN_APPLY:
437 if (((LPNMHDR)lParam)->hwndFrom == GetParent(hWnd))
438 {
439 page = (CLayerUIPropPage*)GetProp(hWnd, ACP_WNDPROP);
440 page->OnApply(hWnd);
441 }
442 break;
443 case NM_CLICK:
444 case NM_RETURN:
445 if (((LPNMHDR)lParam)->idFrom == IDC_INFOLINK)
446 {
447 ShellExecute(NULL, L"open", L"https://www.reactos.org/forum/viewforum.php?f=4", NULL, NULL, SW_SHOW);
448 }
449 break;
450 default:
451 break;
452 }
453 break;
454 }
455
456 return FALSE;
457 }
458
459 static void ListboxChanged(HWND hWnd)
460 {
461 int Sel = ListBox_GetCurSel(GetDlgItem(hWnd, IDC_COMPATIBILITYMODE));
462 EnableWindow(GetDlgItem(hWnd, IDC_EDIT), Sel >= 0);
463 EnableWindow(GetDlgItem(hWnd, IDC_DELETE), Sel >= 0);
464 }
465
466 static void OnAdd(HWND hWnd)
467 {
468 HWND Combo = GetDlgItem(hWnd, IDC_NEWCOMPATIBILITYMODE);
469
470 int Length = ComboBox_GetTextLength(Combo);
471 CComBSTR Str(Length);
472 ComboBox_GetText(Combo, Str, Length+1);
473 HWND List = GetDlgItem(hWnd, IDC_COMPATIBILITYMODE);
474 int Index = ListBox_FindStringExact(List, -1, Str);
475 if (Index == LB_ERR)
476 Index = ListBox_AddString(List, Str);
477 ListBox_SetCurSel(List, Index);
478 ListboxChanged(hWnd);
479 ComboBox_SetCurSel(Combo, -1);
480 SetFocus(Combo);
481 }
482
483 static BOOL ComboHasData(HWND hWnd)
484 {
485 HWND Combo = GetDlgItem(hWnd, IDC_NEWCOMPATIBILITYMODE);
486 if (ComboBox_GetCurSel(Combo) >= 0)
487 return TRUE;
488 ULONG Len = ComboBox_GetTextLength(Combo);
489 return Len > 0;
490 }
491
492 INT_PTR CALLBACK CLayerUIPropPage::EditModesProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
493 {
494 CLayerUIPropPage* page = NULL;
495
496 switch (uMsg)
497 {
498 case WM_INITDIALOG:
499 page = (CLayerUIPropPage*)lParam;
500 page->AddRef();
501 SetProp(hWnd, ACP_WNDPROP, page);
502 {
503 HWND Combo = GetDlgItem(hWnd, IDC_NEWCOMPATIBILITYMODE);
504 CComObject<CLayerStringList> pList;
505
506 while (TRUE)
507 {
508 CComBSTR str;
509 HRESULT hr = pList.Next(1, &str, NULL);
510 if (hr != S_OK)
511 break;
512 ComboBox_AddString(Combo, str);
513 }
514
515 HWND List = GetDlgItem(hWnd, IDC_COMPATIBILITYMODE);
516 for (int n = 0; n < page->m_CustomLayers.GetSize(); ++n)
517 {
518 const WCHAR* Str = page->m_CustomLayers[n].GetString();
519 int Index = ListBox_FindStringExact(List, -1, Str);
520 if (Index == LB_ERR)
521 Index = ListBox_AddString(List, Str);
522 }
523 }
524 break;
525 case WM_ENDSESSION:
526 case WM_DESTROY:
527 page = (CLayerUIPropPage*)GetProp(hWnd, ACP_WNDPROP);
528 RemoveProp(hWnd, ACP_WNDPROP);
529 page->Release();
530 break;
531
532 case WM_COMMAND:
533 switch(LOWORD(wParam))
534 {
535 case IDC_ADD:
536 OnAdd(hWnd);
537 break;
538 case IDC_EDIT:
539 {
540 HWND List = GetDlgItem(hWnd, IDC_COMPATIBILITYMODE);
541 int Cur = ListBox_GetCurSel(List);
542 int Length = ListBox_GetTextLen(List, Cur);
543 CComBSTR Str(Length);
544 ListBox_GetText(List, Cur, Str);
545 ListBox_DeleteString(List, Cur);
546 HWND Combo = GetDlgItem(hWnd, IDC_NEWCOMPATIBILITYMODE);
547 ComboBox_SetCurSel(Combo, -1);
548 ComboBox_SetText(Combo, Str);
549 ListboxChanged(hWnd);
550 ComboBox_SetEditSel(Combo, 30000, 30000);
551 SetFocus(Combo);
552 }
553 break;
554 case IDC_DELETE:
555 {
556 HWND List = GetDlgItem(hWnd, IDC_COMPATIBILITYMODE);
557 ListBox_DeleteString(List, ListBox_GetCurSel(List));
558 ListboxChanged(hWnd);
559 }
560 break;
561 case IDC_COMPATIBILITYMODE:
562 ListboxChanged(hWnd);
563 break;
564 case IDC_NEWCOMPATIBILITYMODE:
565 {
566 EnableWindow(GetDlgItem(hWnd, IDC_ADD), ComboHasData(hWnd));
567 }
568 break;
569 case IDOK:
570 /* Copy from list! */
571 {
572 if (ComboHasData(hWnd))
573 {
574 CComBSTR question, title;
575 title.LoadString(g_hModule, IDS_TABTITLE);
576 question.LoadString(g_hModule, IDS_YOU_DID_NOT_ADD);
577 int result = MessageBoxW(hWnd, question, title, MB_YESNOCANCEL | MB_ICONQUESTION);
578 switch (result)
579 {
580 case IDYES:
581 OnAdd(hWnd);
582 break;
583 case IDNO:
584 break;
585 case IDCANCEL:
586 return FALSE;
587 }
588 }
589
590 page = (CLayerUIPropPage*)GetProp(hWnd, ACP_WNDPROP);
591
592 HWND List = GetDlgItem(hWnd, IDC_COMPATIBILITYMODE);
593 int Count = ListBox_GetCount(List);
594 page->m_CustomLayers.RemoveAll();
595 for (int Cur = 0; Cur < Count; ++Cur)
596 {
597 int Length = ListBox_GetTextLen(List, Cur);
598 CString Str;
599 LPWSTR Buffer = Str.GetBuffer(Length + 1);
600 ListBox_GetText(List, Cur, Buffer);
601 Str.ReleaseBuffer(Length);
602 page->m_CustomLayers.Add(Str);
603 }
604 }
605 /* Fall trough */
606 case IDCANCEL:
607 EndDialog(hWnd, LOWORD(wParam));
608 break;
609 }
610 break;
611 case WM_CLOSE:
612 EndDialog(hWnd, IDCANCEL);
613 break;
614 }
615 return FALSE;
616 }
617
618 static BOOL DisableShellext()
619 {
620 HKEY hkey;
621 LSTATUS ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\Microsoft\\Windows\\AppCompat", 0, KEY_QUERY_VALUE, &hkey);
622 BOOL Disable = FALSE;
623 if (ret == ERROR_SUCCESS)
624 {
625 DWORD dwValue = 0;
626 DWORD type, size = sizeof(dwValue);
627 ret = RegQueryValueExW(hkey, L"DisableEngine", NULL, &type, (PBYTE)&dwValue, &size);
628 if (ret == ERROR_SUCCESS && type == REG_DWORD)
629 {
630 Disable = !!dwValue;
631 }
632 if (!Disable)
633 {
634 size = sizeof(dwValue);
635 ret = RegQueryValueExW(hkey, L"DisablePropPage", NULL, &type, (PBYTE)&dwValue, &size);
636 if (ret == ERROR_SUCCESS && type == REG_DWORD)
637 {
638 Disable = !!dwValue;
639 }
640 }
641
642 RegCloseKey(hkey);
643 }
644 return Disable;
645 }
646
647 STDMETHODIMP CLayerUIPropPage::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hkeyProgID)
648 {
649 FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
650 STGMEDIUM stg;
651
652 if (DisableShellext())
653 return E_ACCESSDENIED;
654
655 HRESULT hr = pDataObj->GetData(&etc, &stg);
656 if (FAILED(hr))
657 {
658 ACDBG(L"Failed to retrieve Data from pDataObj.\r\n");
659 return E_INVALIDARG;
660 }
661 hr = E_FAIL;
662 HDROP hdrop = (HDROP)GlobalLock(stg.hGlobal);
663 if (hdrop)
664 {
665 UINT uNumFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, NULL, 0);
666 if (uNumFiles == 1)
667 {
668 WCHAR szFile[MAX_PATH * 2];
669 if (DragQueryFileW(hdrop, 0, szFile, _countof(szFile)))
670 {
671 this->AddRef();
672 hr = InitFile(szFile);
673 }
674 else
675 {
676 ACDBG(L"Failed to query the file.\r\n");
677 }
678 }
679 else
680 {
681 ACDBG(L"Invalid number of files: %d\r\n", uNumFiles);
682 }
683 GlobalUnlock(stg.hGlobal);
684 }
685 else
686 {
687 ACDBG(L"Could not lock stg.hGlobal\r\n");
688 }
689 ReleaseStgMedium(&stg);
690 return hr;
691 }
692
693 STDMETHODIMP CLayerUIPropPage::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
694 {
695 PROPSHEETPAGEW psp = { 0 };
696 psp.dwSize = sizeof(psp);
697 psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE;
698 psp.hInstance = g_hModule;
699 psp.pszTemplate = MAKEINTRESOURCE(IDD_ACPPAGESHEET);
700 psp.pszTitle = MAKEINTRESOURCE(IDS_TABTITLE);
701 psp.pfnDlgProc = PropDlgProc;
702 psp.lParam = (LPARAM)this;
703 psp.pcRefParent = (PUINT)&g_ModuleRefCnt;
704 HPROPSHEETPAGE hPage = CreatePropertySheetPageW(&psp);
705 if (hPage && !pfnAddPage(hPage, lParam))
706 DestroyPropertySheetPage(hPage);
707
708 return S_OK;
709 }