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