* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/*
-TODO:
-1. The selected items list should not be stored in CControlPanelFolder, it should
- be a result returned by an internal method.
-*/
-
#include <precomp.h>
WINE_DEFAULT_DEBUG_CHANNEL(shell);
CControlPanelEnum();
~CControlPanelEnum();
HRESULT WINAPI Initialize(DWORD dwFlags);
- BOOL RegisterCPanelApp(LPCSTR path);
- int RegisterRegistryCPanelApps(HKEY hkey_root, LPCSTR szRepPath);
- int RegisterCPanelFolders(HKEY hkey_root, LPCSTR szRepPath);
+ BOOL RegisterCPanelApp(LPCWSTR path);
+ int RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath);
+ int RegisterCPanelFolders(HKEY hkey_root, LPCWSTR szRepPath);
BOOL CreateCPanelEnumList(DWORD dwFlags);
BEGIN_COM_MAP(CControlPanelEnum)
return S_OK;
}
-static LPITEMIDLIST _ILCreateCPanelApplet(LPCSTR pszName, LPCSTR pszDisplayName, LPCSTR pszComment, int iIconIdx)
+static LPITEMIDLIST _ILCreateCPanelApplet(LPCWSTR pszName, LPCWSTR pszDisplayName, LPCWSTR pszComment, int iIconIdx)
{
PIDLCPanelStruct *pCP;
LPITEMIDLIST pidl;
int cchName, cchDisplayName, cchComment, cbData;
/* Calculate lengths of given strings */
- cchName = strlen(pszName);
- cchDisplayName = strlen(pszDisplayName);
- cchComment = strlen(pszComment);
+ cchName = wcslen(pszName);
+ cchDisplayName = wcslen(pszDisplayName);
+ cchComment = wcslen(pszComment);
/* Allocate PIDL */
cbData = sizeof(pidl->mkid.cb) + sizeof(pData->type) + sizeof(pData->u.cpanel) - sizeof(pData->u.cpanel.szName)
- + cchName + cchDisplayName + cchComment + 3;
+ + (cchName + cchDisplayName + cchComment + 3) * sizeof(WCHAR);
pidl = (LPITEMIDLIST)SHAlloc(cbData + sizeof(WORD));
if (!pidl)
return NULL;
pCP = &pData->u.cpanel;
pCP->dummy = 0;
pCP->iconIdx = iIconIdx;
- strcpy(pCP->szName, pszName);
+ wcscpy(pCP->szName, pszName);
pCP->offsDispName = cchName + 1;
- strcpy(pCP->szName + pCP->offsDispName, pszDisplayName);
+ wcscpy(pCP->szName + pCP->offsDispName, pszDisplayName);
pCP->offsComment = pCP->offsDispName + cchDisplayName + 1;
- strcpy(pCP->szName + pCP->offsComment, pszComment);
+ wcscpy(pCP->szName + pCP->offsComment, pszComment);
/* Add PIDL NULL terminator */
*(WORD*)(pCP->szName + pCP->offsComment + cchComment + 1) = 0;
return NULL;
}
-BOOL CControlPanelEnum::RegisterCPanelApp(LPCSTR path)
+BOOL CControlPanelEnum::RegisterCPanelApp(LPCWSTR wpath)
{
- LPITEMIDLIST pidl;
- CPlApplet* applet;
- CPanel panel;
- CPLINFO info;
- unsigned i;
+ CPlApplet* applet = Control_LoadApplet(0, wpath, NULL);
int iconIdx;
- char displayName[MAX_PATH];
- char comment[MAX_PATH];
-
- WCHAR wpath[MAX_PATH];
-
- MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH);
-
- panel.first = NULL;
- applet = Control_LoadApplet(0, wpath, &panel);
-
if (applet)
{
- for (i = 0; i < applet->count; ++i)
+ for (UINT i = 0; i < applet->count; ++i)
{
- applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info);
-
- LoadStringA(applet->hModule, info.idName, displayName, MAX_PATH);
- LoadStringA(applet->hModule, info.idInfo, comment, MAX_PATH);
-
- if (info.idIcon > 0)
- iconIdx = -info.idIcon; /* negative icon index instead of icon number */
+ if (applet->info[i].idIcon > 0)
+ iconIdx = -applet->info[i].idIcon; /* negative icon index instead of icon number */
else
iconIdx = 0;
- pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx);
+ LPITEMIDLIST pidl = _ILCreateCPanelApplet(wpath,
+ applet->info[i].name,
+ applet->info[i].info,
+ iconIdx);
if (pidl)
AddToEnumList(pidl);
return TRUE;
}
-int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCSTR szRepPath)
+int CControlPanelEnum::RegisterRegistryCPanelApps(HKEY hkey_root, LPCWSTR szRepPath)
{
- char name[MAX_PATH];
- char value[MAX_PATH];
+ WCHAR name[MAX_PATH];
+ WCHAR value[MAX_PATH];
HKEY hkey;
int cnt = 0;
- if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
+ if (RegOpenKeyW(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
{
int idx = 0;
{
DWORD nameLen = MAX_PATH;
DWORD valueLen = MAX_PATH;
- char buffer[MAX_PATH];
+ WCHAR buffer[MAX_PATH];
- if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS)
+ if (RegEnumValueW(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS)
break;
- if (ExpandEnvironmentStringsA(value, buffer, MAX_PATH))
+ if (ExpandEnvironmentStringsW(value, buffer, MAX_PATH))
{
- strcpy(value, buffer);
+ wcscpy(value, buffer);
}
if (RegisterCPanelApp(value))
return cnt;
}
-int CControlPanelEnum::RegisterCPanelFolders(HKEY hkey_root, LPCSTR szRepPath)
+int CControlPanelEnum::RegisterCPanelFolders(HKEY hkey_root, LPCWSTR szRepPath)
{
- char name[MAX_PATH];
+ WCHAR name[MAX_PATH];
HKEY hkey;
int cnt = 0;
- if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
+ if (RegOpenKeyW(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
{
- int idx = 0;
- for (; ; idx++)
+ for (int idx = 0; ; idx++)
{
- if (RegEnumKeyA(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS)
+ if (RegEnumKeyW(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS)
break;
if (*name == '{')
{
- LPITEMIDLIST pidl = _ILCreateGuidFromStrA(name);
+ LPITEMIDLIST pidl = _ILCreateGuidFromStrW(name);
if (pidl && AddToEnumList(pidl))
++cnt;
*/
BOOL CControlPanelEnum::CreateCPanelEnumList(DWORD dwFlags)
{
- CHAR szPath[MAX_PATH];
- WIN32_FIND_DATAA wfd;
+ WCHAR szPath[MAX_PATH];
+ WIN32_FIND_DATAW wfd;
HANDLE hFile;
TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
/* enumerate control panel folders */
if (dwFlags & SHCONTF_FOLDERS)
- RegisterCPanelFolders(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
+ RegisterCPanelFolders(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
/* enumerate the control panel applets */
if (dwFlags & SHCONTF_NONFOLDERS)
{
- LPSTR p;
+ LPWSTR p;
- GetSystemDirectoryA(szPath, MAX_PATH);
- p = PathAddBackslashA(szPath);
- strcpy(p, "*.cpl");
+ GetSystemDirectoryW(szPath, MAX_PATH);
+ p = PathAddBackslashW(szPath);
+ wcscpy(p, L"*.cpl");
- TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n", this, debugstr_a(szPath));
- hFile = FindFirstFileA(szPath, &wfd);
+ hFile = FindFirstFileW(szPath, &wfd);
if (hFile != INVALID_HANDLE_VALUE)
{
continue;
if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- strcpy(p, wfd.cFileName);
- if (strcmp(wfd.cFileName, "ncpa.cpl"))
+ wcscpy(p, wfd.cFileName);
+ if (wcscmp(wfd.cFileName, L"ncpa.cpl"))
RegisterCPanelApp(szPath);
}
- } while(FindNextFileA(hFile, &wfd));
+ } while(FindNextFileW(hFile, &wfd));
FindClose(hFile);
}
- RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
- RegisterRegistryCPanelApps(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
+ RegisterRegistryCPanelApps(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
+ RegisterRegistryCPanelApps(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls");
}
return TRUE;
}
if (pCPanel)
{
- /* copy display name from pidl - it was retrived from applet before;
- SHGDN_FORPARSING does not need special handling */
- strRet->uType = STRRET_CSTR;
- lstrcpyA(strRet->cStr, pCPanel->szName + pCPanel->offsDispName);
+ return SHSetStrRet(strRet, pCPanel->szName + pCPanel->offsDispName);
}
else if (_ILIsSpecialFolder(pidl))
{
if (!pidl) {
psd->fmt = ControlPanelSFHeader[iColumn].fmt;
psd->cxChar = ControlPanelSFHeader[iColumn].cxChar;
- psd->str.uType = STRRET_CSTR;
- LoadStringA(shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid, psd->str.cStr, MAX_PATH);
- return S_OK;
+ return SHSetStrRet(&psd->str, shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid);
} else {
- psd->str.cStr[0] = 0x00;
- psd->str.uType = STRRET_CSTR;
switch(iColumn) {
case 0: /* name */
hr = GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
{
PIDLCPanelStruct* pCPanel = _ILGetCPanelPointer(pidl);
if (pCPanel)
- lstrcpyA(psd->str.cStr, pCPanel->szName + pCPanel->offsComment);
+ return SHSetStrRet(&psd->str, pCPanel->szName + pCPanel->offsComment);
if (_ILIsSpecialFolder(pidl))
{
HKEY hKey;
GUID *pGuid = _ILGetGUIDPointer(pidl);
if (HCR_RegOpenClassIDKey(*pGuid, &hKey))
{
+ psd->str.cStr[0] = 0x00;
+ psd->str.uType = STRRET_CSTR;
RegLoadMUIStringA(hKey, "InfoTip", psd->str.cStr, MAX_PATH, NULL, 0, NULL);
RegCloseKey(hKey);
}
if (!pcpanel)
return E_INVALIDARG;
- MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, szIconFile, cchMax);
+ wcsncpy(szIconFile, pcpanel->szName, cchMax);
*piIndex = (int)pcpanel->iconIdx != -1 ? pcpanel->iconIdx : 0;
return S_OK;
UINT idCmdLast,
UINT uFlags)
{
- WCHAR szBuffer[30] = {0};
- ULONG Count = 1;
-
- TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
- this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
-
- if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
- {
- szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_OPEN, MFT_STRING, szBuffer, MFS_DEFAULT); //FIXME identifier
- Count++;
- }
-
- if (LoadStringW(shell32_hInstance, IDS_CREATELINK, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
- {
- if (Count)
- {
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_SEPARATOR, NULL, MFS_ENABLED);
- }
- szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
+ _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_OPEN, MFT_STRING, MAKEINTRESOURCEW(IDS_OPEN), MFS_DEFAULT);
+ _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_SEPARATOR, NULL, MFS_ENABLED);
+ _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED);
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_CREATELINK, MFT_STRING, szBuffer, MFS_ENABLED); //FIXME identifier
- Count++;
- }
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 2);
}
EXTERN_C
-void WINAPI Control_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow);
+void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
/**************************************************************************
* ICPanel_IContextMenu_InvokeCommand()
*/
HRESULT WINAPI CCPLItemMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
- WCHAR szPath[MAX_PATH];
- char szTarget[MAX_PATH];
- WCHAR* pszPath;
- INT Length, cLength;
- CComPtr<IPersistFile> ppf;
- CComPtr<IShellLinkA> isl;
HRESULT hResult;
PIDLCPanelStruct *pCPanel = _ILGetCPanelPointer(m_apidl[0]);
if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_OPEN)) //FIXME
{
- CHAR szParams[MAX_PATH];
+ WCHAR wszParams[MAX_PATH];
- strcpy(szParams, pCPanel->szName);
- strcat(szParams, ",");
- strcat(szParams, pCPanel->szName + pCPanel->offsDispName);
+ wcscpy(wszParams, pCPanel->szName);
+ wcscat(wszParams, L",");
+ wcscat(wszParams, pCPanel->szName + pCPanel->offsDispName);
- Control_RunDLLA (NULL, NULL, szParams, SW_NORMAL);
+ Control_RunDLLW (NULL, NULL, wszParams, SW_NORMAL);
}
else if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_CREATELINK)) //FIXME
{
- if (!SHGetSpecialFolderPathW(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
- return E_FAIL;
-
- pszPath = PathAddBackslashW(szPath);
- if (!pszPath)
- return E_FAIL;
+ CComPtr<IDataObject> pDataObj;
+ LPITEMIDLIST pidl = _ILCreateControlPanel();
- CHAR* pszDisplayName = pCPanel->szName + pCPanel->offsDispName;
+ hResult = SHCreateDataObject(pidl, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
+ if (FAILED(hResult))
+ return hResult;
- Length = MAX_PATH - (pszPath - szPath);
- cLength = strlen(pszDisplayName);
- if (Length < cLength + 5)
- {
- FIXME("\n");
- return E_FAIL;
- }
+ SHFree(pidl);
- if (MultiByteToWideChar(CP_ACP, 0, pszDisplayName, cLength + 1, pszPath, Length))
- {
- pszPath += cLength;
- Length -= cLength;
- }
+ //FIXME: Use SHCreateLinks
+ CComPtr<IShellFolder> psf;
+ CComPtr<IDropTarget> pDT;
- if (Length > 10)
- {
- wcscpy(pszPath, L" - ");
- cLength = LoadStringW(shell32_hInstance, IDS_LNK_FILE, &pszPath[3], Length - 4) + 3;
- if (cLength + 5 > Length)
- cLength = Length - 5;
- Length -= cLength;
- pszPath += cLength;
- }
- wcscpy(pszPath, L".lnk");
+ hResult = SHGetDesktopFolder(&psf);
+ if (FAILED(hResult))
+ return hResult;
- strncpy(szTarget, pCPanel->szName, MAX_PATH);
+ hResult = psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pDT));
+ if (FAILED(hResult))
+ return hResult;
- hResult = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkA, &isl));
- if (SUCCEEDED(hResult))
- {
- isl->SetPath(szTarget);
- if (SUCCEEDED(isl->QueryInterface(IID_PPV_ARG(IPersistFile,&ppf))))
- ppf->Save(szPath, TRUE);
- }
- return NOERROR;
+ SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL);
}
return S_OK;
}
#include <winbase.h>
#define NO_SHLWAPI_REG
#include <shlwapi.h>
+#include <shellapi.h>
#include <wine/debug.h>
#include "cpanel.h"
+#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(shlctrl);
-CPlApplet* Control_UnloadApplet(CPlApplet* applet)
+void Control_UnloadApplet(CPlApplet* applet)
{
- unsigned i;
- CPlApplet* next;
+ unsigned i;
for (i = 0; i < applet->count; i++)
- {
- if (!applet->info[i].dwSize)
- continue;
- applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData);
- }
- if (applet->proc)
- applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L);
-
+ applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].data);
+
+ if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L);
FreeLibrary(applet->hModule);
- next = applet->next;
+#ifndef __REACTOS__
+ list_remove( &applet->entry );
+#endif
HeapFree(GetProcessHeap(), 0, applet->cmd);
HeapFree(GetProcessHeap(), 0, applet);
- return next;
}
-CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel)
+CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel)
{
- CPlApplet* applet;
+ CPlApplet* applet;
DWORD len;
- unsigned i;
- CPLINFO info;
+ unsigned i;
+ CPLINFO info;
NEWCPLINFOW newinfo;
- if (!(applet = (CPlApplet *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet))))
+ if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet))))
return applet;
len = ExpandEnvironmentStringsW(cmd, NULL, 0);
applet->hWnd = hWnd;
- if (!(applet->hModule = LoadLibraryW(applet->cmd)))
- {
+ if (!(applet->hModule = LoadLibraryW(applet->cmd))) {
WARN("Cannot load control panel applet %s\n", debugstr_w(applet->cmd));
- goto theError;
+ goto theError;
}
- if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet")))
- {
+ if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) {
WARN("Not a valid control panel applet %s\n", debugstr_w(applet->cmd));
- goto theError;
+ goto theError;
}
- if (!applet->proc(hWnd, CPL_INIT, 0L, 0L))
- {
+ if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) {
WARN("Init of applet has failed\n");
- goto theError;
+ goto theError;
}
- if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0)
- {
+ if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) {
WARN("No subprogram in applet\n");
- goto theError;
+ applet->proc(applet->hWnd, CPL_EXIT, 0, 0);
+ goto theError;
}
- applet = (CPlApplet *)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet,
- sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW));
+ applet = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet,
+ FIELD_OFFSET( CPlApplet, info[applet->count] ));
- for (i = 0; i < applet->count; i++)
- {
- ZeroMemory(&newinfo, sizeof(newinfo));
- newinfo.dwSize = sizeof(NEWCPLINFOW);
- applet->info[i].dwSize = sizeof(NEWCPLINFOW);
+ for (i = 0; i < applet->count; i++) {
+ ZeroMemory(&newinfo, sizeof(newinfo));
+ newinfo.dwSize = sizeof(NEWCPLINFOA);
+ applet->info[i].helpfile[0] = 0;
/* proc is supposed to return a null value upon success for
- * CPL_INQUIRE and CPL_NEWINQUIRE
- * However, real drivers don't seem to behave like this
- * So, use introspection rather than return value
- */
- applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo);
- if (newinfo.hIcon == 0)
- {
- applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info);
- if (info.idIcon == 0 || info.idName == 0)
- {
- WARN("Couldn't get info from sp %u\n", i);
- applet->info[i].dwSize = 0;
- }
- else
- {
- /* convert the old data into the new structure */
- applet->info[i].dwFlags = 0;
- applet->info[i].dwHelpContext = 0;
- applet->info[i].lData = info.lData;
- applet->info[i].hIcon = LoadIconW(applet->hModule,
- MAKEINTRESOURCEW(info.idIcon));
- LoadStringW(applet->hModule, info.idName,
- applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR));
- LoadStringW(applet->hModule, info.idInfo,
- applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR));
- applet->info[i].szHelpFile[0] = '\0';
- }
- }
- else
- {
- CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize);
- if (newinfo.dwSize != sizeof(NEWCPLINFOW))
- {
- applet->info[i].dwSize = sizeof(NEWCPLINFOW);
- lstrcpyW(applet->info[i].szName, newinfo.szName);
- lstrcpyW(applet->info[i].szInfo, newinfo.szInfo);
- lstrcpyW(applet->info[i].szHelpFile, newinfo.szHelpFile);
- }
- }
+ * CPL_INQUIRE and CPL_NEWINQUIRE
+ * However, real drivers don't seem to behave like this
+ * So, use introspection rather than return value
+ */
+ applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info);
+ applet->info[i].data = info.lData;
+#if __REACTOS__
+ applet->info[i].idIcon = info.idIcon;
+#endif
+
+ if (info.idIcon != CPL_DYNAMIC_RES)
+ applet->info[i].icon = LoadIconW(applet->hModule, MAKEINTRESOURCEW(info.idIcon));
+ if (info.idName != CPL_DYNAMIC_RES)
+ LoadStringW(applet->hModule, info.idName,
+ applet->info[i].name, sizeof(applet->info[i].name) / sizeof(WCHAR));
+ if (info.idInfo != CPL_DYNAMIC_RES)
+ LoadStringW(applet->hModule, info.idInfo,
+ applet->info[i].info, sizeof(applet->info[i].info) / sizeof(WCHAR));
+
+ /* some broken control panels seem to return incorrect values in CPL_INQUIRE,
+ but proper data in CPL_NEWINQUIRE. if we get an empty string or a null
+ icon, see what we can get from CPL_NEWINQUIRE */
+
+ if (!applet->info[i].name[0]) info.idName = CPL_DYNAMIC_RES;
+
+ /* zero-length szInfo may not be a buggy applet, but it doesn't hurt for us
+ to check anyway */
+
+ if (!applet->info[i].info[0]) info.idInfo = CPL_DYNAMIC_RES;
+
+ if (applet->info[i].icon == NULL)
+ info.idIcon = CPL_DYNAMIC_RES;
+
+ if ((info.idIcon == CPL_DYNAMIC_RES) || (info.idName == CPL_DYNAMIC_RES) ||
+ (info.idInfo == CPL_DYNAMIC_RES)) {
+ applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo);
+
+ applet->info[i].data = newinfo.lData;
+ if (info.idIcon == CPL_DYNAMIC_RES) {
+ if (!newinfo.hIcon) WARN("couldn't get icon for applet %u\n", i);
+ applet->info[i].icon = newinfo.hIcon;
+ }
+ if (newinfo.dwSize == sizeof(NEWCPLINFOW)) {
+ if (info.idName == CPL_DYNAMIC_RES)
+ memcpy(applet->info[i].name, newinfo.szName, sizeof(newinfo.szName));
+ if (info.idInfo == CPL_DYNAMIC_RES)
+ memcpy(applet->info[i].info, newinfo.szInfo, sizeof(newinfo.szInfo));
+ memcpy(applet->info[i].helpfile, newinfo.szHelpFile, sizeof(newinfo.szHelpFile));
+ } else {
+ if (info.idName == CPL_DYNAMIC_RES)
+ MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szName,
+ sizeof(((LPNEWCPLINFOA)&newinfo)->szName) / sizeof(CHAR),
+ applet->info[i].name, sizeof(applet->info[i].name) / sizeof(WCHAR));
+ if (info.idInfo == CPL_DYNAMIC_RES)
+ MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szInfo,
+ sizeof(((LPNEWCPLINFOA)&newinfo)->szInfo) / sizeof(CHAR),
+ applet->info[i].info, sizeof(applet->info[i].info) / sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szHelpFile,
+ sizeof(((LPNEWCPLINFOA)&newinfo)->szHelpFile) / sizeof(CHAR),
+ applet->info[i].helpfile,
+ sizeof(applet->info[i].helpfile) / sizeof(WCHAR));
+ }
+ }
}
- applet->next = panel->first;
- panel->first = applet;
+#ifndef __REACTOS__
+ list_add_head( &panel->applets, &applet->entry );
+#endif
return applet;
theError:
- Control_UnloadApplet(applet);
+ FreeLibrary(applet->hModule);
+ HeapFree(GetProcessHeap(), 0, applet->cmd);
+ HeapFree(GetProcessHeap(), 0, applet);
return NULL;
}
-static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTW* cs)
+#ifndef __REACTOS__
+
+#define IDC_LISTVIEW 1000
+#define IDC_STATUSBAR 1001
+
+#define NUM_COLUMNS 2
+#define LISTVIEW_DEFSTYLE (WS_CHILD | WS_VISIBLE | WS_TABSTOP |\
+ LVS_SORTASCENDING | LVS_AUTOARRANGE | LVS_SINGLESEL)
+
+static BOOL Control_CreateListView (CPanel *panel)
{
- CPanel* panel = (CPanel*)cs->lpCreateParams;
+ RECT ws, sb;
+ WCHAR empty_string[] = {0};
+ WCHAR buf[MAX_STRING_LEN];
+ LVCOLUMNW lvc;
+
+ /* Create list view */
+ GetClientRect(panel->hWndStatusBar, &sb);
+ GetClientRect(panel->hWnd, &ws);
+
+ panel->hWndListView = CreateWindowExW(WS_EX_CLIENTEDGE, WC_LISTVIEWW,
+ empty_string, LISTVIEW_DEFSTYLE | LVS_ICON,
+ 0, 0, ws.right - ws.left, ws.bottom - ws.top -
+ (sb.bottom - sb.top), panel->hWnd,
+ (HMENU) IDC_LISTVIEW, panel->hInst, NULL);
+
+ if (!panel->hWndListView)
+ return FALSE;
+
+ /* Create image lists for list view */
+ panel->hImageListSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 1, 1);
+ panel->hImageListLarge = ImageList_Create(GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON), ILC_COLOR32 | ILC_MASK, 1, 1);
+
+ SendMessageW(panel->hWndListView, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)panel->hImageListSmall);
+ SendMessageW(panel->hWndListView, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)panel->hImageListLarge);
+
+ /* Create columns for list view */
+ lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
+ lvc.pszText = buf;
+ lvc.fmt = LVCFMT_LEFT;
+
+ /* Name column */
+ lvc.iSubItem = 0;
+ lvc.cx = (ws.right - ws.left) / 3;
+ LoadStringW(shell32_hInstance, IDS_CPANEL_NAME, buf, sizeof(buf) / sizeof(buf[0]));
+
+ if (ListView_InsertColumnW(panel->hWndListView, 0, &lvc) == -1)
+ return FALSE;
+
+ /* Description column */
+ lvc.iSubItem = 1;
+ lvc.cx = ((ws.right - ws.left) / 3) * 2;
+ LoadStringW(shell32_hInstance, IDS_CPANEL_DESCRIPTION, buf, sizeof(buf) /
+ sizeof(buf[0]));
+
+ if (ListView_InsertColumnW(panel->hWndListView, 1, &lvc) == -1)
+ return FALSE;
+
+ return(TRUE);
+}
+
+static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTW* cs)
+{
+ CPanel* panel = cs->lpCreateParams;
+ HMENU hMenu, hSubMenu;
+ CPlApplet* applet;
+ MENUITEMINFOW mii;
+ unsigned int i;
+ int menucount, index;
+ CPlItem *item;
+ LVITEMW lvItem;
+ INITCOMMONCONTROLSEX icex;
+ INT sb_parts;
+ int itemidx;
SetWindowLongPtrW(hWnd, 0, (LONG_PTR)panel);
- panel->status = 0;
panel->hWnd = hWnd;
-}
-#define XICON 32
-#define XSTEP 128
-#define YICON 32
-#define YSTEP 64
+ /* Initialise common control DLL */
+ icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ /* create the status bar */
+ if (!(panel->hWndStatusBar = CreateStatusWindowW(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, NULL, hWnd, IDC_STATUSBAR)))
+ return;
-static BOOL Control_Localize(const CPanel* panel, int cx, int cy,
- CPlApplet** papplet, unsigned* psp)
+ sb_parts = -1;
+ SendMessageW(panel->hWndStatusBar, SB_SETPARTS, 1, (LPARAM) &sb_parts);
+
+ /* create the list view */
+ if (!Control_CreateListView(panel))
+ return;
+
+ hMenu = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(MENU_CPANEL));
+
+ /* insert menu items for applets */
+ hSubMenu = GetSubMenu(hMenu, 0);
+ menucount = 0;
+
+ LIST_FOR_EACH_ENTRY( applet, &panel->applets, CPlApplet, entry )
+ {
+ for (i = 0; i < applet->count; i++) {
+ /* set up a CPlItem for this particular subprogram */
+ item = HeapAlloc(GetProcessHeap(), 0, sizeof(CPlItem));
+
+ if (!item)
+ continue;
+
+ item->applet = applet;
+ item->id = i;
+
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA;
+ mii.dwTypeData = applet->info[i].name;
+ mii.cch = sizeof(applet->info[i].name) / sizeof(WCHAR);
+ mii.wID = IDM_CPANEL_APPLET_BASE + menucount;
+ mii.dwItemData = (ULONG_PTR)item;
+
+ if (InsertMenuItemW(hSubMenu, menucount, TRUE, &mii)) {
+ /* add the list view item */
+ HICON icon = applet->info[i].icon;
+ if (!icon) icon = LoadImageW( 0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_SHARED );
+ index = ImageList_AddIcon(panel->hImageListLarge, icon);
+ ImageList_AddIcon(panel->hImageListSmall, icon);
+
+ lvItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
+ lvItem.iItem = menucount;
+ lvItem.iSubItem = 0;
+ lvItem.pszText = applet->info[i].name;
+ lvItem.iImage = index;
+ lvItem.lParam = (LPARAM) item;
+
+ itemidx = ListView_InsertItemW(panel->hWndListView, &lvItem);
+
+ /* add the description */
+ ListView_SetItemTextW(panel->hWndListView, itemidx, 1, applet->info[i].info);
+
+ /* update menu bar, increment count */
+ DrawMenuBar(hWnd);
+ menucount++;
+ }
+ }
+ }
+
+ panel->total_subprogs = menucount;
+
+ /* check the "large items" icon in the View menu */
+ hSubMenu = GetSubMenu(hMenu, 1);
+ CheckMenuRadioItem(hSubMenu, FCIDM_SHVIEW_BIGICON, FCIDM_SHVIEW_REPORTVIEW,
+ FCIDM_SHVIEW_BIGICON, MF_BYCOMMAND);
+
+ SetMenu(hWnd, hMenu);
+}
+
+static void Control_FreeCPlItems(HWND hWnd, CPanel *panel)
{
- unsigned int i;
- int x = (XSTEP-XICON)/2, y = 0;
- CPlApplet* applet;
- RECT rc;
+ HMENU hMenu, hSubMenu;
+ MENUITEMINFOW mii;
+ unsigned int i;
+
+ /* get the File menu */
+ hMenu = GetMenu(hWnd);
- GetClientRect(panel->hWnd, &rc);
- for (applet = panel->first; applet; applet = applet->next)
+ if (!hMenu)
+ return;
+
+ hSubMenu = GetSubMenu(hMenu, 0);
+
+ if (!hSubMenu)
+ return;
+
+ /* loop and free the item data */
+ for (i = IDM_CPANEL_APPLET_BASE; i <= IDM_CPANEL_APPLET_BASE + panel->total_subprogs; i++)
{
- for (i = 0; i < applet->count; i++)
- {
- if (!applet->info[i].dwSize)
- continue;
- if (x + XSTEP >= rc.right - rc.left)
- {
- x = (XSTEP-XICON)/2;
- y += YSTEP;
- }
- if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP)
- {
- *papplet = applet;
- *psp = i;
- return TRUE;
- }
- x += XSTEP;
- }
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask = MIIM_DATA;
+
+ if (!GetMenuItemInfoW(hSubMenu, i, FALSE, &mii))
+ continue;
+
+ HeapFree(GetProcessHeap(), 0, (LPVOID) mii.dwItemData);
}
- return FALSE;
}
-static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam)
+static void Control_UpdateListViewStyle(CPanel *panel, UINT style, UINT id)
{
- HDC hdc;
- PAINTSTRUCT ps;
- RECT rc, txtRect;
- unsigned int i;
- int x = 0, y = 0;
- CPlApplet* applet;
- HGDIOBJ hOldFont;
-
- hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps);
- hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
- GetClientRect(panel->hWnd, &rc);
-
- for (applet = panel->first; applet; applet = applet->next)
- {
- for (i = 0; i < applet->count; i++)
- {
- if (x + XSTEP >= rc.right - rc.left)
- {
- x = 0;
- y += YSTEP;
- }
- if (!applet->info[i].dwSize)
- continue;
- DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon);
- txtRect.left = x;
- txtRect.right = x + XSTEP;
- txtRect.top = y + YICON;
- txtRect.bottom = y + YSTEP;
- DrawTextW(hdc, applet->info[i].szName, -1, &txtRect,
- DT_CENTER | DT_VCENTER);
- x += XSTEP;
- }
- }
+ HMENU hMenu, hSubMenu;
+
+ SetWindowLongW(panel->hWndListView, GWL_STYLE, LISTVIEW_DEFSTYLE | style);
- SelectObject(hdc, hOldFont);
- if (!wParam)
- EndPaint(panel->hWnd, &ps);
+ /* update the menu */
+ hMenu = GetMenu(panel->hWnd);
+ hSubMenu = GetSubMenu(hMenu, 1);
- return 0;
+ CheckMenuRadioItem(hSubMenu, FCIDM_SHVIEW_BIGICON, FCIDM_SHVIEW_REPORTVIEW,
+ id, MF_BYCOMMAND);
}
-static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up)
+static CPlItem* Control_GetCPlItem_From_MenuID(HWND hWnd, UINT id)
{
- unsigned i;
- CPlApplet* applet;
+ HMENU hMenu, hSubMenu;
+ MENUITEMINFOW mii;
- if (Control_Localize(panel, (short)LOWORD(lParam), (short)HIWORD(lParam), &applet, &i))
+ /* retrieve the CPlItem structure from the menu item data */
+ hMenu = GetMenu(hWnd);
+
+ if (!hMenu)
+ return NULL;
+
+ hSubMenu = GetSubMenu(hMenu, 0);
+
+ if (!hSubMenu)
+ return NULL;
+
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask = MIIM_DATA;
+
+ if (!GetMenuItemInfoW(hSubMenu, id, FALSE, &mii))
+ return NULL;
+
+ return (CPlItem *) mii.dwItemData;
+}
+
+static CPlItem* Control_GetCPlItem_From_ListView(CPanel *panel)
+{
+ LVITEMW lvItem;
+ int selitem;
+
+ selitem = SendMessageW(panel->hWndListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED
+ | LVNI_SELECTED);
+
+ if (selitem != -1)
{
- if (up)
- {
- if (panel->clkApplet == applet && panel->clkSP == i)
- {
- applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData);
- }
- }
- else
- {
- panel->clkApplet = applet;
- panel->clkSP = i;
- }
+ lvItem.iItem = selitem;
+ lvItem.mask = LVIF_PARAM;
+
+ if (SendMessageW(panel->hWndListView, LVM_GETITEMW, 0, (LPARAM) &lvItem))
+ return (CPlItem *) lvItem.lParam;
}
- return 0;
+
+ return NULL;
}
-static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
- WPARAM lParam1, LPARAM lParam2)
+static void Control_StartApplet(HWND hWnd, CPlItem *item)
{
- CPanel* panel = (CPanel*)GetWindowLongPtrW(hWnd, 0);
+ WCHAR verbOpen[] = {'c','p','l','o','p','e','n',0};
+ WCHAR format[] = {'@','%','d',0};
+ WCHAR param[MAX_PATH];
- if (panel || wMsg == WM_CREATE)
+ /* execute the applet if item is valid */
+ if (item)
{
- switch (wMsg)
- {
- case WM_CREATE:
- Control_WndProc_Create(hWnd, (CREATESTRUCTW*)lParam2);
- return 0;
- case WM_DESTROY:
- {
- CPlApplet *applet = panel->first;
- while (applet)
- applet = Control_UnloadApplet(applet);
-
- PostQuitMessage(0);
- break;
- }
- case WM_PAINT:
- return Control_WndProc_Paint(panel, lParam1);
- case WM_LBUTTONUP:
- return Control_WndProc_LButton(panel, lParam2, TRUE);
- case WM_LBUTTONDOWN:
- return Control_WndProc_LButton(panel, lParam2, FALSE);
- /* EPP case WM_COMMAND: */
- /* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */
- }
+ wsprintfW(param, format, item->id);
+ ShellExecuteW(hWnd, verbOpen, item->applet->cmd, param, NULL, SW_SHOW);
}
+}
+
+static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
+ WPARAM lParam1, LPARAM lParam2)
+{
+ CPanel* panel = (CPanel*)GetWindowLongPtrW(hWnd, 0);
+
+ if (panel || wMsg == WM_CREATE) {
+ switch (wMsg) {
+ case WM_CREATE:
+ Control_WndProc_Create(hWnd, (CREATESTRUCTW*)lParam2);
+ return 0;
+ case WM_DESTROY:
+ {
+ CPlApplet *applet, *next;
+ LIST_FOR_EACH_ENTRY_SAFE( applet, next, &panel->applets, CPlApplet, entry )
+ Control_UnloadApplet(applet);
+ }
+ Control_FreeCPlItems(hWnd, panel);
+ PostQuitMessage(0);
+ break;
+ case WM_COMMAND:
+ switch (LOWORD(lParam1))
+ {
+ case IDM_CPANEL_EXIT:
+ SendMessageW(hWnd, WM_CLOSE, 0, 0);
+ return 0;
+
+ case IDM_CPANEL_ABOUT:
+ {
+ WCHAR appName[MAX_STRING_LEN];
+ HICON icon = LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_CONTROL_PANEL),
+ IMAGE_ICON, 48, 48, LR_SHARED);
+
+ LoadStringW(shell32_hInstance, IDS_CPANEL_TITLE, appName,
+ sizeof(appName) / sizeof(appName[0]));
+ ShellAboutW(hWnd, appName, NULL, icon);
+
+ return 0;
+ }
+
+ case FCIDM_SHVIEW_BIGICON:
+ Control_UpdateListViewStyle(panel, LVS_ICON, FCIDM_SHVIEW_BIGICON);
+ return 0;
+
+ case FCIDM_SHVIEW_SMALLICON:
+ Control_UpdateListViewStyle(panel, LVS_SMALLICON, FCIDM_SHVIEW_SMALLICON);
+ return 0;
+
+ case FCIDM_SHVIEW_LISTVIEW:
+ Control_UpdateListViewStyle(panel, LVS_LIST, FCIDM_SHVIEW_LISTVIEW);
+ return 0;
+
+ case FCIDM_SHVIEW_REPORTVIEW:
+ Control_UpdateListViewStyle(panel, LVS_REPORT, FCIDM_SHVIEW_REPORTVIEW);
+ return 0;
+
+ default:
+ /* check if this is an applet */
+ if ((LOWORD(lParam1) >= IDM_CPANEL_APPLET_BASE) &&
+ (LOWORD(lParam1) <= IDM_CPANEL_APPLET_BASE + panel->total_subprogs))
+ {
+ Control_StartApplet(hWnd, Control_GetCPlItem_From_MenuID(hWnd, LOWORD(lParam1)));
+ return 0;
+ }
+
+ break;
+ }
+
+ break;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR nmh = (LPNMHDR) lParam2;
+
+ switch (nmh->idFrom)
+ {
+ case IDC_LISTVIEW:
+ switch (nmh->code)
+ {
+ case NM_RETURN:
+ case NM_DBLCLK:
+ {
+ Control_StartApplet(hWnd, Control_GetCPlItem_From_ListView(panel));
+ return 0;
+ }
+ case LVN_ITEMCHANGED:
+ {
+ CPlItem *item = Control_GetCPlItem_From_ListView(panel);
+
+ /* update the status bar if item is valid */
+ if (item)
+ SetWindowTextW(panel->hWndStatusBar, item->applet->info[item->id].info);
+ else
+ SetWindowTextW(panel->hWndStatusBar, NULL);
+
+ return 0;
+ }
+ }
+
+ break;
+ }
+
+ break;
+ }
+
+ case WM_MENUSELECT:
+ /* check if this is an applet */
+ if ((LOWORD(lParam1) >= IDM_CPANEL_APPLET_BASE) &&
+ (LOWORD(lParam1) <= IDM_CPANEL_APPLET_BASE + panel->total_subprogs))
+ {
+ CPlItem *item = Control_GetCPlItem_From_MenuID(hWnd, LOWORD(lParam1));
+
+ /* update the status bar if item is valid */
+ if (item)
+ SetWindowTextW(panel->hWndStatusBar, item->applet->info[item->id].info);
+ }
+ else if ((HIWORD(lParam1) == 0xFFFF) && (lParam2 == 0))
+ {
+ /* reset status bar description to that of the selected icon */
+ CPlItem *item = Control_GetCPlItem_From_ListView(panel);
+
+ if (item)
+ SetWindowTextW(panel->hWndStatusBar, item->applet->info[item->id].info);
+ else
+ SetWindowTextW(panel->hWndStatusBar, NULL);
+
+ return 0;
+ }
+ else
+ SetWindowTextW(panel->hWndStatusBar, NULL);
+
+ return 0;
+
+ case WM_SIZE:
+ {
+ HDWP hdwp;
+ RECT sb;
+
+ hdwp = BeginDeferWindowPos(2);
+
+ if (hdwp == NULL)
+ break;
+
+ GetClientRect(panel->hWndStatusBar, &sb);
+
+ hdwp = DeferWindowPos(hdwp, panel->hWndListView, NULL, 0, 0,
+ LOWORD(lParam2), HIWORD(lParam2) - (sb.bottom - sb.top),
+ SWP_NOZORDER | SWP_NOMOVE);
+
+ if (hdwp == NULL)
+ break;
+
+ hdwp = DeferWindowPos(hdwp, panel->hWndStatusBar, NULL, 0, 0,
+ LOWORD(lParam2), LOWORD(lParam1), SWP_NOZORDER | SWP_NOMOVE);
+
+ if (hdwp != NULL)
+ EndDeferWindowPos(hdwp);
+
+ return 0;
+ }
+ }
+ }
return DefWindowProcW(hWnd, wMsg, lParam1, lParam2);
}
-static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst)
+static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst)
{
- WNDCLASSW wc;
- MSG msg;
- const WCHAR* appName = L"ReactOS Control Panel";
+ WNDCLASSEXW wc;
+ MSG msg;
+ WCHAR appName[MAX_STRING_LEN];
+ const WCHAR className[] = {'S','h','e','l','l','_','C','o','n','t','r','o',
+ 'l','_','W','n','d','C','l','a','s','s',0};
+
+ LoadStringW(shell32_hInstance, IDS_CPANEL_TITLE, appName, sizeof(appName) / sizeof(appName[0]));
+
+ wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = Control_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(CPlApplet*);
- wc.hInstance = hInst;
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wc.hInstance = panel->hInst = hInst;
+ wc.hIcon = LoadIconW( shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_CONTROL_PANEL) );
+ wc.hCursor = LoadCursorW( 0, (LPWSTR)IDC_ARROW );
+ wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
- wc.lpszClassName = L"Shell_Control_WndClass";
+ wc.lpszClassName = className;
+ wc.hIconSm = LoadImageW( shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_CONTROL_PANEL), IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
- if (!RegisterClassW(&wc)) return;
+ if (!RegisterClassExW(&wc)) return;
CreateWindowExW(0, wc.lpszClassName, appName,
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- hWnd, NULL, hInst, panel);
-
- if (!panel->hWnd)
- return;
-
- if (!panel->first)
- {
- /* FIXME appName & message should be localized */
- MessageBoxW(panel->hWnd, L"Cannot load any applets", appName, MB_OK);
- return;
- }
+ WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hWnd, NULL, hInst, panel);
+ if (!panel->hWnd) return;
- while (GetMessageW(&msg, panel->hWnd, 0, 0))
- {
+ while (GetMessageW(&msg, panel->hWnd, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
-static void Control_DoWindow(CPanel *panel, HWND hWnd, HINSTANCE hInst)
+static void Control_RegisterRegistryApplets(HWND hWnd, CPanel *panel, HKEY hkey_root, LPCWSTR szRepPath)
{
- HANDLE hFind;
- WIN32_FIND_DATAW wfd;
- WCHAR wszPath[MAX_PATH];
- WCHAR *Ptr = wszPath;
-
- Ptr += GetSystemDirectoryW(wszPath, MAX_PATH);
- *Ptr++ = '\\';
- wcscpy(Ptr, L"*.cpl");
+ WCHAR name[MAX_PATH];
+ WCHAR value[MAX_PATH];
+ HKEY hkey;
- hFind = FindFirstFileW(wszPath, &wfd);
- if (hFind != INVALID_HANDLE_VALUE)
+ if (RegOpenKeyW(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
{
- do
+ int idx = 0;
+
+ for(;; ++idx)
{
- wcscpy(Ptr, wfd.cFileName);
- Control_LoadApplet(hWnd, wszPath, panel);
- } while (FindNextFileW(hFind, &wfd));
- FindClose(hFind);
+ DWORD nameLen = MAX_PATH;
+ DWORD valueLen = MAX_PATH;
+
+ if (RegEnumValueW(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)value, &valueLen) != ERROR_SUCCESS)
+ break;
+
+ Control_LoadApplet(hWnd, value, panel);
+ }
+ RegCloseKey(hkey);
}
+}
+
+static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst)
+{
+ HANDLE h;
+ WIN32_FIND_DATAW fd;
+ WCHAR buffer[MAX_PATH];
+ static const WCHAR wszAllCpl[] = {'*','.','c','p','l',0};
+ static const WCHAR wszRegPath[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t',
+ '\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',
+ '\\','C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','C','p','l','s',0};
+ WCHAR *p;
+
+ /* first add .cpl files in the system directory */
+ GetSystemDirectoryW( buffer, MAX_PATH );
+ p = buffer + strlenW(buffer);
+ *p++ = '\\';
+ lstrcpyW(p, wszAllCpl);
+
+ if ((h = FindFirstFileW(buffer, &fd)) != INVALID_HANDLE_VALUE) {
+ do {
+ lstrcpyW(p, fd.cFileName);
+ Control_LoadApplet(hWnd, buffer, panel);
+ } while (FindNextFileW(h, &fd));
+ FindClose(h);
+ }
+
+ /* now check for cpls in the registry */
+ Control_RegisterRegistryApplets(hWnd, panel, HKEY_LOCAL_MACHINE, wszRegPath);
+ Control_RegisterRegistryApplets(hWnd, panel, HKEY_CURRENT_USER, wszRegPath);
Control_DoInterface(panel, hWnd, hInst);
}
-static void Control_DoLaunch(CPanel *pPanel, HWND hWnd, LPCWSTR pwszCmd)
+#else
+static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst)
{
- HANDLE hMutex;
-
- /* Make a pwszCmd copy so we can modify it */
- LPWSTR pwszCmdCopy = _wcsdup(pwszCmd);
+ ShellExecuteW(NULL,
+ L"open",
+ L"explorer.exe",
+ L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}",
+ NULL,
+ SW_SHOWDEFAULT);
+}
+#endif
- LPWSTR pwszPath = pwszCmdCopy, pwszArg = NULL, pwszArg2 = NULL;
- if (!pwszCmdCopy)
- return;
+static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd)
+ /* forms to parse:
+ * foo.cpl,@sp,str
+ * foo.cpl,@sp
+ * foo.cpl,,str
+ * foo.cpl @sp
+ * foo.cpl str
+ * "a path\foo.cpl"
+ */
+{
+ LPWSTR buffer;
+ LPWSTR beg = NULL;
+ LPWSTR end;
+ WCHAR ch;
+ LPWSTR ptr;
+ signed sp = -1;
+ LPWSTR extraPmtsBuf = NULL;
+ LPWSTR extraPmts = NULL;
+ BOOL quoted = FALSE;
+ CPlApplet *applet;
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(wszCmd) + 1) * sizeof(*wszCmd));
+ if (!buffer) return;
+
+ end = lstrcpyW(buffer, wszCmd);
+
+ for (;;) {
+ ch = *end;
+ if (ch == '"') quoted = !quoted;
+ if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) {
+ *end = '\0';
+ if (beg) {
+ if (*beg == '@') {
+ sp = atoiW(beg + 1);
+ } else if (*beg == '\0') {
+ sp = -1;
+ } else {
+ extraPmtsBuf = beg;
+ }
+ }
+ if (ch == '\0') break;
+ beg = end + 1;
+ if (ch == ' ') while (end[1] == ' ') end++;
+ }
+ end++;
+ }
+ while ((ptr = StrChrW(buffer, '"')))
+ memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR));
- /* Path can be quoted */
- if (pwszPath[0] == L'"')
+ /* now check for any quotes in extraPmtsBuf and remove */
+ if (extraPmtsBuf != NULL)
{
- ++pwszPath;
- pwszArg = wcschr(pwszPath, L'"');
- if (pwszArg)
- *(pwszArg++) = '\0';
+ beg = end = extraPmtsBuf;
+ quoted = FALSE;
+
+ for (;;) {
+ ch = *end;
+ if (ch == '"') quoted = !quoted;
+ if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) {
+ *end = '\0';
+ if (beg) {
+ if (*beg != '\0') {
+ extraPmts = beg;
+ }
+ }
+ if (ch == '\0') break;
+ beg = end + 1;
+ if (ch == ' ') while (end[1] == ' ') end++;
+ }
+ end++;
+ }
+
+ while ((ptr = StrChrW(extraPmts, '"')))
+ memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR));
+
+ if (extraPmts == NULL)
+ extraPmts = extraPmtsBuf;
}
- else
- pwszArg = pwszCmdCopy;
- /* First argument starts after space or ','. Note: we ignore characters between '"' and ',' or ' '. */
- if (pwszArg)
- pwszArg = wcspbrk(pwszArg, L" ,");
- if (pwszArg)
- {
- /* NULL terminate path and find first character of arg */
- *(pwszArg++) = L'\0';
- if (pwszArg[0] == L'"')
- {
- ++pwszArg;
- pwszArg2 = wcschr(pwszArg, L'"');
- if (pwszArg2)
- *(pwszArg2++) = L'\0';
- } else
- pwszArg2 = pwszArg;
-
- /* Second argument always starts with ','. Note: we ignore characters between '"' and ','. */
- if (pwszArg2)
- pwszArg2 = wcschr(pwszArg2, L',');
+ /* Now check if there had been a numerical value in the extra params */
+ if ((extraPmts) && (*extraPmts == '@') && (sp == -1)) {
+ sp = atoiW(extraPmts + 1);
}
- TRACE("Launch %ls, arg %ls, arg2 %ls\n", pwszPath, pwszArg, pwszArg2);
+ TRACE("cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp);
- /* Create a mutex to disallow running multiple instances */
- hMutex = CreateMutexW(NULL, TRUE, PathFindFileNameW(pwszPath));
- if (!hMutex || GetLastError() == ERROR_ALREADY_EXISTS)
+ applet = Control_LoadApplet(hWnd, buffer, panel);
+ if (applet)
{
- TRACE("Next instance disallowed\n");
- if (hMutex)
- CloseHandle(hMutex);
- return;
- }
+ /* we've been given a textual parameter (or none at all) */
+ if (sp == -1) {
+ while ((++sp) != applet->count) {
+ TRACE("sp %d, name %s\n", sp, debugstr_w(applet->info[sp].name));
- /* Load applet cpl */
- TRACE("Load applet %ls\n", pwszPath);
- Control_LoadApplet(hWnd, pwszPath, pPanel);
- if (pPanel->first)
- {
- INT i = 0;
- /* First pPanel applet is the new one */
- CPlApplet *pApplet = pPanel->first;
- assert(pApplet && pApplet->next == NULL);
- TRACE("pApplet->count %d\n", pApplet->count);
-
- /* Note: if there is only one applet, first argument is ignored */
- if (pApplet->count > 1 && pwszArg && pwszArg[0])
- {
- /* If arg begins with '@', number specifies applet index */
- if (pwszArg[0] == L'@')
- i = _wtoi(pwszArg + 1);
- else
- {
- /* Otherwise it's applet name */
- for (i = 0; i < (INT)pApplet->count; ++i)
- if (!wcscmp(pwszArg, pApplet->info[i].szName))
- break;
+ if (StrCmpIW(extraPmts, applet->info[sp].name) == 0)
+ break;
}
}
- if (i >= 0 && i < (INT)pApplet->count && pApplet->info[i].dwSize)
- {
- /* Start the applet */
- TRACE("Starting applet %d\n", i);
- if (!pApplet->proc(pApplet->hWnd, CPL_STARTWPARMSW, i, (LPARAM)pwszArg))
- pApplet->proc(pApplet->hWnd, CPL_DBLCLK, i, pApplet->info[i].lData);
- } else
- ERR("Applet not found: %ls\n", pwszArg ? pwszArg : L"NULL");
-
- Control_UnloadApplet(pApplet);
+ if (sp >= applet->count) {
+ WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count);
+ sp = 0;
+ }
+
+ if (!applet->proc(applet->hWnd, CPL_STARTWPARMSW, sp, (LPARAM)extraPmts))
+ applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].data);
+
+ Control_UnloadApplet(applet);
}
- else
- ERR("Failed to load applet %ls\n", pwszPath);
- ReleaseMutex(hMutex);
- CloseHandle(hMutex);
- free(pwszCmdCopy);
+ HeapFree(GetProcessHeap(), 0, buffer);
}
/*************************************************************************
- * Control_RunDLLW [SHELL32.@]
+ * Control_RunDLLW [SHELL32.@]
*
*/
void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
{
- CPanel Panel;
+ CPanel panel;
TRACE("(%p, %p, %s, 0x%08x)\n",
hWnd, hInst, debugstr_w(cmd), nCmdShow);
- memset(&Panel, 0, sizeof(Panel));
+#ifndef __REACTOS__
+ memset(&panel, 0, sizeof(panel));
+ list_init( &panel.applets );
+#endif
- if (!cmd || !*cmd)
- {
- TRACE("[shell32, Control_RunDLLW] Calling Control_DoWindow\n");
- Control_DoWindow(&Panel, hWnd, hInst);
- }
- else
- {
- TRACE("[shell32, Control_RunDLLW] Calling Control_DoLaunch\n");
- Control_DoLaunch(&Panel, hWnd, cmd);
+ if (!cmd || !*cmd) {
+ Control_DoWindow(&panel, hWnd, hInst);
+ } else {
+ Control_DoLaunch(&panel, hWnd, cmd);
}
}
}
+#ifdef __REACTOS__
/*************************************************************************
* RunDll_CallEntry16 [SHELL32.122]
* the name is OK (when written with Dll, and not DLL as in Wine!)
void WINAPI RunDll_CallEntry16( DWORD proc, HWND hwnd, HINSTANCE inst,
LPCSTR cmdline, INT cmdshow )
{
-#if !defined(__CYGWIN__) && !defined (__MINGW32__) && !defined(_MSC_VER)
- WORD args[5];
- SEGPTR cmdline_seg;
-
- TRACE( "proc %x hwnd %p inst %p cmdline %s cmdshow %d\n",
- proc, hwnd, inst, debugstr_a(cmdline), cmdshow );
-
- cmdline_seg = MapLS( cmdline );
- args[4] = HWND_16(hwnd);
- args[3] = MapHModuleLS(inst);
- args[2] = SELECTOROF(cmdline_seg);
- args[1] = OFFSETOF(cmdline_seg);
- args[0] = cmdshow;
- WOWCallback16Ex( proc, WCB16_PASCAL, sizeof(args), args, NULL );
- UnMapLS( cmdline_seg );
-#else
FIXME( "proc %lx hwnd %p inst %p cmdline %s cmdshow %d\n",
proc, hwnd, inst, debugstr_a(cmdline), cmdshow );
-#endif
}
+#endif
/*************************************************************************
- * CallCPLEntry16 [SHELL32.166]
+ * CallCPLEntry16 [SHELL32.166]
*
* called by desk.cpl on "Advanced" with:
* hMod("DeskCp16.Dll"), pFunc("CplApplet"), 0, 1, 0xc, 0
*
*/
-LRESULT WINAPI CallCPLEntry16(HINSTANCE hMod, FARPROC pFunc, HWND dw3, UINT dw4, LPARAM dw5, LPARAM dw6)
+DWORD WINAPI CallCPLEntry16(HMODULE hMod, FARPROC pFunc, DWORD dw3, DWORD dw4, DWORD dw5, DWORD dw6)
{
FIXME("(%p, %p, %08x, %08x, %08x, %08x): stub.\n", hMod, pFunc, dw3, dw4, dw5, dw6);
return 0x0deadbee;