2 * PROJECT: ReactOS Applications
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: base/applications/msconfig_new/toolspage.cpp
5 * PURPOSE: Tools page message handler
6 * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de>
7 * Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr>
11 #include "xmldomparser.hpp"
13 #include "listviewfuncs.h"
15 static HWND hToolsPage
= NULL
;
16 static HWND hToolsListCtrl
= NULL
;
17 static int iSortedColumn
= 0;
21 TOOL(const _bstr_t
& Command
,
22 const _bstr_t
& DefParam
,
23 const _bstr_t
& AdvParam
) :
32 DWORD
Run(BOOL bUseAdvParams
)
34 return RunCommand(m_Command
, bUseAdvParams
? m_AdvParam
: m_DefParam
, SW_SHOW
);
42 static void AddTool(IXMLDOMElement
*, BOOL
);
45 ParseToolsList(IXMLDOMDocument
* pXMLDom
, BOOL bIsStandard
)
47 static const _bstr_t
XMLFileTag(L
"MSCONFIGTOOLFILE");
48 static const _bstr_t
XMLToolsTag(L
"MSCONFIGTOOLS");
52 IXMLDOMNode
*pIterator
= NULL
, *pTmp
= NULL
;
53 IXMLDOMElement
* pEl
= NULL
;
58 return E_POINTER
; // E_INVALIDARG
60 pXMLDom
->get_documentElement(&pEl
);
62 pEl
->get_tagName(&tagName
.GetBSTR());
64 if (tagName
== XMLFileTag
)
66 pEl
->get_firstChild(&pIterator
); SAFE_RELEASE(pEl
);
69 pIterator
->get_nodeType(&type
);
70 if (type
== NODE_ELEMENT
)
72 pIterator
->QueryInterface(IID_PPV_ARG(IXMLDOMElement
, &pEl
) /* IID_PPV_ARGS(&pEl) */);
74 pEl
->get_tagName(&tagName
.GetBSTR());
76 if (tagName
== XMLToolsTag
)
78 pEl
->get_firstChild(&pIterator
); SAFE_RELEASE(pEl
);
81 pIterator
->QueryInterface(IID_PPV_ARG(IXMLDOMElement
, &pEl
) /* IID_PPV_ARGS(&pEl) */);
82 AddTool(pEl
, bIsStandard
);
85 pIterator
->get_nextSibling(&pTmp
);
86 SAFE_RELEASE(pIterator
); pIterator
= pTmp
;
88 // SAFE_RELEASE(pIterator);
96 pIterator
->get_nextSibling(&pTmp
);
97 SAFE_RELEASE(pIterator
); pIterator
= pTmp
;
99 // SAFE_RELEASE(pIterator);
101 else if (tagName
== XMLToolsTag
)
103 pEl
->get_firstChild(&pIterator
); SAFE_RELEASE(pEl
);
106 pIterator
->QueryInterface(IID_PPV_ARG(IXMLDOMElement
, &pEl
) /* IID_PPV_ARGS(&pEl) */);
107 AddTool(pEl
, bIsStandard
);
110 pIterator
->get_nextSibling(&pTmp
);
111 SAFE_RELEASE(pIterator
); pIterator
= pTmp
;
113 // SAFE_RELEASE(pIterator);
122 AddItem(BOOL bIsStandard
, const _bstr_t
& name
, const _bstr_t
& descr
, TOOL
* tool
)
129 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
130 item
.lParam
= (LPARAM
)tool
;
132 item
.pszText
= (LPWSTR
)name
;
134 // item.iItem = ListView_GetItemCount(hToolsListCtrl);
136 ListView_InsertItem(hToolsListCtrl
, &item
);
140 lpszStandard
= LoadResourceString(hInst
, IDS_YES
);
141 ListView_SetItemText(hToolsListCtrl
, item
.iItem
, 1, lpszStandard
);
142 MemFree(lpszStandard
);
146 lpszStandard
= LoadResourceString(hInst
, IDS_NO
);
147 ListView_SetItemText(hToolsListCtrl
, item
.iItem
, 1, lpszStandard
);
148 MemFree(lpszStandard
);
151 ListView_SetItemText(hToolsListCtrl
, item
.iItem
, 2, (LPWSTR
)descr
);
155 AddTool(IXMLDOMElement
* pXMLTool
, BOOL bIsStandard
)
158 _variant_t varLocID
, varName
, varPath
,
159 varDefOpt
, varAdvOpt
, varHelp
;
163 pXMLTool
->getAttribute(_bstr_t(L
"_locID") , &varLocID
);
164 pXMLTool
->getAttribute(_bstr_t(L
"NAME") , &varName
);
165 pXMLTool
->getAttribute(_bstr_t(L
"PATH") , &varPath
);
166 pXMLTool
->getAttribute(_bstr_t(L
"DEFAULT_OPT"), &varDefOpt
);
167 pXMLTool
->getAttribute(_bstr_t(L
"ADV_OPT") , &varAdvOpt
);
168 pXMLTool
->getAttribute(_bstr_t(L
"HELP") , &varHelp
);
170 // TODO: check if the tool really exists... ??
172 tool
= new TOOL(_bstr_t(varPath
), _bstr_t(varDefOpt
), _bstr_t(varAdvOpt
));
173 AddItem(bIsStandard
, _bstr_t(varName
), _bstr_t(varHelp
), tool
);
179 IXMLDOMDocument
* pXMLDom
= NULL
;
181 if (!SUCCEEDED(InitXMLDOMParser()))
184 if (SUCCEEDED(CreateAndInitXMLDOMDocument(&pXMLDom
)))
186 // Load the internal tools list.
187 if (LoadXMLDocumentFromResource(pXMLDom
, L
"MSCFGTL.XML"))
188 ParseToolsList(pXMLDom
, TRUE
);
190 // Try to load the user-provided tools list. If it doesn't exist,
191 // then the second list-view's column "Standard" tool is removed.
192 if (LoadXMLDocumentFromFile(pXMLDom
, L
"MSCFGTLC.XML", TRUE
))
193 ParseToolsList(pXMLDom
, FALSE
);
195 ListView_DeleteColumn(hToolsListCtrl
, 1);
198 SAFE_RELEASE(pXMLDom
);
199 UninitXMLDOMParser();
203 BuildCommandLine(LPWSTR lpszDest
, LPCWSTR lpszCmdLine
, LPCWSTR lpszParam
, size_t bufSize
)
205 size_t numOfChars
= 0; // The null character is counted in ExpandEnvironmentStrings(...).
206 // TODO: Take into account the "plus one" for numOfChars for ANSI version (see MSDN for more details).
208 if (lpszCmdLine
&& *lpszCmdLine
)
210 numOfChars
+= ExpandEnvironmentStringsW(lpszCmdLine
, NULL
, 0);
212 ExpandEnvironmentStringsW(lpszCmdLine
, lpszDest
, (DWORD
)bufSize
); // TODO: size_t to DWORD conversion !
214 if (lpszParam
&& *lpszParam
)
218 wcscat(lpszDest
, L
" ");
222 if (lpszParam
&& *lpszParam
)
224 numOfChars
+= wcslen(lpszParam
);
226 wcscat(lpszDest
, lpszParam
);
232 #define Button_IsEnabled(hwndCtl) IsWindowEnabled((hwndCtl))
234 static void Update_States(int iSelectedItem
)
241 item
.mask
= LVIF_PARAM
;
242 item
.iItem
= iSelectedItem
;
244 if (ListView_GetItem(hToolsListCtrl
, &item
)) // (item.iItem > -1) // TODO: corriger ailleurs ce genre de code...
246 LPTSTR lpszCmdLine
= NULL
;
247 size_t numOfChars
= 0;
248 tool
= reinterpret_cast<TOOL
*>(item
.lParam
);
250 ListView_EnsureVisible(hToolsListCtrl
, item
.iItem
, FALSE
);
252 Button_Enable(GetDlgItem(hToolsPage
, IDC_BTN_RUN
), TRUE
);
254 if (!*(wchar_t*)tool
->m_AdvParam
)
256 ShowWindow(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), SW_HIDE
);
257 Button_Enable(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), FALSE
);
261 Button_Enable(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), TRUE
);
262 ShowWindow(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), SW_NORMAL
);
265 if ( (Button_IsEnabled(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
))) &&
266 (Button_GetCheck(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
)) == BST_CHECKED
) )
268 numOfChars
= BuildCommandLine(NULL
, tool
->m_Command
, tool
->m_AdvParam
, 0);
269 lpszCmdLine
= new WCHAR
[numOfChars
];
270 BuildCommandLine(lpszCmdLine
, tool
->m_Command
, tool
->m_AdvParam
, numOfChars
);
274 numOfChars
= BuildCommandLine(NULL
, tool
->m_Command
, tool
->m_DefParam
, 0);
275 lpszCmdLine
= new WCHAR
[numOfChars
];
276 BuildCommandLine(lpszCmdLine
, tool
->m_Command
, tool
->m_DefParam
, numOfChars
);
279 SendDlgItemMessage(hToolsPage
, IDC_TOOLS_CMDLINE
, WM_SETTEXT
, 0, (LPARAM
)lpszCmdLine
);
281 delete[] lpszCmdLine
;
285 ShowWindow(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), SW_HIDE
);
286 Button_Enable(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), FALSE
);
287 Button_Enable(GetDlgItem(hToolsPage
, IDC_BTN_RUN
), FALSE
);
291 static BOOL
RunSelectedTool(VOID
)
293 BOOL bRetVal
= FALSE
;
297 item
.mask
= LVIF_PARAM
;
298 item
.iItem
= ListView_GetSelectionMark(hToolsListCtrl
);
299 ListView_GetItem(hToolsListCtrl
, &item
);
301 if (ListView_GetItem(hToolsListCtrl
, &item
)) // (item.iItem > -1) // TODO: corriger ailleurs ce genre de code...
303 if ( (Button_IsEnabled(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
))) &&
304 (Button_GetCheck(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
)) == BST_CHECKED
) )
305 bUseAdvParams
= TRUE
;
307 bUseAdvParams
= FALSE
;
309 // Values greater (strictly) than 32 indicate success (see MSDN documentation for ShellExecute(...) API).
310 bRetVal
= (reinterpret_cast<TOOL
*>(item
.lParam
)->Run(bUseAdvParams
) > 32);
319 ToolsPageWndProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
326 hToolsListCtrl
= GetDlgItem(hToolsPage
, IDC_TOOLS_LIST
);
329 // Initialize the styles.
331 DWORD dwStyle
= ListView_GetExtendedListViewStyle(hToolsListCtrl
);
332 ListView_SetExtendedListViewStyle(hToolsListCtrl
, dwStyle
| LVS_EX_FULLROWSELECT
);
333 /** SetWindowTheme(hToolsListCtrl, _T("Explorer"), NULL); // TODO: activate this only if Windows >= XP **/
336 // Initialize the application page's controls.
338 LVCOLUMN column
= {};
340 // First column : Tool's name.
341 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
342 column
.pszText
= LoadResourceString(hInst
, IDS_TOOLS_COLUMN_NAME
);
344 ListView_InsertColumn(hToolsListCtrl
, 0, &column
);
345 MemFree(column
.pszText
);
347 // Second column : Whether the tool is a standard one or not.
348 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
349 column
.pszText
= LoadResourceString(hInst
, IDS_TOOLS_COLUMN_STANDARD
);
351 ListView_InsertColumn(hToolsListCtrl
, 1, &column
);
352 MemFree(column
.pszText
);
354 // Third column : Description.
355 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
356 column
.pszText
= LoadResourceString(hInst
, IDS_TOOLS_COLUMN_DESCR
);
358 ListView_InsertColumn(hToolsListCtrl
, 2, &column
);
359 MemFree(column
.pszText
);
362 // Populate and sort the list.
365 ListView_Sort(hToolsListCtrl
, 0);
367 // Force an update in case of an empty list (giving focus on it when empty won't emit a LVN_ITEMCHANGED message).
368 Update_States(-1 /* Wrong index to initialize all the controls with their default state (i.e. disabled) */);
370 PropSheet_UnChanged(GetParent(hToolsPage
), hToolsPage
);
378 lvitem
.mask
= LVIF_PARAM
;
379 lvitem
.iItem
= -1; // From the beginning.
381 while ((lvitem
.iItem
= ListView_GetNextItem(hToolsListCtrl
, lvitem
.iItem
, LVNI_ALL
)) != -1)
383 // ListView_Update(); // Updates a list-view item.
384 // ListView_FindItem(); // peut être intéressant pour faire de la recherche itérative à partir du nom (ou partie du...) de l'item.
386 ListView_GetItem(hToolsListCtrl
, &lvitem
);
388 delete reinterpret_cast<TOOL
*>(lvitem
.lParam
);
389 lvitem
.lParam
= NULL
;
391 ListView_DeleteAllItems(hToolsListCtrl
);
398 switch (LOWORD(wParam
))
406 case IDC_CBX_TOOLS_ADVOPT
:
408 Update_States(ListView_GetSelectionMark(hToolsListCtrl
));
420 if (((LPNMHDR
)lParam
)->hwndFrom
== hToolsListCtrl
)
422 switch (((LPNMHDR
)lParam
)->code
)
424 case LVN_ITEMCHANGED
:
426 if ( (((LPNMLISTVIEW
)lParam
)->uChanged
& LVIF_STATE
) && /* The state has changed */
427 (((LPNMLISTVIEW
)lParam
)->uNewState
& LVIS_SELECTED
) /* The item has been (de)selected */ )
429 Update_States(((LPNMLISTVIEW
)lParam
)->iItem
);
442 case LVN_COLUMNCLICK
:
444 int iSortingColumn
= ((LPNMLISTVIEW
)lParam
)->iSubItem
;
446 ListView_SortEx(hToolsListCtrl
, iSortingColumn
, iSortedColumn
);
447 iSortedColumn
= iSortingColumn
;
458 switch (((LPNMHDR
)lParam
)->code
)
462 // Since there are nothing to modify, applying modifications
463 // cannot return any error.
464 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
465 PropSheet_UnChanged(GetParent(hToolsPage
), hToolsPage
);
471 MessageBoxW(hToolsPage
, L
"Help not implemented yet!", L
"Help", MB_ICONINFORMATION
| MB_OK
);
475 case PSN_KILLACTIVE
: // Is going to lose activation.
477 // Changes are always valid of course.
478 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, FALSE
);
482 case PSN_QUERYCANCEL
:
484 // Allows cancellation since there are nothing to cancel...
485 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, FALSE
);
489 case PSN_QUERYINITIALFOCUS
:
491 // Give the focus on and select the first item.
492 ListView_SetItemState(hToolsListCtrl
, 0, LVIS_FOCUSED
| LVIS_SELECTED
, LVIS_FOCUSED
| LVIS_SELECTED
);
494 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, (LONG_PTR
)hToolsListCtrl
);
499 // DO NOT TOUCH THESE NEXT MESSAGES, THEY ARE OK LIKE THIS...
501 case PSN_RESET
: // Perform final cleaning, called before WM_DESTROY.
504 case PSN_SETACTIVE
: // Is going to gain activation.
506 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, 0);