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"
14 #include "uxthemesupp.h"
16 static HWND hToolsPage
= NULL
;
17 static HWND hToolsListCtrl
= NULL
;
18 static int iSortedColumn
= 0;
22 TOOL(const _bstr_t
& Command
,
23 const _bstr_t
& DefParam
,
24 const _bstr_t
& AdvParam
) :
33 DWORD
Run(BOOL bUseAdvParams
)
35 return RunCommand(m_Command
, bUseAdvParams
? m_AdvParam
: m_DefParam
, SW_SHOW
);
43 static void AddTool(IXMLDOMElement
*, BOOL
);
46 ParseToolsList(IXMLDOMDocument
* pXMLDom
, BOOL bIsStandard
)
48 static const _bstr_t
XMLFileTag(L
"MSCONFIGTOOLFILE");
49 static const _bstr_t
XMLToolsTag(L
"MSCONFIGTOOLS");
53 IXMLDOMNode
*pIterator
= NULL
, *pTmp
= NULL
;
54 IXMLDOMElement
* pEl
= NULL
;
59 return E_POINTER
; // E_INVALIDARG
61 pXMLDom
->get_documentElement(&pEl
);
63 pEl
->get_tagName(&tagName
.GetBSTR());
65 if (tagName
== XMLFileTag
)
67 pEl
->get_firstChild(&pIterator
); SAFE_RELEASE(pEl
);
70 pIterator
->get_nodeType(&type
);
71 if (type
== NODE_ELEMENT
)
73 pIterator
->QueryInterface(IID_PPV_ARG(IXMLDOMElement
, &pEl
) /* IID_PPV_ARGS(&pEl) */);
75 pEl
->get_tagName(&tagName
.GetBSTR());
77 if (tagName
== XMLToolsTag
)
79 pEl
->get_firstChild(&pIterator
); SAFE_RELEASE(pEl
);
82 pIterator
->QueryInterface(IID_PPV_ARG(IXMLDOMElement
, &pEl
) /* IID_PPV_ARGS(&pEl) */);
83 AddTool(pEl
, bIsStandard
);
86 pIterator
->get_nextSibling(&pTmp
);
87 SAFE_RELEASE(pIterator
); pIterator
= pTmp
;
89 // SAFE_RELEASE(pIterator);
97 pIterator
->get_nextSibling(&pTmp
);
98 SAFE_RELEASE(pIterator
); pIterator
= pTmp
;
100 // SAFE_RELEASE(pIterator);
102 else if (tagName
== XMLToolsTag
)
104 pEl
->get_firstChild(&pIterator
); SAFE_RELEASE(pEl
);
107 pIterator
->QueryInterface(IID_PPV_ARG(IXMLDOMElement
, &pEl
) /* IID_PPV_ARGS(&pEl) */);
108 AddTool(pEl
, bIsStandard
);
111 pIterator
->get_nextSibling(&pTmp
);
112 SAFE_RELEASE(pIterator
); pIterator
= pTmp
;
114 // SAFE_RELEASE(pIterator);
123 AddItem(BOOL bIsStandard
, const _bstr_t
& name
, const _bstr_t
& descr
, TOOL
* tool
)
130 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
131 item
.lParam
= (LPARAM
)tool
;
133 item
.pszText
= (LPWSTR
)name
;
135 // item.iItem = ListView_GetItemCount(hToolsListCtrl);
137 ListView_InsertItem(hToolsListCtrl
, &item
);
141 lpszStandard
= LoadResourceString(hInst
, IDS_YES
);
142 ListView_SetItemText(hToolsListCtrl
, item
.iItem
, 1, lpszStandard
);
143 MemFree(lpszStandard
);
147 lpszStandard
= LoadResourceString(hInst
, IDS_NO
);
148 ListView_SetItemText(hToolsListCtrl
, item
.iItem
, 1, lpszStandard
);
149 MemFree(lpszStandard
);
152 ListView_SetItemText(hToolsListCtrl
, item
.iItem
, 2, (LPWSTR
)descr
);
156 AddTool(IXMLDOMElement
* pXMLTool
, BOOL bIsStandard
)
159 _variant_t varLocID
, varName
, varPath
,
160 varDefOpt
, varAdvOpt
, varHelp
;
164 pXMLTool
->getAttribute(_bstr_t(L
"_locID") , &varLocID
);
165 pXMLTool
->getAttribute(_bstr_t(L
"NAME") , &varName
);
166 pXMLTool
->getAttribute(_bstr_t(L
"PATH") , &varPath
);
167 pXMLTool
->getAttribute(_bstr_t(L
"DEFAULT_OPT"), &varDefOpt
);
168 pXMLTool
->getAttribute(_bstr_t(L
"ADV_OPT") , &varAdvOpt
);
169 pXMLTool
->getAttribute(_bstr_t(L
"HELP") , &varHelp
);
171 // TODO: check if the tool really exists... ??
173 tool
= new TOOL(_bstr_t(varPath
), _bstr_t(varDefOpt
), _bstr_t(varAdvOpt
));
174 AddItem(bIsStandard
, _bstr_t(varName
), _bstr_t(varHelp
), tool
);
180 IXMLDOMDocument
* pXMLDom
= NULL
;
182 if (!SUCCEEDED(InitXMLDOMParser()))
185 if (SUCCEEDED(CreateAndInitXMLDOMDocument(&pXMLDom
)))
187 // Load the internal tools list.
188 if (LoadXMLDocumentFromResource(pXMLDom
, L
"MSCFGTL.XML"))
189 ParseToolsList(pXMLDom
, TRUE
);
191 // Try to load the user-provided tools list. If it doesn't exist,
192 // then the second list-view's column "Standard" tool is removed.
193 if (LoadXMLDocumentFromFile(pXMLDom
, L
"MSCFGTLC.XML", TRUE
))
194 ParseToolsList(pXMLDom
, FALSE
);
196 ListView_DeleteColumn(hToolsListCtrl
, 1);
199 SAFE_RELEASE(pXMLDom
);
200 UninitXMLDOMParser();
204 BuildCommandLine(LPWSTR lpszDest
, LPCWSTR lpszCmdLine
, LPCWSTR lpszParam
, size_t bufSize
)
206 size_t numOfChars
= 0; // The null character is counted in ExpandEnvironmentStrings(...).
207 // TODO: Take into account the "plus one" for numOfChars for ANSI version (see MSDN for more details).
209 if (lpszCmdLine
&& *lpszCmdLine
)
211 numOfChars
+= ExpandEnvironmentStringsW(lpszCmdLine
, NULL
, 0);
213 ExpandEnvironmentStringsW(lpszCmdLine
, lpszDest
, (DWORD
)bufSize
); // TODO: size_t to DWORD conversion !
215 if (lpszParam
&& *lpszParam
)
219 wcscat(lpszDest
, L
" ");
223 if (lpszParam
&& *lpszParam
)
225 numOfChars
+= wcslen(lpszParam
);
227 wcscat(lpszDest
, lpszParam
);
233 static void Update_States(int iSelectedItem
)
240 item
.mask
= LVIF_PARAM
;
241 item
.iItem
= iSelectedItem
;
243 if (ListView_GetItem(hToolsListCtrl
, &item
)) // (item.iItem > -1) // TODO: corriger ailleurs ce genre de code...
245 LPWSTR lpszCmdLine
= NULL
;
246 size_t numOfChars
= 0;
247 tool
= reinterpret_cast<TOOL
*>(item
.lParam
);
249 ListView_EnsureVisible(hToolsListCtrl
, item
.iItem
, FALSE
);
251 Button_Enable(GetDlgItem(hToolsPage
, IDC_BTN_RUN
), TRUE
);
253 if (!*(wchar_t*)tool
->m_AdvParam
)
255 ShowWindow(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), SW_HIDE
);
256 Button_Enable(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), FALSE
);
260 Button_Enable(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), TRUE
);
261 ShowWindow(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), SW_NORMAL
);
264 if ( (Button_IsEnabled(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
))) &&
265 (Button_GetCheck(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
)) == BST_CHECKED
) )
267 numOfChars
= BuildCommandLine(NULL
, tool
->m_Command
, tool
->m_AdvParam
, 0);
268 lpszCmdLine
= (LPWSTR
)MemAlloc(0, numOfChars
* sizeof(WCHAR
));
269 BuildCommandLine(lpszCmdLine
, tool
->m_Command
, tool
->m_AdvParam
, numOfChars
);
273 numOfChars
= BuildCommandLine(NULL
, tool
->m_Command
, tool
->m_DefParam
, 0);
274 lpszCmdLine
= (LPWSTR
)MemAlloc(0, numOfChars
* sizeof(WCHAR
));
275 BuildCommandLine(lpszCmdLine
, tool
->m_Command
, tool
->m_DefParam
, numOfChars
);
278 SendDlgItemMessage(hToolsPage
, IDC_TOOLS_CMDLINE
, WM_SETTEXT
, 0, (LPARAM
)lpszCmdLine
);
280 MemFree(lpszCmdLine
);
284 ShowWindow(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), SW_HIDE
);
285 Button_Enable(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
), FALSE
);
286 Button_Enable(GetDlgItem(hToolsPage
, IDC_BTN_RUN
), FALSE
);
290 static BOOL
RunSelectedTool(VOID
)
292 BOOL Success
= FALSE
;
296 item
.mask
= LVIF_PARAM
;
297 item
.iItem
= ListView_GetSelectionMark(hToolsListCtrl
);
298 ListView_GetItem(hToolsListCtrl
, &item
);
300 if (ListView_GetItem(hToolsListCtrl
, &item
)) // (item.iItem > -1) // TODO: corriger ailleurs ce genre de code...
302 if ( (Button_IsEnabled(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
))) &&
303 (Button_GetCheck(GetDlgItem(hToolsPage
, IDC_CBX_TOOLS_ADVOPT
)) == BST_CHECKED
) )
304 bUseAdvParams
= TRUE
;
306 bUseAdvParams
= FALSE
;
308 // Values greater (strictly) than 32 indicate success (see MSDN documentation for ShellExecute(...) API).
309 Success
= (reinterpret_cast<TOOL
*>(item
.lParam
)->Run(bUseAdvParams
) > 32);
318 ToolsPageWndProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
)
325 hToolsListCtrl
= GetDlgItem(hToolsPage
, IDC_TOOLS_LIST
);
328 // Initialize the styles.
330 DWORD dwStyle
= ListView_GetExtendedListViewStyle(hToolsListCtrl
);
331 ListView_SetExtendedListViewStyle(hToolsListCtrl
, dwStyle
| LVS_EX_FULLROWSELECT
);
332 SetWindowTheme(hToolsListCtrl
, L
"Explorer", NULL
);
335 // Initialize the application page's controls.
337 LVCOLUMN column
= {};
339 // First column : Tool's name.
340 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
341 column
.pszText
= LoadResourceString(hInst
, IDS_TOOLS_COLUMN_NAME
);
343 ListView_InsertColumn(hToolsListCtrl
, 0, &column
);
344 MemFree(column
.pszText
);
346 // Second column : Whether the tool is a standard one or not.
347 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
348 column
.pszText
= LoadResourceString(hInst
, IDS_TOOLS_COLUMN_STANDARD
);
350 ListView_InsertColumn(hToolsListCtrl
, 1, &column
);
351 MemFree(column
.pszText
);
353 // Third column : Description.
354 column
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
355 column
.pszText
= LoadResourceString(hInst
, IDS_TOOLS_COLUMN_DESCR
);
357 ListView_InsertColumn(hToolsListCtrl
, 2, &column
);
358 MemFree(column
.pszText
);
361 // Populate and sort the list.
364 ListView_Sort(hToolsListCtrl
, 0);
366 // Force an update in case of an empty list (giving focus on it when empty won't emit a LVN_ITEMCHANGED message).
367 Update_States(-1 /* Wrong index to initialize all the controls with their default state (i.e. disabled) */);
369 PropSheet_UnChanged(GetParent(hToolsPage
), hToolsPage
);
377 lvitem
.mask
= LVIF_PARAM
;
378 lvitem
.iItem
= -1; // From the beginning.
380 while ((lvitem
.iItem
= ListView_GetNextItem(hToolsListCtrl
, lvitem
.iItem
, LVNI_ALL
)) != -1)
382 // ListView_Update(); // Updates a list-view item.
383 // ListView_FindItem(); // peut être intéressant pour faire de la recherche itérative à partir du nom (ou partie du...) de l'item.
385 ListView_GetItem(hToolsListCtrl
, &lvitem
);
387 delete reinterpret_cast<TOOL
*>(lvitem
.lParam
);
388 lvitem
.lParam
= NULL
;
390 ListView_DeleteAllItems(hToolsListCtrl
);
397 switch (LOWORD(wParam
))
405 case IDC_CBX_TOOLS_ADVOPT
:
407 Update_States(ListView_GetSelectionMark(hToolsListCtrl
));
419 if (((LPNMHDR
)lParam
)->hwndFrom
== hToolsListCtrl
)
421 switch (((LPNMHDR
)lParam
)->code
)
423 case LVN_ITEMCHANGED
:
425 if ( (((LPNMLISTVIEW
)lParam
)->uChanged
& LVIF_STATE
) && /* The state has changed */
426 (((LPNMLISTVIEW
)lParam
)->uNewState
& LVIS_SELECTED
) /* The item has been (de)selected */ )
428 Update_States(((LPNMLISTVIEW
)lParam
)->iItem
);
441 case LVN_COLUMNCLICK
:
443 int iSortingColumn
= ((LPNMLISTVIEW
)lParam
)->iSubItem
;
445 ListView_SortEx(hToolsListCtrl
, iSortingColumn
, iSortedColumn
);
446 iSortedColumn
= iSortingColumn
;
457 switch (((LPNMHDR
)lParam
)->code
)
461 // Since there are nothing to modify, applying modifications
462 // cannot return any error.
463 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
464 PropSheet_UnChanged(GetParent(hToolsPage
), hToolsPage
);
470 MessageBoxW(hToolsPage
, L
"Help not implemented yet!", L
"Help", MB_ICONINFORMATION
| MB_OK
);
474 case PSN_KILLACTIVE
: // Is going to lose activation.
476 // Changes are always valid of course.
477 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, FALSE
);
481 case PSN_QUERYCANCEL
:
483 // Allows cancellation since there are nothing to cancel...
484 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, FALSE
);
488 case PSN_QUERYINITIALFOCUS
:
490 // Give the focus on and select the first item.
491 ListView_SetItemState(hToolsListCtrl
, 0, LVIS_FOCUSED
| LVIS_SELECTED
, LVIS_FOCUSED
| LVIS_SELECTED
);
493 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, (LONG_PTR
)hToolsListCtrl
);
498 // DO NOT TOUCH THESE NEXT MESSAGES, THEY ARE OK LIKE THIS...
500 case PSN_RESET
: // Perform final cleaning, called before WM_DESTROY.
503 case PSN_SETACTIVE
: // Is going to gain activation.
505 SetWindowLongPtr(hToolsPage
, DWLP_MSGRESULT
, 0);