/* * 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 * Copyright 2011-2012 Hermes BELUSCA - MAITO */ #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(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(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 être intéressant pour faire de la recherche itérative à partir du nom (ou partie du...) de l'item. ListView_GetItem(hToolsListCtrl, &lvitem); delete reinterpret_cast(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 */