diff --git a/reactos/base/applications/control/control.c b/reactos/base/applications/control/control.c index 4b260421fe4..aca913b757f 100644 --- a/reactos/base/applications/control/control.c +++ b/reactos/base/applications/control/control.c @@ -1,458 +1,418 @@ /* - * 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 - * FILE: lib/cpl/system/control.c + * FILE: base/applications/control/control.c * PURPOSE: ReactOS System Control Panel - * PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com) - * UPDATE HISTORY: - * 06-13-2004 Created + * PROGRAMMERS: Gero Kuehn (reactos.filter@gkware.com) + * Colin Finck (mail@colinfinck.de) */ -#include -#include -#include -#include -#include -#include -#include +#include "control.h" -#include "resource.h" +static const TCHAR szWindowClass[] = _T("DummyControlClass"); -//#define CONTROL_DEBUG_ENABLE - -#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; +HANDLE hProcessHeap; HINSTANCE hInst; -HWND hMainWnd; -DEVMODE pDevMode; -VOID dbgprint(TCHAR *format,...) +static INT +OpenShellFolder(LPTSTR lpFolderCLSID) { - TCHAR buf[1000]; - va_list va; + TCHAR szParameters[MAX_PATH]; - va_start(va,format); - _vstprintf(buf,format,va); - OutputDebugString(buf); - va_end(va); + /* Open a shell folder using "explorer.exe". + The passed CLSID's are all subfolders of the "Control Panel" shell folder. */ + _tcscpy(szParameters, _T("/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}")); + _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) { - WIN32_FIND_DATA fd; - HANDLE hFind; - TCHAR pszSearchPath[MAX_PATH]; - HIMAGELIST hImgListSmall; - HIMAGELIST hImgListLarge; - int ColorDepth; - HMODULE hDll; - CPLAPPLETFUNC pFunc; - TCHAR pszPath[MAX_PATH]; + TCHAR szParameters[MAX_PATH]; - /* Icon drawing mode */ - pDevMode.dmSize = sizeof(DEVMODE); - pDevMode.dmDriverExtra = 0; + _tcscpy(szParameters, _T("shell32.dll,Control_RunDLL ")); + _tcscat(szParameters, lpCmd); - EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&pDevMode); - switch (pDevMode.dmBitsPerPel) - { - 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); - _tcscat(pszSearchPath,_T("\\*.cpl")); - - hFind = FindFirstFile(pszSearchPath,&fd); - while (hFind != INVALID_HANDLE_VALUE) - { - PCPLLISTENTRY pEntry; - CTL_DEBUG((_T("Found %s\r\n"), fd.cFileName)); - - _tcscpy(pszPath, pszSearchPath); - *_tcsrchr(pszPath, '\\')=0; - _tcscat(pszPath, _T("\\")); - _tcscat(pszPath, fd.cFileName); - - hDll = LoadLibrary(pszPath); - CTL_DEBUG((_T("Handle %08X\r\n"), hDll)); - - pFunc = (CPLAPPLETFUNC)GetProcAddress(hDll, "CPlApplet"); - CTL_DEBUG((_T("CPLFunc %08X\r\n"), pFunc)); - - if (pFunc && pFunc(hLisCtrl, CPL_INIT, 0, 0)) - { - UINT i, uPanelCount; - - uPanelCount = (UINT)pFunc(hLisCtrl, CPL_GETCOUNT, 0, 0); - for (i = 0; i < uPanelCount; i++) - { - HICON hIcon; - TCHAR Name[MAX_PATH]; - int index; - - pEntry = (PCPLLISTENTRY)malloc(sizeof(CPLLISTENTRY)); - if (pEntry == NULL) - return; - - memset(pEntry, 0, sizeof(CPLLISTENTRY)); - pEntry->hDll = hDll; - pEntry->pFunc = pFunc; - _tcscpy(pEntry->pszPath, pszPath); - - pEntry->pFunc(hLisCtrl, CPL_INQUIRE, (LPARAM)i, (LPARAM)&pEntry->CplInfo); - hIcon = LoadImage(pEntry->hDll,MAKEINTRESOURCE(pEntry->CplInfo.idIcon),IMAGE_ICON,16,16,LR_DEFAULTCOLOR); - index = ImageList_AddIcon(hImgListSmall,hIcon); - DestroyIcon(hIcon); - hIcon = LoadImage(pEntry->hDll,MAKEINTRESOURCE(pEntry->CplInfo.idIcon),IMAGE_ICON,32,32,LR_DEFAULTCOLOR); - ImageList_AddIcon(hImgListLarge,hIcon); - DestroyIcon(hIcon); - - if (LoadString(pEntry->hDll, pEntry->CplInfo.idName, Name, MAX_PATH)) - { - LV_ITEM lvi; - - memset(&lvi,0x00,sizeof(lvi)); - lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; - lvi.pszText = Name; - lvi.state = 0; - lvi.iImage = index; - lvi.lParam = (LPARAM)pEntry; - pEntry->nIndex = ListView_InsertItem(hLisCtrl,&lvi); - - if (LoadString(pEntry->hDll, pEntry->CplInfo.idInfo, Name, MAX_PATH)) - ListView_SetItemText(hLisCtrl, pEntry->nIndex, 1, Name); - } - } - } - - if (!FindNextFile(hFind,&fd)) - hFind = INVALID_HANDLE_VALUE; - } - - (void)ListView_SetImageList(hLisCtrl,hImgListSmall,LVSIL_SMALL); - (void)ListView_SetImageList(hLisCtrl,hImgListLarge,LVSIL_NORMAL); + return RUNDLL(szParameters); } -LRESULT CALLBACK MyWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +static VOID +PopulateCPLList(HWND hLisCtrl) { - TCHAR szBuf[1024]; + WIN32_FIND_DATA fd; + HANDLE hFind; + TCHAR pszSearchPath[MAX_PATH]; + HIMAGELIST hImgListSmall; + HIMAGELIST hImgListLarge; + HMODULE hDll; + CPLAPPLETFUNC pFunc; + TCHAR pszPath[MAX_PATH]; + TCHAR szPanelNum[CCH_UINT_MAX + 1]; + DEVMODE pDevMode; - switch (uMsg) - { - case WM_CREATE: - { - RECT rect; - LV_COLUMN column; + /* Icon drawing mode */ + pDevMode.dmSize = sizeof(DEVMODE); + pDevMode.dmDriverExtra = 0; - 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); - CTL_DEBUG((_T("Listview Window %08X\r\n"),hListView)); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode); + hImgListSmall = ImageList_Create(16, 16, pDevMode.dmBitsPerPel | ILC_MASK, 5, 5); + hImgListLarge = ImageList_Create(32, 32, pDevMode.dmBitsPerPel | ILC_MASK, 5, 5); - memset(&column,0x00,sizeof(column)); - column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT; - column.fmt = LVCFMT_LEFT; - column.cx = (rect.right - rect.left) / 3; - column.iSubItem = 0; - LoadString(hInst, IDS_NAME, szBuf, sizeof(szBuf) / sizeof(TCHAR)); - column.pszText = szBuf; - (void)ListView_InsertColumn(hListView,0,&column); - column.cx = (rect.right - rect.left) - ((rect.right - rect.left) / 3) - 1; - column.iSubItem = 1; - LoadString(hInst, IDS_COMMENT, szBuf, sizeof(szBuf) / sizeof(TCHAR)); - column.pszText = szBuf; - (void)ListView_InsertColumn(hListView,1,&column); - PopulateCPLList(hListView); - (void)ListView_SetColumnWidth(hListView,2,LVSCW_AUTOSIZE_USEHEADER); - (void)ListView_Update(hListView,0); + GetSystemDirectory(pszSearchPath, MAX_PATH); + _tcscat(pszSearchPath, _T("\\*.cpl")); - SetFocus(hListView); - } - break; + hFind = FindFirstFile(pszSearchPath, &fd); - case WM_DESTROY: - PostQuitMessage(0); - break; + while (hFind != INVALID_HANDLE_VALUE) + { + _tcscpy(pszPath, pszSearchPath); + *_tcsrchr(pszPath, '\\') = 0; + _tcscat(pszPath, _T("\\")); + _tcscat(pszPath, fd.cFileName); - case WM_SIZE: - { - RECT rect; + hDll = LoadLibrary(pszPath); + pFunc = (CPLAPPLETFUNC)GetProcAddress(hDll, "CPlApplet"); - GetClientRect(hWnd,&rect); - MoveWindow(hListView,0,0,rect.right,rect.bottom,TRUE); - } - break; + if (pFunc && pFunc(hLisCtrl, CPL_INIT, 0, 0)) + { + UINT i, uPanelCount; - case WM_NOTIFY: - { - NMHDR *phdr; - phdr = (NMHDR*)lParam; - switch(phdr->code) - { - case NM_RETURN: - case NM_DBLCLK: - { - int nSelect; - LV_ITEM lvi; - PCPLLISTENTRY pEntry; + uPanelCount = (UINT)pFunc(hLisCtrl, CPL_GETCOUNT, 0, 0); - nSelect=SendMessage(hListView,LVM_GETNEXTITEM,(WPARAM)-1,LVNI_FOCUSED); + for (i = 0; i < uPanelCount; i++) + { + CPLINFO CplInfo; + HICON hIcon; + TCHAR Name[MAX_PATH]; + int index; + LPTSTR pszCmd; - if (nSelect==-1) - { - /* no items */ - LoadString(hInst, IDS_NO_ITEMS, szBuf, sizeof(szBuf) / sizeof(TCHAR)); - MessageBox(hWnd,(LPCTSTR)szBuf,NULL,MB_OK|MB_ICONINFORMATION); - break; - } + pszCmd = (LPTSTR) HeapAlloc(hProcessHeap, 0, MAX_PATH * sizeof(TCHAR)); + if(!pszCmd) + return; - CTL_DEBUG((_T("Select %d\r\n"),nSelect)); - memset(&lvi,0x00,sizeof(lvi)); - lvi.iItem = nSelect; - lvi.mask = LVIF_PARAM; - (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)); - } + /* Build the command, which is later passed to RunControlPanel */ + _tcscpy(pszCmd, fd.cFileName); + _tcscat(pszCmd, _T(" @")); + _itot(i, szPanelNum, 10); + _tcscat(pszCmd, szPanelNum); - if (pEntry && pEntry->pFunc) - pEntry->pFunc(hListView,CPL_DBLCLK,pEntry->CplInfo.lData,0); - } - } - } - break; + pFunc(hLisCtrl, CPL_INQUIRE, (LPARAM)i, (LPARAM)&CplInfo); - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDM_LARGEICONS: - SetWindowLong(hListView,GWL_STYLE,LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); - break; - case IDM_SMALLICONS: - SetWindowLong(hListView,GWL_STYLE,LVS_SMALLICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); - break; - case IDM_LIST: - SetWindowLong(hListView,GWL_STYLE,LVS_LIST | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); - break; - case IDM_DETAILS: - SetWindowLong(hListView,GWL_STYLE,LVS_REPORT | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); - break; - case IDM_CLOSE: - DestroyWindow(hWnd); - break; - case IDM_ABOUT: - { - TCHAR Title[256]; - - LoadString(hInst, IDS_ABOUT, szBuf, sizeof(szBuf) / sizeof(TCHAR)); - LoadString(hInst, IDS_ABOUT_TITLE, Title, sizeof(Title) / sizeof(TCHAR)); - - MessageBox(hWnd,(LPCTSTR)szBuf,(LPCTSTR)Title,MB_OK | MB_ICONINFORMATION); - } - break; - } - break; + hIcon = LoadImage(hDll, MAKEINTRESOURCE(CplInfo.idIcon), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + index = ImageList_AddIcon(hImgListSmall, hIcon); + DestroyIcon(hIcon); - default: - return DefWindowProc(hWnd,uMsg,wParam,lParam); - } + hIcon = LoadImage(hDll, MAKEINTRESOURCE(CplInfo.idIcon), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImgListLarge, hIcon); + DestroyIcon(hIcon); - return 0; + if (LoadString(hDll, CplInfo.idName, Name, MAX_PATH)) + { + INT nIndex; + LV_ITEM lvi = {0}; + + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; + lvi.pszText = Name; + lvi.state = 0; + lvi.iImage = index; + lvi.lParam = (LPARAM)pszCmd; + nIndex = ListView_InsertItem(hLisCtrl, &lvi); + + if (LoadString(hDll, CplInfo.idInfo, Name, MAX_PATH)) + ListView_SetItemText(hLisCtrl, nIndex, 1, Name); + } + } + } + + if (!FindNextFile(hFind, &fd)) + hFind = INVALID_HANDLE_VALUE; + } + + (void)ListView_SetImageList(hLisCtrl, hImgListSmall, LVSIL_SMALL); + (void)ListView_SetImageList(hLisCtrl, hImgListLarge, LVSIL_NORMAL); +} + +LRESULT CALLBACK +MyWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HWND hListView; + TCHAR szBuf[1024]; + + switch (uMsg) + { + case WM_CREATE: + { + RECT rect; + LV_COLUMN column = {0}; + + GetClientRect(hWnd, &rect); + 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); + + column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT; + column.fmt = LVCFMT_LEFT; + column.cx = (rect.right - rect.left) / 3; + column.iSubItem = 0; + LoadString(hInst, IDS_NAME, szBuf, sizeof(szBuf) / sizeof(TCHAR)); + column.pszText = szBuf; + (void)ListView_InsertColumn(hListView, 0, &column); + + column.cx = (rect.right - rect.left) - ((rect.right - rect.left) / 3) - 1; + column.iSubItem = 1; + LoadString(hInst, IDS_COMMENT, szBuf, sizeof(szBuf) / sizeof(TCHAR)); + column.pszText = szBuf; + (void)ListView_InsertColumn(hListView, 1, &column); + + PopulateCPLList(hListView); + + (void)ListView_SetColumnWidth(hListView, 2, LVSCW_AUTOSIZE_USEHEADER); + (void)ListView_Update(hListView, 0); + + SetFocus(hListView); + + return 0; + } + + 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); + return 0; + } + + case WM_SIZE: + { + RECT rect; + + GetClientRect(hWnd, &rect); + MoveWindow(hListView, 0, 0, rect.right, rect.bottom, TRUE); + + return 0; + } + + case WM_NOTIFY: + { + NMHDR *phdr; + phdr = (NMHDR*)lParam; + + switch(phdr->code) + { + case NM_RETURN: + case NM_DBLCLK: + { + int nSelect; + LV_ITEM lvi = {0}; + LPTSTR pszCmd; + + nSelect = SendMessage(hListView, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_FOCUSED); + + if (nSelect == -1) + { + /* no items */ + LoadString(hInst, IDS_NO_ITEMS, szBuf, sizeof(szBuf) / sizeof(TCHAR)); + MessageBox(hWnd, (LPCTSTR)szBuf, NULL, MB_OK | MB_ICONINFORMATION); + break; + } + + lvi.iItem = nSelect; + lvi.mask = LVIF_PARAM; + (void)ListView_GetItem(hListView, &lvi); + + pszCmd = (LPTSTR)lvi.lParam; + + if (pszCmd) + RunControlPanel(pszCmd); + + return 0; + } + } + } + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDM_LARGEICONS: + SetWindowLong(hListView,GWL_STYLE,LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); + return 0; + + case IDM_SMALLICONS: + SetWindowLong(hListView,GWL_STYLE,LVS_SMALLICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); + return 0; + + case IDM_LIST: + SetWindowLong(hListView,GWL_STYLE,LVS_LIST | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); + return 0; + + case IDM_DETAILS: + SetWindowLong(hListView,GWL_STYLE,LVS_REPORT | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | WS_VISIBLE | WS_CHILD|WS_BORDER|WS_TABSTOP); + return 0; + + case IDM_CLOSE: + DestroyWindow(hWnd); + return 0; + + case IDM_ABOUT: + { + TCHAR Title[256]; + + LoadString(hInst, IDS_ABOUT, szBuf, sizeof(szBuf) / sizeof(TCHAR)); + LoadString(hInst, IDS_ABOUT_TITLE, Title, sizeof(Title) / sizeof(TCHAR)); + + MessageBox(hWnd, (LPCTSTR)szBuf, (LPCTSTR)Title, MB_OK | MB_ICONINFORMATION); + + return 0; + } + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); } static INT RunControlPanelWindow(int nCmdShow) { - MSG msg; - WNDCLASS wc; - TCHAR szBuf[256]; + MSG msg; + HWND hMainWnd; + INITCOMMONCONTROLSEX icex; + WNDCLASSEX wcex = {0}; + TCHAR szBuf[256]; - memset(&wc,0x00,sizeof(wc)); - wc.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAINICON)); - wc.lpszClassName = MYWNDCLASS; - wc.lpszMenuName = _T("MAINMENU"); - wc.lpfnWndProc = MyWindowProc; - RegisterClass(&wc); + wcex.cbSize = sizeof(wcex); + wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAINICON)); + wcex.lpszClassName = MYWNDCLASS; + wcex.lpfnWndProc = MyWindowProc; + RegisterClassEx(&wcex); - InitCommonControls(); - - LoadString(hInst, IDS_WINDOW_TITLE, szBuf, sizeof(szBuf) / sizeof(TCHAR)); - hMainWnd = CreateWindowEx(WS_EX_CLIENTEDGE, - MYWNDCLASS, - (LPCTSTR)szBuf, - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - NULL, - LoadMenu(hInst, MAKEINTRESOURCE(IDM_MAINMENU)), - hInst, - 0); - if (!hMainWnd) + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_LISTVIEW_CLASSES; + InitCommonControlsEx(&icex); + + LoadString(hInst, IDS_WINDOW_TITLE, szBuf, sizeof(szBuf) / sizeof(TCHAR)); + + hMainWnd = CreateWindowEx(WS_EX_CLIENTEDGE, + MYWNDCLASS, + (LPCTSTR)szBuf, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + LoadMenu(hInst, MAKEINTRESOURCE(IDM_MAINMENU)), + hInst, + 0); + if (!hMainWnd) + return 1; + + ShowWindow(hMainWnd, nCmdShow); + + while (GetMessage(&msg, 0, 0, 0)) { - CTL_DEBUG((_T("Unable to create window\r\n"))); - return -1; + TranslateMessage(&msg); + DispatchMessage(&msg); } - ShowWindow(hMainWnd, nCmdShow); - while (GetMessage(&msg, 0, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return 0; + return 0; } - -static INT -RunControlPanel(LPCTSTR lpName, UINT uIndex) +int WINAPI +_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { - CPLINFO CplInfo; - HMODULE hDll; - CPLAPPLETFUNC pFunc; - UINT uPanelCount; + HKEY hKey; - hDll = LoadLibrary(lpName); - if (hDll == 0) + hInst = hInstance; + hProcessHeap = GetProcessHeap(); + + /* Show the control panel window if no argument or "panel" was passed */ + if(lpCmdLine[0] == 0 || !_tcsicmp(lpCmdLine, _T("panel"))) + return RunControlPanelWindow(nCmdShow); + + /* 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) { - return -1; - } - CTL_DEBUG((_T("Handle %08X\r\n"), hDll)); + DWORD dwIndex; - pFunc = (CPLAPPLETFUNC)GetProcAddress(hDll, "CPlApplet"); - if (pFunc == NULL) - { - FreeLibrary(hDll); - return -1; - } - CTL_DEBUG((_T("CPLFunc %08X\r\n"), pFunc)); - - if (!pFunc(NULL, CPL_INIT, 0, 0)) - { - FreeLibrary(hDll); - return -1; - } - - uPanelCount = (UINT)pFunc(NULL, CPL_GETCOUNT, 0, 0); - if (uIndex >= uPanelCount) - { - FreeLibrary(hDll); - return -1; - } - - pFunc(NULL, CPL_INQUIRE, (LPARAM)uIndex, (LPARAM)&CplInfo); - - pFunc(NULL, CPL_DBLCLK, CplInfo.lData, 0); - - FreeLibrary(hDll); - - return 0; -} - -int -_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) - { - 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) + for(dwIndex = 0; ; ++dwIndex) { - /* FIXME for now ignore page index */ - szSep[4] = _T('\0'); + 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; + } + + nReturnValue = RunControlPanel(pszData); + HeapFree(hProcessHeap, 0, pszData); + RegCloseKey(hKey); + + return nReturnValue; + } + + HeapFree(hProcessHeap, 0, pszData); + } } - return RunControlPanel(szCPL, selPage); + + RegCloseKey(hKey); } - return 0; + /* It's none of the known parameters, so interpret the parameter as the file name of a control panel applet */ + return RunControlPanel(lpCmdLine); } diff --git a/reactos/base/applications/control/control.h b/reactos/base/applications/control/control.h new file mode 100644 index 00000000000..67c50c9407d --- /dev/null +++ b/reactos/base/applications/control/control.h @@ -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 +#include +#include +#include + +#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) diff --git a/reactos/base/applications/control/control.rbuild b/reactos/base/applications/control/control.rbuild index 1aee2aaff1d..d191eb8e372 100644 --- a/reactos/base/applications/control/control.rbuild +++ b/reactos/base/applications/control/control.rbuild @@ -4,9 +4,11 @@ . 0x600 0x501 - kernel32 - user32 + advapi32 comctl32 + kernel32 + shell32 + user32 control.c control.rc