bool SettingsXML::IsXmlAllowed() { IXMLDOMDocument* pFile = CreateDomDocument(); if (pFile) pFile->Release(); return (pFile != NULL); }
bool SettingsXML::OpenStorage(uint access, wchar_t (&szErr)[512]) { bool bRc = false; bool bNeedReopen = (mp_File == NULL); LPCWSTR pszXmlFile; HRESULT hr = S_OK; VARIANT_BOOL bSuccess; IXMLDOMParseError* pErr = NULL; VARIANT vt; VariantInit(&vt); bool bAllowCreate = (access & KEY_WRITE) == KEY_WRITE; szErr[0] = 0; if (m_Storage.pszFile && *m_Storage.pszFile) { pszXmlFile = m_Storage.pszFile; } else { // Must be already initialized _ASSERTE(m_Storage.pszFile && *m_Storage.pszFile); pszXmlFile = gpConEmu->ConEmuXml(); if (!pszXmlFile || !*pszXmlFile) { goto wrap; } } m_Storage.pszFile = pszXmlFile; // Changed access type? if (bNeedReopen || (mn_access != access)) { DWORD dwAccess = GENERIC_READ; DWORD dwMode = OPEN_EXISTING; if ((access & KEY_WRITE) == KEY_WRITE) { dwAccess |= GENERIC_WRITE; dwMode = OPEN_ALWAYS; } HANDLE hFile = CreateFile(pszXmlFile, dwAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, dwMode, 0, 0); // XML-файл отсутсвует if (!hFile || (hFile == INVALID_HANDLE_VALUE)) { goto wrap; } else { BY_HANDLE_FILE_INFORMATION bfi = {0}; if (GetFileInformationByHandle(hFile, &bfi)) { mb_Empty = (bfi.nFileSizeHigh == 0 && bfi.nFileSizeLow == 0); if (!mb_Empty) { // UTF-8 BOM? Xml DOM does not allows BOM if (bfi.nFileSizeHigh == 0 && bfi.nFileSizeLow == 3) { BYTE bom[3] = {}; DWORD nRead = 0; if (ReadFile(hFile, bom, sizeof(bom), &nRead, NULL) && (nRead == sizeof(bom)) && (bom[0]==0xEF && bom[1]==0xBB && bom[2]==0xBF)) { mb_Empty = true; } } } } CloseHandle(hFile); hFile = NULL; if (mb_Empty && bAllowCreate) { bNeedReopen = true; hFile = CreateFile(pszXmlFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, 0); if (!hFile || (hFile == INVALID_HANDLE_VALUE)) { goto wrap; } else { LPCSTR pszDefault = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" "<key name=\"Software\">\r\n" "\t<key name=\"ConEmu\">\r\n" "\t</key>\r\n" "</key>\r\n"; DWORD nLen = lstrlenA(pszDefault); WriteFile(hFile, pszDefault, nLen, &nLen, NULL); CloseHandle(hFile); } hFile = NULL; } } } if (!bNeedReopen) { bRc = true; goto wrap; } if (mb_Empty && !bAllowCreate) goto wrap; CloseStorage(); SAFETRY { _ASSERTE(mp_File == NULL); mp_File = CreateDomDocument(szErr, countof(szErr)); if (FAILED(hr) || !mp_File) { //Ошибка уже в szErr //_wsprintf(szErr, SKIPLEN(countof(szErr)) L"Can't create IID_IXMLDOMDocument!\nErrCode=0x%08X", (DWORD)hr); goto wrap; } hr = mp_File->put_preserveWhiteSpace(VARIANT_TRUE); hr = mp_File->put_async(VARIANT_FALSE); // Загрузить xml-ку bSuccess = VARIANT_FALSE; vt.vt = VT_BSTR; vt.bstrVal = ::SysAllocString(pszXmlFile); hr = mp_File->load(vt, &bSuccess); VariantClear(&vt); if (hr == S_FALSE) { mb_Empty = true; // Файл пуст (может только заголовок?) } else if (FAILED(hr) || !bSuccess) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"Failed to load ConEmu.xml!\nHR=0x%08X\n", (DWORD)hr); hr = mp_File->get_parseError(&pErr); if (pErr) { long errorCode = 0; // Contains the error code of the last parse error. Read-only. long line = 0; // Specifies the line number that contains the error. Read-only. long linepos = 0; // Contains the character position within the line where the error occurred. Read-only. hr = pErr->get_errorCode(&errorCode); hr = pErr->get_line(&line); hr = pErr->get_linepos(&linepos); wsprintf(szErr+_tcslen(szErr), L"XmlErrCode=%i, Line=%i, Pos=%i", errorCode, line, linepos); } goto wrap; } mn_access = access; bRc = true; } SAFECATCH { lstrcpy(szErr, L"Exception in SettingsXML::OpenStorage"); bRc = false; } wrap: SafeRelease(pErr); if (!bRc) CloseStorage(); return bRc; }
bool SettingsXML::OpenKey(const wchar_t *regPath, uint access, BOOL abSilent /*= FALSE*/) { _ASSERTE(!gpConEmu->IsResetBasicSettings() || ((access & KEY_WRITE)!=KEY_WRITE)); bool lbRc = false; HRESULT hr = S_OK; wchar_t szErr[512]; szErr[0] = 0; wchar_t szName[MAX_PATH]; const wchar_t* psz = NULL; VARIANT_BOOL bSuccess; IXMLDOMParseError* pErr = NULL; //IXMLDOMNodeList* pList = NULL; IXMLDOMNode* pKey = NULL; IXMLDOMNode* pChild = NULL; VARIANT vt; VariantInit(&vt); bool bAllowCreate = (access & KEY_WRITE) == KEY_WRITE; CloseKey(); // на всякий if (!regPath || !*regPath) { return false; } HANDLE hFile = NULL; DWORD dwAccess = GENERIC_READ; if ((access & KEY_WRITE) == KEY_WRITE) dwAccess |= GENERIC_WRITE; LPCWSTR pszXmlFile; if (m_Storage.pszFile && *m_Storage.pszFile) { pszXmlFile = m_Storage.pszFile; } else { _ASSERTE(m_Storage.pszFile && *m_Storage.pszFile); m_Storage.pszFile = pszXmlFile = gpConEmu->ConEmuXml(); } if (!pszXmlFile || !*pszXmlFile) { return false; } hFile = CreateFile(pszXmlFile, dwAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); // XML-файл отсутсвует if (hFile == INVALID_HANDLE_VALUE) { return false; } else { BY_HANDLE_FILE_INFORMATION bfi = {0}; if (GetFileInformationByHandle(hFile, &bfi)) mb_Empty = (bfi.nFileSizeHigh == 0 && bfi.nFileSizeLow == 0); CloseHandle(hFile); hFile = NULL; if (mb_Empty && bAllowCreate) { hFile = CreateFile(pszXmlFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { LPCSTR pszDefault = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<key name=\"Software\">\r\n\t<key name=\"ConEmu\">\r\n\t</key>\r\n</key>\r\n"; DWORD nLen = lstrlenA(pszDefault); WriteFile(hFile, pszDefault, nLen, &nLen, NULL); CloseHandle(hFile); } hFile = NULL; } } if (mb_Empty && !bAllowCreate) return false; SAFETRY { _ASSERTE(mp_File == NULL); mp_File = CreateDomDocument(szErr, countof(szErr)); if (FAILED(hr) || !mp_File) { //Ошибка уже в szErr //_wsprintf(szErr, SKIPLEN(countof(szErr)) L"Can't create IID_IXMLDOMDocument!\nErrCode=0x%08X", (DWORD)hr); goto wrap; } hr = mp_File->put_preserveWhiteSpace(VARIANT_TRUE); hr = mp_File->put_async(VARIANT_FALSE); // Загрузить xml-ку bSuccess = VARIANT_FALSE; vt.vt = VT_BSTR; vt.bstrVal = ::SysAllocString(pszXmlFile); hr = mp_File->load(vt, &bSuccess); VariantClear(&vt); if (hr == S_FALSE) { mb_Empty = true; // Файл пуст (может только заголовок?) } else if (FAILED(hr) || !bSuccess) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"Failed to load ConEmu.xml!\nHR=0x%08X\n", (DWORD)hr); hr = mp_File->get_parseError(&pErr); if (pErr) { long errorCode = 0; // Contains the error code of the last parse error. Read-only. long line = 0; // Specifies the line number that contains the error. Read-only. long linepos = 0; // Contains the character position within the line where the error occurred. Read-only. hr = pErr->get_errorCode(&errorCode); hr = pErr->get_line(&line); hr = pErr->get_linepos(&linepos); wsprintf(szErr+_tcslen(szErr), L"XmlErrCode=%i, Line=%i, Pos=%i", errorCode, line, linepos); } goto wrap; } hr = mp_File->QueryInterface(IID_IXMLDOMNode, (void **)&pKey); if (FAILED(hr)) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: Root node not found!\nErrCode=0x%08X", (DWORD)hr); goto wrap; } mi_Level = 0; while(*regPath) { // Получить следующий токен psz = wcschr(regPath, L'\\'); if (!psz) psz = regPath + _tcslen(regPath); lstrcpyn(szName, regPath, psz-regPath+1); // Найти в структуре XML pChild = FindItem(pKey, L"key", szName, bAllowCreate); pKey->Release(); pKey = pChild; pChild = NULL; mi_Level++; if (!pKey) { if (bAllowCreate) { _wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: Can't create key <%s>!", szName); } else { //_wsprintf(szErr, SKIPLEN(countof(szErr)) L"XML: key <%s> not found!", szName); szErr[0] = 0; // ошибку не показывать - настройки по умолчанию } goto wrap; } if (*psz == L'\\') { regPath = psz + 1; } else { break; } } // Нашли, запомнили mp_Key = pKey; pKey = NULL; if (mp_Key) { SYSTEMTIME st; wchar_t szTime[32]; GetLocalTime(&st); _wsprintf(szTime, SKIPLEN(countof(szTime)) L"%04i-%02i-%02i %02i:%02i:%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); SetAttr(mp_Key, L"modified", szTime); SetAttr(mp_Key, L"build", gpConEmu->ms_ConEmuBuild); } lbRc = true; } SAFECATCH { lstrcpy(szErr, L"Exception in SettingsXML::OpenKey"); lbRc = false; } wrap: if (pErr) { pErr->Release(); pErr = NULL; } if (pChild) { pChild->Release(); pChild = NULL; } if (pKey) { pKey->Release(); pKey = NULL; } if (!lbRc && szErr[0] && !abSilent) { MBoxA(szErr); } return lbRc; }