windows-nt/Source/XPSP1/NT/shell/applets/control/init.c
2020-09-26 16:20:57 +08:00

406 lines
15 KiB
C

//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
#include "control.h"
#include <cpl.h>
#include <cplp.h>
#include <shlwapi.h>
#include <shlwapip.h>
#include "rcids.h"
BOOL ImmDisableIME(DWORD dwThreadId);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// LEAVE THESE IN ENGLISH
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const TCHAR c_szCtlPanelClass[] = TEXT("CtlPanelClass");
const TCHAR c_szExplorer[] = TEXT("explorer.exe");
const TCHAR c_szRunDLL32[] = TEXT("rundll32.exe");
const TCHAR c_szRunDLLShell32Etc[] = TEXT("Shell32.dll,Control_RunDLL ");
const TCHAR c_szControlPanelFolder[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\"");
const TCHAR c_szDoPrinters[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}\"");
const TCHAR c_szDoFonts[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11d2-A40B-0C5020524152}\"");
const TCHAR c_szDoAdminTools[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11d2-A40B-0C5020524153}\"");
const TCHAR c_szDoSchedTasks[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}\"");
const TCHAR c_szDoNetConnections[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}\"");
const TCHAR c_szDoNetplwizUsers[] =
TEXT("netplwiz.dll,UsersRunDll");
const TCHAR c_szDoFolderOptions[] =
TEXT("shell32.dll,Options_RunDLL 0");
const TCHAR c_szDoScannerCamera[] =
TEXT("\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{E211B736-43FD-11D1-9EFB-0000F8757FCD}\"");
typedef struct
{
LPCTSTR szOldForm;
DWORD dwOS;
LPCTSTR szFile;
LPCTSTR szParameters;
} COMPATCPL;
#define OS_ANY ((DWORD)-1)
COMPATCPL const c_aCompatCpls[] =
{
{ TEXT("DESKTOP"), OS_ANY, TEXT("desk.cpl"), NULL },
{ TEXT("COLOR"), OS_ANY, TEXT("desk.cpl"), TEXT(",2") },
{ TEXT("DATE/TIME"), OS_ANY, TEXT("timedate.cpl"), NULL },
{ TEXT("PORTS"), OS_ANY, TEXT("sysdm.cpl"), TEXT(",1") },
{ TEXT("INTERNATIONAL"), OS_ANY, TEXT("intl.cpl"), NULL },
{ TEXT("MOUSE"), OS_ANY, TEXT("main.cpl"), NULL },
{ TEXT("KEYBOARD"), OS_ANY, TEXT("main.cpl"), TEXT("@1") },
{ TEXT("NETWARE"), OS_ANY, TEXT("nwc.cpl"), NULL },
{ TEXT("TELEPHONY"), OS_ANY, TEXT("telephon.cpl"), NULL },
{ TEXT("INFRARED"), OS_ANY, TEXT("irprops.cpl"), NULL },
{ TEXT("USERPASSWORDS"), OS_ANYSERVER, TEXT("lusrmgr.msc"), NULL },
{ TEXT("USERPASSWORDS"), OS_WHISTLERORGREATER, TEXT("nusrmgr.cpl"), NULL },
{ TEXT("USERPASSWORDS2"), OS_ANY, c_szRunDLL32, c_szDoNetplwizUsers },
{ TEXT("PRINTERS"), OS_ANY, c_szExplorer, c_szDoPrinters },
{ TEXT("FONTS"), OS_ANY, c_szExplorer, c_szDoFonts },
{ TEXT("ADMINTOOLS"), OS_ANY, c_szExplorer, c_szDoAdminTools },
{ TEXT("SCHEDTASKS"), OS_ANY, c_szExplorer, c_szDoSchedTasks },
{ TEXT("NETCONNECTIONS"), OS_ANY, c_szExplorer, c_szDoNetConnections },
{ TEXT("FOLDERS"), OS_ANY, c_szRunDLL32, c_szDoFolderOptions },
{ TEXT("SCANNERCAMERA"), OS_ANY, c_szExplorer, c_szDoScannerCamera },
{ TEXT("STICPL.CPL"), OS_ANY, c_szExplorer, c_szDoScannerCamera },
};
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Timer
#define TIMER_QUITNOW 1
#define TIMEOUT 10000
#define DM_CPTRACE 0
DWORD GetRegisteredCplPath(LPCTSTR pszNameIn, LPTSTR pszPathOut, UINT cchPathOut)
{
const HKEY rghkeyRoot[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER };
const TCHAR szSubkey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
DWORD dwResult = ERROR_INSUFFICIENT_BUFFER;
if (0 < cchPathOut)
{
int i;
*pszPathOut = TEXT('\0');
for (i = 0; i < ARRAYSIZE(rghkeyRoot) && TEXT('\0') == *pszPathOut; i++)
{
HKEY hkey;
dwResult = RegOpenKeyEx(rghkeyRoot[i],
szSubkey,
0,
KEY_QUERY_VALUE,
&hkey);
if (ERROR_SUCCESS == dwResult)
{
TCHAR szName[MAX_PATH]; // Destination for value name.
TCHAR szPath[MAX_PATH * 2]; // Destination for value data.
DWORD dwIndex = 0;
DWORD cbPath;
DWORD cchName;
DWORD dwType;
do
{
cchName = ARRAYSIZE(szName);
cbPath = sizeof(szPath);
dwResult = RegEnumValue(hkey,
dwIndex++,
szName,
&cchName,
NULL,
&dwType,
(LPBYTE)szPath,
&cbPath);
if (ERROR_SUCCESS == dwResult && sizeof(TCHAR) < cbPath)
{
if (REG_SZ == dwType || REG_EXPAND_SZ == dwType)
{
if (0 == lstrcmpi(pszNameIn, szName))
{
//
// We have a match. Expand the path if necessary.
//
TCHAR szExpanded[ARRAYSIZE(szPath)];
DWORD cchExpanded = ExpandEnvironmentStrings(szPath, szExpanded, ARRAYSIZE(szExpanded));
//
// Account for adding enclosing double quotes. Needed
// in case path contains embedded spaces.
//
if (cchExpanded && ((cchExpanded + 2) < cchPathOut))
{
wsprintf(pszPathOut, TEXT("\"%s\""), szExpanded);
}
}
}
else
{
//
// Invalid data type. Someone has hacked the registry.
// Continue searching.
//
}
}
}
while(ERROR_SUCCESS == dwResult && TEXT('\0') == *pszPathOut);
RegCloseKey(hkey);
}
}
}
return dwResult;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK DummyControlPanelProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam)
{
switch (uMsg)
{
case WM_CREATE:
DebugMsg(DM_CPTRACE, TEXT("cp.dcpp: Created..."));
// We only want to hang around for a little while.
SetTimer(hwnd, TIMER_QUITNOW, TIMEOUT, NULL);
return 0;
case WM_DESTROY:
DebugMsg(DM_CPTRACE, TEXT("cp.dcpp: Destroyed..."));
// Quit the app when this window goes away.
PostQuitMessage(0);
return 0;
case WM_TIMER:
DebugMsg(DM_CPTRACE, TEXT("cp.dcpp: Timer %d"), wparam);
if (wparam == TIMER_QUITNOW)
{
// Get this window to go away.
DestroyWindow(hwnd);
}
return 0;
case WM_COMMAND:
DebugMsg(DM_CPTRACE, TEXT("cp.dcpp: Command %d"), wparam);
// NB Hack for hollywood - they send a menu command to try
// and open the printers applet. They try to search control panels
// menu for the printers item and then post the associated command.
// As our fake window doesn't have a menu they can't find the item
// and post us a -1 instead (ripping on the way).
if (wparam == (WPARAM)-1)
{
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_WAITFORINPUTIDLE;
sei.lpFile = c_szExplorer;
sei.lpParameters = c_szDoPrinters;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
}
return 0;
default:
DebugMsg(DM_CPTRACE, TEXT("cp.dcpp: %x %x %x %x"), hwnd, uMsg, wparam, lparam);
return DefWindowProc(hwnd, uMsg, wparam, lparam);
}
}
//---------------------------------------------------------------------------
HWND _CreateDummyControlPanel(HINSTANCE hinst)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = DummyControlPanelProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = c_szCtlPanelClass;
RegisterClass(&wc);
return CreateWindow(c_szCtlPanelClass, NULL, 0, 0, 0, 0, 0, NULL, NULL, hinst, NULL);
}
void ProcessPolicy(void)
{
HINSTANCE hInst;
APPLET_PROC pfnCPLApplet;
hInst = LoadLibrary (TEXT("desk.cpl"));
if (!hInst) {
return;
}
pfnCPLApplet = (APPLET_PROC) GetProcAddress (hInst, "CPlApplet");
if (pfnCPLApplet) {
(*pfnCPLApplet)(NULL, CPL_POLICYREFRESH, 0, 0);
}
FreeLibrary (hInst);
}
//---------------------------------------------------------------------------
int WinMainT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
SHELLEXECUTEINFO sei = {0};
TCHAR szParameters[MAX_PATH * 2];
MSG msg;
HWND hwndDummy;
DebugMsg(DM_TRACE, TEXT("cp.wm: Control starting."));
ImmDisableIME(0);
hwndDummy = _CreateDummyControlPanel(hInstance);
// we need to check for PANEL passed in as an arg. The run dialog
// autocomplete shows "Control Panel" as a choice and we used to
// interpret this as Control with panel as an arg. So if we have
// panel as an arg then we do the same processing as when we have
// "Control" only.
if (*lpCmdLine && lstrcmpi(lpCmdLine, TEXT("PANEL")))
{
int i;
//
// Policy hook. Userenv.dll will call control.exe with the
// /policy command line switch. If so, we need to load the
// desk.cpl applet and refresh the colors / bitmap.
//
if (lstrcmpi(TEXT("/policy"), lpCmdLine) == 0) {
ProcessPolicy();
return TRUE;
}
//
// COMPAT HACK: special case some applets since apps depend on them
//
for (i = 0; !sei.lpFile && i < ARRAYSIZE(c_aCompatCpls); i++)
{
COMPATCPL const * pItem = &c_aCompatCpls[i];
if (lstrcmpi(pItem->szOldForm, lpCmdLine) == 0
&& (pItem->dwOS == OS_ANY || IsOS(pItem->dwOS)))
{
sei.lpFile = pItem->szFile;
sei.lpParameters = pItem->szParameters;
}
}
if (!sei.lpFile)
{
int cch;
//
// Not a special-case CPL.
// See if it's registered under "Control Panel\Cpls".
// If so, we use the registered path.
//
lstrcpy(szParameters, c_szRunDLLShell32Etc);
cch = lstrlen(szParameters);
sei.lpFile = c_szRunDLL32;
sei.lpParameters = szParameters;
if (ERROR_SUCCESS != GetRegisteredCplPath(lpCmdLine,
szParameters + cch,
ARRAYSIZE(szParameters) - cch))
{
//
// Not registered. Pass command line through.
//
lstrcpyn(szParameters + cch, lpCmdLine, ARRAYSIZE(szParameters) - cch);
}
}
}
else
{
// Open the Control Panel folder
sei.lpFile = c_szExplorer;
sei.lpParameters = c_szControlPanelFolder;
}
// HACK: NerdPerfect tries to open a hidden control panel to talk to
// we are blowing off fixing the communication stuff so just make
// sure the folder does not appear hidden
if (nCmdShow == SW_HIDE)
nCmdShow = SW_SHOWNORMAL;
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_WAITFORINPUTIDLE;
sei.nShow = nCmdShow;
ShellExecuteEx(&sei);
if (IsWindow(hwndDummy))
{
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
}
DebugMsg(DM_TRACE, TEXT("cp.wm: Control exiting."));
return TRUE;
}
#ifdef WIN32
//---------------------------------------------------------------------------
// Stolen from the CRT, used to shrink our code.
int _stdcall ModuleEntry(void)
{
STARTUPINFO si;
LPTSTR pszCmdLine = GetCommandLine();
if ( *pszCmdLine == TEXT('\"') ) {
/*
* Scan, and skip over, subsequent characters until
* another double-quote or a null is encountered.
*/
while ( *++pszCmdLine && (*pszCmdLine
!= TEXT('\"')) );
/*
* If we stopped on a double-quote (usual case), skip
* over it.
*/
if ( *pszCmdLine == TEXT('\"') )
pszCmdLine++;
}
else {
while (*pszCmdLine > TEXT(' '))
pszCmdLine++;
}
/*
* Skip past any white space preceeding the second token.
*/
while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) {
pszCmdLine++;
}
si.dwFlags = 0;
GetStartupInfo(&si);
ExitProcess(WinMainT(GetModuleHandle(NULL), NULL, pszCmdLine,
si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT));
return 0;
}
#endif