|
|
/*
* tweakui - User interface customization */
#include "tweakui.h"
#include <string.h>
/*
* Because prsht.h doesn't define it. */
typedef struct _PROPSHEETPAGE_V1 { DWORD dwSize; DWORD dwFlags; HINSTANCE hInstance; union { LPCSTR pszTemplate; LPCDLGTEMPLATE pResource; } DUMMYUNIONNAME; union { HICON hIcon; LPCSTR pszIcon; } DUMMYUNIONNAME2; LPCTSTR pszTitle; DLGPROC pfnDlgProc; LPARAM lParam; LPFNPSPCALLBACK pfnCallback; UINT FAR * pcRefParent; } PROPSHEETPAGE_V0, *LPPROPSHEETPAGE_V0;
#pragma BEGIN_CONST_DATA
HKEY CODESEG c_hkCR = hkCR; HKEY CODESEG c_hkCU = hkCU; HKEY CODESEG c_hkLM = hkLM;
KL const c_klNoRegedit = { &g_hkCUSMWCV, c_tszPoliciesSystem, c_tszNoRegedit }; KL const c_klIEVersion = { &g_hkLMSMIE, NULL, c_tszVersion };
#pragma END_CONST_DATA
/*
* Globals */ TCH g_tszName[80]; /* Program name goes here */ TCH g_tszMsdosSys[] = TEXT("@:\\MSDOS.SYS"); /* Boot file */
TCH g_tszPathShell32[MAX_PATH]; /* Full path to shell32.dll */ TCH g_tszPathMe[MAX_PATH]; /* Full path to myself */
PSF psfDesktop; /* Desktop IShellFolder */
HKEY g_hkLMSMWCV; /* HKLM\Software\MS\Win\CurrentVer */ HKEY g_hkCUSMWCV; /* HKCU\Software\MS\Win\CurrentVer */ HKEY g_hkLMSMIE; /* HKLM\Software\MS\IE */ HKEY g_hkCUSMIE; /* HKCU\Software\MS\IE */
HKEY g_hkLMSMWNTCV; /* HKLM\Software\MS\Win (NT)?\CurrentVer */
HINSTANCE hinstCur; DWORD g_dwShellVer;
UINT g_flWeirdStuff; /* What components are weird */
#define MIT_Item(a, b) b, /* Emit the ordinal and tag */
/*
* LOWORD(c_umit[iit]) == ordinal to obtain * HIWORD(c_umit[iit]) == 1 if we can survive without the function */ const DWORD c_umit[] = { MIT_Contents }; #undef MIT_Item
MIT mit;
/*
* Instanced */ CDII cdii;
/*****************************************************************************
* * iFromPtsz * * Parse an integer out of a string, skipping leading spaces. * Returns iErr on error. * *****************************************************************************/
int PASCAL iFromPtsz(LPTSTR ptsz) { int i; int sign;
while (*ptsz == ' ') ptsz++; if (*ptsz == '-') { sign = -1; ptsz++; } else { sign = 1; }
for (i = 0; (unsigned)(*ptsz - '0') < 10; ptsz++) { i = i * 10 + (*ptsz - '0'); if (i < 0) return iErr; } return sign * i; }
/*****************************************************************************
* * StrChr * * Return the first occurrence of ch in psz, or 0 if none. * *****************************************************************************/
LPTSTR PASCAL ptszStrChr(LPCTSTR ptsz, TCH tch) { for ( ; *ptsz; ptsz = CharNext(ptsz)) { if (*ptsz == tch) return (LPTSTR)ptsz; } return 0; }
/*****************************************************************************
* * ParseIconSpec * * Given an icon spec of the form "DLL,icon", parse out the icon * index and return it, changing the comma to a null, so that the * remaining stuff is a valid DLL name. * * If no comma is found, then the entire string is a DLL name, * and the icon index is zero. * *****************************************************************************/
int PASCAL ParseIconSpec(LPTSTR ptszSrc) { LPTSTR ptsz = ptszStrChr(ptszSrc, ','); if (ptsz) { *ptsz = '\0'; return iFromPtsz(ptsz+1); } else { return 0; } }
/*****************************************************************************
* * LoadIconId * * Load an icon by identifier. * *****************************************************************************/
HICON PASCAL LoadIconId(UINT id) { return LoadIcon(hinstCur, MAKEINTRESOURCE(id)); }
/*****************************************************************************
* * SafeDestroyIcon * * DestroyIcon, except it doesn't try to destroy the null icon. * *****************************************************************************/
void PASCAL SafeDestroyIcon(HICON hicon) { if (hicon) { DestroyIcon(hicon); } }
/*****************************************************************************
* * InitOpenFileName * * Initialize a COFN structure. * *****************************************************************************/
void PASCAL InitOpenFileName(HWND hwnd, PCOFN pcofn, UINT ids, LPCSTR pszInit) { int itchMax; TCH tch;
ZeroMemory(&pcofn->ofn, sizeof(pcofn->ofn)); pcofn->ofn.lStructSize |= sizeof(pcofn->ofn); pcofn->ofn.hwndOwner = hwnd; pcofn->ofn.lpstrFilter = pcofn->tszFilter; pcofn->ofn.lpstrFile = pcofn->tsz; pcofn->ofn.nMaxFile = MAX_PATH; pcofn->ofn.Flags |= OFN_HIDEREADONLY;
/* Get the filter string */ itchMax = LoadString(hinstCur, ids, pcofn->tszFilter, cA(pcofn->tszFilter));
if (itchMax) { /* Marker character must not be DBCS */ tch = pcofn->tszFilter[itchMax-1]; LPTSTR ptsz = pcofn->tszFilter; while (ptsz < &pcofn->tszFilter[itchMax]) { if (*ptsz == tch) *ptsz++ = '\0'; else ptsz = CharNext(ptsz); } }
/* Set the initial value */ lstrcpyn(pcofn->tsz, pszInit, cA(pcofn->tsz)); }
/*****************************************************************************
* * MessageBoxId * * Wrapper for MessageBox that uses an id instead of a string. * *****************************************************************************/
int PASCAL MessageBoxId(HWND hwnd, UINT id, LPCSTR pszTitle, UINT fl) { char szBuf[256]; LoadString(hinstCur, id, szBuf, cA(szBuf)); return MessageBox(hwnd, szBuf, pszTitle, fl); }
/*****************************************************************************
* * TweakUi_TrimTrailingBs * * Bs stands for backslash. Returns pointer to trailing 0. * *****************************************************************************/
PTSTR PASCAL TweakUi_TrimTrailingBs(LPTSTR ptsz) { ptsz = ptszFilenameCqn(ptsz); if (ptsz[0] == TEXT('\0')) { *--ptsz = TEXT('\0'); } else { ptsz += lstrlen(ptsz); } return ptsz; }
/*****************************************************************************
* * TweakUi_BuildPathToFile * * Callback procedure (GetWindowsDirectory or GetSystemDirectory) * generates the base directory. Then we cat the file to the path. * * ptszOut must be MAX_PATH bytes in length. * *****************************************************************************/
typedef UINT (CALLBACK *PATHPROC)(LPTSTR, UINT);
void PASCAL TweakUi_BuildPathToFile(PTSTR ptszOut, PATHPROC pfn, LPCTSTR ptszFile) { pfn(ptszOut, MAX_PATH); Path_Append(ptszOut, ptszFile); }
/*****************************************************************************
* * BuildRundll * * ptszOut must be 1024 bytes in length. * * ptszInUn is "I" for DefaultInstall, and "Uni" for DefaultUninstall. * * Builds the string * * "<windir>\rundll.exe setupx.dll,InstallHinfSection Default<x>nstall 4 " * * Returns a pointer to the terminating null, so you can put the * inf file name into place. * *****************************************************************************/
LPTSTR PASCAL BuildRundll(LPTSTR ptszOut, LPCTSTR ptszInUn) { TCH tszWindir[MAX_PATH]; TweakUi_BuildPathToFile(tszWindir, GetWindowsDirectory, c_tszNil); return ptszOut + wsprintf(ptszOut, g_fNT ? c_tszFormatRundllNT : c_tszFormatRundll, tszWindir, ptszInUn); }
/*****************************************************************************
* * RunShellInf * * Re-run the shell.inf file to fix the registry. * * The bad news is that CtlGetLdidPath is 16-bit, and we aren't. * * The "good" news is that there is currently no override to * put the Inf directory anywhere other than Windows\Inf, so we * can hard-code the Inf subdirectory name. * *****************************************************************************/
void PASCAL RunShellInf(HWND hwnd) { TCH tszOut[1024]; TweakUi_BuildPathToFile(BuildRundll(tszOut, c_tszI), GetWindowsDirectory, c_tszInfBsShellInf); WinExec(tszOut, SW_NORMAL); }
/*****************************************************************************
* * InitPpspDidDp * * Initialize a single PROPSHEETPAGE to load the dialog resource did * with dialog procedure dp. * * We must use the original property sheet page structure because * we need to run on Win95 Golden, which has the old comctl32. * * In particular, we cannot use DS_SHELLFONT because the old comctl32 * does not support DIALOGEX, which DS_SHELLFONT requires. * *****************************************************************************/
void PASCAL InitPpspResDp(LPPROPSHEETHEADER ppsh, LPCTSTR ptszDlg, DLGPROC dp) { LPPROPSHEETPAGE_V0 ppsp;
#ifdef DEBUG
if (ppsh->nPages >= MAX_TWEAKUIPAGES) { DebugBreak(); }
{ HRSRC hrsrc = FindResource(hinstCur, ptszDlg, RT_DIALOG); LPDLGTEMPLATE pdt = (LPDLGTEMPLATE)LoadResource(hinstCur, hrsrc); if (pdt && HIWORD(pdt->style) != 0xFFFF) { /* Template is okay */ } else { /* ERROR! Win95 Golden does not support DIALOGEX */ DebugBreak(); } }
#endif
ppsp = (LPPROPSHEETPAGE_V0)ppsh->ppsp; ppsp = &ppsp[ppsh->nPages++];
ppsp->dwSize = sizeof(PROPSHEETPAGE_V0); ppsp->dwFlags = PSP_DEFAULT; ppsp->hInstance = hinstCur; ppsp->pszTemplate = ptszDlg; ppsp->pfnDlgProc = dp; /* ppsp->lParam = ??; */ /* No refdata needed */ }
#define InitPpspDidDp(ppsh, did, dp) \
InitPpspResDp(ppsh, MAKEINTRESOURCE(did), dp)
/*****************************************************************************
* * Open * * Start the show. * *****************************************************************************/
void PASCAL Open(HWND hwnd) { PROPSHEETPAGE_V0 rgpsp[MAX_TWEAKUIPAGES]; PROPSHEETHEADER psh;
/*
* Make us Alt+Tab'able by removing WS_EX_TOOLWINDOW from our * parent's extended window style. */ SetWindowLong(hwnd, GWL_EXSTYLE, (LONG)(GetWindowExStyle(hwnd) & ~WS_EX_TOOLWINDOW));
/*
* Give our hidden parent an icon so the user can Alt+Tab to it. */ SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hinstCur, MAKEINTRESOURCE(IDI_DEFAULT)));
/* Init our cached pidls */ pcdii->pidlTemplates = NULL; SHGetSpecialFolderLocation(0, CSIDL_TEMPLATES, &pcdii->pidlTemplates);
psh.dwSize = PROPSHEETHEADER_V1_SIZE; psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK; psh.hwndParent = hwnd; psh.pszCaption = g_tszName; psh.nPages = 0; psh.nStartPage = 0; psh.ppsp = (PROPSHEETPAGE*)rgpsp; psh.pfnCallback = Prsht_PropertySheetCallback;
InitPpspDidDp(&psh, IDD_MOUSE, Mouse_DlgProc); InitPpspDidDp(&psh, IDD_GENERAL, General_DlgProc); InitPpspDidDp(&psh, IDD_EXPLORER, Explorer_DlgProc);
/*
* Display IE4 only if IE4 is installed. */ if (g_fIE4) { InitPpspDidDp(&psh, IDD_IE4, IE4_DlgProc); }
/*
* Display CMD only if NT5 is installed. */ if (g_fNT5) { InitPpspDidDp(&psh, IDD_CMD, Cmd_DlgProc); }
InitPpspDidDp(&psh, IDD_DESKTOP, Desktop_DlgProc);
/*
* Display My Computer only if the user has permission to * edit the appropriate registry key. */ if (RegCanModifyKey(g_hkCUSMWCV, c_tszRestrictions)) { InitPpspDidDp(&psh, IDD_MYCOMP, MyComp_DlgProc); }
InitPpspDidDp(&psh, IDD_CONTROL, Control_DlgProc);
/*
* Display Network only if the user has permission to * edit the appropriate registry key. */ if (RegCanModifyKey(g_hkLMSMWNTCV, c_tszWinlogon)) { InitPpspDidDp(&psh, IDD_NETWORK, Network_DlgProc); }
if (pcdii->pidlTemplates) { InitPpspDidDp(&psh, IDD_TOOLS, Template_DlgProc); }
/*
* Add/Remove Programs on NT5 is completely different. */ if (!g_fNT5) { InitPpspDidDp(&psh, IDD_ADDREMOVE, AddRm_DlgProc); }
#ifdef _X86_
if (g_tszMsdosSys[0] && !g_fNT && !g_fMillennium) { InitPpspDidDp(&psh, IDD_BOOT, Boot_DlgProc); } #endif
InitPpspDidDp(&psh, IDD_REPAIR, Repair_DlgProc); InitPpspDidDp(&psh, IDD_PARANOIA, Paranoia_DlgProc);
/*
* Common dialog features. */ if (RegCanModifyKey(g_hkCUSMWCV, TEXT("Policies")) && GetProcAddress(GetModuleHandle("COMDLG32"), "PrintDlgExA")) { InitPpspDidDp(&psh, IDD_COMDLG32, Comdlg32_DlgProc); }
pcdii->hmenu = LoadMenu(hinstCur, MAKEINTRESOURCE(IDM_MAIN)); _RegOpenKey(HKEY_CLASSES_ROOT, c_tszClsid, &pcdii->hkClsid); pcdii->himlState = ImageList_LoadImage(hinstCur, MAKEINTRESOURCE(IDB_CHECK), 0, 2, CLR_NONE, IMAGE_BITMAP, LR_LOADTRANSPARENT); pcdii->fRunShellInf = 0;
#ifndef DEBUG
/* Reinstall our run key in case somebody nuked it */ SetRegStr(g_hkLMSMWCV, c_tszRun, g_tszName, c_tszFixLink); #endif
#if defined(PRERELEASE) || defined(PUBLIC_PRERELEASE)
if (!IsExpired(hwnd)) #endif
switch (PropertySheet(&psh)) { case ID_PSRESTARTWINDOWS: if (pcdii->fRunShellInf) { RunShellInf(hwnd); } MessageBoxId(hwnd, IDS_LOGONOFF, g_tszName, MB_OK); break; }
RegCloseKey(pcdii->hkClsid); if (pcdii->hmenu) DestroyMenu(pcdii->hmenu);
/* Now free them cached shell things */ Ole_Free(pcdii->pidlTemplates); }
/*****************************************************************************
* * TweakUi_OnBadRun * * Somebody double-clicked our icon, but we aren't being run as * a control panel. Offer to install. * *****************************************************************************/
void PASCAL TweakUi_OnBadRun(HWND hwnd) { if (MessageBoxId(hwnd, IDS_BADRUN, g_tszName, MB_YESNO) == IDYES) { TCH tszOut[1024]; PTSTR ptsz; ptsz = BuildRundll(tszOut, c_tszI); lstrcpy(ptsz, g_tszPathMe); PTSTR ptszExt = ptszStrRChr(ptsz, TEXT('.')); if (ptszExt) { strcpy(ptszExt, c_tszDotInf); if (GetFileAttributes(ptsz) != (DWORD)-1) { WinExec(tszOut, SW_NORMAL); } else { MessageBoxId(hwnd, IDS_CANTINSTALL, g_tszName, MB_OK); } } else { MessageBoxId(hwnd, IDS_CANTINSTALL, g_tszName, MB_OK); } } }
/*****************************************************************************
* * CriticalInit * * Here is where we put the stuff to impede reverse-engineering. * * 1. All of our strings are encoded. Decode them now. * * 2. Get the shell32 internal entry points via GetProcAddress * so that a "hdr" won't see them. * *****************************************************************************/
HRESULT PASCAL CriticalInit(void) { int itch; int iit; HINSTANCE hinst;
itch = cA(c_rgtchCommon)-1; do { c_rgtchCommon[itch] ^= c_rgtchCommon[itch-1]; } while (--itch);
hinst = GetModuleHandle(c_tszShell32Dll); for (iit = 0; iit < sizeof(mit) / sizeof(LPCSTR); iit++) { DWORD dwOrd = c_umit[iit]; ((FARPROC *)&mit)[iit] = GetProcAddress(hinst, MAKEINTRESOURCE(dwOrd)); if (((FARPROC *)&mit)[iit] == 0 && !HIWORD(dwOrd)) { return E_FAIL; } } return Ole_Init(); }
/*****************************************************************************
* * GetObjectBuild * * Get the build number on the specified module, in the form * * 0xMMmmbbbb * * MM = major * mm = minor * bbbb = build * * The input parameter is either an OSVERSIONINFO or a DLLVERSIONINFO. * Fortunately, the two are the same in the places we care about. * *****************************************************************************/
DWORD PASCAL GetObjectBuild(LPOSVERSIONINFO posv) { return MAKELONG(LOWORD(posv->dwBuildNumber), MAKEWORD(posv->dwMinorVersion, posv->dwMajorVersion)); }
/*****************************************************************************
* * GetModuleBuild * * Get the build number on the specified module, in the form * * 0xMMmmbbbb * * MM = major * mm = minor * bbbb = build * * Returns 0 if DLL does not have DllGetVersion. * *****************************************************************************/
DWORD PASCAL GetModuleBuild(LPCTSTR ptszDll) { HINSTANCE hinst = GetModuleHandle(ptszDll); DLLGETVERSIONPROC DllGetVersion; DWORD dwRc; DllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinst, "DllGetVersion"); if (DllGetVersion) { DLLVERSIONINFO dvi; dvi.cbSize = sizeof(dvi); if (SUCCEEDED(DllGetVersion(&dvi))) { dwRc = GetObjectBuild((LPOSVERSIONINFO)&dvi); } else { dwRc = 0; } } else { dwRc = 0; } return dwRc; }
/*****************************************************************************
* * CheckWin95Versions * * Determine whether we're on Win95 OPK2 or later. We already know * that we're not Windows NT. * *****************************************************************************/
void PASCAL CheckWin95Versions(void) { BOOL fRc; OSVERSIONINFO osv; osv.dwOSVersionInfoSize = sizeof(osv); if (GetVersionEx(&osv)) { DWORD dwBuild = GetObjectBuild(&osv); if (dwBuild >= MAKELONG(1045, 0x0400)) { g_flWeirdStuff |= flbsOPK2; if (dwBuild >= MAKELONG(0, 0x040A)) { g_flWeirdStuff |= flbsMemphis; if (dwBuild >= MAKELONG(0, 0x045A)) { g_flWeirdStuff |= flbsMillennium; } } } } }
/*****************************************************************************
* * LibMain * * Initialize globals. * * Get our own name. * * Get our own path. * * Build path to shell32.dll. * *****************************************************************************/
BOOL FAR PASCAL LibMain(HINSTANCE hinst) { if (SUCCEEDED(CriticalInit())) { DWORD dwBuild; DWORD dwVersion;
RegCreateKey(HKEY_LOCAL_MACHINE, c_tszSMWCV, &g_hkLMSMWCV); RegCreateKey(HKEY_CURRENT_USER, c_tszSMWCV, &g_hkCUSMWCV); RegCreateKey(g_hkLMSMWCV, c_tszExplorer, &pcdii->hkLMExplorer); RegCreateKey(g_hkCUSMWCV, c_tszExplorer, &pcdii->hkCUExplorer);
RegOpenKey(hkLM, c_tszSMWIE, &g_hkLMSMIE); RegOpenKey(hkCU, c_tszSMWIE, &g_hkCUSMIE);
hinstCur = hinst; LoadString(hinst, IDS_NAME, g_tszName, cA(g_tszName));
dwBuild = GetModuleBuild(c_tszComCtl32Dll); if (dwBuild == 0) { g_flWeirdStuff |= flbsComCtl32; }
if (dwBuild >= MAKELONG(0, 0x447)) { /* 4.71 */ g_flWeirdStuff |= flbsSmoothScroll; }
dwVersion = GetVersion(); if ((LONG)dwVersion >= 0) { g_flWeirdStuff |= flbsNT; if (LOBYTE(dwVersion) >= 5) { g_flWeirdStuff |= flbsNT5; } } else { CheckWin95Versions(); }
g_dwShellVer = dwBuild = GetModuleBuild(c_tszShell32Dll); if (dwBuild || g_fNT) { g_flWeirdStuff |= flbsShellSz; }
/*
* Some things need to be turned off if IE5. Go figure. * Borrow g_tszPathMe for scratch space. */ if (GetStrPkl(g_tszPathMe, cA(g_tszPathMe), &c_klIEVersion) && iFromPtsz(g_tszPathMe) >= 5) { g_flWeirdStuff |= flbsIE5; }
GetModuleFileName(hinst, g_tszPathMe, cA(g_tszPathMe));
/*
* Check if we're being run from the proper directory. */ TweakUi_BuildPathToFile(g_tszPathShell32, GetSystemDirectory, c_tszTweakUICpl); if (lstrcmpi(g_tszPathMe, g_tszPathShell32)) { #ifndef DEBUG
g_flWeirdStuff |= flbsBadRun; /* Nope */ #endif
}
/*
* Stash the location of shell32. */ TweakUi_BuildPathToFile(g_tszPathShell32, GetSystemDirectory, c_tszShell32Dll);
/* See if we have an msdos.sys file to tweak */
#if defined(_X86_)
Boot_FindMsdosSys();
#endif
/*
* Build the platform-sensitive base key. */ RegCreateKey(hkLM, g_fNT ? c_tszSMWNTCV : c_tszSMWCV, &g_hkLMSMWNTCV);
InitCommonControls();
return 1; } else { return 0; } }
/*****************************************************************************
* * LibExit * * Clean up globals. * *****************************************************************************/
void PASCAL LibExit(void) { if (g_hkCUSMIE) { RegCloseKey(g_hkCUSMIE); } if (g_hkLMSMIE) { RegCloseKey(g_hkLMSMIE); } RegCloseKey(pcdii->hkCUExplorer); RegCloseKey(pcdii->hkLMExplorer); RegCloseKey(g_hkLMSMWCV); RegCloseKey(g_hkLMSMWNTCV); RegCloseKey(g_hkCUSMWCV); Ole_Term(); }
/*****************************************************************************
* * _DllMainCRTStartup * * Hi. * *****************************************************************************/
STDAPI_(BOOL) Entry32(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { return LibMain(hinst); } else if (dwReason == DLL_PROCESS_DETACH) { LibExit(); } return TRUE; }
/*****************************************************************************
* * CPlApplet * * Control panel entry point. * *****************************************************************************/
LRESULT EXPORT CPlApplet(HWND hwnd, UINT wm, LPARAM lp1, LPARAM lp2) { switch (wm) { case CPL_INIT: return 1; /* Yes I'm here */
case CPL_GETCOUNT: return 1; /* I provide one icon */
case CPL_INQUIRE: if (lp1 == 0) { /* For the zero'th icon... */ LPCPLINFO lpci = (LPCPLINFO)lp2; lpci->idIcon = IDI_DEFAULT; lpci->idName = IDS_NAME; lpci->idInfo = IDS_DESCRIPTION; /* lpci->lData = 0; */ /* Garbage doesn't hurt */ return 1; } else { return 0; /* Huh? */ }
/*
* Note! Do not open if registry tools have been disabled. * * This is particularly important for the Network page, which * lets the user view passwords! * * Make this check *before* checking for a bad run, so a * user can't do an end-run by just double-clicking the CPL. */ case CPL_DBLCLK: /* Hey, somebody's knocking */ if (GetDwordPkl(&c_klNoRegedit, 0)) { MessageBoxId(hwnd, IDS_RESTRICTED, g_tszName, MB_OK); } else if (!g_fBadRun) { Open(hwnd); } else { TweakUi_OnBadRun(hwnd); } break; }
return 0; }
/*****************************************************************************
* * WithSelector * * Call the callback after creating a particular selector alias to a * chunk of memory. The memory block is confirmed for read access, * or for write access if fWrite is set. * * Note that the validation doesn't work in Win16 if the data crosses * a page boundary, so be careful. * *****************************************************************************/
BOOL PASCAL WithSelector(DWORD_PTR lib, UINT cb, WITHPROC wp, LPVOID pvRef, BOOL fWrite) { BOOL fRc;
#ifdef WIN32
#define lpv (LPVOID)lib
#else
UINT sel = AllocSelector((UINT)hinstCur); if (sel) { SetSelectorBase(sel, lib); SetSelectorLimit(sel, cb); #define lpv MAKELP(sel, 0)
#endif
if (!IsBadReadPtr(lpv, cb) && !(fWrite && IsBadWritePtr(lpv, cb))) { fRc = wp(lpv, pvRef); } else { fRc = 0; } #undef lpv
#ifndef WIN32
FreeSelector(sel); } else { fRc = 0; } #endif
return fRc; }
/*****************************************************************************
* * TweakUi_OnLogon * * This hacks around two bugs. * * The first is a bug in Shell32, where a bad comparison causes the * Link registry key not to be restored properly. So we patch the * correct value into the registry for them. * * The second is a bug in commctrl where it gets confused by overlay * bitmaps with no pixels. * * And then we do the paranoia stuff. * *****************************************************************************/
void PASCAL TweakUi_OnLogon(void) { UINT cxIcon;
/*
* This shell bug was fixed sometime before July 1997, though I * can't tell exactly when. Definitely fixed before the ShellSz * support was added, so let's just use that. */ if (!g_fShellSz && !Link_GetShortcutTo()) { Link_SetShortcutTo(1); Link_SetShortcutTo(0); }
/*
* If the shell icon size is wacked out for some bizarre reason, * then unwack it. This is theoretically impossible, but somehow * it happens, so we fix it ex post facto. */ cxIcon = Misc_GetShellIconSize(); if (((cxIcon + 1) & 0x1F) == 0) { Misc_SetShellIconSize(cxIcon + 1); }
Explorer_HackPtui(); Paranoia_CoverTracks(); }
/*****************************************************************************
* * TweakUi_OnInstall * * Upgrade the previous version of Tweak UI. * * 1. Fix the LinkOverlay gizmo. If we have a buggy ComCtl32 and the * overlay is set to IDI_BLANK - 1, then set HackPtui. * #ifdef UPGRADE_V1_ICON
* 2. Rebuild the icon cache, to work around a bug in the control panel, * where it doesn't update its cached image properly when the cpl changes. #endif
* *****************************************************************************/
void PASCAL TweakUi_OnInstall(void) { TCHAR tsz[MAX_PATH];
if (g_fBuggyComCtl32 && Explorer_GetIconSpecFromRegistry(tsz) == IDI_BLANK - 1 && lstrcmpi(tsz, g_tszPathMe) == 0) { SetIntPkl(1, &c_klHackPtui); }
#ifdef UPGRADE_V1_ICON
/*
* We no longer try to upgrade the V1 icon because it tickles * the shell icon cache in a way that may expose pre-existing * corruption. */ Misc_RebuildIcoCache(); #endif
}
/*****************************************************************************
* * TweakUi_OnFix * * Put our Uninstall script back into the registry. * *****************************************************************************/
#pragma BEGIN_CONST_DATA
KL const c_klDisplayName = { &g_hkLMSMWCV, c_tszUninstallTweakUI, c_tszDisplayName }; KL const c_klUninstallString = { &g_hkLMSMWCV, c_tszUninstallTweakUI, c_tszUninstallString };
#pragma END_CONST_DATA
void EXPORT TweakUi_OnFix(HWND hwnd, BOOL fVerbose) { TCH tszOut[1024]; SetStrPkl(&c_klDisplayName, g_tszName); TweakUi_BuildPathToFile(BuildRundll(tszOut, c_tszUni), GetWindowsDirectory, c_tszInfBsTweakuiInf); SetStrPkl(&c_klUninstallString, tszOut); if (fVerbose) { MessageBoxId(hwnd, IDS_FIXED, g_tszName, MB_OK); } }
/*****************************************************************************
* * TweakMeUp * * Rundll entry point. * * The command line tells us what we're trying to do. * * Null command line - User has just logged on; do logon stuff. * * '0' - We've just been installed; upgrade the previous version. * Since unisntalling on NT is different from on Win95, we fall * through to... * * '1' - The user wants to restore the Uninstall string. * *****************************************************************************/
void EXPORT TweakMeUp(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { switch (lpszCmdLine[0]) { case '\0': TweakUi_OnLogon(); break; case '0': TweakUi_OnInstall(); TweakUi_OnFix(hwnd, 0); break; case '1': TweakUi_OnFix(hwnd, 1); break; } }
|