TEST(UpdateCrypto, Binary) { CAutoTempDir tempdir; CString testFile = tempdir.GetTempDir() + L"\\test.bin"; unsigned char binaryFile[99] = // based on link.png { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, 0xFE, 0xC1, 0x2C, 0xC8, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4C, 0x54, 0x45, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xA5, 0xD9, 0x9F, 0xDD, 0x00, 0x00, 0x00, 0x18, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5E, 0x63, 0xF8, 0xC0, 0xF0, 0x87, 0xE1, 0x17, 0x83, 0x18, 0x43, 0x3E, 0x43, 0x38, 0x43, 0x39, 0x03, 0x3B, 0x00, 0x2C, 0x98, 0x04, 0x41, 0xFA, 0xEC, 0xE7, 0x75, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, }; CAutoFile file = ::CreateFile(testFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); ASSERT_TRUE(file.IsValid()); DWORD written = 0; EXPECT_TRUE(::WriteFile(file, binaryFile, sizeof(binaryFile), &written, nullptr)); EXPECT_EQ(sizeof(binaryFile), written); EXPECT_TRUE(file.CloseHandle()); CString testFileSignature = testFile + _T(".rsa.asc"); EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFileSignature, L"-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v2\n\niQIcBAABCgAGBQJVxPvgAAoJEPfxez+d2VOerKsP/iQlt4S20LdUknT5udD8fFpT\nEFhZDPTXMRWkd8OhCLxa+t5b/ijyxFKWNz808Q7BDQcQoOQtC19NDvVmAcfqXflt\nR4Z+ugCG/lqP+3y0xBrL9m4UT9fNzQCiUY8Xpaih+6riLGnXVVpUe29BgVZppEWn\nMG9RVXpXwC+M3VQ0yQWu1F2Yy5OjdH4Ww5kpluoseZMOPhT6VaSfXeyQmg2DrBbw\nUfVV+w718noZ5znDH9MiD5y+sd4o7vqN2YFdg6FNvTjHyha39aFV8UCpPX1lH9ME\nN9v1vt5IWGCWL0zsZ6umHqibGG3Q2S3mlqktFhKJGWci+Swy4cNMpXDHIKY6e5v7\nxPIP92djyFtbjdixcSqBaYFC/Dd0KuCa1eYmyi2KxzUP29rZ+EHWoazfbeL1Y2Pu\nkSBrVFv64j0URzSMxUpJMqYXZRC5QW7vdbVwHGAPzoS+0rBBddwfSKteBQjagcHA\nkLk3sAIZNj1JaP5dcGL2K4Wxlaae0WgwI48lZSBMoL8SaInQvcKq9iL64xfpU+FU\nG0mzbidvTfZpyEU3eeSNiFi+6z4XLQ3NUFxsOr5jEPVKvgRoPljhJ4nCx034KQRQ\nHbVF9KYgMJSroKN9bNi/UFkC45Pc4wVov/XyH82XCVS30Du4hsVXsTdAiiXb3i6w\nkrWIJWYRxx76XGtQoHrR\n=PlFQ\n-----END PGP SIGNATURE-----")); EXPECT_EQ(0, VerifyIntegrity(testFile, testFileSignature, nullptr)); // signature is shorter than pubkey; did not work w/o commit 941c103c00e48b0ffe592ab4d87d40ff48f899f6 EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFileSignature, L"-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v2\n\niQIbBAABCgAGBQJVxQQOAAoJEPfxez+d2VOe7GoP+KflvYJVpNXSwnteXyDc1zTo\nJAyAJFtW6mgqCLrN6KoMrncEvd0cHrD07hT5mxULkbP6zy9fGaFYF0gHO0mOqErF\nIIbDcpPTWooJWUHMbnuQjf2I0x70Cr8ikycZQ7uDg7scZx7E8EIwHOJX60dcfdVX\nK1SQ+c+VIvo1uxL1PndloACaeINz6rL0Pj504lVDJaaGBvzdAV6KEIcjjm+Jb4r0\n6CYEntmt1i3Mc8FM6Xp1QfGtJqp4ogjv6o89hvtaBBLihB54EVQn66/2qIjdhX8W\nkdqJE6+pmFTfuD02XNECwl6stDIZcxXCw6EE87/1hdHip8oW9enIVTxKWB3fUWHl\n236eE2qb8zAN/WWGx/2Cvi6ctyosy9Cc/1hopnmV0KgZFfmDJWw0lISlC/3ZYWEe\nQFiXs5FPzLwfKnkq4REpoOKKfbZNk329J2iLFnwrF0mlL4vUZ1m26BBBk6lhm41J\nnjOSFWhJG/AqBbR5DqdJfXMqnxpfVZfaE5cry2rhjI4mfzw0xzrgvL4M9FZ7R9F8\njVHAV11CMqtp/7gMHXu6ljkTEBBQ7cgbU5DEAwfWddaJF+R30jmNSVliN2JW2FAk\nIbE8yV+uPiyXebn49CmRzkOWOAZqx+DShqriXGam37qjhdys147wPMMiwk8lZKjP\n4V66gTFw45UvBpophyg=\n=0bmW\n-----END PGP SIGNATURE-----")); EXPECT_EQ(0, VerifyIntegrity(testFile, testFileSignature, nullptr)); }
TEST(UpdateCrypto, BinarySignature) { CAutoTempDir tempdir; CString testFile = tempdir.GetTempDir() + L"\\test.txt"; EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFile, L"Text with\r\nNewline")); unsigned char binarySignature[543] = { 0x89, 0x02, 0x1C, 0x04, 0x00, 0x01, 0x0A, 0x00, 0x06, 0x05, 0x02, 0x55, 0xC5, 0x03, 0x29, 0x00, 0x0A, 0x09, 0x10, 0xF7, 0xF1, 0x7B, 0x3F, 0x9D, 0xD9, 0x53, 0x9E, 0x1E, 0xDF, 0x0F, 0xFF, 0x6C, 0xE9, 0x7B, 0xE0, 0xD6, 0x97, 0x1A, 0xC0, 0x07, 0x77, 0x1C, 0xAB, 0x63, 0x67, 0x9A, 0x75, 0x34, 0xF7, 0x17, 0x84, 0xE2, 0x52, 0xD8, 0x79, 0x4E, 0x35, 0x60, 0xF6, 0x2D, 0x30, 0x1D, 0xF1, 0x09, 0x55, 0x56, 0x4D, 0x00, 0x2E, 0xBF, 0x2C, 0x1A, 0xCA, 0xDE, 0xEF, 0xA2, 0x86, 0xF5, 0xE1, 0x07, 0x7B, 0x48, 0xB5, 0x42, 0x73, 0x59, 0x7D, 0xE0, 0xC9, 0x57, 0x86, 0x06, 0x12, 0xAE, 0xF0, 0xC4, 0xF1, 0x73, 0x9B, 0x23, 0xB8, 0xF8, 0x67, 0x99, 0xB0, 0xB3, 0xCA, 0x0F, 0xF9, 0x1F, 0xD1, 0x5D, 0xD3, 0xFD, 0x44, 0x5C, 0x30, 0x17, 0x4D, 0x84, 0x3A, 0x4E, 0x7B, 0x01, 0xB4, 0x07, 0x37, 0x70, 0x0F, 0x5D, 0xE1, 0x8C, 0x1A, 0x6B, 0xAE, 0x7D, 0x5E, 0x58, 0x6F, 0x16, 0xE8, 0xBD, 0x3D, 0xC1, 0x83, 0x89, 0x52, 0x56, 0x57, 0x5E, 0x3A, 0xA6, 0xD1, 0x5E, 0xC6, 0xB0, 0x3F, 0x8D, 0xDC, 0xA8, 0xAF, 0x32, 0xC4, 0x30, 0x33, 0x9A, 0x5F, 0x5F, 0xF9, 0xAA, 0xFE, 0xCE, 0xBA, 0x4C, 0x86, 0xFD, 0xC1, 0x46, 0x85, 0x0B, 0x0B, 0x5F, 0xF3, 0x78, 0x55, 0x74, 0x85, 0x13, 0x0D, 0xA0, 0x4B, 0xEF, 0x36, 0x37, 0xB0, 0xC8, 0x8B, 0x16, 0x10, 0x2D, 0x97, 0xBD, 0x9E, 0x83, 0x14, 0x70, 0x76, 0xD5, 0x3C, 0xC1, 0x70, 0x35, 0xEF, 0xD1, 0x0D, 0xDA, 0x0B, 0xEA, 0x2B, 0x3F, 0x31, 0x24, 0x26, 0xF8, 0x6E, 0x2F, 0x43, 0x4B, 0xDD, 0xC2, 0x2F, 0x7B, 0x98, 0x3B, 0x1B, 0x6B, 0x3B, 0x12, 0x6D, 0x94, 0xC2, 0x04, 0x41, 0x16, 0xF0, 0xB7, 0xE1, 0xBD, 0x2B, 0x35, 0x3F, 0x0D, 0x3A, 0x8B, 0x2D, 0xE0, 0x1A, 0x07, 0x3E, 0x51, 0xB6, 0xD7, 0x06, 0x27, 0x2E, 0x71, 0x8F, 0x88, 0x0A, 0xC0, 0xF9, 0xE4, 0x0D, 0x71, 0x86, 0x9F, 0x80, 0xCB, 0x72, 0xC4, 0x8F, 0x2E, 0x4E, 0x7B, 0x83, 0x35, 0xBA, 0xAD, 0x73, 0xAB, 0x8A, 0x69, 0xEE, 0xCE, 0xA7, 0x34, 0x69, 0x88, 0xF7, 0x39, 0x13, 0xE9, 0x67, 0xE5, 0x4E, 0x74, 0x16, 0xAB, 0xA4, 0x84, 0xD4, 0x7A, 0x19, 0x5A, 0x71, 0x72, 0xC9, 0xCD, 0x52, 0xFA, 0xE8, 0x16, 0x33, 0xAF, 0x0B, 0x78, 0xC8, 0xA9, 0x05, 0x57, 0xD1, 0x6A, 0x0D, 0x46, 0x36, 0x46, 0x45, 0x4A, 0xC4, 0x64, 0x81, 0xC8, 0x0E, 0x8A, 0xDC, 0xF3, 0x75, 0xD2, 0x5D, 0x60, 0x86, 0xE9, 0x23, 0x02, 0xFA, 0x9C, 0xF5, 0x95, 0xEE, 0x80, 0x47, 0x7F, 0xD1, 0xEE, 0xCC, 0xCF, 0x2D, 0x62, 0x3E, 0x8A, 0x29, 0xEE, 0x8E, 0x43, 0x5F, 0x74, 0xED, 0xB1, 0x8D, 0xC7, 0x41, 0x5A, 0x51, 0xC8, 0xE6, 0xCE, 0xCE, 0x03, 0x77, 0x86, 0x60, 0xEA, 0x73, 0xFC, 0x6D, 0x62, 0x62, 0xAF, 0x6C, 0x2A, 0x1F, 0x84, 0xC4, 0x10, 0x61, 0x78, 0x51, 0x38, 0x8B, 0x4F, 0xE3, 0xDA, 0x39, 0xB6, 0x32, 0x58, 0x84, 0x0C, 0xE7, 0xCD, 0xDF, 0xB1, 0x6D, 0x72, 0xFD, 0xF6, 0x22, 0x50, 0xB0, 0x7F, 0x35, 0x56, 0xF0, 0x9B, 0x47, 0xF1, 0x45, 0x13, 0x06, 0xE5, 0x71, 0x15, 0xE9, 0xB2, 0x5E, 0x78, 0xE0, 0x70, 0xAB, 0x98, 0xBF, 0xF3, 0x15, 0x6A, 0x3D, 0x3E, 0xDF, 0x2D, 0x23, 0xBF, 0x16, 0x96, 0x0D, 0xF3, 0x4F, 0xD4, 0x48, 0x66, 0x2E, 0x52, 0xB0, 0x48, 0x2E, 0x37, 0x7A, 0xCA, 0xFA, 0x89, 0x3B, 0x21, 0xAA, 0xD1, 0x96, 0x1C, 0x2E, 0x28, 0x7A, 0xEF, 0xCB, 0x09, 0x62, 0xF4, 0xC5, 0x3E, 0x81, 0x87, 0xBB, 0x9B, 0x48, 0xAB, 0x1E, 0xD5, 0xAE, 0x3B, 0x20, 0x1A, 0xD1, 0x51, 0x9D, 0xE0, 0x6E, 0x6E, 0xCC, 0x29, 0x24, 0x34, 0xCF, 0x07, 0xF4, 0x33, 0x42, 0x3A, 0xF2, 0x86, 0x4F, 0xFA, 0xEE, 0x5D, 0x0A, 0x6A, 0x33, 0xE0, 0xFC, 0xBB, 0x1C, 0xA0, 0xA4, 0x76, 0xE8, 0xB1, 0x17, 0xF5, 0xE4, }; CString testFileSignature = testFile + _T(".rsa.asc"); CAutoFile file = ::CreateFile(testFileSignature, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); ASSERT_TRUE(file.IsValid()); DWORD written = 0; EXPECT_TRUE(::WriteFile(file, binarySignature, sizeof(binarySignature), &written, nullptr)); EXPECT_EQ(sizeof(binarySignature), written); EXPECT_TRUE(file.CloseHandle()); EXPECT_EQ(0, VerifyIntegrity(testFile, testFileSignature, nullptr)); EXPECT_TRUE(CStringUtils::WriteStringToTextFile((LPCTSTR)testFile, L"Text with\nNewline")); EXPECT_EQ(-1, VerifyIntegrity(testFile, testFileSignature, nullptr)); }
bool CRemoteCacheLink::InternalEnsurePipeOpen ( CAutoFile& hPipe , const CString& pipeName) const { if (hPipe) return true; int tryleft = 2; while (!hPipe && tryleft--) { hPipe = CreateFile( pipeName, // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe FILE_FLAG_OVERLAPPED, // default attributes NULL); // no template file if ((!hPipe) && (GetLastError() == ERROR_PIPE_BUSY)) { // TGitCache is running but is busy connecting a different client. // Do not give up immediately but wait for a few milliseconds until // the server has created the next pipe instance if (!WaitNamedPipe (pipeName, 50)) { continue; } } } if (hPipe) { // The pipe connected; change to message-read mode. DWORD dwMode; dwMode = PIPE_READMODE_MESSAGE; if(!SetNamedPipeHandleState( hPipe, // pipe handle &dwMode, // new pipe mode NULL, // don't set maximum bytes NULL)) // don't set maximum time { CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed"); hPipe.CloseHandle(); } } return hPipe; }
bool SyncCommand::Execute() { bool bRet = false; CRegString rSyncPath(L"Software\\TortoiseSVN\\SyncPath"); CTSVNPath syncPath = CTSVNPath(CString(rSyncPath)); CTSVNPath syncFolder = syncPath; CRegDWORD regCount(L"Software\\TortoiseSVN\\SyncCounter"); CRegDWORD regSyncAuth(L"Software\\TortoiseSVN\\SyncAuth"); bool bSyncAuth = DWORD(regSyncAuth) != 0; if (!cmdLinePath.IsEmpty()) syncPath = cmdLinePath; if (syncPath.IsEmpty() && !parser.HasKey(L"askforpath")) { return false; } syncPath.AppendPathString(L"tsvnsync.tsex"); BOOL bWithLocals = FALSE; if (parser.HasKey(L"askforpath")) { // ask for the path first, then for the password // this is used for a manual import/export CString path; bool bGotPath = FileOpenSave(path, bWithLocals, !!parser.HasKey(L"load"), GetExplorerHWND()); if (bGotPath) { syncPath = CTSVNPath(path); if (!parser.HasKey(L"load") && syncPath.GetFileExtension().IsEmpty()) syncPath.AppendRawString(L".tsex"); } else return false; } CSimpleIni iniFile; iniFile.SetMultiLine(true); SVNAuthData authData; CAutoRegKey hMainKey; RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\TortoiseSVN", 0, KEY_READ, hMainKey.GetPointer()); FILETIME filetime = { 0 }; RegQueryInfoKey(hMainKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &filetime); bool bCloudIsNewer = false; if (!parser.HasKey(L"save")) { // open the file in read mode CAutoFile hFile = CreateFile(syncPath.GetWinPathString(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile.IsValid()) { // load the file LARGE_INTEGER fsize = { 0 }; if (GetFileSizeEx(hFile, &fsize)) { auto filebuf = std::make_unique<char[]>(DWORD(fsize.QuadPart)); DWORD bytesread = 0; if (ReadFile(hFile, filebuf.get(), DWORD(fsize.QuadPart), &bytesread, NULL)) { // decrypt the file contents std::string encrypted; if (bytesread > 0) encrypted = std::string(filebuf.get(), bytesread); CRegString regPW(L"Software\\TortoiseSVN\\SyncPW"); CString password; if (parser.HasKey(L"askforpath") && parser.HasKey(L"load")) { INT_PTR dlgret = 0; bool bPasswordMatches = true; do { bPasswordMatches = true; CPasswordDlg passDlg(CWnd::FromHandle(GetExplorerHWND())); passDlg.m_bForSave = !!parser.HasKey(L"save"); dlgret = passDlg.DoModal(); password = passDlg.m_sPW1; if ((dlgret == IDOK) && (parser.HasKey(L"load"))) { std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password); std::string decrypted = CStringUtils::Decrypt(encrypted, passworda); if ((decrypted.size() < 3) || (decrypted.substr(0, 3) != "***")) { bPasswordMatches = false; } } } while ((dlgret == IDOK) && !bPasswordMatches); if (dlgret != IDOK) return false; } else { auto passwordbuf = CStringUtils::Decrypt(CString(regPW)); if (passwordbuf.get()) { password = passwordbuf.get(); } else { // password does not match or it couldn't be read from // the registry! // TaskDialog(GetExplorerHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_ERR_ERROROCCURED), MAKEINTRESOURCE(IDS_SYNC_WRONGPASSWORD), TDCBF_OK_BUTTON, TD_ERROR_ICON, NULL); CString sCmd = L" /command:settings /page:21"; CAppUtils::RunTortoiseProc(sCmd); return false; } } std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password); std::string decrypted = CStringUtils::Decrypt(encrypted, passworda); if (decrypted.size() >= 3) { if (decrypted.substr(0, 3) == "***") { decrypted = decrypted.substr(3); // pass the decrypted data to the ini file iniFile.LoadFile(decrypted.c_str(), decrypted.size()); int inicount = _wtoi(iniFile.GetValue(L"sync", L"synccounter", L"")); if (inicount != 0) { if (int(DWORD(regCount)) < inicount) { bCloudIsNewer = true; regCount = inicount; } } // load the auth data, but do not overwrite already stored auth data! if (bSyncAuth) authData.ImportAuthData(syncFolder.GetWinPathString(), password); } else { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error decrypting, password may be wrong\n"); return false; } } } } } else { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error opening file %s, Error %u\n", syncPath.GetWinPath(), GetLastError()); auto lasterr = GetLastError(); if ((lasterr != ERROR_FILE_NOT_FOUND) && (lasterr != ERROR_PATH_NOT_FOUND)) return false; } } if (parser.HasKey(L"load")) bCloudIsNewer = true; if (parser.HasKey(L"save")) bCloudIsNewer = false; bool bHaveChanges = false; if (bWithLocals || parser.HasKey(L"local")) { // remove all blocks that are allowed for local exports for (const auto& allow : regBlockLocalArray) { regBlockArray.erase(std::remove(regBlockArray.begin(), regBlockArray.end(), allow), regBlockArray.end()); } } // go through all registry values and update either the registry // or the ini file, depending on which is newer for (const auto& regname : regUseArray) { bool bChanges = HandleRegistryKey(regname, iniFile, bCloudIsNewer); bHaveChanges = bHaveChanges || bChanges; } if (bWithLocals || parser.HasKey(L"local")) { for (const auto& regname : regUseLocalArray) { bool bChanges = HandleRegistryKey(regname, iniFile, bCloudIsNewer); bHaveChanges = bHaveChanges || bChanges; } } if (bCloudIsNewer) { CString regpath = L"Software\\"; CSimpleIni::TNamesDepend keys; iniFile.GetAllKeys(L"registry_dword", keys); for (const auto& k : keys) { CRegDWORD reg(regpath + k); reg = _wtol(iniFile.GetValue(L"registry_dword", k, L"")); } keys.clear(); iniFile.GetAllKeys(L"registry_qword", keys); for (const auto& k : keys) { CRegQWORD reg(regpath + k); reg = _wtoi64(iniFile.GetValue(L"registry_qword", k, L"")); } keys.clear(); iniFile.GetAllKeys(L"registry_string", keys); for (const auto& k : keys) { CRegString reg(regpath + k); reg = CString(iniFile.GetValue(L"registry_string", k, L"")); } } { // sync project monitor settings CString sDataFilePath = CPathUtils::GetAppDataDirectory(); sDataFilePath += L"\\MonitoringData.ini"; CSimpleIni monitorIni; monitorIni.SetMultiLine(true); if (bCloudIsNewer) { CSimpleIni origMonitorIni; origMonitorIni.SetMultiLine(true); origMonitorIni.LoadFile(sDataFilePath); CSimpleIni::TNamesDepend keys; iniFile.GetAllKeys(L"ini_monitor", keys); for (const auto& k : keys) { CString sKey = k; CString sSection = sKey.Left(sKey.Find('.')); sKey = sKey.Mid(sKey.Find('.') + 1); if (sKey.CompareNoCase(L"name") == 0) { // make sure the non-synced values are still used monitorIni.SetValue(sSection, L"lastchecked", origMonitorIni.GetValue(sSection, L"lastchecked", L"0")); monitorIni.SetValue(sSection, L"lastcheckedrobots", origMonitorIni.GetValue(sSection, L"lastcheckedrobots", L"0")); monitorIni.SetValue(sSection, L"lastHEAD", origMonitorIni.GetValue(sSection, L"lastHEAD", L"0")); monitorIni.SetValue(sSection, L"UnreadItems", origMonitorIni.GetValue(sSection, L"UnreadItems", L"0")); monitorIni.SetValue(sSection, L"unreadFirst", origMonitorIni.GetValue(sSection, L"unreadFirst", L"0")); monitorIni.SetValue(sSection, L"WCPathOrUrl", origMonitorIni.GetValue(sSection, L"WCPathOrUrl", L"")); } CString sValue = CString(iniFile.GetValue(L"ini_monitor", k, L"")); if ((sKey.Compare(L"username") == 0) || (sKey.Compare(L"password") == 0)) { sValue = CStringUtils::Encrypt(sValue); } monitorIni.SetValue(sSection, sKey, sValue); } FILE * pFile = NULL; errno_t err = 0; int retrycount = 5; CString sTempfile = CTempFiles::Instance().GetTempFilePathString(); do { err = _tfopen_s(&pFile, sTempfile, L"wb"); if ((err == 0) && pFile) { monitorIni.SaveFile(pFile); err = fclose(pFile); } if (err) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error saving %s, retrycount %d\n", (LPCWSTR)sTempfile, retrycount); Sleep(500); } } while (err && retrycount--); if (err == 0) { if (!CopyFile(sTempfile, sDataFilePath, FALSE)) CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error %u\n", (LPCWSTR)sTempfile, (LPCWSTR)sDataFilePath, GetLastError()); else { // now send a message to a possible running monitor to force it // to reload the ini file. Otherwise it would overwrite the ini // file without using the synced data! HWND hWnd = FindWindow(NULL, CString(MAKEINTRESOURCE(IDS_MONITOR_DLGTITLE))); if (hWnd) { UINT TSVN_COMMITMONITOR_RELOADINI = RegisterWindowMessage(L"TSVNCommitMonitor_ReloadIni"); PostMessage(hWnd, TSVN_COMMITMONITOR_RELOADINI, 0, 0); } } } } else { CSimpleIni::TNamesDepend mitems; if (PathFileExists(sDataFilePath)) { int retrycount = 5; SI_Error err = SI_OK; do { err = monitorIni.LoadFile(sDataFilePath); if (err == SI_FILE) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error loading %s, retrycount %d\n", (LPCWSTR)sDataFilePath, retrycount); Sleep(500); } } while ((err == SI_FILE) && retrycount--); if (err == SI_FILE) { return false; } monitorIni.GetAllSections(mitems); } for (const auto& mitem : mitems) { CString sSection = mitem; CString Name = monitorIni.GetValue(mitem, L"Name", L""); if (!Name.IsEmpty()) { CString newval = monitorIni.GetValue(mitem, L"WCPathOrUrl", L""); iniFile.SetValue(L"ini_monitor", sSection + L".Name", Name); CString oldval = iniFile.GetValue(L"ini_monitor", sSection + L".WCPathOrUrl", L""); bHaveChanges |= ((newval != oldval) && (!oldval.IsEmpty())); // only save monitored working copies if local settings are included, or // if the monitored path is an url. // Don't save paths to working copies for non-local stores if (bWithLocals || newval.IsEmpty() || !PathIsDirectory(newval)) iniFile.SetValue(L"ini_monitor", sSection + L".WCPathOrUrl", newval); newval = monitorIni.GetValue(mitem, L"interval", L"5"); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".interval", L"0"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".interval", newval); newval = monitorIni.GetValue(mitem, L"minminutesinterval", L"0"); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".minminutesinterval", L"0"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".minminutesinterval", newval); newval = CStringUtils::Decrypt(monitorIni.GetValue(mitem, L"username", L"")).get(); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".username", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".username", newval); newval = CStringUtils::Decrypt(monitorIni.GetValue(mitem, L"password", L"")).get(); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".password", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".password", newval); newval = monitorIni.GetValue(mitem, L"MsgRegex", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".MsgRegex", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".MsgRegex", newval); newval = monitorIni.GetValue(mitem, L"ignoreauthors", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".ignoreauthors", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".ignoreauthors", newval); newval = monitorIni.GetValue(mitem, L"parentTreePath", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".parentTreePath", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".parentTreePath", newval); newval = monitorIni.GetValue(mitem, L"uuid", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".uuid", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".uuid", newval); newval = monitorIni.GetValue(mitem, L"root", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".root", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".root", newval); ProjectProperties ProjProps; ProjProps.LoadFromIni(monitorIni, sSection); ProjProps.SaveToIni(iniFile, L"ini_monitor", sSection + L".pp_"); } else if (sSection.CompareNoCase(L"global") == 0) { CString newval = monitorIni.GetValue(mitem, L"PlaySound", L"1"); CString oldval = iniFile.GetValue(L"ini_monitor", sSection + L".PlaySound", L"1"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".PlaySound", newval); newval = monitorIni.GetValue(mitem, L"ShowNotifications", L"1"); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".ShowNotifications", L"1"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".ShowNotifications", newval); } } } } { // sync TortoiseMerge regex filters CSimpleIni regexIni; regexIni.SetMultiLine(true); CString sDataFilePath = CPathUtils::GetAppDataDirectory(); sDataFilePath += L"\\regexfilters.ini"; if (bCloudIsNewer) { CSimpleIni origRegexIni; if (PathFileExists(sDataFilePath)) { int retrycount = 5; SI_Error err = SI_OK; do { err = origRegexIni.LoadFile(sDataFilePath); if (err == SI_FILE) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error loading %s, retrycount %d\n", (LPCWSTR)sDataFilePath, retrycount); Sleep(500); } } while ((err == SI_FILE) && retrycount--); if (err == SI_FILE) { return false; } } CSimpleIni::TNamesDepend keys; iniFile.GetAllKeys(L"ini_tmergeregex", keys); for (const auto& k : keys) { CString sKey = k; CString sSection = sKey.Left(sKey.Find('.')); sKey = sKey.Mid(sKey.Find('.') + 1); CString sValue = CString(iniFile.GetValue(L"ini_tmergeregex", k, L"")); regexIni.SetValue(sSection, sKey, sValue); } FILE * pFile = NULL; errno_t err = 0; int retrycount = 5; CString sTempfile = CTempFiles::Instance().GetTempFilePathString(); do { err = _tfopen_s(&pFile, sTempfile, L"wb"); if ((err == 0) && pFile) { regexIni.SaveFile(pFile); err = fclose(pFile); } if (err) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error saving %s, retrycount %d\n", (LPCWSTR)sTempfile, retrycount); Sleep(500); } } while (err && retrycount--); if (err == 0) { if (!CopyFile(sTempfile, sDataFilePath, FALSE)) CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error: %u\n", (LPCWSTR)sTempfile, (LPCWSTR)sDataFilePath, GetLastError()); } } else { if (PathFileExists(sDataFilePath)) { int retrycount = 5; SI_Error err = SI_OK; do { err = regexIni.LoadFile(sDataFilePath); if (err == SI_FILE) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error loading %s, retrycount %d\n", (LPCWSTR)sDataFilePath, retrycount); Sleep(500); } } while ((err == SI_FILE) && retrycount--); if (err == SI_FILE) { return false; } } CSimpleIni::TNamesDepend mitems; regexIni.GetAllSections(mitems); for (const auto& mitem : mitems) { CString sSection = mitem; CString newval = regexIni.GetValue(mitem, L"regex", L""); CString oldval = iniFile.GetValue(L"ini_tmergeregex", sSection + L".regex", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_tmergeregex", sSection + L".regex", newval); newval = regexIni.GetValue(mitem, L"replace", L"5"); oldval = iniFile.GetValue(L"ini_tmergeregex", sSection + L".replace", L"0"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_tmergeregex", sSection + L".replace", newval); } } } if (bHaveChanges) { iniFile.SetValue(L"sync", L"version", TSVN_SYNC_VERSION_STR); DWORD count = regCount; ++count; regCount = count; CString tmp; tmp.Format(L"%lu", count); iniFile.SetValue(L"sync", L"synccounter", tmp); // save the ini file std::string iniData; iniFile.SaveString(iniData); iniData = "***" + iniData; // encrypt the string CString password; if (parser.HasKey(L"askforpath")) { CPasswordDlg passDlg(CWnd::FromHandle(GetExplorerHWND())); passDlg.m_bForSave = true; if (passDlg.DoModal() != IDOK) return false; password = passDlg.m_sPW1; } else { CRegString regPW(L"Software\\TortoiseSVN\\SyncPW"); auto passwordbuf = CStringUtils::Decrypt(CString(regPW)); if (passwordbuf.get()) { password = passwordbuf.get(); } } std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password); std::string encrypted = CStringUtils::Encrypt(iniData, passworda); CPathUtils::MakeSureDirectoryPathExists(syncPath.GetContainingDirectory().GetWinPathString()); CString sTempfile = CTempFiles::Instance().GetTempFilePathString(); CAutoFile hFile = CreateFile(sTempfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile.IsValid()) { DWORD written = 0; if (WriteFile(hFile, encrypted.c_str(), DWORD(encrypted.size()), &written, NULL)) { if (hFile.CloseHandle()) { if (!CopyFile(sTempfile, syncPath.GetWinPath(), FALSE)) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error: %u\n", (LPCWSTR)sTempfile, syncPath.GetWinPath(), GetLastError()); } else bRet = true; } else CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error closing file %s, Error: %u\n", (LPCWSTR)sTempfile, GetLastError()); } else CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error writing to file %s, Error: %u\n", (LPCWSTR)sTempfile, GetLastError()); } else CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error creating file %s for writing, Error: %u\n", (LPCWSTR)sTempfile, GetLastError()); if (bSyncAuth) { // now save all auth data CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.simple"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.ssl.client-passphrase"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.ssl.server"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.username"); authData.ExportAuthData(syncFolder.GetWinPathString(), password); } } return bRet; }
DWORD WINAPI CommandWaitThread(LPVOID lpvParam) { ATLTRACE("CommandWaitThread started\n"); bool * bRun = (bool *)lpvParam; // The main loop creates an instance of the named pipe and // then waits for a client to connect to it. When the client // connects, a thread is created to handle communications // with that client, and the loop is repeated. DWORD dwThreadId; BOOL fConnected; CAutoFile hPipe; while (*bRun) { hPipe = CreateNamedPipe( GetCacheCommandPipeName(), PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFSIZE, // output buffer size BUFSIZE, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out NULL); // NULL DACL if (!hPipe) { //OutputDebugStringA("TSVNCache: CreatePipe failed\n"); //DebugOutputLastError(); if (*bRun) Sleep(200); continue; // never leave the thread! } // Wait for the client to connect; if it succeeds, // the function returns a nonzero value. If the function returns // zero, GetLastError returns ERROR_PIPE_CONNECTED. fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); if (fConnected) { // Create a thread for this client. CAutoGeneralHandle hCommandThread = CreateThread( NULL, // no security attribute 0, // default stack size CommandThread, (HANDLE) hPipe, // thread parameter 0, // not suspended &dwThreadId); // returns thread ID if (!hCommandThread) { //OutputDebugStringA("TSVNCache: Could not create Command thread\n"); //DebugOutputLastError(); DisconnectNamedPipe(hPipe); hPipe.CloseHandle(); // since we're now closing this thread, we also have to close the whole application! // otherwise the thread is dead, but the app is still running, refusing new instances // but no pipe will be available anymore. PostMessage(hWnd, WM_CLOSE, 0, 0); return 1; } // detach the handle, since we passed it to the thread hPipe.Detach(); } else { // The client could not connect, so close the pipe. //OutputDebugStringA("TSVNCache: ConnectNamedPipe failed\n"); //DebugOutputLastError(); hPipe.CloseHandle(); if (*bRun) Sleep(200); continue; // don't end the thread! } } ATLTRACE("CommandWait thread exited\n"); return 0; }
bool CPicture::Load(tstring sFilePathName) { bool bResult = false; bIsIcon = false; lpIcons = NULL; //CFile PictureFile; //CFileException e; FreePictureData(); // Important - Avoid Leaks... // No-op if no file specified if (sFilePathName.empty()) return true; // Load & initialize the GDI+ library if available HMODULE hGdiPlusLib = AtlLoadSystemLibraryUsingFullPath(_T("gdiplus.dll")); if (hGdiPlusLib && GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Ok) { bHaveGDIPlus = true; } // Since we loaded the gdiplus.dll only to check if it's available, we // can safely free the library here again - GdiplusStartup() loaded it too // and reference counting will make sure that it stays loaded until GdiplusShutdown() // is called. FreeLibrary(hGdiPlusLib); // Attempt to load using GDI+ if available if (bHaveGDIPlus) { pBitmap = new Bitmap(sFilePathName.c_str(), FALSE); GUID guid; pBitmap->GetRawFormat(&guid); if (pBitmap->GetLastStatus() != Ok) { delete pBitmap; pBitmap = NULL; } // gdiplus only loads the first icon found in an icon file // so we have to handle icon files ourselves :( // Even though gdiplus can load icons, it can't load the new // icons from Vista - in Vista, the icon format changed slightly. // But the LoadIcon/LoadImage API still can load those icons, // at least those dimensions which are also used on pre-Vista // systems. // For that reason, we don't rely on gdiplus telling us if // the image format is "icon" or not, we also check the // file extension for ".ico". std::transform(sFilePathName.begin(), sFilePathName.end(), sFilePathName.begin(), ::tolower); bIsIcon = (guid == ImageFormatIcon) || (wcsstr(sFilePathName.c_str(), L".ico") != NULL) || (wcsstr(sFilePathName.c_str(), L".cur") != NULL); bIsTiff = (guid == ImageFormatTIFF) || (_tcsstr(sFilePathName.c_str(), _T(".tiff")) != NULL); m_Name = sFilePathName; if (bIsIcon) { // Icon file, get special treatment... if (pBitmap) { // Cleanup first... delete (pBitmap); pBitmap = NULL; bIsIcon = true; } CAutoFile hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { BY_HANDLE_FILE_INFORMATION fileinfo; if (GetFileInformationByHandle(hFile, &fileinfo)) { lpIcons = new BYTE[fileinfo.nFileSizeLow]; DWORD readbytes; if (ReadFile(hFile, lpIcons, fileinfo.nFileSizeLow, &readbytes, NULL)) { // we have the icon. Now gather the information we need later if (readbytes >= sizeof(ICONDIR)) { // we are going to open same file second time so we have to close the file now hFile.CloseHandle(); LPICONDIR lpIconDir = (LPICONDIR)lpIcons; if ((lpIconDir->idCount) && ((lpIconDir->idCount * sizeof(ICONDIR)) <= fileinfo.nFileSizeLow)) { try { bResult = false; nCurrentIcon = 0; hIcons = new HICON[lpIconDir->idCount]; // check that the pointers point to data that we just loaded if (((BYTE*)lpIconDir->idEntries > (BYTE*)lpIconDir) && (((BYTE*)lpIconDir->idEntries) + (lpIconDir->idCount * sizeof(ICONDIRENTRY)) < ((BYTE*)lpIconDir) + fileinfo.nFileSizeLow)) { m_Width = lpIconDir->idEntries[0].bWidth; m_Height = lpIconDir->idEntries[0].bHeight; bResult = true; for (int i=0; i<lpIconDir->idCount; ++i) { hIcons[i] = (HICON)LoadImage(NULL, sFilePathName.c_str(), IMAGE_ICON, lpIconDir->idEntries[i].bWidth, lpIconDir->idEntries[i].bHeight, LR_LOADFROMFILE); if (hIcons[i] == NULL) { // if the icon couldn't be loaded, the data is most likely corrupt delete [] lpIcons; lpIcons = NULL; bResult = false; break; } } } } catch (...) { delete [] lpIcons; lpIcons = NULL; bResult = false; } } else { delete [] lpIcons; lpIcons = NULL; bResult = false; } } else { delete [] lpIcons; lpIcons = NULL; bResult = false; } } else { delete [] lpIcons; lpIcons = NULL; } } } } else if (pBitmap) // Image loaded successfully with GDI+ { m_Height = pBitmap->GetHeight(); m_Width = pBitmap->GetWidth(); bResult = true; } // If still failed to load the file... if (!bResult) { // Attempt to load the FreeImage library as an optional DLL to support additional formats // NOTE: Currently just loading via FreeImage & using GDI+ for drawing. // It might be nice to remove this dependency in the future. HMODULE hFreeImageLib = LoadLibrary(_T("FreeImage.dll")); // FreeImage DLL functions typedef const char* (__stdcall *FreeImage_GetVersion_t)(void); typedef int (__stdcall *FreeImage_GetFileType_t)(const TCHAR *filename, int size); typedef int (__stdcall *FreeImage_GetFIFFromFilename_t)(const TCHAR *filename); typedef void* (__stdcall *FreeImage_Load_t)(int format, const TCHAR *filename, int flags); typedef void (__stdcall *FreeImage_Unload_t)(void* dib); typedef int (__stdcall *FreeImage_GetColorType_t)(void* dib); typedef unsigned (__stdcall *FreeImage_GetWidth_t)(void* dib); typedef unsigned (__stdcall *FreeImage_GetHeight_t)(void* dib); typedef void (__stdcall *FreeImage_ConvertToRawBits_t)(BYTE *bits, void *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown); //FreeImage_GetVersion_t FreeImage_GetVersion = NULL; FreeImage_GetFileType_t FreeImage_GetFileType = NULL; FreeImage_GetFIFFromFilename_t FreeImage_GetFIFFromFilename = NULL; FreeImage_Load_t FreeImage_Load = NULL; FreeImage_Unload_t FreeImage_Unload = NULL; //FreeImage_GetColorType_t FreeImage_GetColorType = NULL; FreeImage_GetWidth_t FreeImage_GetWidth = NULL; FreeImage_GetHeight_t FreeImage_GetHeight = NULL; FreeImage_ConvertToRawBits_t FreeImage_ConvertToRawBits = NULL; if (hFreeImageLib) { bool exportsValid = true; //FreeImage_GetVersion = (FreeImage_GetVersion_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetVersion@0", valid); FreeImage_GetWidth = (FreeImage_GetWidth_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetWidth@4", exportsValid); FreeImage_GetHeight = (FreeImage_GetHeight_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetHeight@4", exportsValid); FreeImage_Unload = (FreeImage_Unload_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_Unload@4", exportsValid); FreeImage_ConvertToRawBits = (FreeImage_ConvertToRawBits_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_ConvertToRawBits@32", exportsValid); #ifdef UNICODE FreeImage_GetFileType = (FreeImage_GetFileType_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFileTypeU@8", exportsValid); FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFIFFromFilenameU@4", exportsValid); FreeImage_Load = (FreeImage_Load_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_LoadU@12", exportsValid); #else FreeImage_GetFileType = (FreeImage_GetFileType_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFileType@8", exportsValid); FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFIFFromFilename@4", exportsValid); FreeImage_Load = (FreeImage_Load_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_Load@12", exportsValid); #endif //const char* version = FreeImage_GetVersion(); // Check the DLL is using compatible exports if (exportsValid) { // Derive file type from file header. int fileType = FreeImage_GetFileType(sFilePathName.c_str(), 0); if (fileType < 0) { // No file header available, attempt to parse file name for extension. fileType = FreeImage_GetFIFFromFilename(sFilePathName.c_str()); } // If we have a valid file type if (fileType >= 0) { void* dib = FreeImage_Load(fileType, sFilePathName.c_str(), 0); if (dib) { unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); // Create a GDI+ bitmap to load into... pBitmap = new Bitmap(width, height, PixelFormat32bppARGB); if (pBitmap && pBitmap->GetLastStatus() == Ok) { // Write & convert the loaded data into the GDI+ Bitmap Rect rect(0, 0, width, height); BitmapData bitmapData; if (pBitmap->LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData) == Ok) { FreeImage_ConvertToRawBits((BYTE*)bitmapData.Scan0, dib, bitmapData.Stride, 32, 0xff << RED_SHIFT, 0xff << GREEN_SHIFT, 0xff << BLUE_SHIFT, FALSE); pBitmap->UnlockBits(&bitmapData); m_Width = width; m_Height = height; bResult = true; } else // Failed to lock the destination Bitmap { delete pBitmap; pBitmap = NULL; } } else // Bitmap allocation failed { delete pBitmap; pBitmap = NULL; } FreeImage_Unload(dib); dib = NULL; } } } FreeLibrary(hFreeImageLib); hFreeImageLib = NULL; } } }
BOOL CFileTextLines::Load(const CString& sFilePath, int lengthHint /* = 0*/) { m_LineEndings = EOL_AUTOLINE; m_UnicodeType = CFileTextLines::AUTOTYPE; RemoveAll(); m_endings.clear(); if(lengthHint != 0) { Reserve(lengthHint); } if (PathIsDirectory(sFilePath)) { m_sErrorString.Format(IDS_ERR_FILE_NOTAFILE, (LPCTSTR)sFilePath); return FALSE; } if (!PathFileExists(sFilePath)) { //file does not exist, so just return SUCCESS return TRUE; } CAutoFile hFile = CreateFile(sFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); if (!hFile) { SetErrorString(); return FALSE; } LARGE_INTEGER fsize; if (!GetFileSizeEx(hFile, &fsize)) { SetErrorString(); return false; } if (fsize.HighPart) { // file is way too big for us m_sErrorString.LoadString(IDS_ERR_FILE_TOOBIG); return FALSE; } // If new[] was done for type T delete[] must be called on a pointer of type T*, // otherwise the behavior is undefined. // +1 is to address possible truncation when integer division is done wchar_t* pFileBuf = new wchar_t[fsize.LowPart/sizeof(wchar_t) + 1]; DWORD dwReadBytes = 0; if (!ReadFile(hFile, pFileBuf, fsize.LowPart, &dwReadBytes, NULL)) { delete [] pFileBuf; SetErrorString(); return FALSE; } if (m_UnicodeType == CFileTextLines::AUTOTYPE) { m_UnicodeType = this->CheckUnicodeType(pFileBuf, dwReadBytes); } if (m_LineEndings == EOL_AUTOLINE) { m_LineEndings = CheckLineEndings(pFileBuf, min(10000, dwReadBytes)); } hFile.CloseHandle(); if (m_UnicodeType == CFileTextLines::BINARY) { m_sErrorString.Format(IDS_ERR_FILE_BINARY, (LPCTSTR)sFilePath); delete [] pFileBuf; return FALSE; } // we may have to convert the file content if ((m_UnicodeType == UTF8)||(m_UnicodeType == UTF8BOM)) { int ret = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pFileBuf, dwReadBytes, NULL, 0); wchar_t * pWideBuf = new wchar_t[ret]; int ret2 = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pFileBuf, dwReadBytes, pWideBuf, ret); if (ret2 == ret) { delete [] pFileBuf; pFileBuf = pWideBuf; dwReadBytes = ret2; } else delete [] pWideBuf; } else if (m_UnicodeType == ASCII) { int ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)pFileBuf, dwReadBytes, NULL, 0); wchar_t * pWideBuf = new wchar_t[ret]; int ret2 = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)pFileBuf, dwReadBytes, pWideBuf, ret); if (ret2 == ret) { delete [] pFileBuf; pFileBuf = pWideBuf; dwReadBytes = ret2; } else delete [] pWideBuf; } // fill in the lines into the array wchar_t * pTextBuf = pFileBuf; wchar_t * pLineStart = pFileBuf; if (m_UnicodeType == UNICODE_LE) { // UTF16 have two bytes per char dwReadBytes/=2; } if ((m_UnicodeType == UTF8BOM)||(m_UnicodeType == UNICODE_LE)) { // ignore the BOM ++pTextBuf; ++pLineStart; --dwReadBytes; } for (DWORD i = 0; i<dwReadBytes; ++i) { if (*pTextBuf == '\r') { if ((i + 1) < dwReadBytes) { if (*(pTextBuf+1) == '\n') { // crlf line ending CString line(pLineStart, (int)(pTextBuf-pLineStart)); Add(line, EOL_CRLF); pLineStart = pTextBuf+2; ++pTextBuf; ++i; } else { // cr line ending CString line(pLineStart, (int)(pTextBuf-pLineStart)); Add(line, EOL_CR); pLineStart =pTextBuf+1; } } } else if (*pTextBuf == '\n') { // lf line ending CString line(pLineStart, (int)(pTextBuf-pLineStart)); Add(line, EOL_LF); pLineStart =pTextBuf+1; } ++pTextBuf; } if (pLineStart < pTextBuf) { CString line(pLineStart, (int)(pTextBuf-pLineStart)); Add(line, EOL_NOENDING); m_bReturnAtEnd = false; } else m_bReturnAtEnd = true; delete [] pFileBuf; return TRUE; }