Completely revamped "control.exe":

- Now uses shell32 functions for loading the control panel applets, so that the mutex is used as well (see bug #781)
- Supports all built-in command-line parameters, which are supported by the WinXP version.
  This also added support for opening shell folders.
- Loads other possible parameters from the registry.
- Only passes the command for RunControlPanel to each ListView item, not a whole struct whose members aren't needed later.
- Fixed memory leaks
- Added a header file
- Fixed indentation

This is the last version of the standalone Control Panel.
I will change it to call the Explorer shell folder in my next commit.
See issue #781 for more details.

svn path=/trunk/; revision=33507
This commit is contained in:
Colin Finck 2008-05-13 21:30:55 +00:00
parent ce69bc85e4
commit 6efebc63d2
3 changed files with 390 additions and 404 deletions

View file

@ -1,172 +1,127 @@
/* /*
* ReactOS
* Copyright (C) 2004 ReactOS Team
* Copyright (C) 2004 GkWare e.K.
*
* 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$
*
* PROJECT: ReactOS System Control Panel * PROJECT: ReactOS System Control Panel
* FILE: lib/cpl/system/control.c * FILE: base/applications/control/control.c
* PURPOSE: ReactOS System Control Panel * PURPOSE: ReactOS System Control Panel
* PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com) * PROGRAMMERS: Gero Kuehn (reactos.filter@gkware.com)
* UPDATE HISTORY: * Colin Finck (mail@colinfinck.de)
* 06-13-2004 Created
*/ */
#include <windows.h>
#include <commctrl.h>
#include <cpl.h>
#include <stdlib.h> #include "control.h"
#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include "resource.h" static const TCHAR szWindowClass[] = _T("DummyControlClass");
//#define CONTROL_DEBUG_ENABLE HANDLE hProcessHeap;
#ifdef CONTROL_DEBUG_ENABLE
#define CTL_DEBUG(x) dbgprint x
#else
#define CTL_DEBUG(x)
#endif
#define MYWNDCLASS _T("CTLPANELCLASS")
typedef LONG (CALLBACK *CPLAPPLETFUNC)(HWND hwndCPL, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
typedef struct CPLLISTENTRY
{
TCHAR pszPath[MAX_PATH];
HMODULE hDll;
CPLAPPLETFUNC pFunc;
CPLINFO CplInfo;
int nIndex;
} CPLLISTENTRY, *PCPLLISTENTRY;
HWND hListView;
HINSTANCE hInst; HINSTANCE hInst;
HWND hMainWnd;
DEVMODE pDevMode;
VOID dbgprint(TCHAR *format,...) static INT
OpenShellFolder(LPTSTR lpFolderCLSID)
{ {
TCHAR buf[1000]; TCHAR szParameters[MAX_PATH];
va_list va;
va_start(va,format); /* Open a shell folder using "explorer.exe".
_vstprintf(buf,format,va); The passed CLSID's are all subfolders of the "Control Panel" shell folder. */
OutputDebugString(buf); _tcscpy(szParameters, _T("/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"));
va_end(va); _tcscat(szParameters, lpFolderCLSID);
return (int)ShellExecute(NULL, _T("open"), _T("explorer.exe"), szParameters, NULL, SW_SHOWDEFAULT) > 32;
} }
VOID PopulateCPLList(HWND hLisCtrl) static INT
RunControlPanel(LPTSTR lpCmd)
{
TCHAR szParameters[MAX_PATH];
_tcscpy(szParameters, _T("shell32.dll,Control_RunDLL "));
_tcscat(szParameters, lpCmd);
return RUNDLL(szParameters);
}
static VOID
PopulateCPLList(HWND hLisCtrl)
{ {
WIN32_FIND_DATA fd; WIN32_FIND_DATA fd;
HANDLE hFind; HANDLE hFind;
TCHAR pszSearchPath[MAX_PATH]; TCHAR pszSearchPath[MAX_PATH];
HIMAGELIST hImgListSmall; HIMAGELIST hImgListSmall;
HIMAGELIST hImgListLarge; HIMAGELIST hImgListLarge;
int ColorDepth;
HMODULE hDll; HMODULE hDll;
CPLAPPLETFUNC pFunc; CPLAPPLETFUNC pFunc;
TCHAR pszPath[MAX_PATH]; TCHAR pszPath[MAX_PATH];
TCHAR szPanelNum[CCH_UINT_MAX + 1];
DEVMODE pDevMode;
/* Icon drawing mode */ /* Icon drawing mode */
pDevMode.dmSize = sizeof(DEVMODE); pDevMode.dmSize = sizeof(DEVMODE);
pDevMode.dmDriverExtra = 0; pDevMode.dmDriverExtra = 0;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode); EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode);
switch (pDevMode.dmBitsPerPel) hImgListSmall = ImageList_Create(16, 16, pDevMode.dmBitsPerPel | ILC_MASK, 5, 5);
{ hImgListLarge = ImageList_Create(32, 32, pDevMode.dmBitsPerPel | ILC_MASK, 5, 5);
case 32: ColorDepth = ILC_COLOR32; break;
case 24: ColorDepth = ILC_COLOR24; break;
case 16: ColorDepth = ILC_COLOR16; break;
case 8: ColorDepth = ILC_COLOR8; break;
case 4: ColorDepth = ILC_COLOR4; break;
default: ColorDepth = ILC_COLOR; break;
}
hImgListSmall = ImageList_Create(16,16,ColorDepth | ILC_MASK,5,5);
hImgListLarge = ImageList_Create(32,32,ColorDepth | ILC_MASK,5,5);
GetSystemDirectory(pszSearchPath, MAX_PATH); GetSystemDirectory(pszSearchPath, MAX_PATH);
_tcscat(pszSearchPath, _T("\\*.cpl")); _tcscat(pszSearchPath, _T("\\*.cpl"));
hFind = FindFirstFile(pszSearchPath, &fd); hFind = FindFirstFile(pszSearchPath, &fd);
while (hFind != INVALID_HANDLE_VALUE) while (hFind != INVALID_HANDLE_VALUE)
{ {
PCPLLISTENTRY pEntry;
CTL_DEBUG((_T("Found %s\r\n"), fd.cFileName));
_tcscpy(pszPath, pszSearchPath); _tcscpy(pszPath, pszSearchPath);
*_tcsrchr(pszPath, '\\') = 0; *_tcsrchr(pszPath, '\\') = 0;
_tcscat(pszPath, _T("\\")); _tcscat(pszPath, _T("\\"));
_tcscat(pszPath, fd.cFileName); _tcscat(pszPath, fd.cFileName);
hDll = LoadLibrary(pszPath); hDll = LoadLibrary(pszPath);
CTL_DEBUG((_T("Handle %08X\r\n"), hDll));
pFunc = (CPLAPPLETFUNC)GetProcAddress(hDll, "CPlApplet"); pFunc = (CPLAPPLETFUNC)GetProcAddress(hDll, "CPlApplet");
CTL_DEBUG((_T("CPLFunc %08X\r\n"), pFunc));
if (pFunc && pFunc(hLisCtrl, CPL_INIT, 0, 0)) if (pFunc && pFunc(hLisCtrl, CPL_INIT, 0, 0))
{ {
UINT i, uPanelCount; UINT i, uPanelCount;
uPanelCount = (UINT)pFunc(hLisCtrl, CPL_GETCOUNT, 0, 0); uPanelCount = (UINT)pFunc(hLisCtrl, CPL_GETCOUNT, 0, 0);
for (i = 0; i < uPanelCount; i++) for (i = 0; i < uPanelCount; i++)
{ {
CPLINFO CplInfo;
HICON hIcon; HICON hIcon;
TCHAR Name[MAX_PATH]; TCHAR Name[MAX_PATH];
int index; int index;
LPTSTR pszCmd;
pEntry = (PCPLLISTENTRY)malloc(sizeof(CPLLISTENTRY)); pszCmd = (LPTSTR) HeapAlloc(hProcessHeap, 0, MAX_PATH * sizeof(TCHAR));
if (pEntry == NULL) if(!pszCmd)
return; return;
memset(pEntry, 0, sizeof(CPLLISTENTRY)); /* Build the command, which is later passed to RunControlPanel */
pEntry->hDll = hDll; _tcscpy(pszCmd, fd.cFileName);
pEntry->pFunc = pFunc; _tcscat(pszCmd, _T(" @"));
_tcscpy(pEntry->pszPath, pszPath); _itot(i, szPanelNum, 10);
_tcscat(pszCmd, szPanelNum);
pEntry->pFunc(hLisCtrl, CPL_INQUIRE, (LPARAM)i, (LPARAM)&pEntry->CplInfo); pFunc(hLisCtrl, CPL_INQUIRE, (LPARAM)i, (LPARAM)&CplInfo);
hIcon = LoadImage(pEntry->hDll,MAKEINTRESOURCE(pEntry->CplInfo.idIcon),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
hIcon = LoadImage(hDll, MAKEINTRESOURCE(CplInfo.idIcon), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
index = ImageList_AddIcon(hImgListSmall, hIcon); index = ImageList_AddIcon(hImgListSmall, hIcon);
DestroyIcon(hIcon); DestroyIcon(hIcon);
hIcon = LoadImage(pEntry->hDll,MAKEINTRESOURCE(pEntry->CplInfo.idIcon),IMAGE_ICON,32,32,LR_DEFAULTCOLOR);
hIcon = LoadImage(hDll, MAKEINTRESOURCE(CplInfo.idIcon), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
ImageList_AddIcon(hImgListLarge, hIcon); ImageList_AddIcon(hImgListLarge, hIcon);
DestroyIcon(hIcon); DestroyIcon(hIcon);
if (LoadString(pEntry->hDll, pEntry->CplInfo.idName, Name, MAX_PATH)) if (LoadString(hDll, CplInfo.idName, Name, MAX_PATH))
{ {
LV_ITEM lvi; INT nIndex;
LV_ITEM lvi = {0};
memset(&lvi,0x00,sizeof(lvi));
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
lvi.pszText = Name; lvi.pszText = Name;
lvi.state = 0; lvi.state = 0;
lvi.iImage = index; lvi.iImage = index;
lvi.lParam = (LPARAM)pEntry; lvi.lParam = (LPARAM)pszCmd;
pEntry->nIndex = ListView_InsertItem(hLisCtrl,&lvi); nIndex = ListView_InsertItem(hLisCtrl, &lvi);
if (LoadString(pEntry->hDll, pEntry->CplInfo.idInfo, Name, MAX_PATH)) if (LoadString(hDll, CplInfo.idInfo, Name, MAX_PATH))
ListView_SetItemText(hLisCtrl, pEntry->nIndex, 1, Name); ListView_SetItemText(hLisCtrl, nIndex, 1, Name);
} }
} }
} }
@ -179,8 +134,10 @@ VOID PopulateCPLList(HWND hLisCtrl)
(void)ListView_SetImageList(hLisCtrl, hImgListLarge, LVSIL_NORMAL); (void)ListView_SetImageList(hLisCtrl, hImgListLarge, LVSIL_NORMAL);
} }
LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) LRESULT CALLBACK
MyWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
static HWND hListView;
TCHAR szBuf[1024]; TCHAR szBuf[1024];
switch (uMsg) switch (uMsg)
@ -188,13 +145,11 @@ LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
case WM_CREATE: case WM_CREATE:
{ {
RECT rect; RECT rect;
LV_COLUMN column; LV_COLUMN column = {0};
GetClientRect(hWnd, &rect); GetClientRect(hWnd, &rect);
hListView = CreateWindow(WC_LISTVIEW,_T(""),LVS_REPORT | LVS_ALIGNLEFT | LVS_SORTASCENDING | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD | WS_TABSTOP,0,0,rect.right ,rect.bottom,hWnd,NULL,hInst,0); hListView = CreateWindow(WC_LISTVIEW, NULL, LVS_REPORT | LVS_ALIGNLEFT | LVS_SORTASCENDING | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, rect.right, rect.bottom, hWnd, NULL, hInst, 0);
CTL_DEBUG((_T("Listview Window %08X\r\n"),hListView));
memset(&column,0x00,sizeof(column));
column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
column.fmt = LVCFMT_LEFT; column.fmt = LVCFMT_LEFT;
column.cx = (rect.right - rect.left) / 3; column.cx = (rect.right - rect.left) / 3;
@ -202,22 +157,41 @@ LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
LoadString(hInst, IDS_NAME, szBuf, sizeof(szBuf) / sizeof(TCHAR)); LoadString(hInst, IDS_NAME, szBuf, sizeof(szBuf) / sizeof(TCHAR));
column.pszText = szBuf; column.pszText = szBuf;
(void)ListView_InsertColumn(hListView, 0, &column); (void)ListView_InsertColumn(hListView, 0, &column);
column.cx = (rect.right - rect.left) - ((rect.right - rect.left) / 3) - 1; column.cx = (rect.right - rect.left) - ((rect.right - rect.left) / 3) - 1;
column.iSubItem = 1; column.iSubItem = 1;
LoadString(hInst, IDS_COMMENT, szBuf, sizeof(szBuf) / sizeof(TCHAR)); LoadString(hInst, IDS_COMMENT, szBuf, sizeof(szBuf) / sizeof(TCHAR));
column.pszText = szBuf; column.pszText = szBuf;
(void)ListView_InsertColumn(hListView, 1, &column); (void)ListView_InsertColumn(hListView, 1, &column);
PopulateCPLList(hListView); PopulateCPLList(hListView);
(void)ListView_SetColumnWidth(hListView, 2, LVSCW_AUTOSIZE_USEHEADER); (void)ListView_SetColumnWidth(hListView, 2, LVSCW_AUTOSIZE_USEHEADER);
(void)ListView_Update(hListView, 0); (void)ListView_Update(hListView, 0);
SetFocus(hListView); SetFocus(hListView);
return 0;
} }
break;
case WM_DESTROY: case WM_DESTROY:
{
LV_ITEM lvi;
INT nItems;
lvi.mask = LVIF_PARAM;
/* Free the memory used for the command strings */
for(nItems = ListView_GetItemCount(hListView); --nItems >= 0;)
{
lvi.iItem = nItems;
(void)ListView_GetItem(hListView, &lvi);
HeapFree(hProcessHeap, 0, (LPVOID)lvi.lParam);
}
PostQuitMessage(0); PostQuitMessage(0);
break; return 0;
}
case WM_SIZE: case WM_SIZE:
{ {
@ -225,21 +199,23 @@ LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
GetClientRect(hWnd, &rect); GetClientRect(hWnd, &rect);
MoveWindow(hListView, 0, 0, rect.right, rect.bottom, TRUE); MoveWindow(hListView, 0, 0, rect.right, rect.bottom, TRUE);
return 0;
} }
break;
case WM_NOTIFY: case WM_NOTIFY:
{ {
NMHDR *phdr; NMHDR *phdr;
phdr = (NMHDR*)lParam; phdr = (NMHDR*)lParam;
switch(phdr->code) switch(phdr->code)
{ {
case NM_RETURN: case NM_RETURN:
case NM_DBLCLK: case NM_DBLCLK:
{ {
int nSelect; int nSelect;
LV_ITEM lvi; LV_ITEM lvi = {0};
PCPLLISTENTRY pEntry; LPTSTR pszCmd;
nSelect = SendMessage(hListView, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_FOCUSED); nSelect = SendMessage(hListView, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_FOCUSED);
@ -251,43 +227,43 @@ LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
break; break;
} }
CTL_DEBUG((_T("Select %d\r\n"),nSelect));
memset(&lvi,0x00,sizeof(lvi));
lvi.iItem = nSelect; lvi.iItem = nSelect;
lvi.mask = LVIF_PARAM; lvi.mask = LVIF_PARAM;
(void)ListView_GetItem(hListView, &lvi); (void)ListView_GetItem(hListView, &lvi);
pEntry = (PCPLLISTENTRY)lvi.lParam;
CTL_DEBUG((_T("Listview DblClk Entry %08X\r\n"),pEntry));
if (pEntry)
{
CTL_DEBUG((_T("Listview DblClk Entry Func %08X\r\n"),pEntry->pFunc));
}
if (pEntry && pEntry->pFunc) pszCmd = (LPTSTR)lvi.lParam;
pEntry->pFunc(hListView,CPL_DBLCLK,pEntry->CplInfo.lData,0);
if (pszCmd)
RunControlPanel(pszCmd);
return 0;
} }
} }
} }
break;
case WM_COMMAND: case WM_COMMAND:
switch (LOWORD(wParam)) switch (LOWORD(wParam))
{ {
case IDM_LARGEICONS: case IDM_LARGEICONS:
SetWindowLong(hListView,GWL_STYLE,LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); SetWindowLong(hListView,GWL_STYLE,LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP);
break; return 0;
case IDM_SMALLICONS: case IDM_SMALLICONS:
SetWindowLong(hListView,GWL_STYLE,LVS_SMALLICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); SetWindowLong(hListView,GWL_STYLE,LVS_SMALLICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP);
break; return 0;
case IDM_LIST: case IDM_LIST:
SetWindowLong(hListView,GWL_STYLE,LVS_LIST | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); SetWindowLong(hListView,GWL_STYLE,LVS_LIST | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP);
break; return 0;
case IDM_DETAILS: case IDM_DETAILS:
SetWindowLong(hListView,GWL_STYLE,LVS_REPORT | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); SetWindowLong(hListView,GWL_STYLE,LVS_REPORT | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP);
break; return 0;
case IDM_CLOSE: case IDM_CLOSE:
DestroyWindow(hWnd); DestroyWindow(hWnd);
break; return 0;
case IDM_ABOUT: case IDM_ABOUT:
{ {
TCHAR Title[256]; TCHAR Title[256];
@ -296,36 +272,37 @@ LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
LoadString(hInst, IDS_ABOUT_TITLE, Title, sizeof(Title) / sizeof(TCHAR)); LoadString(hInst, IDS_ABOUT_TITLE, Title, sizeof(Title) / sizeof(TCHAR));
MessageBox(hWnd, (LPCTSTR)szBuf, (LPCTSTR)Title, MB_OK | MB_ICONINFORMATION); MessageBox(hWnd, (LPCTSTR)szBuf, (LPCTSTR)Title, MB_OK | MB_ICONINFORMATION);
}
break;
}
break;
default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return 0; return 0;
} }
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
static INT static INT
RunControlPanelWindow(int nCmdShow) RunControlPanelWindow(int nCmdShow)
{ {
MSG msg; MSG msg;
WNDCLASS wc; HWND hMainWnd;
INITCOMMONCONTROLSEX icex;
WNDCLASSEX wcex = {0};
TCHAR szBuf[256]; TCHAR szBuf[256];
memset(&wc,0x00,sizeof(wc)); wcex.cbSize = sizeof(wcex);
wc.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAINICON)); wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAINICON));
wc.lpszClassName = MYWNDCLASS; wcex.lpszClassName = MYWNDCLASS;
wc.lpszMenuName = _T("MAINMENU"); wcex.lpfnWndProc = MyWindowProc;
wc.lpfnWndProc = MyWindowProc; RegisterClassEx(&wcex);
RegisterClass(&wc);
InitCommonControls(); icex.dwSize = sizeof(icex);
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
LoadString(hInst, IDS_WINDOW_TITLE, szBuf, sizeof(szBuf) / sizeof(TCHAR)); LoadString(hInst, IDS_WINDOW_TITLE, szBuf, sizeof(szBuf) / sizeof(TCHAR));
hMainWnd = CreateWindowEx(WS_EX_CLIENTEDGE, hMainWnd = CreateWindowEx(WS_EX_CLIENTEDGE,
MYWNDCLASS, MYWNDCLASS,
(LPCTSTR)szBuf, (LPCTSTR)szBuf,
@ -339,12 +316,10 @@ RunControlPanelWindow(int nCmdShow)
hInst, hInst,
0); 0);
if (!hMainWnd) if (!hMainWnd)
{ return 1;
CTL_DEBUG((_T("Unable to create window\r\n")));
return -1;
}
ShowWindow(hMainWnd, nCmdShow); ShowWindow(hMainWnd, nCmdShow);
while (GetMessage(&msg, 0, 0, 0)) while (GetMessage(&msg, 0, 0, 0))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
@ -354,105 +329,90 @@ RunControlPanelWindow(int nCmdShow)
return 0; return 0;
} }
int WINAPI
static INT _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
RunControlPanel(LPCTSTR lpName, UINT uIndex)
{ {
CPLINFO CplInfo; HKEY hKey;
HMODULE hDll;
CPLAPPLETFUNC pFunc;
UINT uPanelCount;
hDll = LoadLibrary(lpName); hInst = hInstance;
if (hDll == 0) hProcessHeap = GetProcessHeap();
{
return -1;
}
CTL_DEBUG((_T("Handle %08X\r\n"), hDll));
pFunc = (CPLAPPLETFUNC)GetProcAddress(hDll, "CPlApplet"); /* Show the control panel window if no argument or "panel" was passed */
if (pFunc == NULL) if(lpCmdLine[0] == 0 || !_tcsicmp(lpCmdLine, _T("panel")))
{ return RunControlPanelWindow(nCmdShow);
FreeLibrary(hDll);
return -1;
}
CTL_DEBUG((_T("CPLFunc %08X\r\n"), pFunc));
if (!pFunc(NULL, CPL_INIT, 0, 0)) /* Check one of the built-in control panel handlers */
if (!_tcsicmp(lpCmdLine, _T("admintools"))) return OpenShellFolder(_T("\\::{D20EA4E1-3957-11d2-A40B-0C5020524153}"));
else if (!_tcsicmp(lpCmdLine, _T("color"))) return RunControlPanel(_T("desk.cpl")); /* TODO: Switch to the "Apperance" tab */
else if (!_tcsicmp(lpCmdLine, _T("date/time"))) return RunControlPanel(_T("timedate.cpl"));
else if (!_tcsicmp(lpCmdLine, _T("desktop"))) return RunControlPanel(_T("desk.cpl"));
else if (!_tcsicmp(lpCmdLine, _T("folders"))) return RUNDLL(_T("shell32.dll,Options_RunDLL"));
else if (!_tcsicmp(lpCmdLine, _T("fonts"))) return OpenShellFolder(_T("\\::{D20EA4E1-3957-11d2-A40B-0C5020524152}"));
else if (!_tcsicmp(lpCmdLine, _T("infrared"))) return RunControlPanel(_T("irprops.cpl"));
else if (!_tcsicmp(lpCmdLine, _T("international"))) return RunControlPanel(_T("intl.cpl"));
else if (!_tcsicmp(lpCmdLine, _T("keyboard"))) return RunControlPanel(_T("main.cpl @1"));
else if (!_tcsicmp(lpCmdLine, _T("mouse"))) return RunControlPanel(_T("main.cpl @0"));
else if (!_tcsicmp(lpCmdLine, _T("netconnections"))) return OpenShellFolder(_T("\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}"));
else if (!_tcsicmp(lpCmdLine, _T("netware"))) return RunControlPanel(_T("nwc.cpl"));
else if (!_tcsicmp(lpCmdLine, _T("ports"))) return RunControlPanel(_T("sysdm.cpl")); /* TODO: Switch to the "Computer Name" tab */
else if (!_tcsicmp(lpCmdLine, _T("printers"))) return OpenShellFolder(_T("\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"));
else if (!_tcsicmp(lpCmdLine, _T("scannercamera"))) return OpenShellFolder(_T("\\::{E211B736-43FD-11D1-9EFB-0000F8757FCD}"));
else if (!_tcsicmp(lpCmdLine, _T("schedtasks"))) return OpenShellFolder(_T("\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}"));
else if (!_tcsicmp(lpCmdLine, _T("telephony"))) return RunControlPanel(_T("telephon.cpl"));
else if (!_tcsicmp(lpCmdLine, _T("userpasswords"))) return RunControlPanel(_T("nusrmgr.cpl")); /* Graphical User Account Manager */
else if (!_tcsicmp(lpCmdLine, _T("userpasswords2"))) return RUNDLL(_T("netplwiz.dll,UsersRunDll")); /* Dialog based advanced User Account Manager */
/* It is none of them, so look for a handler in the registry */
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{ {
FreeLibrary(hDll); DWORD dwIndex;
return -1;
for(dwIndex = 0; ; ++dwIndex)
{
DWORD dwDataSize;
DWORD dwValueSize = MAX_VALUE_NAME;
TCHAR szValueName[MAX_VALUE_NAME];
/* Get the value name and data size */
if(RegEnumValue(hKey, dwIndex, szValueName, &dwValueSize, 0, NULL, NULL, &dwDataSize) != ERROR_SUCCESS)
break;
/* Check if the parameter is the value name */
if(!_tcsicmp(lpCmdLine, szValueName))
{
LPTSTR pszData;
/* Allocate memory for the data plus two more characters, so we can quote the file name if required */
pszData = (LPTSTR) HeapAlloc(hProcessHeap, 0, dwDataSize + 2 * sizeof(TCHAR));
++pszData;
/* This value is the one we are looking for, so get the data. It is the path to a .cpl file */
if(RegQueryValueEx(hKey, szValueName, 0, NULL, (LPBYTE)pszData, &dwDataSize) == ERROR_SUCCESS)
{
INT nReturnValue;
/* Quote the file name if required */
if(*pszData != '\"')
{
*(--pszData) = '\"';
pszData[dwDataSize / sizeof(TCHAR)] = '\"';
pszData[(dwDataSize / sizeof(TCHAR)) + 1] = 0;
} }
uPanelCount = (UINT)pFunc(NULL, CPL_GETCOUNT, 0, 0); nReturnValue = RunControlPanel(pszData);
if (uIndex >= uPanelCount) HeapFree(hProcessHeap, 0, pszData);
{ RegCloseKey(hKey);
FreeLibrary(hDll);
return -1; return nReturnValue;
} }
pFunc(NULL, CPL_INQUIRE, (LPARAM)uIndex, (LPARAM)&CplInfo); HeapFree(hProcessHeap, 0, pszData);
}
pFunc(NULL, CPL_DBLCLK, CplInfo.lData, 0);
FreeLibrary(hDll);
return 0;
} }
int RegCloseKey(hKey);
_tmain(int argc, const TCHAR *argv[])
{
STARTUPINFO si;
TCHAR * szExt;
si.cb = sizeof(si);
GetStartupInfo(&si);
hInst = GetModuleHandle(NULL);
if (argc <= 1)
{
/* No argument on the command line */
return RunControlPanelWindow(si.wShowWindow);
} }
if (_tcsicmp(argv[1], _T("desktop")) == 0) /* It's none of the known parameters, so interpret the parameter as the file name of a control panel applet */
{ return RunControlPanel(lpCmdLine);
return RunControlPanel(_T("desk.cpl"), 0);
}
else if (_tcsicmp(argv[1], _T("date/time")) == 0)
{
return RunControlPanel(_T("timedate.cpl"), 0);
}
else if (_tcsicmp(argv[1], _T("international")) == 0)
{
return RunControlPanel(_T("intl.cpl"), 0);
}
else if (_tcsicmp(argv[1], _T("mouse")) == 0)
{
return RunControlPanel(_T("main.cpl"), 0);
}
else if (_tcsicmp(argv[1], _T("keyboard")) == 0)
{
return RunControlPanel(_T("main.cpl"), 1);
}
else if ((szExt = _tcsstr(argv[1], _T(".cpl"))))
{
TCHAR * szSep;
TCHAR szCPL[MAX_PATH];
UINT selPage = 0;
_tcscpy(szCPL, argv[1]);
szSep = _tcsstr(szCPL, _T(".cpl,"));
if (szSep)
{
/* FIXME for now ignore page index */
szSep[4] = _T('\0');
}
return RunControlPanel(szCPL, selPage);
}
return 0;
} }

View file

@ -0,0 +1,24 @@
/*
* PROJECT: ReactOS System Control Panel
* FILE: base/applications/control/control.h
* PURPOSE: ReactOS System Control Panel
* PROGRAMMERS: Gero Kuehn (reactos.filter@gkware.com)
* Colin Finck (mail@colinfinck.de)
*/
#include <windows.h>
#include <commctrl.h>
#include <cpl.h>
#include <tchar.h>
#include "resource.h"
#define MYWNDCLASS _T("CTLPANELCLASS")
typedef LONG (CALLBACK *CPLAPPLETFUNC)(HWND hwndCPL, UINT uMsg, LPARAM lParam1, LPARAM lParam2);
#define CCH_UINT_MAX 11
#define MAX_VALUE_NAME 16383
/* Macro for calling "rundll32.exe"
According to MSDN, ShellExecute returns a value greater than 32 if the operation was successful. */
#define RUNDLL(param) ((int)ShellExecute(NULL, _T("open"), _T("rundll32.exe"), (param), NULL, SW_SHOWDEFAULT) > 32)

View file

@ -4,9 +4,11 @@
<include base="control">.</include> <include base="control">.</include>
<define name="_WIN32_IE">0x600</define> <define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define> <define name="_WIN32_WINNT">0x501</define>
<library>kernel32</library> <library>advapi32</library>
<library>user32</library>
<library>comctl32</library> <library>comctl32</library>
<library>kernel32</library>
<library>shell32</library>
<library>user32</library>
<file>control.c</file> <file>control.c</file>
<file>control.rc</file> <file>control.rc</file>
</module> </module>