reactos/dll/shellext/slayer/slayer.c
Hermès Bélusca-Maïto 65ce146169 Create a branch for working on csrss and co.
svn path=/branches/ros-csrss/; revision=57561
2012-10-14 13:04:31 +00:00

1144 lines
31 KiB
C

/*
* ReactOS Compatibility Layer Shell Extension
* Copyright (C) 2004 - 2005 ReactOS Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* $Id$
*
* PROJECT: ReactOS Compatibility Layer Shell Extension
* FILE: lib/shellext/cplsample/cplsample.c
* PURPOSE: ReactOS Compatibility Layer Shell Extension
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
* 09/25/2004 Created
*/
#include <precomp.h>
HINSTANCE hInstance = NULL;
static LONG dllrefs = 0;
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,
};
/******************************************************************************
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;
SendMessage(hListBox,
LB_RESETCONTENT,
0,
0);
for (item = info->CItems, i = 0;
item != NULL;
item = item->next, i++)
{
SendMessage(hListBox,
LB_ADDSTRING,
0,
(LPARAM)item->szName);
}
if (bDisableControlsIfEmpty)
{
}
}
static 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 && sel != NULL;
i--)
{
sel = sel->next;
}
/* 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);
}
static 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;
}
static 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 = {0};
HPROPSHEETPAGE hPage;
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 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
DllRegisterServer(VOID)
{
LONG e = E_ACCESSDENIED;
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 TCHAR 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 WINAPI
DllMain(HINSTANCE hinstDLL,
DWORD dwReason,
LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
hInstance = hinstDLL;
DisableThreadLibraryCalls(hInstance);
break;
}
return TRUE;
}