diff --git a/reactos/Makefile b/reactos/Makefile index 8ba0d33fecd..d96f7078e38 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.249 2004/09/15 10:16:05 mf Exp $ +# $Id: Makefile,v 1.250 2004/09/26 09:56:22 weiden Exp $ # # Global makefile # @@ -46,6 +46,9 @@ DLLS_KBD = kbddv kbdfr kbdgr kbdse kbduk kbdus # Control Panels DLLS_CPL = cpl +# Shell extensions +DLLS_SHELLEXT = shellext + # User mode libraries # libpcap packet epsapi DLLS = acledit aclui advapi32 advpack cabinet cards comctl32 crtdll comdlg32 d3d8thk expat fmifs freetype \ @@ -54,7 +57,7 @@ DLLS = acledit aclui advapi32 advpack cabinet cards comctl32 crtdll comdlg32 d3d richedit rpcrt4 samlib secur32 setupapi shell32 shlwapi snmpapi syssetup twain unicode user32 \ userenv version wininet winmm winspool ws2help ws2_32 wsock32 wshirda \ dnsapi \ - $(DLLS_KBD) $(DLLS_CPL) + $(DLLS_KBD) $(DLLS_CPL) $(DLLS_SHELLEXT) SUBSYS = smss win32k csrss ntvdm diff --git a/reactos/lib/shellext/Makefile b/reactos/lib/shellext/Makefile new file mode 100644 index 00000000000..6887ecdeca2 --- /dev/null +++ b/reactos/lib/shellext/Makefile @@ -0,0 +1,55 @@ +# +# ReactOS shell extensions makefile +# + +PATH_TO_TOP = ../.. + +include $(PATH_TO_TOP)/rules.mak + +SHELL_EXTENSIONS = slayer + +all: $(SHELL_EXTENSIONS) + +depends: + +implib: $(SHELL_EXTENSIONS:%=%_implib) + +test: $(SHELL_EXTENSIONS:%=%_test) + +clean: $(SHELL_EXTENSIONS:%=%_clean) + +install: $(SHELL_EXTENSIONS:%=%_install) + +bootcd: $(SHELL_EXTENSIONS:%=%_bootcd) + +.PHONY: all depends implib clean install bootcd + + +# +# Control Panels +# +$(SHELL_EXTENSIONS): %: + $(MAKE) -C $* + +$(SHELL_EXTENSIONS:%=%_implib): %_implib: + $(MAKE) -C $* implib + +$(SHELL_EXTENSIONS:%=%_test): %_test: + $(MAKE) -C $* test + +$(SHELL_EXTENSIONS:%=%_clean): %_clean: + $(MAKE) -C $* clean + +$(SHELL_EXTENSIONS:%=%_install): %_install: + $(MAKE) -C $* install + +$(SHELL_EXTENSIONS:%=%_bootcd): %_bootcd: + $(MAKE) -C $* bootcd + +.PHONY: $(SHELL_EXTENSIONS) $(SHELL_EXTENSIONS:%=%_implib) $(SHELL_EXTENSIONS:%=%_test) \ + $(SHELL_EXTENSIONS:%=%_clean) $(SHELL_EXTENSIONS:%=%_install) \ + $(SHELL_EXTENSIONS:%=%_bootcd) + + +etags: + find . -name "*.[ch]" -print | etags --language=c - diff --git a/reactos/lib/shellext/slayer/.cvsignore b/reactos/lib/shellext/slayer/.cvsignore new file mode 100644 index 00000000000..ee6046a948c --- /dev/null +++ b/reactos/lib/shellext/slayer/.cvsignore @@ -0,0 +1,8 @@ +*.coff +*.cpl +*.d +*.a +*.o +*.sym +*.map +*.tmp diff --git a/reactos/lib/shellext/slayer/Makefile b/reactos/lib/shellext/slayer/Makefile new file mode 100644 index 00000000000..5f26a89328a --- /dev/null +++ b/reactos/lib/shellext/slayer/Makefile @@ -0,0 +1,47 @@ +# $Id: Makefile,v 1.1 2004/09/26 09:56:23 weiden Exp $ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = slayer + +TARGET_INSTALLDIR = system32 + +TARGET_BASE = 0x5C7E0000 + +TARGET_CFLAGS = \ + -I./include \ + -DUNICODE \ + -D_UNICODE \ + -D__REACTOS__ \ + -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 -D__USE_W32API \ + -Wall \ + -Werror \ + -fno-builtin + +TARGET_LFLAGS = -nostartfiles + +TARGET_SDKLIBS = kernel32.a advapi32.a user32.a gdi32.a wine_uuid.a ole32.a \ + shell32.a comctl32.a comdlg32.a + +TARGET_GCCLIBS = gcc + +TARGET_PCH = + +TARGET_CLEAN = + +TARGET_OBJECTS = slayer.o + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/depend.mk + +%/TAGS: + etags -o $(@D)/TAGS $(@D)/\*.c + +etags: ./TAGS diff --git a/reactos/lib/shellext/slayer/en.rc b/reactos/lib/shellext/slayer/en.rc new file mode 100644 index 00000000000..b78d892695b --- /dev/null +++ b/reactos/lib/shellext/slayer/en.rc @@ -0,0 +1,38 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +IDD_SLAYERSHEET DIALOGEX 0, 0, 224, 226 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Compatibility" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "If you have problems running this program in ReactOS, select an operating system ReactOS should report to the application.", -1, 7,7,210,31 + GROUPBOX "Compatibility mode", IDC_COMPATGROUP, 7,41,210,49 + CHECKBOX "Run this program in compatibility mode for:", IDC_CHKRUNCOMPATIBILITY, 18,57,188,10, BS_AUTOCHECKBOX | WS_TABSTOP + COMBOBOX IDC_COMPATIBILITYMODE, 18,70,188,85, CBS_HASSTRINGS | CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED + GROUPBOX "Display settings", -1, 7,99,210,61, BS_GROUPBOX | WS_DISABLED + CHECKBOX "Run in 256 colors", IDC_CHKRUNIN256COLORS, 18,114,188,10, BS_AUTOCHECKBOX | WS_TABSTOP | WS_DISABLED + CHECKBOX "Run in 640x480 screenresolution", IDC_CHKRUNIN640480RES, 18,129,188,10, BS_AUTOCHECKBOX | WS_TABSTOP | WS_DISABLED + CHECKBOX "Disable visual themes", IDC_CHKDISABLEVISUALTHEMES, 18,144,188,10, BS_AUTOCHECKBOX | WS_TABSTOP | WS_DISABLED + PUSHBUTTON "E&dit compatibility modes...", IDC_EDITCOMPATIBILITYMODES, 117,167,100,15 + /* CONTROL "Learn more about program compatibility.", IDC_INFOLINK, "SysLink", WS_CHILD | WS_TABSTOP | WS_VISIBLE, 7,207,210,10, WS_EX_NOPARENTNOTIFY */ +END + +IDD_EDITCOMPATIBILITYMODES DIALOGEX 0, 0, 230, 139 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Compatibility Modes" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LISTBOX IDC_COMPATIBILITYMODE, 9,6,148,108, LBS_NOTIFY | LBS_WANTKEYBOARDINPUT | WS_BORDER + PUSHBUTTON "&Add...", IDC_ADD, 162,6,60,14, WS_DISABLED + PUSHBUTTON "&Edit...", IDC_EDIT, 162,24,60,14, WS_DISABLED + PUSHBUTTON "&Delete", IDC_DELETE, 162,42,60,14, WS_DISABLED + PUSHBUTTON "&OK", IDOK, 95,116,60,14 + PUSHBUTTON "&Cancel", IDCANCEL, 162,116,60,14 +END + +STRINGTABLE +BEGIN + IDS_SLAYER "Slayer" + IDS_DESCRIPTION "Application Compatibility Layer Shell Extension" +END + diff --git a/reactos/lib/shellext/slayer/resource.h b/reactos/lib/shellext/slayer/resource.h new file mode 100644 index 00000000000..a0f23b47fc3 --- /dev/null +++ b/reactos/lib/shellext/slayer/resource.h @@ -0,0 +1,24 @@ +#ifndef __SLAYER_RESOURCE_H +#define __SLAYER_RESOURCE_H + +#define IDD_SLAYERSHEET 100 +#define IDD_EDITCOMPATIBILITYMODES 101 + +#define IDC_CHKRUNCOMPATIBILITY 1001 +#define IDC_COMPATIBILITYMODE 1002 +#define IDC_CHKRUNIN256COLORS 1003 +#define IDC_CHKRUNIN640480RES 1004 +#define IDC_CHKDISABLEVISUALTHEMES 1005 +#define IDC_EDITCOMPATIBILITYMODES 1006 +#define IDC_INFOLINK 1007 +#define IDC_COMPATGROUP 1008 +#define IDC_ADD 1009 +#define IDC_EDIT 1010 +#define IDC_DELETE 1011 + +#define IDS_SLAYER 100 +#define IDS_DESCRIPTION 101 + +#endif /* __SLAYER_RESOURCE_H */ + +/* EOF */ diff --git a/reactos/lib/shellext/slayer/slayer.c b/reactos/lib/shellext/slayer/slayer.c new file mode 100644 index 00000000000..1a8a885780a --- /dev/null +++ b/reactos/lib/shellext/slayer/slayer.c @@ -0,0 +1,939 @@ +/* + * ReactOS + * Copyright (C) 2004 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: slayer.c,v 1.1 2004/09/26 09:56:23 weiden Exp $ + * + * PROJECT: ReactOS Compatibility Layer Shell Extension + * FILE: lib/shellext/cplsample/cplsample.c + * PURPOSE: ReactOS Compatibility Layer Shell Extension + * PROGRAMMER: Thomas Weidenmueller + * UPDATE HISTORY: + * 09/25/2004 Created + */ +#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */ +#define INITGUID +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "resource.h" +#include "slayer.h" + +HINSTANCE hInstance = NULL; +LONG dllrefs = 0; + +/* FIXME - they should be exported somewhere instead of defined here... */ +DEFINE_SHLGUID(IID_IPropSheetPage, 0x000214F6L, 0, 0); +DEFINE_SHLGUID(IID_IShellPropSheetExt, 0x000214E9L, 0, 0); + +/****************************************************************************** + ICompatibilityPage + ******************************************************************************/ + +static VOID +ClearCItemList(LPCOMPATIBILITYPAGE info) +{ + PCITEM item, next; + + for(item = info->CItems; + item != NULL; + item = next) + { + next = item->next; + HeapFree(GetProcessHeap(), 0, item); + } + + info->CSelectedItem = NULL; + info->CItems = NULL; + info->nItems = 0; +} + +static BOOL +ReadDWORDFlag(HKEY hk, LPTSTR szValueName, LPDWORD lpOutValue, DWORD dwDefault) +{ + DWORD dwType, dwSize = sizeof(DWORD); + LONG e = RegQueryValueEx(hk, + szValueName, + 0, + &dwType, + (LPBYTE)lpOutValue, + &dwSize); + + if(e != ERROR_SUCCESS || dwSize != sizeof(DWORD)) + { + *lpOutValue = dwDefault; + + return TRUE; + } + + return FALSE; +} + +static BOOL +LoadAndParseAppCompatibilityFlags(LPCOMPATIBILITYPAGE info, LPTSTR szValueName) +{ + LONG e; + HKEY hk; + DWORD dwType, dwSize; + TCHAR szStr[256]; + + e = RegOpenKey(HKEY_CURRENT_USER, + TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"), + &hk); + if(e == ERROR_SUCCESS) + { + dwSize = sizeof(szStr); + e = RegQueryValueEx(hk, + szValueName, + 0, + &dwType, + (LPBYTE)szStr, + &dwSize); + if(e == ERROR_SUCCESS) + { + /* FIXME - make sure the string is NULL-terminated! */ + TCHAR *c; + for(c = szStr; *c != TEXT('\0'); c++) + { + /* only the first word represents the compatibility mode */ + /* FIXME - parse all words! */ + if(*c == TEXT(' ')) + { + *c = TEXT('\0'); + break; + } + } + + info->CSelectedItem = NULL; + if(_tcslen(szStr) > 0) + { + PCITEM item; + + for(item = info->CItems; item != NULL; item = item->next) + { + if(!_tcsicmp(szStr, item->szKeyName)) + { + info->CSelectedItem = item; + break; + } + } + } + } + RegCloseKey(hk); + } + + return FALSE; +} + +static BOOL +LoadCompatibilityModes(LPCOMPATIBILITYPAGE info) +{ + BOOL Ret; + LONG e; + HKEY hk, hk2; + TCHAR szKey[256]; + + ClearCItemList(info); + + e = RegOpenKey(HKEY_CURRENT_USER, + TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"), + &hk); + if(e == ERROR_SUCCESS) + { + DWORD i; + PCITEM lastitem = NULL; + + for(i = 0; + (RegEnumKey(hk, i,szKey, sizeof(szKey) / sizeof(szKey[0])) == ERROR_SUCCESS); + i++) + { + e = RegOpenKey(hk, + szKey, + &hk2); + if(e == ERROR_SUCCESS) + { + DWORD dwType; + + e = RegQueryValueEx(hk2, + NULL, + 0, + &dwType, + NULL, + NULL); + if(e != ERROR_SUCCESS || (e == ERROR_SUCCESS && dwType == REG_SZ)) + { + PCITEM item; + + item = HeapAlloc(GetProcessHeap(), 0, sizeof(CITEM)); + if(item != NULL) + { + DWORD cdb = sizeof(item->szName); + + /* description */ + e = RegQueryValueEx(hk2, + NULL, + 0, + NULL, + (LPBYTE)item->szName, + &cdb); + + /* make sure it is null-terminated */ + if(cdb > sizeof(item->szName) - sizeof(item->szName[0])) + { + item->szName[(sizeof(item->szName) / sizeof(item->szName[0])) - 1] = TEXT('\0'); + } + if(e != ERROR_SUCCESS || + cdb < sizeof(item->szName[0])) + { + _tcscpy(item->szName, szKey); + e = ERROR_SUCCESS; + } + _tcscpy(item->szKeyName, szKey); + info->nItems++; + + ReadDWORDFlag(hk2, TEXT("MajorVersion"), &item->MajorVersion, 0); + ReadDWORDFlag(hk2, TEXT("MinorVersion"), &item->MinorVersion, 0); + ReadDWORDFlag(hk2, TEXT("BuildNumber"), &item->BuildNumber, 0); + ReadDWORDFlag(hk2, TEXT("PlatformId"), &item->PlatformId, 0); + ReadDWORDFlag(hk2, TEXT("SPMajorVersion"), &item->SPMajorVersion, 0); + ReadDWORDFlag(hk2, TEXT("SPMinorVersion"), &item->SPMinorVersion, 0); + + if(e == ERROR_SUCCESS) + { + item->next = NULL; + if(lastitem != NULL) + { + lastitem->next = item; + } + else + { + info->CItems = item; + } + lastitem = item; + } + else + { + HeapFree(GetProcessHeap(), 0, item); + } + } + } + + RegCloseKey(hk2); + } + + if(e != ERROR_SUCCESS) + { + e = ERROR_SUCCESS; + } + } + RegCloseKey(hk); + } + + Ret = ((e == ERROR_SUCCESS || e == ERROR_NO_MORE_ITEMS) ? TRUE : FALSE); + + return Ret; +} + +static VOID +FillComboBoxWithCompatibilityModes(LPCOMPATIBILITYPAGE info, HWND hwndDlg, HWND hCombo, BOOL bSelectItem, BOOL bDisableControlsIfEmpty) +{ + PCITEM item; + int i = 0; + BOOL sel = FALSE; + + SendMessage(hCombo, CB_RESETCONTENT, 0, 0); + + for(item = info->CItems; item != NULL; item = item->next) + { + int iIndex = (int)SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)item->szName); + if(item == info->CSelectedItem && bSelectItem) + { + SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iIndex, 0); + sel = TRUE; + } + i++; + } + + if(!sel && bSelectItem && i > 0) + { + /* select the first item */ + SendMessage(hCombo, CB_SETCURSEL, 0, 0); + } + + if(bDisableControlsIfEmpty) + { + BOOL enable = (i > 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_COMPATGROUP), enable); + EnableWindow(hCombo, (enable && sel)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CHKRUNCOMPATIBILITY), enable); + CheckDlgButton(hwndDlg, IDC_CHKRUNCOMPATIBILITY, ((enable && sel) ? BST_CHECKED : BST_UNCHECKED)); + } +} + +static VOID +FillEditListBoxWithCompatibilityModes(LPCOMPATIBILITYPAGE info, HWND hwndDlg, HWND hListBox, BOOL bDisableControlsIfEmpty) +{ + PCITEM item; + int i = 0; + + SendMessage(hListBox, LB_RESETCONTENT, 0, 0); + + for(item = info->CItems; item != NULL; item = item->next) + { + SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)item->szName); + i++; + } + + if(bDisableControlsIfEmpty) + { + } +} + +INT_PTR CALLBACK +EditCompatibilityModesProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LPCOMPATIBILITYPAGE this; + + switch(uMsg) + { + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + EndDialog(hwndDlg, IDOK); + break; + + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + } + break; + } + case WM_CLOSE: + { + EndDialog(hwndDlg, IDCANCEL); + break; + } + case WM_INITDIALOG: + { + HWND hList = GetDlgItem(hwndDlg, IDC_COMPATIBILITYMODE); + this = (LPCOMPATIBILITYPAGE)lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)this); + FillEditListBoxWithCompatibilityModes(this, hwndDlg, hList, FALSE); + break; + } + } + return FALSE; +} + +static VOID +InitializePage(LPCOMPATIBILITYPAGE this, HWND hwndDlg) +{ + HWND hList; + + LoadCompatibilityModes(this); + + /* initialize the controls */ + hList = GetDlgItem(hwndDlg, IDC_COMPATIBILITYMODE); + LoadAndParseAppCompatibilityFlags(this, this->szFile); + FillComboBoxWithCompatibilityModes(this, hwndDlg, hList, TRUE, TRUE); +} + +static VOID +ReportPropertyChange(LPCOMPATIBILITYPAGE this, HWND hwndDlg) +{ + this->Changed = TRUE; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); +} + +static BOOL +ComposeFlags(LPCOMPATIBILITYPAGE this, LPTSTR szFlags) +{ + if(this->CSelectedItem != NULL) + { + _tcscpy(szFlags, this->CSelectedItem->szKeyName); + return TRUE; + } + + return FALSE; +} + +static BOOL +ApplySettings(LPCOMPATIBILITYPAGE this, HWND hwndDlg) +{ + HKEY hk; + LONG e; + TCHAR szFlags[256]; + BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_CHKRUNCOMPATIBILITY) == BST_CHECKED; + + if(enabled) + { + HWND hCombo = GetDlgItem(hwndDlg, IDC_COMPATIBILITYMODE); + int index = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0); + if(index >= 0) + { + int i; + PCITEM sel = this->CItems; + + /* map the index to a CITEM structure */ + for(i = index; i > 0; i--) + { + sel = sel->next; + if(sel == NULL) + { + break; + } + } + + /* update the CSelectedItem member */ + this->CSelectedItem = sel; + } + else + enabled = FALSE; + } + + e = RegOpenKey(HKEY_CURRENT_USER, + TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"), + &hk); + if(e == ERROR_SUCCESS) + { + if(!enabled) + { + /* FIXME - only delete if nothing else is selected! */ + e = RegDeleteValue(hk, this->szFile); + } + else + { + if(ComposeFlags(this, szFlags)) + { + e = RegSetValueEx(hk, + this->szFile, + 0, + REG_SZ, + (LPBYTE)szFlags, + (_tcslen(szFlags) + 1) * sizeof(TCHAR)); + } + else + { + e = RegDeleteValue(hk, this->szFile); + } + } + + RegCloseKey(hk); + } + + this->Changed = FALSE; + return (e == ERROR_SUCCESS); +} + +INT_PTR CALLBACK +CompatibilityPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LPCOMPATIBILITYPAGE this = (LPCOMPATIBILITYPAGE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch(uMsg) + { + case WM_COMMAND: + { + if(HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMPATIBILITYMODE) + { + ReportPropertyChange(this, hwndDlg); + } + else + { + switch(LOWORD(wParam)) + { + case IDC_CHKRUNCOMPATIBILITY: + { + HWND hList = GetDlgItem(hwndDlg, IDC_COMPATIBILITYMODE); + if(hList != NULL) + { + EnableWindow(hList, IsDlgButtonChecked(hwndDlg, IDC_CHKRUNCOMPATIBILITY) == BST_CHECKED); + } + /* fall through */ + } + case IDC_CHKRUNIN256COLORS: + case IDC_CHKRUNIN640480RES: + case IDC_CHKDISABLEVISUALTHEMES: + ReportPropertyChange(this, hwndDlg); + break; + case IDC_EDITCOMPATIBILITYMODES: + { + if(DialogBoxParam(hInstance, + MAKEINTRESOURCE(IDD_EDITCOMPATIBILITYMODES), + hwndDlg, + EditCompatibilityModesProc, + (LPARAM)this) == IDOK) + { + InitializePage(this, hwndDlg); + } + break; + } + } + } + break; + } + + case WM_NOTIFY: + { + NMHDR *hdr = (NMHDR*)lParam; + switch(hdr->code) + { + case PSN_APPLY: + if(this->Changed) + { + return ApplySettings(this, hwndDlg); + } + break; + } + break; + } + + case WM_INITDIALOG: + { + LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE)lParam; + this = (LPCOMPATIBILITYPAGE)psp->lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)this); + + InitializePage(this, hwndDlg); + break; + } + } + + return FALSE; +} + +UINT CALLBACK +CompatibilityPageCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp) +{ + LPCOMPATIBILITYPAGE this = (LPCOMPATIBILITYPAGE)ppsp->lParam; + + switch(uMsg) + { + case PSPCB_CREATE: + return TRUE; + + case PSPCB_RELEASE: + ICompatibilityPage_fnRelease(this); + return FALSE; + + default: + return FALSE; + } +} + +static LPCOMPATIBILITYPAGE +ICompatibilityPage_fnConstructor(VOID) +{ + LPCOMPATIBILITYPAGE cp; + + cp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITYPAGE)); + if(cp != NULL) + { + cp->lpVtbl = &efvt; + cp->lpVtbl->fn.IShellPropSheetExt = efvtIShellPropSheetExt; + cp->ref = 1; + InterlockedIncrement(&dllrefs); + } + + return cp; +} + +HRESULT STDMETHODCALLTYPE +ICompatibilityPage_fnQueryInterface(LPCOMPATIBILITYPAGE this, REFIID iid, PVOID *pvObject) +{ + if(IsEqualIID(iid, &IID_IShellPropSheetExt)) + { + this->lpVtbl->fn.IShellPropSheetExt = efvtIShellPropSheetExt; + ICompatibilityPage_fnAddRef(this); + *pvObject = this; + return S_OK; + } + else if(IsEqualIID(iid, &IID_IShellExtInit)) + { + this->lpVtbl->fn.IShellExtInit = efvtIShellExtInit; + ICompatibilityPage_fnAddRef(this); + *pvObject = this; + return S_OK; + } + else if(IsEqualIID(iid, &IID_IClassFactory)) + { + this->lpVtbl->fn.IClassFactory = efvtIClassFactory; + ICompatibilityPage_fnAddRef(this); + *pvObject = this; + return S_OK; + } + else if(IsEqualIID(iid, &IID_IUnknown)) + { + ICompatibilityPage_fnAddRef(this); + *pvObject = this; + return S_OK; + } + + *pvObject = NULL; + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE +ICompatibilityPage_fnAddRef(LPCOMPATIBILITYPAGE this) +{ + return (ULONG)InterlockedIncrement(&this->ref); +} + +ULONG STDMETHODCALLTYPE +ICompatibilityPage_fnRelease(LPCOMPATIBILITYPAGE this) +{ + ULONG rfc; + + rfc = (ULONG)InterlockedDecrement(&this->ref); + if(rfc == 0) + { + HeapFree(GetProcessHeap(), 0, this); + InterlockedDecrement(&dllrefs); + } + return rfc; +} + +HRESULT STDMETHODCALLTYPE +ICompatibilityPage_fnAddPages(LPCOMPATIBILITYPAGE this, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) +{ + PROPSHEETPAGE psp; + HPROPSHEETPAGE hPage; + + ZeroMemory(&psp, sizeof(psp)); + + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK; + psp.hInstance = hInstance; + psp.pszTemplate = MAKEINTRESOURCE(IDD_SLAYERSHEET); + psp.pfnDlgProc = CompatibilityPageProc; + psp.lParam = (LPARAM)this; + psp.pfnCallback = CompatibilityPageCallback; + + hPage = CreatePropertySheetPage(&psp); + + if(hPage != NULL) + { + if(!lpfnAddPage(hPage, lParam)) + { + DestroyPropertySheetPage(hPage); + return E_OUTOFMEMORY; + } + + ICompatibilityPage_fnAddRef(this); + return S_OK; + } + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE +ICompatibilityPage_fnReplacePage(LPCOMPATIBILITYPAGE this, UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplacePage, LPARAM lParam) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE +ICompatibilityPage_fnInitialize(LPCOMPATIBILITYPAGE this, + LPCITEMIDLIST pidlFolder, + IDataObject *pdtobj, + HKEY hkeyProgID) +{ + FORMATETC fetc; + STGMEDIUM smdm; + + if(pdtobj == NULL) + { + return E_INVALIDARG; + } + + fetc.cfFormat = CF_HDROP; + fetc.ptd = NULL; + fetc.dwAspect = DVASPECT_CONTENT; + fetc.lindex = -1; + fetc.tymed = TYMED_HGLOBAL; + + if(SUCCEEDED(pdtobj->lpVtbl->GetData(pdtobj, &fetc, &smdm))) + { + UINT nFiles = DragQueryFile(smdm.hGlobal, 0xFFFFFFFF, this->szFile, sizeof(this->szFile) / sizeof(this->szFile[0])); + if(nFiles == 1) + { + /* FIXME - support editing of multiple files later */ + DragQueryFile(smdm.hGlobal, 0, this->szFile, sizeof(this->szFile) / sizeof(this->szFile[0])); + ReleaseStgMedium(&smdm); + + return S_OK; + } + } + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE +ICompatibilityPage_fnCreateInstance(LPCOMPATIBILITYPAGE this, + LPUNKNOWN pUnkOuter, + REFIID riid, + PVOID *ppvObject) +{ + LPCOMPATIBILITYPAGE cp; + + if(pUnkOuter != NULL && + !IsEqualIID(riid, &IID_IUnknown)) + { + return CLASS_E_NOAGGREGATION; + } + + cp = ICompatibilityPage_fnConstructor(); + if(cp != NULL) + { + HRESULT ret = ICompatibilityPage_fnQueryInterface(cp, riid, ppvObject); + ICompatibilityPage_fnRelease(cp); + return ret; + } + + return E_OUTOFMEMORY; +} + +HRESULT STDMETHODCALLTYPE +ICompatibilityPage_fnLockServer(LPCOMPATIBILITYPAGE this, + BOOL fLock) +{ + if(fLock) + { + InterlockedIncrement(&dllrefs); + } + else + { + InterlockedDecrement(&dllrefs); + } + + return S_OK; +} + +/****************************************************************************** + Exported + ******************************************************************************/ + +HRESULT STDCALL +DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +{ + if(ppv == NULL) + { + return E_INVALIDARG; + } + + if(IsEqualCLSID(&CLSID_ICompatibilityPage, rclsid)) + { + LPCOMPATIBILITYPAGE iface = ICompatibilityPage_fnConstructor(); + if(iface != NULL) + { + HRESULT ret = ICompatibilityPage_fnQueryInterface(iface, iid, ppv); + ICompatibilityPage_fnRelease(iface); + return ret; + } + return E_OUTOFMEMORY; + } + + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT STDCALL +DllCanUnloadNow(VOID) +{ + return ((dllrefs == 0) ? S_OK : S_FALSE); +} + +static int +UnregisterPropSheetHandler(LPTSTR szType) +{ + TCHAR szKey[255]; + + _stprintf(szKey, TEXT("%s\\shellex\\PropertySheetHandlers\\Compatibility Property Page"), szType); + return RegDeleteKey(HKEY_CLASSES_ROOT, + szKey); +} + +HRESULT STDCALL +DllUnregisterServer(VOID) +{ + LONG e; + HKEY hk; + WCHAR szGuid[40]; + + StringFromGUID2(&CLSID_ICompatibilityPage, szGuid, sizeof(szGuid) / sizeof(szGuid[0])); + e = RegOpenKey(HKEY_LOCAL_MACHINE, + TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), + &hk); + if(e == ERROR_SUCCESS) + { + e = RegDeleteValueW(hk, szGuid); + RegCloseKey(hk); + } + + if(e == ERROR_SUCCESS) + { + e = UnregisterPropSheetHandler(TEXT("exefile")); + } + + if(e == ERROR_SUCCESS) + { + e = RegOpenKey(HKEY_CLASSES_ROOT, + TEXT("CLSID"), + &hk); + if(e == ERROR_SUCCESS) + { + TCHAR szInprocKey[255]; + _stprintf(szInprocKey, TEXT("%ws\\InprocServer32"), szGuid); + + e = RegDeleteKey(hk, + szInprocKey); + if(e == ERROR_SUCCESS) + { + e = RegDeleteKeyW(hk, + szGuid); + } + RegCloseKey(hk); + } + } + + return ((e == ERROR_SUCCESS) ? S_OK : E_ACCESSDENIED); +} + +static int +RegisterPropSheetHandler(LPTSTR szType, LPWSTR szGuid) +{ + TCHAR szKey[255]; + HKEY hk; + int e; + + _stprintf(szKey, TEXT("%s\\shellex\\PropertySheetHandlers\\Compatibility Property Page"), szType); + e = RegCreateKey(HKEY_CLASSES_ROOT, + szKey, + &hk); + if(e == ERROR_SUCCESS) + { + e = RegSetValueExW(hk, + NULL, + 0, + REG_SZ, + (BYTE*)szGuid, + (wcslen(szGuid) + 1) * sizeof(WCHAR)); + RegCloseKey(hk); + } + + return e; +} + +HRESULT STDCALL +DllRegisterServer(VOID) +{ + LONG e; + HKEY hk; + WCHAR szGuid[40]; + WCHAR szDescription[255]; + TCHAR szModule[MAX_PATH + 1]; + int lnszDescription; + + if(!GetModuleFileName(hInstance, szModule, sizeof(szModule) / sizeof(szModule[0]))) + { + return E_ACCESSDENIED; + } + + /* unregister first */ + DllUnregisterServer(); + + lnszDescription = LoadStringW(hInstance, IDS_DESCRIPTION, szDescription, sizeof(szDescription) / sizeof(szDescription[0])); + if(lnszDescription > 0) + { + StringFromGUID2(&CLSID_ICompatibilityPage, szGuid, sizeof(szGuid) / sizeof(szGuid[0])); + + e = RegOpenKey(HKEY_LOCAL_MACHINE, + TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), + &hk); + if(e == ERROR_SUCCESS) + { + e = RegSetValueExW(hk, + szGuid, + 0, + REG_SZ, + (BYTE*)szDescription, + (lnszDescription + 1) * sizeof(WCHAR)); + RegCloseKey(hk); + } + + if(e == ERROR_SUCCESS) + { + TCHAR szInprocKey[255]; + _stprintf(szInprocKey, TEXT("CLSID\\%ws\\InprocServer32"), szGuid); + + e = RegCreateKey(HKEY_CLASSES_ROOT, + szInprocKey, + &hk); + if(e == ERROR_SUCCESS) + { + e = RegSetValueEx(hk, + NULL, + 0, + REG_SZ, + (BYTE*)szModule, + (_tcslen(szModule) + 1) * sizeof(TCHAR)); + if(e == ERROR_SUCCESS) + { + const LPTSTR szApartment = TEXT("Apartment"); + e = RegSetValueEx(hk, + TEXT("ThreadingModel"), + 0, + REG_SZ, + (BYTE*)szApartment, + (_tcslen(szApartment) + 1) * sizeof(TCHAR)); + } + + RegCloseKey(hk); + } + } + + if(e == ERROR_SUCCESS) + { + e = RegisterPropSheetHandler(TEXT("exefile"), szGuid); + } + } + + return ((e == ERROR_SUCCESS) ? S_OK : E_ACCESSDENIED); +} + +BOOL STDCALL +DllMain(HINSTANCE hinstDLL, + DWORD dwReason, + LPVOID lpvReserved) +{ + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + hInstance = hinstDLL; + DisableThreadLibraryCalls(hInstance); + break; + } + return TRUE; +} + diff --git a/reactos/lib/shellext/slayer/slayer.def b/reactos/lib/shellext/slayer/slayer.def new file mode 100644 index 00000000000..6330852ebf9 --- /dev/null +++ b/reactos/lib/shellext/slayer/slayer.def @@ -0,0 +1,9 @@ +LIBRARY slayer.dll + +EXPORTS +DllCanUnloadNow@0 +DllGetClassObject@12 +DllRegisterServer@0 +DllUnregisterServer@0 + +; EOF diff --git a/reactos/lib/shellext/slayer/slayer.h b/reactos/lib/shellext/slayer/slayer.h new file mode 100644 index 00000000000..6a141fe98e2 --- /dev/null +++ b/reactos/lib/shellext/slayer/slayer.h @@ -0,0 +1,154 @@ +#ifndef __SLAYER_H +#define __SLAYER_H + +extern HINSTANCE hInstance; + +typedef struct _CITEM +{ + struct _CITEM *next; + TCHAR szName[256]; + TCHAR szKeyName[256]; + DWORD MajorVersion; + DWORD MinorVersion; + DWORD BuildNumber; + DWORD PlatformId; + DWORD SPMajorVersion; + DWORD SPMinorVersion; +} CITEM, *PCITEM; + +/****************************************************************************** + ICompatibilityPage + ******************************************************************************/ + +DEFINE_GUID(CLSID_ICompatibilityPage, 0x513D916F, 0x2A8E, 0x4F51, 0x00AE, 0xAB,0x0C,0xBC,0x76,0xFB,0x1A,0xF9); /* F8 on XP! */ + +typedef struct ICompatibilityPage *LPCOMPATIBILITYPAGE; + +/* IShellPropSheetExt */ +typedef struct ifaceIShellPropSheetExtVbtl ifaceIShellPropSheetExtVbtl; +struct ifaceIShellPropSheetExtVbtl +{ + HRESULT (STDMETHODCALLTYPE *AddPages)(LPCOMPATIBILITYPAGE this, + LPFNADDPROPSHEETPAGE lpfnAddPage, + LPARAM lParam); + HRESULT (STDMETHODCALLTYPE *ReplacePage)(LPCOMPATIBILITYPAGE this, + UINT uPageID, + LPFNADDPROPSHEETPAGE lpfnReplacePage, + LPARAM lParam); +}; + +/* IShellExtInit */ +typedef struct ifaceIShellExtInitVbtl ifaceIShellExtInitVbtl; +struct ifaceIShellExtInitVbtl +{ + HRESULT (STDMETHODCALLTYPE *Initialize)(LPCOMPATIBILITYPAGE this, + LPCITEMIDLIST pidlFolder, + IDataObject *pdtobj, + HKEY hkeyProgID); +}; + +/* IClassFactory */ +typedef struct ifaceIClassFactoryVbtl ifaceIClassFactoryVbtl; +struct ifaceIClassFactoryVbtl +{ + HRESULT (STDMETHODCALLTYPE *CreateInstance)(LPCOMPATIBILITYPAGE this, + LPUNKNOWN pUnkOuter, + REFIID riid, + PVOID *ppvObject); + HRESULT (STDMETHODCALLTYPE *LockServer)(LPCOMPATIBILITYPAGE this, + BOOL fLock); +}; + +/* ICompatibilityPage */ +typedef struct ifaceICompatibilityPageVbtl ifaceICompatibilityPageVbtl; +struct ifaceICompatibilityPageVbtl +{ + /* IUnknown */ + HRESULT (STDMETHODCALLTYPE *QueryInterface)(LPCOMPATIBILITYPAGE this, + REFIID iid, + PVOID *pvObject); + ULONG (STDMETHODCALLTYPE *AddRef)(LPCOMPATIBILITYPAGE this); + ULONG (STDMETHODCALLTYPE *Release)(LPCOMPATIBILITYPAGE this); + + union + { + ifaceIShellPropSheetExtVbtl IShellPropSheetExt; + ifaceIShellExtInitVbtl IShellExtInit; + ifaceIClassFactoryVbtl IClassFactory; + } fn; +}; + +typedef struct ICompatibilityPage +{ + /* IUnknown fields */ + ifaceICompatibilityPageVbtl* lpVtbl; + LONG ref; + /* ICompatibilityPage fields */ + TCHAR szFile[MAX_PATH + 1]; + BOOL Changed; + + PCITEM CItems; + PCITEM CSelectedItem; + UINT nItems; +} COMPATIBILITYPAGE; + +/* IUnknown */ +HRESULT STDMETHODCALLTYPE ICompatibilityPage_fnQueryInterface(LPCOMPATIBILITYPAGE this, + REFIID iid, + PVOID *pvObject); +ULONG STDMETHODCALLTYPE ICompatibilityPage_fnAddRef(LPCOMPATIBILITYPAGE this); +ULONG STDMETHODCALLTYPE ICompatibilityPage_fnRelease(LPCOMPATIBILITYPAGE this); + +/* IShellPropSheetExt */ +HRESULT STDMETHODCALLTYPE ICompatibilityPage_fnAddPages(LPCOMPATIBILITYPAGE this, + LPFNADDPROPSHEETPAGE lpfnAddPage, + LPARAM lParam); +HRESULT STDMETHODCALLTYPE ICompatibilityPage_fnReplacePage(LPCOMPATIBILITYPAGE this, + UINT uPageID, + LPFNADDPROPSHEETPAGE lpfnReplacePage, + LPARAM lParam); +/* IShellExtInit */ +HRESULT STDMETHODCALLTYPE ICompatibilityPage_fnInitialize(LPCOMPATIBILITYPAGE this, + LPCITEMIDLIST pidlFolder, + IDataObject *pdtobj, + HKEY hkeyProgID); +/* IClassFactory */ +HRESULT STDMETHODCALLTYPE ICompatibilityPage_fnCreateInstance(LPCOMPATIBILITYPAGE this, + LPUNKNOWN pUnkOuter, + REFIID riid, + PVOID *ppvObject); +HRESULT STDMETHODCALLTYPE ICompatibilityPage_fnLockServer(LPCOMPATIBILITYPAGE this, + BOOL fLock); + + +static ifaceICompatibilityPageVbtl efvt = +{ + /* IUnknown methods */ + ICompatibilityPage_fnQueryInterface, + ICompatibilityPage_fnAddRef, + ICompatibilityPage_fnRelease, +}; + +static ifaceIShellPropSheetExtVbtl efvtIShellPropSheetExt = +{ + /* IShellPropSheetExt */ + ICompatibilityPage_fnAddPages, + ICompatibilityPage_fnReplacePage, +}; + +static ifaceIShellExtInitVbtl efvtIShellExtInit = +{ + /* IShellExtInit */ + ICompatibilityPage_fnInitialize, +}; + +static ifaceIClassFactoryVbtl efvtIClassFactory = +{ + /* IClassFactory */ + ICompatibilityPage_fnCreateInstance, + ICompatibilityPage_fnLockServer, +}; + +#endif /* __SLAYER_H */ + +/* EOF */ diff --git a/reactos/lib/shellext/slayer/slayer.rc b/reactos/lib/shellext/slayer/slayer.rc new file mode 100644 index 00000000000..c2a8178f362 --- /dev/null +++ b/reactos/lib/shellext/slayer/slayer.rc @@ -0,0 +1,41 @@ +#include +#include +#include "resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Compatibility Layer Shell Extension\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "slayer\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "slayer.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#include "en.rc" +