bool PWSfile::Decrypt(const stringT &fn, const StringX &passwd, stringT &errmess) { ulong64 file_len; size_t len; unsigned char* buf = nullptr; bool status = true; unsigned char salt[SaltLength]; unsigned char ipthing[8]; unsigned char randstuff[StuffSize]; unsigned char randhash[SHA1::HASHLEN]; unsigned char temphash[SHA1::HASHLEN]; FILE *in = pws_os::FOpen(fn, _T("rb")); if (in == nullptr) { status = false; goto exit; } file_len = pws_os::fileLength(in); if (file_len < (8 + sizeof(randhash) + 8 + SaltLength)) { fclose(in); LoadAString(errmess, IDSC_FILE_TOO_SHORT); return false; } fread(randstuff, 1, 8, in); randstuff[8] = randstuff[9] = TCHAR('\0'); // ugly bug workaround fread(randhash, 1, sizeof(randhash), in); GenRandhash(passwd, randstuff, temphash); if (memcmp(reinterpret_cast<char *>(randhash), reinterpret_cast<char *>(temphash), SHA1::HASHLEN) != 0) { fclose(in); LoadAString(errmess, IDSC_BADPASSWORD); return false; } { // decryption in a block, since we use goto fread(salt, 1, SaltLength, in); fread(ipthing, 1, 8, in); unsigned char dummyType; unsigned char *pwd = nullptr; size_t passlen = 0; ConvertPasskey(passwd, pwd, passlen); Fish *fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<unsigned int &>(passlen), salt, SaltLength); trashMemory(pwd, passlen); delete[] pwd; // gross - ConvertPasskey allocates. if (_readcbc(in, buf, len,dummyType, fish, ipthing, 0, file_len) == 0) { delete fish; delete[] buf; // if not yet allocated, delete[] nullptr, which is OK return false; } delete fish; fclose(in); } // decrypt { // write decrypted data size_t suffix_len = CIPHERTEXT_SUFFIX.length(); size_t filepath_len = fn.length(); stringT out_fn = fn; out_fn = out_fn.substr(0,filepath_len - suffix_len); FILE *out = pws_os::FOpen(out_fn, _T("wb")); if (out != nullptr) { size_t fret = fwrite(buf, 1, len, out); if (fret != len) { int save_errno = errno; fclose(out); errno = save_errno; goto exit; } if (fclose(out) != 0) { status = false; goto exit; } } else { // open failed status = false; goto exit; } } // write decrypted exit: if (!status) errmess = ErrorMessages(); delete[] buf; // allocated by _readcbc return status; }
void pws_os::HexDump(unsigned char *pmemory, const int &length, const stringT &cs_prefix, const int &maxnum) { TCHAR szBuffer[256]; unsigned char *pmem; stringT cs_outbuff, cs_hexbuff, cs_charbuff; int i, j, len(length); unsigned char c; pmem = pmemory; while (len > 0) { // Show offset for this line. cs_charbuff.clear(); cs_hexbuff.clear(); Format(cs_outbuff, _T("%s: %08x *"), cs_prefix.c_str(), pmem); // Format hex portion of line and save chars for ascii portion if (len > maxnum) j = maxnum; else j = len; for (i = 0; i < j; i++) { c = *pmem++; if ((i % 4) == 0 && i != 0) cs_outbuff += _T(' '); Format(cs_hexbuff, _T("%02x"), c); cs_outbuff += cs_hexbuff; if (c >= 32 && c < 127) cs_charbuff += (TCHAR)c; else cs_charbuff += _T('.'); } j = maxnum - j; // Fill out hex portion of short lines. for (i = j; i > 0; i--) { if ((i % 4) != 0) cs_outbuff += _T(" "); else cs_outbuff += _T(" "); } // Add ASCII character portion to line. cs_outbuff += _T("* |"); cs_outbuff += cs_charbuff; // Fill out end of short lines. for (i = j; i > 0; i--) cs_outbuff += _T(' '); cs_outbuff += _T('|'); // Next line len -= maxnum; _stprintf_s(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), _T("%s\n"), cs_outbuff.c_str()); Trace0(szBuffer); }; }
//------------------------------------------------------------------------- bool ResetPermissionDialog::ExecuteCommand(stringT &Cmd) { std::string Utf8Cmd; #ifdef _UNICODE std::string utf8_str; bool bEncodingRequired; if (!ConvertUtf16ToUtf8(Cmd.c_str(), &bEncodingRequired, &utf8_str)) { MessageBox( hDlg, _TEXT("Failed to convert input command to UTF-8"), TEXT("Error"), MB_OK | MB_ICONERROR); return false; } if (bEncodingRequired) { // 65001 = utf-8 # ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx Utf8Cmd = "CHCP 65001\r\n\r\n" + utf8_str; } else { Utf8Cmd = utf8_str; } #else Utf8Cmd = Cmd; #endif // Overwrite/create the previous temp Batch file LPCTSTR CmdFileName = GenerateWorkBatchFileName(); // Write the temp Batch file (as binary) FILE *fp; if (_tfopen_s(&fp, CmdFileName, _TEXT("wb")) != 0) { stringT err_msg = TEXT("Failed to write batch file to: "); err_msg += CmdFileName; MessageBox( hDlg, err_msg.c_str(), TEXT("Error"), MB_OK | MB_ICONERROR); return false; } fwrite(&Utf8Cmd[0], 1, Utf8Cmd.size(), fp); fclose(fp); // Execute the temp batch file return SUCCEEDED( ShellExecute( hDlg, _TEXT("open"), CmdFileName, NULL, NULL, SW_SHOW)); }
int PWScore::MergeDependents(PWScore *pothercore, MultiCommands *pmulticmds, uuid_array_t &base_uuid, uuid_array_t &new_base_uuid, const bool bTitleRenamed, stringT &str_timestring, const CItemData::EntryType et, std::vector<StringX> &vs_added) { UUIDVector dependentslist; UUIDVectorIter paiter; ItemListIter iter; ItemListConstIter foundPos; CItemData ci_temp; int numadded(0); StringX sx_merged; LoadAString(sx_merged, IDSC_MERGED); // Get all the dependents pothercore->GetAllDependentEntries(base_uuid, dependentslist, et); for (paiter = dependentslist.begin(); paiter != dependentslist.end(); paiter++) { iter = pothercore->Find(*paiter); if (iter == pothercore->GetEntryEndIter()) continue; CItemData *pci = &iter->second; ci_temp = (*pci); if (Find(*paiter) != GetEntryEndIter()) { ci_temp.CreateUUID(); } // If the base title was renamed - we should automatically rename any dependent. // If we didn't, we still need to check uniqueness! StringX sx_newTitle = ci_temp.GetTitle(); if (bTitleRenamed) { StringX sx_otherTitle(sx_newTitle); Format(sx_newTitle, L"%ls%ls%ls", sx_otherTitle.c_str(), sx_merged.c_str(), str_timestring.c_str()); ci_temp.SetTitle(sx_newTitle); } // Check this is unique - if not - don't add this one! - its only an alias/shortcut! // We can't keep trying for uniqueness after adding a timestamp! foundPos = Find(ci_temp.GetGroup(), sx_newTitle, ci_temp.GetUser()); if (foundPos != GetEntryEndIter()) continue; Command *pcmd1 = AddEntryCommand::Create(this, ci_temp, new_base_uuid); pcmd1->SetNoGUINotify(); pmulticmds->Add(pcmd1); if (et == CItemData::ET_ALIAS) { ci_temp.SetPassword(_T("[Alias]")); ci_temp.SetAlias(); } else if (et == CItemData::ET_SHORTCUT) { ci_temp.SetPassword(_T("[Shortcut]")); ci_temp.SetShortcut(); } else ASSERT(0); StringX sx_added; Format(sx_added, GROUPTITLEUSERINCHEVRONS, ci_temp.GetGroup().c_str(), ci_temp.GetTitle().c_str(), ci_temp.GetUser().c_str()); vs_added.push_back(sx_added); numadded++; } return numadded; }
bool XFilterXMLProcessor::Process(const bool &bvalidation, const StringX &strXMLData, const stringT &strXMLFileName, const stringT &strXSDFileName) { USES_XMLCH_STR bool bErrorOccurred = false; stringT cs_validation; LoadAString(cs_validation, IDSC_XMLVALIDATION); stringT cs_import; LoadAString(cs_import, IDSC_XMLIMPORT); stringT strResultText(_T("")); m_bValidation = bvalidation; // Validate or Import XSecMemMgr sec_mm; // Initialize the XML4C2 system try { XMLPlatformUtils::Initialize(XMLUni::fgXercescDefaultLocale, 0, 0, &sec_mm); } catch (const XMLException& toCatch) { #ifdef UNICODE m_strXMLErrors = stringT(_X2ST(toCatch.getMessage())); #else char *szData = XMLString::transcode(toCatch.getMessage()); strResultText = stringT(szData); XMLString::release(&szData); #endif return false; } // Create a SAX2 parser object. SAX2XMLReader* pSAX2Parser = XMLReaderFactory::createXMLReader(&sec_mm); // Set non-default features pSAX2Parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true); pSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, true); pSAX2Parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); pSAX2Parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false); pSAX2Parser->setFeature(XMLUni::fgXercesSkipDTDValidation, true); // Set properties pSAX2Parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, (void *)strXSDFileName.c_str()); pSAX2Parser->setProperty(XMLUni::fgXercesScannerName, (void *)XMLUni::fgSGXMLScanner); pSAX2Parser->setInputBufferSize(4096); // Create SAX handler object and install it on the pSAX2Parser, as the // document and error pSAX2Handler. XFilterSAX2Handlers * pSAX2Handler = new XFilterSAX2Handlers; pSAX2Parser->setContentHandler(pSAX2Handler); pSAX2Parser->setErrorHandler(pSAX2Handler); // Workaround/bypass until Xerces supports retrieving version from the // <xs:schema ...> statement! // Set 'dummy' schema version to arbitrary value > 1 pSAX2Handler->SetSchemaVersion(99); pSAX2Handler->SetVariables(m_pAsker, &m_MapFilters, m_FPool, m_bValidation); try { // Let's begin the parsing now if (!strXMLFileName.empty()) { pSAX2Parser->parse(_W2X(strXMLFileName.c_str())); } else { const char *szID = "database_filters"; #ifdef UNICODE const char *buffer = XMLString::transcode(_W2X(strXMLData.c_str())); #else const char *buffer = strXMLData.c_str(); #endif MemBufInputSource* memBufIS = new MemBufInputSource( (const XMLByte*)buffer, strXMLData.length(), szID, false); pSAX2Parser->parse(*memBufIS); delete memBufIS; #ifdef UNICODE XMLString::release((char **)&buffer); #endif } } catch (const OutOfMemoryException&) { LoadAString(strResultText, IDCS_XERCESOUTOFMEMORY); bErrorOccurred = true; } catch (const XMLException& e) { #ifdef UNICODE strResultText = stringT(_X2ST(e.getMessage())); #else char *szData = XMLString::transcode(e.getMessage()); strResultText = stringT(szData); XMLString::release(&szData); #endif bErrorOccurred = true; } catch (...) { LoadAString(strResultText, IDCS_XERCESEXCEPTION); bErrorOccurred = true; } if (pSAX2Handler->getIfErrors() || bErrorOccurred) { bErrorOccurred = true; strResultText = pSAX2Handler->getValidationResult(); Format(m_strXMLErrors, IDSC_XERCESPARSEERROR, m_bValidation ? cs_validation.c_str() : cs_import.c_str(), strResultText.c_str()); } else { m_strXMLErrors = strResultText; } // Delete the pSAX2Parser itself. Must be done prior to calling Terminate, below. delete pSAX2Parser; delete pSAX2Handler; USES_XMLCH_STR_END // And call the termination method XMLPlatformUtils::Terminate(); return !bErrorOccurred; }
//------------------------------------------------------------------------- void ResetPermissionDialog::QuotePath(stringT &Path) { if (Path.find(_T(' ')) != stringT::npos) Path = _TEXT("\"") + Path + _TEXT("\""); }
bool MFilterXMLProcessor::Process(const bool &bvalidation, const StringX &strXMLData, const stringT &strXMLFileName, const stringT &strXSDFileName) { HRESULT hr, hr0, hr60; bool b_ok(false); stringT cs_validation; LoadAString(cs_validation, IDSC_XMLVALIDATION); stringT cs_import; LoadAString(cs_import, IDSC_XMLIMPORT); m_strXMLErrors = _T(""); m_bValidation = bvalidation; // Validate or Import // Create SAXReader object ISAXXMLReader *pSAX2Reader = nullptr; // Get ready for XSD schema validation IXMLDOMSchemaCollection2 *pSchemaCache = nullptr; if (m_bValidation) { //XMLValidate hr60 = CoCreateInstance(__uuidof(SAXXMLReader60), nullptr, CLSCTX_ALL, __uuidof(ISAXXMLReader), (void **)&pSAX2Reader); if (FAILED(hr60)) { LoadAString(m_strXMLErrors, IDSC_NOMSXMLREADER); goto exit; } } else { // XMLImport hr0 = CoCreateInstance(__uuidof(SAXXMLReader60), nullptr, CLSCTX_ALL, __uuidof(ISAXXMLReader), (void **)&pSAX2Reader); } // Create ContentHandlerImpl object MFilterSAX2ContentHandler *pCH = new MFilterSAX2ContentHandler; // Create ErrorHandlerImpl object MFilterSAX2ErrorHandler *pEH = new MFilterSAX2ErrorHandler; pCH->SetVariables(m_pAsker, &m_MapXMLFilters, m_FPool, m_bValidation); // Set Content Handler hr = pSAX2Reader->putContentHandler(pCH); // Set Error Handler hr = pSAX2Reader->putErrorHandler(pEH); hr = CoCreateInstance(__uuidof(XMLSchemaCache60), nullptr, CLSCTX_ALL, __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache); if (!FAILED(hr)) { // Create SchemaCache // Initialize the SchemaCache object with the XSD filename CComVariant cvXSDFileName = strXSDFileName.c_str(); hr = pSchemaCache->add(L"", cvXSDFileName); if (hr != S_OK) { LoadAString(m_strXMLErrors, IDSC_INVALID_SCHEMA); goto exit; } hr = pSchemaCache->validate(); if (hr != S_OK) { LoadAString(m_strXMLErrors, IDSC_INVALID_SCHEMA); goto exit; } // Check that we can get the Schema version BSTR bst_schema, bst_schema_version; bst_schema = L""; ISchema *pischema; hr = pSchemaCache->getSchema(bst_schema, &pischema); if (hr != S_OK) { LoadAString(m_strXMLErrors, IDSC_MISSING_SCHEMA_VER); goto exit; } hr = pischema->get_version(&bst_schema_version); if (hr != S_OK) { LoadAString(m_strXMLErrors, IDSC_INVALID_SCHEMA_VER); goto exit; } pCH->SetSchemaVersion(&bst_schema_version); // Set the SAXReader/Schema Cache features and properties { /* Documentation is unclear as to what is in which release. Try them all - if they don't get set, the world will not end! Common Error codes: S_OK Operation successful 0x00000000 E_NOTIMPL Not implemented 0x80004001 E_NOINTERFACE No such interface supported 0x80004002 E_ABORT Operation aborted 0x80004004 E_FAIL Unspecified failure 0x80004005 E_INVALIDARG Invalid argument 0x80070057 Normally not supported on a back level MSXMLn.DLL */ // Want all validation errors hr = pSAX2Reader->putFeature(L"exhaustive-errors", VARIANT_TRUE); // Don't allow user to override validation by using DTDs hr = pSAX2Reader->putFeature(L"prohibit-dtd", VARIANT_TRUE); // Don't allow user to override validation by using DTDs (2 features) hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-general-entities", VARIANT_FALSE); hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-parameter-entities", VARIANT_FALSE); // Want to validate XML file hr = pSAX2Reader->putFeature(L"schema-validation", VARIANT_TRUE); // Ignore any schema specified in the XML file hr = pSAX2Reader->putFeature(L"use-schema-location", VARIANT_FALSE); // Ignore any schema in the XML file hr = pSAX2Reader->putFeature(L"use-inline-schema", VARIANT_FALSE); // Only use the XSD in PWSafe's installation directory! hr = pSAX2Reader->putProperty(L"schemas", _variant_t(pSchemaCache)); } // Let's begin the parsing now if (!strXMLFileName.empty()) { wchar_t wcURL[MAX_PATH]={0}; _tcscpy_s(wcURL, MAX_PATH, strXMLFileName.c_str()); hr = pSAX2Reader->parseURL(wcURL); } else { CComVariant cvXMLData = strXMLData.c_str(); hr = pSAX2Reader->parse(cvXMLData); } if (!FAILED(hr)) { // Check for parsing errors if (pEH->bErrorsFound == TRUE) { m_strXMLErrors = pEH->m_strValidationResult; } else { b_ok = true; } } else { if (pEH->bErrorsFound == TRUE) { m_strXMLErrors = pEH->m_strValidationResult; } else { Format(m_strXMLErrors, IDSC_MSXMLPARSEERROR, hr, m_bValidation ? cs_validation.c_str() : cs_import.c_str()); } } // End Check for parsing errors } else { Format(m_strXMLErrors, IDSC_MSXMLBADCREATESCHEMA, hr, m_bValidation ? cs_validation.c_str() : cs_import.c_str()); } // End Create Schema Cache exit: if (pSchemaCache != nullptr) pSchemaCache->Release(); if (pSAX2Reader != nullptr) pSAX2Reader->Release(); return b_ok; }
int _tmain(int argc, TCHAR *argv[]) { int ierr = 0; // Check parameters if (argc < 2) { _tprintf(_T("Usage: ProcessUserStreams <Full path to MiniDumpFile>\n")); return 0; } const TCHAR *pFileName = argv[1]; _tprintf(_T("Minidump: %s \n"), pFileName); TCHAR sz_Drive[_MAX_DRIVE], sz_Dir[_MAX_DIR], sz_FName[_MAX_FNAME]; TCHAR sz_output[_MAX_PATH], sz_config[_MAX_PATH], sz_Import[_MAX_PATH], sz_Log[_MAX_PATH]; _tsplitpath_s(pFileName, sz_Drive, _MAX_DRIVE, sz_Dir, _MAX_DIR, sz_FName, _MAX_FNAME, NULL, 0); // Create output files _tmakepath_s(sz_output, _MAX_PATH, sz_Drive, sz_Dir, sz_FName, _T("txt")); _tmakepath_s(sz_config, _MAX_PATH, sz_Drive, sz_Dir, _T("pwsafe"), _T("cfg")); _tmakepath_s(sz_Import, _MAX_PATH, sz_Drive, sz_Dir, _T("Import"), _T("xml")); _tmakepath_s(sz_Log, _MAX_PATH, sz_Drive, sz_Dir, _T("Log"), _T("txt")); // Open them errno_t err; err = _tfopen_s(&pOutputFile, sz_output, _T("wt")); if (err != 0) { _tprintf(_T("Cannot open output file: %s \n"), sz_output); return 90; } err = _tfopen_s(&pConfigFile, sz_config, _T("wt")); if (err != 0) { _tprintf(_T("Cannot open Config file for output: %s \n"), sz_output); return 91; } err = _tfopen_s(&pImportFile, sz_Import, _T("wt")); if (err != 0) { _tprintf(_T("Cannot open Import file for output: %s \n"), sz_output); return 92; } err = _tfopen_s(&pLogFile, sz_Log, _T("wt")); if (err != 0) { _tprintf(_T("Cannot open Logfile for output: %s \n"), sz_output); return 93; } const TCHAR *IMPORT_HEADER = _T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?xml-stylesheet type=\"text/xsl\" href=\"pwsafe.xsl\"?>\n\n"); const TCHAR *PASSWORDSAFE = _T("passwordsafe"); const TCHAR *PREFERENCES = _T("Preferences"); const TCHAR *CONFIG_HEADER = _T("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"); const TCHAR *CONFIG_SETTINGS = _T("Pwsafe_Settings"); const TCHAR *LASTUPDATED = _T("LastUpdated"); stringT username = getusername(); stringT hostname = gethostname(); time_t time_now; time(&time_now); const stringT now = ConvertToDateTimeString(time_now); _ftprintf_s(pImportFile, _T("%s"), IMPORT_HEADER); _ftprintf_s(pImportFile, _T("<%s delimiter=\"z\">\n"), PASSWORDSAFE); _ftprintf_s(pImportFile, _T(" <%s>\n"), PREFERENCES); _ftprintf_s(pConfigFile, _T("%s"), CONFIG_HEADER); _ftprintf_s(pConfigFile, _T("<%s>\n"), CONFIG_SETTINGS); _ftprintf_s(pConfigFile, _T(" <%s>\n"), hostname.c_str()); _ftprintf_s(pConfigFile, _T(" <%s>\n"), username.c_str()); _ftprintf_s(pConfigFile, _T(" <%s>%s</%s>\n"), LASTUPDATED, now.c_str(), LASTUPDATED); _ftprintf_s(pConfigFile, _T(" <%s>\n"), PREFERENCES); // Read the user data streams and display their contents HANDLE hFile = NULL; HANDLE hMapFile = NULL; PVOID pViewOfFile = NULL; // Map the minidump into memory hFile = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) { _tprintf(_T("Error: CreateFile failed. Error: %u \n"), GetLastError()); ierr = 99; goto exit; } hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMapFile == NULL) { _tprintf(_T("Error: CreateFileMapping failed. Error: %u \n"), GetLastError()); ierr = 98; goto exit; } pViewOfFile = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); if (pViewOfFile == NULL) { _tprintf(_T("Error: MapViewOfFile failed. Error: %u \n"), GetLastError()); ierr = 97; goto exit; } else { // Show the contents of user data streams GetUserStreams(pViewOfFile); } _ftprintf_s(pImportFile, _T(" </%s>\n"), PREFERENCES); _ftprintf_s(pImportFile, _T("</%s>\n"), PASSWORDSAFE); _ftprintf_s(pConfigFile, _T(" </%s>\n"), PREFERENCES); _ftprintf_s(pConfigFile, _T(" </%s>\n"), username.c_str()); _ftprintf_s(pConfigFile, _T(" </%s>\n"), hostname.c_str()); _ftprintf_s(pConfigFile, _T("</%s>\n"), CONFIG_SETTINGS); exit: // Cleanup if (hMapFile != NULL) CloseHandle(hMapFile); if (hFile != NULL) CloseHandle(hFile); if (pOutputFile) fclose(pOutputFile); if (pConfigFile) fclose(pConfigFile); if (pImportFile) fclose(pImportFile); if (pLogFile) fclose(pLogFile); // Complete return ierr; }
bool XFilterXMLProcessor::Process(const bool &bvalidation, const StringX &strXMLData, const stringT &strXMLFileName, const stringT &strXSDFileName) { USES_XMLCH_STR bool bErrorOccurred = false; stringT cs_validation; LoadAString(cs_validation, IDSC_XMLVALIDATION); stringT cs_import; LoadAString(cs_import, IDSC_XMLIMPORT); stringT strResultText(_T("")); m_bValidation = bvalidation; // Validate or Import XSecMemMgr sec_mm; // Initialize the XML4C2 system try { XMLPlatformUtils::Initialize(XMLUni::fgXercescDefaultLocale, 0, 0, &sec_mm); } catch (const XMLException& toCatch) { m_strXMLErrors = stringT(_X2ST(toCatch.getMessage())); return false; } // Create a SAX2 parser object. SAX2XMLReader* pSAX2Parser = XMLReaderFactory::createXMLReader(&sec_mm); // Set non-default features pSAX2Parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true); pSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, true); pSAX2Parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); pSAX2Parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false); pSAX2Parser->setFeature(XMLUni::fgXercesSkipDTDValidation, true); // Set properties // we need const_cast here, because _W2X return const wchar_t* when // WCHAR_INCOMPATIBLE_XMLCH isn't set pSAX2Parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, const_cast<XMLCh*>(_W2X(strXSDFileName.c_str()))); pSAX2Parser->setProperty(XMLUni::fgXercesScannerName, const_cast<XMLCh*>(XMLUni::fgSGXMLScanner)); pSAX2Parser->setInputBufferSize(4096); // Create SAX handler object and install it on the pSAX2Parser, as the // document and error pSAX2Handler. XFilterSAX2Handlers * pSAX2Handler = new XFilterSAX2Handlers; pSAX2Parser->setContentHandler(pSAX2Handler); pSAX2Parser->setErrorHandler(pSAX2Handler); // Workaround/bypass until Xerces supports retrieving version from the // <xs:schema ...> statement! // Set 'dummy' schema version to arbitrary value > 1 pSAX2Handler->SetSchemaVersion(99); pSAX2Handler->SetVariables(m_pAsker, &m_MapXMLFilters, m_FPool, m_bValidation); // instantiate converter out of if/else to be sure that string will be valid // till the end of pSAX2Parser, that may capture pointer to string from MemBufInputSource CUTF8Conv conv; try { // Let's begin the parsing now if (!strXMLFileName.empty()) { pSAX2Parser->parse(_W2X(strXMLFileName.c_str())); } else { const char *szID = "database_filters"; // Xerces use encoding from XML (we have set it to utf-8), but transcode() on Windows convert to one-byte cpXXXX, // so we need to manually convert from wchar to UTF-8 const unsigned char* buffer=nullptr; size_t len; if (!conv.ToUTF8(strXMLData, buffer, len)) { throw std::runtime_error("Can't convert data to UTF-8"); } //2nd parameter must be number of bytes, so we use a length for char* representation MemBufInputSource* memBufIS = new MemBufInputSource( reinterpret_cast<const XMLByte *>(buffer), strlen(reinterpret_cast<const char*>(buffer)), szID, false); pSAX2Parser->parse(*memBufIS); delete memBufIS; } } catch (const OutOfMemoryException&) { LoadAString(strResultText, IDCS_XERCESOUTOFMEMORY); bErrorOccurred = true; } catch (const XMLException& e) { strResultText = stringT(_X2ST(e.getMessage())); bErrorOccurred = true; } catch (...) { LoadAString(strResultText, IDCS_XERCESEXCEPTION); bErrorOccurred = true; } if (pSAX2Handler->getIfErrors() || bErrorOccurred) { bErrorOccurred = true; if (pSAX2Handler->getIfErrors()) strResultText = pSAX2Handler->getValidationResult(); Format(m_strXMLErrors, IDSC_XERCESPARSEERROR, m_bValidation ? cs_validation.c_str() : cs_import.c_str(), strResultText.c_str()); } else { m_strXMLErrors = strResultText; } // Delete the pSAX2Parser itself. Must be done prior to calling Terminate, below. delete pSAX2Parser; delete pSAX2Handler; USES_XMLCH_STR_END // And call the termination method XMLPlatformUtils::Terminate(); return !bErrorOccurred; }
//----------------------------------------------------------------- // Internal functions //----------------------------------------------------------------- static UINT ParseRunCommand(const StringX &sxInputString, std::vector<st_RunCommandTokens> &v_rctokens, bool &bDoAutoType, StringX &sxAutoType, stringT &serrmsg, StringX::size_type &st_column) { // tokenize into separate elements std::vector<st_RunCommandTokens>::iterator rc_iter; std::vector<size_t> v_pos; StringX::iterator str_Iter; st_RunCommandTokens st_rctoken; size_t st_num_quotes(0); UINT uierr(0); int var_index(0); const stringT alphanum = _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); if (sxInputString.empty()) { // String is empty! uierr = IDSC_EXS_INPUTEMPTY; goto exit; } for (StringX::size_type l = 0; l < sxInputString.length(); l++) { if (sxInputString[l] == _T('"')) st_num_quotes++; } if (st_num_quotes % 2 != 0) { st_column = sxInputString.find(_T('"')); // Unmatched quotes uierr = IDSC_EXS_UNMATCHEDQUOTES; goto exit; } // tokenize into separate elements using $ as the field separator for (StringX::size_type st_startpos = 0; st_startpos < sxInputString.size(); /* st_startpos advanced in body */) { StringX::size_type st_next = sxInputString.find(_T('$'), st_startpos); if (st_next == StringX::npos) st_next = sxInputString.size(); if (st_next > 0) { st_rctoken.sxname = sxInputString.substr(st_startpos, st_next - st_startpos); st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = st_startpos == 0 ? false : true; st_rctoken.has_brackets = false; v_rctokens.push_back(st_rctoken); v_pos.push_back(st_startpos); } st_startpos = st_next + 1; // too complex for for statement } // tokenization for loop // Check if escaped - ending character of previous token == '\' // Make sure this '\' is not escaped itself! for (size_t st_idx = v_rctokens.size() - 1; st_idx > 0 ; st_idx--) { st_RunCommandTokens &st_rctokens = v_rctokens[st_idx - 1]; StringX::size_type name_len = st_rctokens.sxname.length(); if (name_len == 0 || (name_len >= 2 && st_rctokens.sxname.substr(name_len - 2, 2).compare(_T("\\\\")) == 0)) continue; if (st_rctokens.sxname.substr(name_len - 1, 1).compare(_T("\\")) == 0) { st_rctokens.sxname = st_rctokens.sxname.substr(0, name_len - 1) + _T("$") + v_rctokens[st_idx].sxname; v_rctokens.erase(v_rctokens.begin() + st_idx); } } // Check if variable enclosed in curly brackets for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (v_rctokens[st_idx].sxname.length() == 0) continue; str_Iter = v_rctokens[st_idx].sxname.begin(); // Does it start with a curly bracket? if (*str_Iter == _T('{')) { v_rctokens[st_idx].has_brackets = true; StringX sxvar, sxnonvar, sxindex(_T("")); // Yes - Find end curly bracket StringX::size_type st_end_cb = v_rctokens[st_idx].sxname.find(_T('}')); if (st_end_cb == StringX::npos) { st_column = v_pos[st_idx] + v_rctokens[st_idx].sxname.length(); // Missing end curly bracket uierr = IDSC_EXS_MISSINGCURLYBKT; goto exit; } // Now see if there is an Index here StringX::size_type st_start_sb = v_rctokens[st_idx].sxname.find(_T('[')); if (st_start_sb != StringX::npos) { // Yes - find end square bracket if (st_start_sb > st_end_cb) { // Square backet after end of variable sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); v_rctokens[st_idx].sxname = sxvar; if (sxnonvar.length() > 0) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb); } continue; } StringX::size_type st_end_sb = v_rctokens[st_idx].sxname.find(_T(']'), st_start_sb); if (st_end_sb == StringX::npos) { st_column = v_pos[st_idx] + 1; // Missing end square bracket uierr = IDSC_EXS_MISSINGSQUAREBKT; goto exit; } // The end-curly backet must immediately follow the end-square bracket if (st_end_cb != st_end_sb + 1) { st_column = v_pos[st_idx] + st_end_sb + 1; // Characters between ']' and ')' uierr = IDSC_EXS_INVALIDBRACKETS; goto exit; } sxindex = v_rctokens[st_idx].sxname.substr(st_start_sb + 1, st_end_sb - st_start_sb - 1); v_rctokens[st_idx].sxindex = sxindex; // Now check index uierr = ProcessIndex(sxindex, var_index, st_column); if (uierr > 0) { st_column += v_pos[st_idx]; goto exit; } v_rctokens[st_idx].index = var_index; sxvar = v_rctokens[st_idx].sxname.substr(1, st_start_sb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); } else { // No square bracket // Split current token into 'variable' and 'non-variable' parts sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); } v_rctokens[st_idx].sxname = sxvar; if (sxnonvar.length() > 0) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb); } } } // Now use rules of variables to get the real variable for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (!v_rctokens[st_idx].is_variable) continue; if (v_rctokens[st_idx].sxname.length() == 0) { st_column = v_pos[st_idx]; // Variable name is empty uierr = IDSC_EXS_VARNAMEEMPTY; goto exit; } str_Iter = v_rctokens[st_idx].sxname.begin(); if (!isalpha(*str_Iter)) { st_column = v_pos[st_idx]; // First character of variable is not alphabetic uierr = IDSC_EXS_FIRSTNOTALPHA; goto exit; } StringX::size_type st_next = v_rctokens[st_idx].sxname.find_first_not_of(alphanum.c_str()); if (st_next != StringX::npos) { // Split current token into 'variable' and 'non-variable' parts StringX sxvar = v_rctokens[st_idx].sxname.substr(0, st_next); StringX sxnonvar = v_rctokens[st_idx].sxname.substr(st_next); v_rctokens[st_idx].sxname = sxvar; // Before saving non-variable part - check if it is an Index e.g. var[i] if (sxnonvar.c_str()[0] == _T('[')) { // Find ending square bracket StringX::size_type st_end_sb = sxnonvar.find(_T(']')); if (st_end_sb == StringX::npos) { st_column = v_pos[st_idx] + sxvar.length() + 2; // Missing end square bracket uierr = IDSC_EXS_MISSINGSQUAREBKT; goto exit; } StringX sxindex = sxnonvar.substr(1, st_end_sb - 1); v_rctokens[st_idx].sxindex = sxindex; // Now check index uierr = ProcessIndex(sxindex, var_index, st_column); if (uierr > 0) { st_column += v_pos[st_idx] + sxvar.length(); goto exit; } v_rctokens[st_idx].index = var_index; sxnonvar = sxnonvar.substr(st_end_sb + 1); } else { // Not a square bracket if (v_rctokens[st_idx].has_brackets) { st_column = v_pos[st_idx] + st_next + 1; // Variable must be alphanumeric uierr = IDSC_EXS_VARNAMEINVALID; goto exit; } } if (!sxnonvar.empty()) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_next); } } } // Special Autotype processing bDoAutoType = false; sxAutoType = _T(""); for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (!v_rctokens[st_idx].is_variable) continue; // Is it a autotype variable? if (v_rctokens[st_idx].sxname == _T("a") || v_rctokens[st_idx].sxname == _T("autotype")) { bDoAutoType = true; // Is the next token text and starts with '('? if (st_idx + 1 < v_rctokens.size() && !v_rctokens[st_idx + 1].is_variable && v_rctokens[st_idx + 1].sxname.c_str()[0] == _T('(')) { // Find ending round bracket StringX sx_autotype = v_rctokens[st_idx + 1].sxname; StringX::size_type st_end_rb = sx_autotype.find(_T(')')); if (st_end_rb == StringX::npos) { st_column = v_pos[st_idx + 1] + sx_autotype.length() + 2; // Missing end round bracket uierr = IDSC_EXS_MISSINGROUNDBKT; goto exit; } sxAutoType = sx_autotype.substr(1, st_end_rb - 1); v_rctokens[st_idx + 1].sxname = sx_autotype.substr(st_end_rb + 1); // Check if anything left in this text - none -> delete if (v_rctokens[st_idx + 1].sxname.length() == 0) v_rctokens.erase(v_rctokens.begin() + st_idx + 1); // Now delete Autotype variable v_rctokens.erase(v_rctokens.begin() + st_idx); break; } } } exit: if (uierr != 0) LoadAString(serrmsg, uierr); else serrmsg = _T(""); if (uierr > 0) { v_rctokens.clear(); } v_pos.clear(); return uierr; }
// --------------------------------------------------------------------------- bool XFileXMLProcessor::Process(const bool &bvalidation, const stringT &ImportedPrefix, const stringT &strXMLFileName, const stringT &strXSDFileName, const bool &bImportPSWDsOnly) { USES_XMLCH_STR bool bErrorOccurred = false; bool b_into_empty = false; stringT cs_validation; LoadAString(cs_validation, IDSC_XMLVALIDATION); stringT cs_import; LoadAString(cs_import, IDSC_XMLIMPORT); stringT strResultText(_T("")); m_bValidation = bvalidation; // Validate or Import XSecMemMgr sec_mm; // Initialize the XML4C2 system try { XMLPlatformUtils::Initialize(XMLUni::fgXercescDefaultLocale, 0, 0, &sec_mm); } catch (const XMLException& toCatch) { strResultText = stringT(_X2ST(toCatch.getMessage())); return false; } const XMLCh* xmlfilename = _W2X(strXMLFileName.c_str()); const XMLCh* schemafilename = _W2X(strXSDFileName.c_str()); // Create a SAX2 parser object. SAX2XMLReader* pSAX2Parser = XMLReaderFactory::createXMLReader(&sec_mm); // Set non-default features pSAX2Parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true); pSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, true); pSAX2Parser->setFeature(XMLUni::fgXercesDynamic, false); pSAX2Parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); pSAX2Parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false); pSAX2Parser->setFeature(XMLUni::fgXercesSkipDTDValidation, true); // Set properties pSAX2Parser->setProperty(XMLUni::fgXercesScannerName, const_cast<void*>(reinterpret_cast<const void*>(XMLUni::fgSGXMLScanner))); pSAX2Parser->setInputBufferSize(4096); // Set schema file name (also via property) pSAX2Parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, const_cast<void*>(reinterpret_cast<const void*>(schemafilename))); // Create SAX handler object and install it on the pSAX2Parser, as the // document and error pSAX2Handler. XFileSAX2Handlers * pSAX2Handler = new XFileSAX2Handlers; pSAX2Parser->setContentHandler(pSAX2Handler); pSAX2Parser->setErrorHandler(pSAX2Handler); pSAX2Handler->SetVariables(m_bValidation ? NULL : m_pXMLcore, m_bValidation, ImportedPrefix, m_delimiter, bImportPSWDsOnly, m_bValidation ? NULL : m_pPossible_Aliases, m_bValidation ? NULL : m_pPossible_Shortcuts, m_pmulticmds, m_prpt); if (!m_bValidation) { b_into_empty = m_pXMLcore->GetNumEntries() == 0; } try { // Let's begin the parsing now pSAX2Parser->parse(xmlfilename); } catch (const OutOfMemoryException&) { LoadAString(strResultText, IDCS_XERCESOUTOFMEMORY); bErrorOccurred = true; } catch (const XMLException& e) { strResultText = stringT(_X2ST(e.getMessage())); bErrorOccurred = true; } catch (...) { LoadAString(strResultText, IDCS_XERCESEXCEPTION); bErrorOccurred = true; } if (pSAX2Handler->getIfErrors() || bErrorOccurred) { bErrorOccurred = true; strResultText = pSAX2Handler->getValidationResult(); Format(m_strXMLErrors, IDSC_XERCESPARSEERROR, m_bValidation ? cs_validation.c_str() : cs_import.c_str(), strResultText.c_str()); } else { if (m_bValidation) { m_strXMLErrors = pSAX2Handler->getValidationResult(); m_numEntriesValidated = pSAX2Handler->getNumEntries(); m_delimiter = pSAX2Handler->getDelimiter(); } else { pSAX2Handler->AddXMLEntries(); // Get numbers (may have been modified by AddXMLEntries m_numEntriesImported = pSAX2Handler->getNumEntries(); m_numEntriesSkipped = pSAX2Handler->getNumSkipped(); m_numEntriesRenamed = pSAX2Handler->getNumRenamed(); m_numEntriesPWHErrors = pSAX2Handler->getNumPWHErrors(); m_numNoPolicies = pSAX2Handler->getNumNoPolicies(); m_numRenamedPolicies = pSAX2Handler->getNumRenamedPolicies(); m_numShortcutsRemoved = pSAX2Handler->getNumShortcutsRemoved(); // Get lists m_strXMLErrors = pSAX2Handler->getXMLErrors(); m_strSkippedList = pSAX2Handler->getSkippedList(); m_strPWHErrorList = pSAX2Handler->getPWHErrorList(); m_strRenameList = pSAX2Handler->getRenameList(); if (b_into_empty) { pSAX2Handler->AddDBPreferences(); } } } // Delete the pSAX2Parser itself. Must be done prior to calling Terminate, below. delete pSAX2Parser; delete pSAX2Handler; USES_XMLCH_STR_END // And call the termination method XMLPlatformUtils::Terminate(); return !bErrorOccurred; }
// --------------------------------------------------------------------------- bool MFileXMLProcessor::Process(const bool &bvalidation, const stringT &ImportedPrefix, const stringT &strXMLFileName, const stringT &strXSDFileName, const bool &bImportPSWDsOnly) { HRESULT hr, hr0, hr60; bool b_ok = false; bool b_into_empty; stringT cs_validation; LoadAString(cs_validation, IDSC_XMLVALIDATION); stringT cs_import; LoadAString(cs_import, IDSC_XMLIMPORT); m_strXMLErrors = _T(""); m_bValidation = bvalidation; // Validate or Import // Create SAXReader object ISAXXMLReader *pSAX2Reader = NULL; // Get ready for XSD schema validation IXMLDOMSchemaCollection2 *pSchemaCache = NULL; if (m_bValidation) { //XMLValidate hr60 = CoCreateInstance(__uuidof(SAXXMLReader60), NULL, CLSCTX_ALL, __uuidof(ISAXXMLReader), (void **)&pSAX2Reader); if (FAILED(hr60)) { LoadAString(m_strXMLErrors, IDSC_NOMSXMLREADER); goto exit; } } else { // XMLImport b_into_empty = m_pXMLcore->GetNumEntries() == 0; hr0 = CoCreateInstance(__uuidof(SAXXMLReader60), NULL, CLSCTX_ALL, __uuidof(ISAXXMLReader), (void **)&pSAX2Reader); } // Create ContentHandlerImpl object MFileSAX2ContentHandler *pCH = new MFileSAX2ContentHandler(); pCH->SetVariables(m_bValidation ? NULL : m_pXMLcore, m_bValidation, ImportedPrefix, m_delimiter, bImportPSWDsOnly, m_bValidation ? NULL : m_pPossible_Aliases, m_bValidation ? NULL : m_pPossible_Shortcuts, m_pmulticmds, m_prpt); // Create ErrorHandlerImpl object MFileSAX2ErrorHandler *pEH = new MFileSAX2ErrorHandler(); // Set Content Handler hr = pSAX2Reader->putContentHandler(pCH); // Set Error Handler hr = pSAX2Reader->putErrorHandler(pEH); hr = CoCreateInstance(__uuidof(XMLSchemaCache60), NULL, CLSCTX_ALL, __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache); if (!FAILED(hr)) { // Create SchemaCache // Initialize the SchemaCache object with the XSD filename CComVariant cvXSDFileName = strXSDFileName.c_str(); hr = pSchemaCache->add(L"", cvXSDFileName); // Set the SAXReader/Schema Cache features and properties { /* Documentation is unclear as to what is in which release. Try them all - if they don't get set, the world will not end! Common Error codes: S_OK Operation successful 0x00000000 E_NOTIMPL Not implemented 0x80004001 E_NOINTERFACE No such interface supported 0x80004002 E_ABORT Operation aborted 0x80004004 E_FAIL Unspecified failure 0x80004005 E_INVALIDARG Invalid argument 0x80070057 Normally not supported on a back level MSXMLn.DLL */ // Want all validation errors hr = pSAX2Reader->putFeature(L"exhaustive-errors", VARIANT_TRUE); // Don't allow user to override validation by using DTDs hr = pSAX2Reader->putFeature(L"prohibit-dtd", VARIANT_TRUE); // Don't allow user to override validation by using DTDs (2 features) hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-general-entities", VARIANT_FALSE); hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-parameter-entities", VARIANT_FALSE); // Want to validate XML file hr = pSAX2Reader->putFeature(L"schema-validation", VARIANT_TRUE); // Ignore any schema specified in the XML file hr = pSAX2Reader->putFeature(L"use-schema-location", VARIANT_FALSE); // Ignore any schema in the XML file hr = pSAX2Reader->putFeature(L"use-inline-schema", VARIANT_FALSE); // Only use the XSD in PWSafe's installation directory! hr = pSAX2Reader->putProperty(L"schemas", _variant_t(pSchemaCache)); } // Let's begin the parsing now wchar_t wcURL[MAX_PATH] = {0}; _tcscpy_s(wcURL, MAX_PATH, strXMLFileName.c_str()); hr = pSAX2Reader->parseURL(wcURL); if (!FAILED(hr)) { // Check for parsing errors if (pEH->bErrorsFound == TRUE) { m_strXMLErrors = pEH->m_strValidationResult; } else { if (m_bValidation) { m_numEntriesValidated = pCH->m_numEntries; m_delimiter = pCH->m_delimiter; } else { // Now add entries pCH->AddXMLEntries(); // Get numbers (may have been modified by AddXMLEntries m_numEntriesImported = pCH->m_numEntries; m_numEntriesSkipped = pCH->getNumSkipped(); m_numEntriesRenamed = pCH->getNumRenamed(); m_numEntriesPWHErrors = pCH->getNumPWHErrors(); m_numNoPolicies = pCH->getNumNoPolicies(); m_numRenamedPolicies = pCH->getNumRenamedPolicies(); m_numShortcutsRemoved = pCH->getNumShortcutsRemoved(); // Get lists m_strXMLErrors = pCH->getXMLErrors(); m_strSkippedList = pCH->getSkippedList(); m_strPWHErrorList = pCH->getPWHErrorList(); m_strRenameList = pCH->getRenameList(); if (b_into_empty) { pCH->AddDBPreferences(); } } b_ok = true; } } else { if (pEH->bErrorsFound == TRUE) { m_strXMLErrors = pEH->m_strValidationResult; } else { Format(m_strXMLErrors, IDSC_MSXMLPARSEERROR, hr, m_bValidation ? cs_validation.c_str() : cs_import.c_str()); } } // End Check for parsing errors } else { Format(m_strXMLErrors, IDSC_MSXMLBADCREATESCHEMA, hr, m_bValidation ? cs_validation.c_str() : cs_import.c_str()); } // End Create Schema Cache exit: if (pSchemaCache != NULL) pSchemaCache->Release(); if (pSAX2Reader != NULL) pSAX2Reader->Release(); return b_ok; }
bool pws_os::LockFile(const stringT &filename, stringT &locker, HANDLE &lockFileHandle, int &LockCount) { const stringT lock_filename = GetLockFileName(filename); stringT s_locker; const stringT user = pws_os::getusername(); const stringT host = pws_os::gethostname(); const stringT pid = pws_os::getprocessid(); // Use Win32 API for locking - supposedly better at // detecting dead locking processes if (lockFileHandle != INVALID_HANDLE_VALUE) { // here if we've open another (or same) dbase previously, // need to unlock it. A bit inelegant... // If app was minimized and ClearData() called, we've a small // potential for a TOCTTOU issue here. Worse case, lock // will fail. const stringT cs_me = user + _T("@") + host + _T(":") + pid; GetLocker(lock_filename, s_locker); if (cs_me == s_locker) { LockCount++; locker.clear(); return true; } else { pws_os::UnlockFile(filename, lockFileHandle, LockCount); } } // Since ::CreateFile can't create directories, we need to check it exists // first and, if not, try and create it. // This is primarily for the config directory in the local APPDATA directory // but will also be called for the database lock file - and since the database // is already there, it is a bit of a redundant check but easier than coding // for every different situation. stringT sDrive, sDir, sName, sExt; pws_os::splitpath(lock_filename, sDrive, sDir, sName, sExt); stringT sNewDir = sDrive + sDir; DWORD dwAttrib = GetFileAttributes(sNewDir.c_str()); DWORD dwerr(0); if (dwAttrib == INVALID_FILE_ATTRIBUTES) dwerr = GetLastError(); BOOL brc(TRUE); if (dwerr == ERROR_FILE_NOT_FOUND || (dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { SECURITY_ATTRIBUTES secatt = {0}; secatt.nLength = sizeof(secatt); brc = ::CreateDirectory(sNewDir.c_str(), &secatt); } // Obviously, if we can't create the directory - don't bother trying to // create the lock file! if (brc) { lockFileHandle = ::CreateFile(lock_filename.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, // rely on share to fail if exists! FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | // (Lockheed Martin) Secure Coding 11-14-2007 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL); // Make sure it's a file and not a pipe. (Lockheed Martin) Secure Coding 11-14-2007 if (lockFileHandle != INVALID_HANDLE_VALUE) { if (::GetFileType( lockFileHandle ) != FILE_TYPE_DISK) { ::CloseHandle( lockFileHandle ); lockFileHandle = INVALID_HANDLE_VALUE; } } // End of Change. (Lockheed Martin) Secure Coding 11-14-2007 } if (lockFileHandle == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); switch (error) { case ERROR_SHARING_VIOLATION: // already open by a live process GetLocker(lock_filename, s_locker); locker = s_locker.c_str(); break; default: { // Give detailed error message, if possible LPTSTR lpMsgBuf = NULL; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL) != 0) { locker = lpMsgBuf; LocalFree(lpMsgBuf); } else { // should never happen! LoadAString(locker, IDSC_NOLOCKACCESS); // berrer than nothing } } break; } // switch (error) return false; } else { // valid filehandle, write our info DWORD numWrit, sumWrit; BOOL write_status; write_status = ::WriteFile(lockFileHandle, user.c_str(), (DWORD)(user.length() * sizeof(TCHAR)), &sumWrit, NULL); write_status &= ::WriteFile(lockFileHandle, _T("@"), (DWORD)(sizeof(TCHAR)), &numWrit, NULL); sumWrit += numWrit; write_status &= ::WriteFile(lockFileHandle, host.c_str(), (DWORD)(host.length() * sizeof(TCHAR)), &numWrit, NULL); sumWrit += numWrit; write_status &= ::WriteFile(lockFileHandle, _T(":"), (DWORD)(sizeof(TCHAR)), &numWrit, NULL); sumWrit += numWrit; write_status &= ::WriteFile(lockFileHandle, pid.c_str(), (DWORD)(pid.length() * sizeof(TCHAR)), &numWrit, NULL); sumWrit += numWrit; ASSERT(sumWrit > 0); LockCount++; return (write_status == TRUE); } }
bool pws_os::DeleteAFile(const stringT &filename) { return DeleteFile(filename.c_str()) == TRUE; }
bool pws_os::RenameFile(const stringT &oldname, const stringT &newname) { _tremove(newname.c_str()); // otherwise rename may fail if newname exists return FileOP(oldname, newname, FO_MOVE); }