mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 13:18:51 +00:00
527 lines
16 KiB
C++
527 lines
16 KiB
C++
/*
|
||
* PROJECT: ReactOS Applications
|
||
* LICENSE: LGPL - See COPYING in the top level directory
|
||
* FILE: base/applications/msconfig_new/toolspage.cpp
|
||
* PURPOSE: Tools page message handler
|
||
* COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de>
|
||
* Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr>
|
||
*/
|
||
|
||
#include "precomp.h"
|
||
#include "xmldomparser.hpp"
|
||
#include "utils.h"
|
||
#include "listview.h"
|
||
#include "uxthemesupp.h"
|
||
|
||
static HWND hToolsPage = NULL;
|
||
static HWND hToolsListCtrl = NULL;
|
||
static int iToolsPageSortedColumn = 0;
|
||
|
||
struct TOOL
|
||
{
|
||
TOOL(const _bstr_t& Command,
|
||
const _bstr_t& DefParam,
|
||
const _bstr_t& AdvParam) :
|
||
m_Command(Command),
|
||
m_DefParam(DefParam),
|
||
m_AdvParam(AdvParam)
|
||
{ }
|
||
|
||
~TOOL(void)
|
||
{ }
|
||
|
||
DWORD Run(BOOL bUseAdvParams)
|
||
{
|
||
return RunCommand(m_Command, bUseAdvParams ? m_AdvParam : m_DefParam, SW_SHOW);
|
||
}
|
||
|
||
_bstr_t m_Command;
|
||
_bstr_t m_DefParam;
|
||
_bstr_t m_AdvParam;
|
||
};
|
||
|
||
static void AddTool(IXMLDOMElement*, BOOL);
|
||
|
||
static HRESULT
|
||
ParseToolsList(IXMLDOMDocument* pXMLDom, BOOL bIsStandard)
|
||
{
|
||
static const _bstr_t XMLFileTag(L"MSCONFIGTOOLFILE");
|
||
static const _bstr_t XMLToolsTag(L"MSCONFIGTOOLS");
|
||
|
||
HRESULT hr = S_OK;
|
||
|
||
IXMLDOMNode *pIterator = NULL, *pTmp = NULL;
|
||
IXMLDOMElement* pEl = NULL;
|
||
DOMNodeType type;
|
||
_bstr_t tagName;
|
||
|
||
if (!pXMLDom)
|
||
return E_POINTER; // E_INVALIDARG
|
||
|
||
pXMLDom->get_documentElement(&pEl);
|
||
|
||
pEl->get_tagName(&tagName.GetBSTR());
|
||
_wcsupr(tagName);
|
||
if (tagName == XMLFileTag)
|
||
{
|
||
pEl->get_firstChild(&pIterator); SAFE_RELEASE(pEl);
|
||
while (pIterator)
|
||
{
|
||
pIterator->get_nodeType(&type);
|
||
if (type == NODE_ELEMENT)
|
||
{
|
||
pIterator->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pEl) /* IID_PPV_ARGS(&pEl) */);
|
||
|
||
pEl->get_tagName(&tagName.GetBSTR());
|
||
_wcsupr(tagName);
|
||
if (tagName == XMLToolsTag)
|
||
{
|
||
pEl->get_firstChild(&pIterator); SAFE_RELEASE(pEl);
|
||
while (pIterator)
|
||
{
|
||
pIterator->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pEl) /* IID_PPV_ARGS(&pEl) */);
|
||
AddTool(pEl, bIsStandard);
|
||
SAFE_RELEASE(pEl);
|
||
|
||
pIterator->get_nextSibling(&pTmp);
|
||
SAFE_RELEASE(pIterator); pIterator = pTmp;
|
||
}
|
||
// SAFE_RELEASE(pIterator);
|
||
|
||
break;
|
||
}
|
||
|
||
SAFE_RELEASE(pEl);
|
||
}
|
||
|
||
pIterator->get_nextSibling(&pTmp);
|
||
SAFE_RELEASE(pIterator); pIterator = pTmp;
|
||
}
|
||
// SAFE_RELEASE(pIterator);
|
||
}
|
||
else if (tagName == XMLToolsTag)
|
||
{
|
||
pEl->get_firstChild(&pIterator); SAFE_RELEASE(pEl);
|
||
while (pIterator)
|
||
{
|
||
pIterator->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pEl) /* IID_PPV_ARGS(&pEl) */);
|
||
AddTool(pEl, bIsStandard);
|
||
SAFE_RELEASE(pEl);
|
||
|
||
pIterator->get_nextSibling(&pTmp);
|
||
SAFE_RELEASE(pIterator); pIterator = pTmp;
|
||
}
|
||
// SAFE_RELEASE(pIterator);
|
||
}
|
||
|
||
SAFE_RELEASE(pEl);
|
||
|
||
return hr;
|
||
}
|
||
|
||
static void
|
||
AddItem(BOOL bIsStandard, const _bstr_t& name, const _bstr_t& descr, TOOL* tool)
|
||
{
|
||
LPWSTR lpszStandard;
|
||
LVITEM item = {};
|
||
|
||
assert(tool);
|
||
|
||
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||
item.lParam = (LPARAM)tool;
|
||
|
||
item.pszText = (LPWSTR)name;
|
||
item.iSubItem = 0;
|
||
// item.iItem = ListView_GetItemCount(hToolsListCtrl);
|
||
|
||
ListView_InsertItem(hToolsListCtrl, &item);
|
||
|
||
if (bIsStandard)
|
||
{
|
||
lpszStandard = LoadResourceString(hInst, IDS_YES);
|
||
ListView_SetItemText(hToolsListCtrl, item.iItem, 1, lpszStandard);
|
||
MemFree(lpszStandard);
|
||
}
|
||
else
|
||
{
|
||
lpszStandard = LoadResourceString(hInst, IDS_NO);
|
||
ListView_SetItemText(hToolsListCtrl, item.iItem, 1, lpszStandard);
|
||
MemFree(lpszStandard);
|
||
}
|
||
|
||
ListView_SetItemText(hToolsListCtrl, item.iItem, 2, (LPWSTR)descr);
|
||
}
|
||
|
||
static void
|
||
AddTool(IXMLDOMElement* pXMLTool, BOOL bIsStandard)
|
||
{
|
||
TOOL* tool;
|
||
_variant_t varLocID, varName, varPath,
|
||
varDefOpt, varAdvOpt, varHelp;
|
||
|
||
assert(pXMLTool);
|
||
|
||
pXMLTool->getAttribute(_bstr_t(L"_locID") , &varLocID );
|
||
pXMLTool->getAttribute(_bstr_t(L"NAME") , &varName );
|
||
pXMLTool->getAttribute(_bstr_t(L"PATH") , &varPath );
|
||
pXMLTool->getAttribute(_bstr_t(L"DEFAULT_OPT"), &varDefOpt);
|
||
pXMLTool->getAttribute(_bstr_t(L"ADV_OPT") , &varAdvOpt);
|
||
pXMLTool->getAttribute(_bstr_t(L"HELP") , &varHelp );
|
||
|
||
// TODO: check if the tool really exists... ??
|
||
|
||
tool = new TOOL(_bstr_t(varPath), _bstr_t(varDefOpt), _bstr_t(varAdvOpt));
|
||
AddItem(bIsStandard, _bstr_t(varName), _bstr_t(varHelp), tool);
|
||
}
|
||
|
||
static void
|
||
FillListView(void)
|
||
{
|
||
IXMLDOMDocument* pXMLDom = NULL;
|
||
|
||
if (!SUCCEEDED(InitXMLDOMParser()))
|
||
return;
|
||
|
||
if (SUCCEEDED(CreateAndInitXMLDOMDocument(&pXMLDom)))
|
||
{
|
||
// Load the internal tools list.
|
||
if (LoadXMLDocumentFromResource(pXMLDom, L"MSCFGTL.XML"))
|
||
ParseToolsList(pXMLDom, TRUE);
|
||
|
||
// Try to load the user-provided tools list. If it doesn't exist,
|
||
// then the second list-view's column "Standard" tool is removed.
|
||
if (LoadXMLDocumentFromFile(pXMLDom, L"MSCFGTLC.XML", TRUE))
|
||
ParseToolsList(pXMLDom, FALSE);
|
||
else
|
||
ListView_DeleteColumn(hToolsListCtrl, 1);
|
||
}
|
||
|
||
SAFE_RELEASE(pXMLDom);
|
||
UninitXMLDOMParser();
|
||
}
|
||
|
||
static size_t
|
||
BuildCommandLine(LPWSTR lpszDest, LPCWSTR lpszCmdLine, LPCWSTR lpszParam, size_t bufSize)
|
||
{
|
||
size_t numOfChars = 0; // The null character is counted in ExpandEnvironmentStrings(...).
|
||
// TODO: Take into account the "plus one" for numOfChars for ANSI version (see MSDN for more details).
|
||
|
||
if (lpszCmdLine && *lpszCmdLine)
|
||
{
|
||
numOfChars += ExpandEnvironmentStringsW(lpszCmdLine, NULL, 0);
|
||
if (lpszDest)
|
||
ExpandEnvironmentStringsW(lpszCmdLine, lpszDest, (DWORD)bufSize); // TODO: size_t to DWORD conversion !
|
||
|
||
if (lpszParam && *lpszParam)
|
||
{
|
||
++numOfChars;
|
||
if (lpszDest)
|
||
wcscat(lpszDest, L" ");
|
||
}
|
||
}
|
||
|
||
if (lpszParam && *lpszParam)
|
||
{
|
||
numOfChars += wcslen(lpszParam);
|
||
if (lpszDest)
|
||
wcscat(lpszDest, lpszParam);
|
||
}
|
||
|
||
return numOfChars;
|
||
}
|
||
|
||
static void Update_States(int iSelectedItem)
|
||
{
|
||
TOOL* tool;
|
||
LVITEM item = {};
|
||
|
||
assert(hToolsPage);
|
||
|
||
item.mask = LVIF_PARAM;
|
||
item.iItem = iSelectedItem;
|
||
|
||
if (ListView_GetItem(hToolsListCtrl, &item)) // (item.iItem > -1) // TODO: corriger ailleurs ce genre de code...
|
||
{
|
||
LPWSTR lpszCmdLine = NULL;
|
||
size_t numOfChars = 0;
|
||
tool = reinterpret_cast<TOOL*>(item.lParam);
|
||
|
||
ListView_EnsureVisible(hToolsListCtrl, item.iItem, FALSE);
|
||
|
||
Button_Enable(GetDlgItem(hToolsPage, IDC_BTN_RUN), TRUE);
|
||
|
||
if (!*(wchar_t*)tool->m_AdvParam)
|
||
{
|
||
ShowWindow(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT), SW_HIDE);
|
||
Button_Enable(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT), FALSE);
|
||
}
|
||
else
|
||
{
|
||
Button_Enable(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT), TRUE);
|
||
ShowWindow(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT), SW_NORMAL);
|
||
}
|
||
|
||
if ( (Button_IsEnabled(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT))) &&
|
||
(Button_GetCheck(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT)) == BST_CHECKED) )
|
||
{
|
||
numOfChars = BuildCommandLine(NULL, tool->m_Command, tool->m_AdvParam, 0);
|
||
lpszCmdLine = (LPWSTR)MemAlloc(0, numOfChars * sizeof(WCHAR));
|
||
BuildCommandLine(lpszCmdLine, tool->m_Command, tool->m_AdvParam, numOfChars);
|
||
}
|
||
else
|
||
{
|
||
numOfChars = BuildCommandLine(NULL, tool->m_Command, tool->m_DefParam, 0);
|
||
lpszCmdLine = (LPWSTR)MemAlloc(0, numOfChars * sizeof(WCHAR));
|
||
BuildCommandLine(lpszCmdLine, tool->m_Command, tool->m_DefParam, numOfChars);
|
||
}
|
||
|
||
SendDlgItemMessage(hToolsPage, IDC_TOOLS_CMDLINE, WM_SETTEXT, 0, (LPARAM)lpszCmdLine);
|
||
|
||
MemFree(lpszCmdLine);
|
||
}
|
||
else
|
||
{
|
||
ShowWindow(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT), SW_HIDE);
|
||
Button_Enable(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT), FALSE);
|
||
Button_Enable(GetDlgItem(hToolsPage, IDC_BTN_RUN), FALSE);
|
||
}
|
||
}
|
||
|
||
static BOOL RunSelectedTool(VOID)
|
||
{
|
||
BOOL Success = FALSE;
|
||
BOOL bUseAdvParams;
|
||
|
||
LVITEM item = {};
|
||
item.mask = LVIF_PARAM;
|
||
item.iItem = ListView_GetSelectionMark(hToolsListCtrl);
|
||
ListView_GetItem(hToolsListCtrl, &item);
|
||
|
||
if (ListView_GetItem(hToolsListCtrl, &item)) // (item.iItem > -1) // TODO: corriger ailleurs ce genre de code...
|
||
{
|
||
if ( (Button_IsEnabled(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT))) &&
|
||
(Button_GetCheck(GetDlgItem(hToolsPage, IDC_CBX_TOOLS_ADVOPT)) == BST_CHECKED) )
|
||
bUseAdvParams = TRUE;
|
||
else
|
||
bUseAdvParams = FALSE;
|
||
|
||
// Values greater (strictly) than 32 indicate success (see MSDN documentation for ShellExecute(...) API).
|
||
Success = (reinterpret_cast<TOOL*>(item.lParam)->Run(bUseAdvParams) > 32);
|
||
}
|
||
|
||
return Success;
|
||
}
|
||
|
||
extern "C" {
|
||
|
||
INT_PTR CALLBACK
|
||
ToolsPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch (message)
|
||
{
|
||
case WM_INITDIALOG:
|
||
{
|
||
hToolsPage = hDlg;
|
||
hToolsListCtrl = GetDlgItem(hToolsPage, IDC_TOOLS_LIST);
|
||
|
||
//
|
||
// Initialize the styles.
|
||
//
|
||
DWORD dwStyle = ListView_GetExtendedListViewStyle(hToolsListCtrl);
|
||
ListView_SetExtendedListViewStyle(hToolsListCtrl, dwStyle | LVS_EX_FULLROWSELECT);
|
||
SetWindowTheme(hToolsListCtrl, L"Explorer", NULL);
|
||
|
||
//
|
||
// Initialize the application page's controls.
|
||
//
|
||
LVCOLUMN column = {};
|
||
|
||
// First column : Tool's name.
|
||
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
||
column.pszText = LoadResourceString(hInst, IDS_TOOLS_COLUMN_NAME);
|
||
column.cx = 150;
|
||
ListView_InsertColumn(hToolsListCtrl, 0, &column);
|
||
MemFree(column.pszText);
|
||
|
||
// Second column : Whether the tool is a standard one or not.
|
||
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
||
column.pszText = LoadResourceString(hInst, IDS_TOOLS_COLUMN_STANDARD);
|
||
column.cx = 60;
|
||
ListView_InsertColumn(hToolsListCtrl, 1, &column);
|
||
MemFree(column.pszText);
|
||
|
||
// Third column : Description.
|
||
column.mask = LVCF_TEXT | LVCF_WIDTH;
|
||
column.pszText = LoadResourceString(hInst, IDS_TOOLS_COLUMN_DESCR);
|
||
column.cx = 500;
|
||
ListView_InsertColumn(hToolsListCtrl, 2, &column);
|
||
MemFree(column.pszText);
|
||
|
||
//
|
||
// Populate and sort the list.
|
||
//
|
||
FillListView();
|
||
ListView_Sort(hToolsListCtrl, 0);
|
||
|
||
// Force an update in case of an empty list (giving focus on it when empty won't emit a LVN_ITEMCHANGED message).
|
||
Update_States(-1 /* Wrong index to initialize all the controls with their default state (i.e. disabled) */);
|
||
|
||
PropSheet_UnChanged(GetParent(hToolsPage), hToolsPage);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
case WM_DESTROY:
|
||
{
|
||
LVITEM lvitem = {};
|
||
lvitem.mask = LVIF_PARAM;
|
||
lvitem.iItem = -1; // From the beginning.
|
||
|
||
while ((lvitem.iItem = ListView_GetNextItem(hToolsListCtrl, lvitem.iItem, LVNI_ALL)) != -1)
|
||
{
|
||
// ListView_Update(); // Updates a list-view item.
|
||
// ListView_FindItem(); // peut <20>tre int<6E>ressant pour faire de la recherche it<69>rative <20> partir du nom (ou partie du...) de l'item.
|
||
|
||
ListView_GetItem(hToolsListCtrl, &lvitem);
|
||
|
||
delete reinterpret_cast<TOOL*>(lvitem.lParam);
|
||
lvitem.lParam = NULL;
|
||
}
|
||
ListView_DeleteAllItems(hToolsListCtrl);
|
||
|
||
return 0;
|
||
}
|
||
|
||
case WM_COMMAND:
|
||
{
|
||
switch (LOWORD(wParam))
|
||
{
|
||
case IDC_BTN_RUN:
|
||
{
|
||
RunSelectedTool();
|
||
return TRUE;
|
||
}
|
||
|
||
case IDC_CBX_TOOLS_ADVOPT:
|
||
{
|
||
Update_States(ListView_GetSelectionMark(hToolsListCtrl));
|
||
return TRUE;
|
||
}
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
case WM_NOTIFY:
|
||
{
|
||
if (((LPNMHDR)lParam)->hwndFrom == hToolsListCtrl)
|
||
{
|
||
switch (((LPNMHDR)lParam)->code)
|
||
{
|
||
case LVN_ITEMCHANGED:
|
||
{
|
||
if ( (((LPNMLISTVIEW)lParam)->uChanged & LVIF_STATE) && /* The state has changed */
|
||
(((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED) /* The item has been (de)selected */ )
|
||
{
|
||
Update_States(((LPNMLISTVIEW)lParam)->iItem);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
case NM_DBLCLK:
|
||
case NM_RDBLCLK:
|
||
{
|
||
RunSelectedTool();
|
||
return TRUE;
|
||
}
|
||
|
||
case LVN_COLUMNCLICK:
|
||
{
|
||
int iSortingColumn = ((LPNMLISTVIEW)lParam)->iSubItem;
|
||
|
||
ListView_SortEx(hToolsListCtrl, iSortingColumn, iToolsPageSortedColumn);
|
||
iToolsPageSortedColumn = iSortingColumn;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
switch (((LPNMHDR)lParam)->code)
|
||
{
|
||
case PSN_APPLY:
|
||
{
|
||
// Since there are nothing to modify, applying modifications
|
||
// cannot return any error.
|
||
SetWindowLongPtr(hToolsPage, DWLP_MSGRESULT, PSNRET_NOERROR);
|
||
PropSheet_UnChanged(GetParent(hToolsPage), hToolsPage);
|
||
return TRUE;
|
||
}
|
||
|
||
case PSN_HELP:
|
||
{
|
||
MessageBoxW(hToolsPage, L"Help not implemented yet!", L"Help", MB_ICONINFORMATION | MB_OK);
|
||
return TRUE;
|
||
}
|
||
|
||
case PSN_KILLACTIVE: // Is going to lose activation.
|
||
{
|
||
// Changes are always valid of course.
|
||
SetWindowLongPtr(hToolsPage, DWLP_MSGRESULT, FALSE);
|
||
return TRUE;
|
||
}
|
||
|
||
case PSN_QUERYCANCEL:
|
||
{
|
||
// Allows cancellation since there are nothing to cancel...
|
||
SetWindowLongPtr(hToolsPage, DWLP_MSGRESULT, FALSE);
|
||
return TRUE;
|
||
}
|
||
|
||
case PSN_QUERYINITIALFOCUS:
|
||
{
|
||
// Give the focus on and select the first item.
|
||
ListView_SetItemState(hToolsListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
|
||
|
||
SetWindowLongPtr(hToolsPage, DWLP_MSGRESULT, (LONG_PTR)hToolsListCtrl);
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// DO NOT TOUCH THESE NEXT MESSAGES, THEY ARE OK LIKE THIS...
|
||
//
|
||
case PSN_RESET: // Perform final cleaning, called before WM_DESTROY.
|
||
return TRUE;
|
||
|
||
case PSN_SETACTIVE: // Is going to gain activation.
|
||
{
|
||
SetWindowLongPtr(hToolsPage, DWLP_MSGRESULT, 0);
|
||
return TRUE;
|
||
}
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
|
||
// return FALSE;
|
||
}
|
||
|
||
}
|
||
|
||
/* EOF */
|