summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/customComboBox.cpp73
-rw-r--r--shared/customComboBox.h29
-rw-r--r--shared/dllLoader.cpp44
-rw-r--r--shared/dllLoader.h40
-rw-r--r--shared/fileHandling.cpp172
-rw-r--r--shared/globalFunctions.h24
-rw-r--r--shared/inotify/inotify-cxx.cpp4
-rw-r--r--shared/localization.cpp12
-rw-r--r--shared/serialize.cpp50
-rw-r--r--shared/serialize.h198
-rw-r--r--shared/shadow.cpp112
-rw-r--r--shared/shadow.h3
-rw-r--r--shared/standardPaths.cpp4
-rw-r--r--shared/standardPaths.h2
-rw-r--r--shared/zstring.cpp65
-rw-r--r--shared/zstring.h3
16 files changed, 700 insertions, 135 deletions
diff --git a/shared/customComboBox.cpp b/shared/customComboBox.cpp
new file mode 100644
index 00000000..f2eec7a9
--- /dev/null
+++ b/shared/customComboBox.cpp
@@ -0,0 +1,73 @@
+#include "customComboBox.h"
+
+
+CustomComboBox::CustomComboBox(wxWindow* parent,
+ wxWindowID id,
+ const wxString& value,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n,
+ const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name) :
+ wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name)
+{
+ //register key event to enable item deletion
+ this->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(CustomComboBox::OnKeyEvent), NULL, this );
+}
+
+
+void CustomComboBox::OnKeyEvent(wxKeyEvent& event)
+{
+ const int keyCode = event.GetKeyCode();
+ if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE)
+ {
+ //try to delete the currently selected config history item
+ const int selectedItem = this->GetCurrentSelection();
+ if (0 <= selectedItem && selectedItem < static_cast<int>(this->GetCount()) &&
+ (GetValue() != GetString(selectedItem) || //avoid problems when letter shall be deleted instead of list item
+ GetValue() == wxEmptyString) //exception: always allow removing empty entry
+ )
+ {
+ //save old (selected) value: deletion seems to have influence on this
+ const wxString currentVal = this->GetValue();
+ this->SetSelection(wxNOT_FOUND);
+
+ //delete selected row
+ this->Delete(selectedItem);
+
+ //(re-)set value
+ this->SetValue(currentVal);
+
+ //eat up key event
+ return;
+ }
+ }
+ event.Skip();
+}
+
+
+void CustomComboBox::addPairToFolderHistory(const wxString& newFolder, unsigned int maxHistSize)
+{
+ const wxString oldVal = this->GetValue();
+
+ //insert new folder or put it to the front if already existing
+#ifdef FFS_WIN //don't respect case in windows build
+ const int pos = FindString(newFolder, false);
+#elif defined FFS_LINUX
+ const int pos = FindString(newFolder, true);
+#endif
+ if (pos != wxNOT_FOUND)
+ this->Delete(pos);
+
+ this->Insert(newFolder, 0);
+
+ //keep maximal size of history list
+ if (this->GetCount() > maxHistSize)
+ this->Delete(maxHistSize);
+
+ this->SetSelection(wxNOT_FOUND); //don't select anything
+ this->SetValue(oldVal); //but preserve main text!
+}
+
diff --git a/shared/customComboBox.h b/shared/customComboBox.h
new file mode 100644
index 00000000..b6af43bf
--- /dev/null
+++ b/shared/customComboBox.h
@@ -0,0 +1,29 @@
+#ifndef CUSTOMCOMBOBOX_H_INCLUDED
+#define CUSTOMCOMBOBOX_H_INCLUDED
+
+#include <wx/combobox.h>
+
+//combobox with history function + functionality to delete items (DEL)
+
+class CustomComboBox : public wxComboBox
+{
+public:
+ CustomComboBox(wxWindow* parent,
+ wxWindowID id,
+ const wxString& value = wxEmptyString,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ int n = 0,
+ const wxString choices[] = (const wxString *) NULL,
+ long style = 0,
+ const wxValidator& validator = wxDefaultValidator,
+ const wxString& name = wxComboBoxNameStr);
+
+ void addPairToFolderHistory(const wxString& newFolder, unsigned int maxHistSize);
+
+private:
+ void OnKeyEvent(wxKeyEvent& event);
+};
+
+
+#endif // CUSTOMCOMBOBOX_H_INCLUDED
diff --git a/shared/dllLoader.cpp b/shared/dllLoader.cpp
new file mode 100644
index 00000000..e37ded54
--- /dev/null
+++ b/shared/dllLoader.cpp
@@ -0,0 +1,44 @@
+#include "dllLoader.h"
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+
+namespace
+{
+class KernelDllHandler //dynamically load "kernel32.dll"
+{
+public:
+ static const KernelDllHandler& getInstance()
+ {
+ static KernelDllHandler instance;
+ return instance;
+ }
+
+ HINSTANCE getHandle() const
+ {
+ return hKernel;
+ }
+
+private:
+ KernelDllHandler() :
+ hKernel(NULL)
+ {
+ //get a handle to the DLL module containing required functionality
+ hKernel = ::LoadLibrary(L"kernel32.dll");
+ }
+
+ ~KernelDllHandler()
+ {
+ if (hKernel) ::FreeLibrary(hKernel);
+ }
+
+ HINSTANCE hKernel;
+};
+}
+
+
+void* Utility::loadSymbolKernel(const std::string& functionName)
+{
+ if (KernelDllHandler::getInstance().getHandle() != NULL)
+ return reinterpret_cast<void*>(::GetProcAddress(KernelDllHandler::getInstance().getHandle(), functionName.c_str()));
+ else
+ return NULL;
+}
diff --git a/shared/dllLoader.h b/shared/dllLoader.h
new file mode 100644
index 00000000..bf62b542
--- /dev/null
+++ b/shared/dllLoader.h
@@ -0,0 +1,40 @@
+#ifndef DLLLOADER_H_INCLUDED
+#define DLLLOADER_H_INCLUDED
+
+#include <string>
+
+namespace Utility
+{
+ //load kernel dll functions
+template <typename FunctionType>
+FunctionType loadDllFunKernel(const std::string& functionName);
+
+
+
+
+
+
+
+
+
+
+
+
+
+//---------------Inline Implementation---------------------------------------------------
+void* loadSymbolKernel(const std::string& functionName);
+
+template <typename FunctionType>
+inline
+FunctionType loadDllFunKernel(const std::string& functionName)
+{
+ return reinterpret_cast<FunctionType>(loadSymbolKernel(functionName));
+}
+
+#ifndef FFS_WIN
+use in windows build only!
+#endif
+
+}
+
+#endif // DLLLOADER_H_INCLUDED
diff --git a/shared/fileHandling.cpp b/shared/fileHandling.cpp
index 495e3d49..4b9901e0 100644
--- a/shared/fileHandling.cpp
+++ b/shared/fileHandling.cpp
@@ -11,8 +11,10 @@
#include <wx/log.h>
#include <wx/datetime.h>
#include "stringConv.h"
+#include <wx/utils.h>
#ifdef FFS_WIN
+#include "dllLoader.h"
#include <wx/msw/wrapwin.h> //includes "windows.h"
#include "shadow.h"
@@ -30,10 +32,70 @@
using FreeFileSync::FileError;
+bool replaceMacro(wxString& macro) //macro without %-characters, return true if replaced successfully
+{
+ if (macro.IsEmpty())
+ return false;
+
+ //there are equally named environment variables %TIME%, %DATE% existing, so replace these first!
+ if (macro.CmpNoCase(wxT("time")) == 0)
+ {
+ macro = wxDateTime::Now().FormatISOTime();
+ macro.Replace(wxT(":"), wxT("-"));
+ return true;
+ }
+
+ if (macro.CmpNoCase(wxT("date")) == 0)
+ {
+ macro = wxDateTime::Now().FormatISODate();
+ return true;
+ }
+
+ //try to apply environment variables
+ wxString envValue;
+ if (wxGetEnv(macro, &envValue))
+ {
+ macro = envValue;
+ return true;
+ }
+
+ return false;
+}
+
+
+void expandMacros(wxString& text)
+{
+ const wxChar SEPARATOR = '%';
+
+ if (text.Find(SEPARATOR) != wxNOT_FOUND)
+ {
+ wxString prefix = text.BeforeFirst(SEPARATOR);
+ wxString postfix = text.AfterFirst(SEPARATOR);
+ if (postfix.Find(SEPARATOR) != wxNOT_FOUND)
+ {
+ wxString potentialMacro = postfix.BeforeFirst(SEPARATOR);
+ wxString rest = postfix.AfterFirst(SEPARATOR); //text == prefix + SEPARATOR + potentialMacro + SEPARATOR + rest
+
+ if (replaceMacro(potentialMacro))
+ {
+ expandMacros(rest);
+ text = prefix + potentialMacro + rest;
+ }
+ else
+ {
+ rest = wxString() + SEPARATOR + rest;
+ expandMacros(rest);
+ text = prefix + SEPARATOR + potentialMacro + rest;
+ }
+ }
+ }
+}
+
+
Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname)
{
//Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names.
- //Also improves usability.
+ //note: don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix!
wxString dirnameTmp = zToWx(dirname);
dirnameTmp.Trim(true); //remove whitespace characters from right
@@ -46,14 +108,8 @@ Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname)
dirnameTmp += zToWx(globalFunctions::FILE_NAME_SEPARATOR);
//replace macros
- wxString timeNow = wxDateTime::Now().FormatISOTime();
- timeNow.Replace(wxT(":"), wxT("-"));
- dirnameTmp.Replace(wxT("%time%"), timeNow.c_str());
-
- const wxString dateToday = wxDateTime::Now().FormatISODate();
- dirnameTmp.Replace(wxT("%date%"), dateToday.c_str());
+ expandMacros(dirnameTmp);
- //don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix
return wxToZ(dirnameTmp);
}
@@ -717,57 +773,16 @@ void FreeFileSync::copyFileTimes(const Zstring& sourceDir, const Zstring& target
#ifdef FFS_WIN
-class KernelDllHandler //dynamically load windows API functions
-{
- typedef DWORD (WINAPI *GetFinalPath)(
- HANDLE hFile,
- LPTSTR lpszFilePath,
- DWORD cchFilePath,
- DWORD dwFlags);
-
-public:
- static const KernelDllHandler& getInstance() //lazy creation of KernelDllHandler
- {
- static KernelDllHandler instance;
-
- if (instance.getFinalPathNameByHandle == NULL)
- throw FileError(wxString(_("Error loading library function:")) + wxT("\n\"") + wxT("GetFinalPathNameByHandleW") + wxT("\""));
-
- return instance;
- }
-
- GetFinalPath getFinalPathNameByHandle;
-
-private:
- KernelDllHandler() :
- getFinalPathNameByHandle(NULL),
- hKernel(NULL)
- {
- //get a handle to the DLL module containing required functionality
- hKernel = ::LoadLibrary(wxT("kernel32.dll"));
- if (hKernel)
- getFinalPathNameByHandle = reinterpret_cast<GetFinalPath>(::GetProcAddress(hKernel, "GetFinalPathNameByHandleW")); //load unicode version!
- }
-
- ~KernelDllHandler()
- {
- if (hKernel) ::FreeLibrary(hKernel);
- }
-
- HINSTANCE hKernel;
-};
-
-
Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target path of symbolic link to a directory
{
//open handle to target of symbolic link
- HANDLE hDir = CreateFile(dirLinkName.c_str(),
- 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- NULL);
+ HANDLE hDir = ::CreateFile(dirLinkName.c_str(),
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
if (hDir == INVALID_HANDLE_VALUE)
return Zstring();
@@ -776,7 +791,20 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa
const unsigned int BUFFER_SIZE = 10000;
TCHAR targetPath[BUFFER_SIZE];
- const DWORD rv = KernelDllHandler::getInstance().getFinalPathNameByHandle(
+
+ //dynamically load windows API function
+ typedef DWORD (WINAPI *GetFinalPathNameByHandleWFunc)(
+ HANDLE hFile,
+ LPTSTR lpszFilePath,
+ DWORD cchFilePath,
+ DWORD dwFlags);
+ static const GetFinalPathNameByHandleWFunc getFinalPathNameByHandle =
+ Utility::loadDllFunKernel<GetFinalPathNameByHandleWFunc>("GetFinalPathNameByHandleW");
+
+ if (getFinalPathNameByHandle == NULL)
+ throw FileError(wxString(_("Error loading library function:")) + wxT("\n\"") + wxT("GetFinalPathNameByHandleW") + wxT("\""));
+
+ const DWORD rv = (*getFinalPathNameByHandle)(
hDir,
targetPath,
BUFFER_SIZE,
@@ -987,7 +1015,7 @@ void FreeFileSync::createDirectory(const Zstring& directory, const Zstring& temp
Zstring createTempName(const Zstring& filename)
{
- Zstring output = filename + DefaultStr(".tmp");
+ Zstring output = filename + DefaultStr(".ffs_tmp");
//ensure uniqueness
if (FreeFileSync::fileExists(output))
@@ -1007,7 +1035,7 @@ Zstring createTempName(const Zstring& filename)
#ifdef FFS_WIN
#ifndef COPY_FILE_COPY_SYMLINK
-const DWORD COPY_FILE_COPY_SYMLINK = 0x00000800;
+#define COPY_FILE_COPY_SYMLINK 0x00000800
#endif
DWORD CALLBACK copyCallbackInternal(
@@ -1063,7 +1091,26 @@ bool supportForSymbolicLinks()
//symbolic links are supported starting with Vista
if (GetVersionEx(&osvi))
return osvi.dwMajorVersion > 5; //XP has majorVersion == 5, minorVersion == 1, Vista majorVersion == 6
+ //overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
+ return false;
+}
+
+#ifndef COPY_FILE_ALLOW_DECRYPTED_DESTINATION
+#define COPY_FILE_ALLOW_DECRYPTED_DESTINATION 0x00000008
+#endif
+
+
+bool supportForNonEncryptedDestination()
+{
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ //symbolic links are supported starting with Vista
+ if (GetVersionEx(&osvi))
+ return osvi.dwMajorVersion >= 5 && osvi.dwMinorVersion >= 1; //XP has majorVersion == 5, minorVersion == 1, Vista majorVersion == 6
+ //overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
return false;
}
@@ -1081,6 +1128,12 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
if (copyFileSymLinks && symlinksSupported)
copyFlags |= COPY_FILE_COPY_SYMLINK;
+ //allow copying from encrypted to non-encrytped location
+ static const bool nonEncSupported = supportForNonEncryptedDestination();
+ if (nonEncSupported)
+ copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION;
+
+
const Zstring temporary = createTempName(targetFile); //use temporary file until a correct date has been set
if (!::CopyFileEx( //same performance as CopyFile()
sourceFile.c_str(),
@@ -1312,3 +1365,4 @@ bool FreeFileSync::isFatDrive(const Zstring& directoryName)
}
#endif //FFS_WIN
*/
+
diff --git a/shared/globalFunctions.h b/shared/globalFunctions.h
index 74387959..06238236 100644
--- a/shared/globalFunctions.h
+++ b/shared/globalFunctions.h
@@ -10,10 +10,7 @@
#include <memory>
#include <sstream>
#include <fstream>
-#include <wx/stream.h>
-class wxInputStream;
-class wxOutputStream;
class wxStopWatch;
@@ -61,9 +58,6 @@ unsigned int getDigitCount(const unsigned int number); //count number of digits
template <class T> T readNumber(std::ifstream& stream);
template <class T> void writeNumber(std::ofstream& stream, T number);
-template <class T> T readNumber(wxInputStream& stream);
-template <class T> void writeNumber(wxOutputStream& stream, T number);
-
inline
wxLongLong convertToSigned(const wxULongLong number)
{
@@ -221,24 +215,6 @@ void globalFunctions::writeNumber(std::ofstream& stream, T number)
}
-template <class T>
-inline
-T globalFunctions::readNumber(wxInputStream& stream)
-{
- T result = 0;
- stream.Read(&result, sizeof(T));
- return result;
-}
-
-
-template <class T>
-inline
-void globalFunctions::writeNumber(wxOutputStream& stream, T number)
-{
- stream.Write(&number, sizeof(T));
-}
-
-
inline
wxString globalFunctions::numberToWxString(const unsigned int number)
{
diff --git a/shared/inotify/inotify-cxx.cpp b/shared/inotify/inotify-cxx.cpp
index 7870e825..7c523afb 100644
--- a/shared/inotify/inotify-cxx.cpp
+++ b/shared/inotify/inotify-cxx.cpp
@@ -18,7 +18,9 @@
* please visit http://www.gnu.org/licenses/license-list.html.
*
*/
-
+
+//added by ZenJu
+#include <cstdio>
#include <errno.h>
#include <unistd.h>
diff --git a/shared/localization.cpp b/shared/localization.cpp
index ff14c980..ad3cbb99 100644
--- a/shared/localization.cpp
+++ b/shared/localization.cpp
@@ -127,6 +127,13 @@ LocalizationInfo::LocalizationInfo()
newEntry.languageFlag = wxT("slovakia.png");
locMapping.push_back(newEntry);
+ newEntry.languageID = wxLANGUAGE_FINNISH;
+ newEntry.languageName = wxT("Suomi");
+ newEntry.languageFile = wxT("finnish.lng");
+ newEntry.translatorName = wxT("Nalle Juslén");
+ newEntry.languageFlag = wxT("finland.png");
+ locMapping.push_back(newEntry);
+
newEntry.languageID = wxLANGUAGE_TURKISH;
newEntry.languageName = wxT("Türkçe");
newEntry.languageFile = wxT("turkish.lng");
@@ -224,6 +231,7 @@ int mapLanguageDialect(const int language)
return wxLANGUAGE_SPANISH;
//case wxLANGUAGE_CZECH:
+ //case wxLANGUAGE_FINNISH:
//case wxLANGUAGE_JAPANESE:
//case wxLANGUAGE_POLISH:
//case wxLANGUAGE_SLOVENIAN:
@@ -378,8 +386,8 @@ void CustomLocale::setLanguage(const int language)
translationDB->clear();
if (!languageFile.empty())
{
- UnicodeFileReader langFile(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) +
- wxT("Languages") + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + languageFile);
+ UnicodeFileReader langFile(FreeFileSync::getInstallationDir() + wxT("Languages") +
+ zToWx(globalFunctions::FILE_NAME_SEPARATOR) + languageFile);
if (langFile.isOkay())
{
int rowNumber = 0;
diff --git a/shared/serialize.cpp b/shared/serialize.cpp
new file mode 100644
index 00000000..616d244d
--- /dev/null
+++ b/shared/serialize.cpp
@@ -0,0 +1,50 @@
+#include "serialize.h"
+#include <wx/intl.h>
+
+using namespace Utility;
+
+
+void ReadInputStream::throwReadError() //throw FileError()
+{
+ throw FreeFileSync::FileError(wxString(_("Error reading from synchronization database:")) + wxT(" \n") +
+ wxT("\"") + errorObjName_ + wxT("\""));
+}
+
+
+ReadInputStream::CharArray ReadInputStream::readArrayC()
+{
+ CharArray buffer(new std::vector<char>);
+ const size_t byteCount = readNumberC<size_t>();
+ if (byteCount > 0)
+ {
+ buffer->resize(byteCount);
+ stream_.Read(&(*buffer)[0], byteCount);
+ check();
+ if (stream_.LastRead() != byteCount) //some additional check
+ throwReadError();
+ }
+ return buffer;
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+void WriteOutputStream::throwWriteError() //throw FileError()
+{
+ throw FreeFileSync::FileError(wxString(_("Error writing to synchronization database:")) + wxT(" \n") +
+ wxT("\"") + errorObjName_ + wxT("\""));
+}
+
+
+void WriteOutputStream::writeArrayC(const std::vector<char>& buffer)
+{
+ writeNumberC<size_t>(buffer.size());
+ if (buffer.size() > 0)
+ {
+ stream_.Write(&buffer[0], buffer.size());
+ check();
+ if (stream_.LastWrite() != buffer.size()) //some additional check
+ throwWriteError();
+ }
+}
+
+
diff --git a/shared/serialize.h b/shared/serialize.h
new file mode 100644
index 00000000..85f57370
--- /dev/null
+++ b/shared/serialize.h
@@ -0,0 +1,198 @@
+#ifndef SERIALIZE_H_INCLUDED
+#define SERIALIZE_H_INCLUDED
+
+#include "zstring.h"
+#include <wx/stream.h>
+#include "fileError.h"
+#include <boost/scoped_array.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace Utility
+{
+template <class T>
+T readNumber(wxInputStream& stream);
+
+template <class T>
+void writeNumber(wxOutputStream& stream, T number);
+
+
+Zstring readString(wxInputStream& stream);
+void writeString(wxOutputStream& stream, const Zstring& str);
+
+
+class ReadInputStream //throw FileError()
+{
+protected:
+ ReadInputStream(wxInputStream& stream, const wxString& errorObjName) : stream_(stream), errorObjName_(errorObjName) {}
+
+ template <class T>
+ T readNumberC(); //checked read operation
+
+ Zstring readStringC(); //checked read operation
+
+ typedef boost::shared_ptr<std::vector<char> > CharArray;
+ CharArray readArrayC();
+
+ void check();
+
+protected:
+ wxInputStream& stream_;
+
+private:
+ void throwReadError(); //throw FileError()
+ const wxString& errorObjName_; //used for error text only
+};
+
+
+class WriteOutputStream //throw FileError()
+{
+protected:
+ WriteOutputStream(const wxString& errorObjName, wxOutputStream& stream) : stream_(stream), errorObjName_(errorObjName) {}
+
+ template <class T>
+ void writeNumberC(T number); //checked write operation
+
+ void writeStringC(const Zstring& str); //checked write operation
+
+ void writeArrayC(const std::vector<char>& buffer);
+
+ void check();
+
+protected:
+ wxOutputStream& stream_;
+
+private:
+ void throwWriteError(); //throw FileError()
+ const wxString& errorObjName_; //used for error text only!
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//---------------Inline Implementation---------------------------------------------------
+template <class T>
+inline
+T readNumber(wxInputStream& stream)
+{
+ T result = 0;
+ stream.Read(&result, sizeof(T));
+ return result;
+}
+
+
+template <class T>
+inline
+void writeNumber(wxOutputStream& stream, T number)
+{
+ stream.Write(&number, sizeof(T));
+}
+
+
+inline
+Zstring readString(wxInputStream& stream) //read string from file stream
+{
+ const size_t strLength = readNumber<size_t>(stream);
+ if (strLength <= 1000)
+ {
+ DefaultChar buffer[1000];
+ stream.Read(buffer, sizeof(DefaultChar) * strLength);
+ return Zstring(buffer, strLength);
+ }
+ else
+ {
+ boost::scoped_array<DefaultChar> buffer(new DefaultChar[strLength]);
+ stream.Read(buffer.get(), sizeof(DefaultChar) * strLength);
+ return Zstring(buffer.get(), strLength);
+ }
+}
+
+
+inline
+void writeString(wxOutputStream& stream, const Zstring& str) //write string to filestream
+{
+ writeNumber<size_t>(stream, str.length());
+ stream.Write(str.c_str(), sizeof(DefaultChar) * str.length());
+}
+
+
+inline
+void ReadInputStream::check()
+{
+ if (stream_.GetLastError() != wxSTREAM_NO_ERROR)
+ throwReadError();
+}
+
+
+template <class T>
+inline
+T ReadInputStream::readNumberC() //checked read operation
+{
+ T output = readNumber<T>(stream_);
+ check();
+ return output;
+}
+
+
+inline
+Zstring ReadInputStream::readStringC() //checked read operation
+{
+ Zstring output = readString(stream_);
+ check();
+ return output;
+}
+
+
+template <class T>
+inline
+void WriteOutputStream::writeNumberC(T number) //checked write operation
+{
+ writeNumber<T>(stream_, number);
+ check();
+}
+
+
+inline
+void WriteOutputStream::writeStringC(const Zstring& str) //checked write operation
+{
+ writeString(stream_, str);
+ check();
+}
+
+
+
+inline
+void WriteOutputStream::check()
+{
+ if (stream_.GetLastError() != wxSTREAM_NO_ERROR)
+ throwWriteError();
+}
+
+
+}
+
+#endif // SERIALIZE_H_INCLUDED
diff --git a/shared/shadow.cpp b/shared/shadow.cpp
index da7cfd99..29eec53b 100644
--- a/shared/shadow.cpp
+++ b/shared/shadow.cpp
@@ -6,7 +6,43 @@
using FreeFileSync::ShadowCopy;
-class ShadowlDllHandler //dynamically load windows API functions
+bool newerThanXP()
+{
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ //symbolic links are supported starting with Vista
+ if (GetVersionEx(&osvi))
+ return osvi.dwMajorVersion > 5 ||
+ (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion > 1) ;
+ //XP has majorVersion == 5, minorVersion == 1
+ //Server 2003 has majorVersion == 5, minorVersion == 2
+ //version overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
+ return false;
+}
+
+
+bool runningWOW64() //test if process is running under WOW64 (reference http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx)
+{
+ typedef BOOL (WINAPI *IsWow64ProcessFunc)(
+ HANDLE hProcess,
+ PBOOL Wow64Process);
+
+ const IsWow64ProcessFunc isWow64Process = reinterpret_cast<IsWow64ProcessFunc>(
+ ::GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"));
+ if (isWow64Process != NULL)
+ {
+ BOOL isWow64 = FALSE;
+ if ((*isWow64Process)(::GetCurrentProcess(), &isWow64))
+ return isWow64 == TRUE;
+ }
+
+ return false;
+}
+
+
+class ShadowCopy::ShadowlDllHandler //dynamically load windows API functions
{
typedef bool (*CreateShadowCopyFct)( //volumeName must end with "\", while shadowVolName does not end with "\"
const wchar_t* volumeName,
@@ -19,23 +55,33 @@ class ShadowlDllHandler //dynamically load windows API functions
typedef void (*ReleaseShadowCopyFct)(void* backupHandle);
public:
- static const ShadowlDllHandler& getInstance()
+ static const wxString& getShadowDllName()
{
- static ShadowlDllHandler instance;
- return instance;
+ /*
+ distinguish a bunch of VSS builds: we use XP and Server 2003 implementations...
+ VSS version and compatibility overview: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx
+ */
+#if defined _WIN64 //note: _WIN32 is defined for 64-bit compilations, too, while _WIN64 only for 64-bit
+ static const wxString filename(newerThanXP() ?
+ wxT("Shadow_Server2003_x64.dll") :
+ wxT("Shadow_XP_x64.dll"));
+#elif defined(_WIN32)
+ static const wxString filename(newerThanXP() ?
+ wxT("Shadow_Server2003_win32.dll") :
+ wxT("Shadow_XP_win32.dll"));
+#else
+ Are we at 128 bit already?
+#endif
+ return filename;
}
- CreateShadowCopyFct createShadowCopy;
- ReleaseShadowCopyFct releaseShadowCopy;
-
-private:
ShadowlDllHandler() :
createShadowCopy(NULL),
releaseShadowCopy(NULL),
hShadow(NULL)
{
//get a handle to the DLL module containing the required functionality
- hShadow = ::LoadLibrary(L"Shadow.dll");
+ hShadow = ::LoadLibrary(getShadowDllName().c_str());
if (hShadow)
{
createShadowCopy = reinterpret_cast<CreateShadowCopyFct>(::GetProcAddress(hShadow, "createShadowCopy"));
@@ -48,41 +94,56 @@ private:
if (hShadow) ::FreeLibrary(hShadow);
}
+ CreateShadowCopyFct createShadowCopy;
+ ReleaseShadowCopyFct releaseShadowCopy;
+
+private:
HINSTANCE hShadow;
};
+//#############################################################################################################
ShadowCopy::ShadowCopy() :
- backupHandle(NULL) {}
+ backupHandle(NULL)
+{
+ shadowDll = new ShadowlDllHandler;
+}
ShadowCopy::~ShadowCopy()
{
if (backupHandle != NULL)
- ShadowlDllHandler::getInstance().releaseShadowCopy(backupHandle);
-}
-
+ shadowDll->releaseShadowCopy(backupHandle);
-bool ShadowCopy::isOkay()
-{
- //check that all functions could be loaded
- return ShadowlDllHandler::getInstance().createShadowCopy != NULL &&
- ShadowlDllHandler::getInstance().releaseShadowCopy != NULL;
+ delete shadowDll;
}
Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile)
{
//check if shadow copy dll was loaded correctly
- if (!isOkay())
+ if ( shadowDll->createShadowCopy == NULL ||
+ shadowDll->releaseShadowCopy == NULL)
{
wxString errorMsg = _("Error copying locked file %x!");
errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\""));
throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") +
- _("Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature."));
+ _("Could not load a required DLL:") + wxT(" \"") + ShadowlDllHandler::getShadowDllName() + wxT("\""));
+ }
+
+ //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003
+ //(Reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx)
+ static const bool wow64Active = runningWOW64();
+ if (wow64Active)
+ {
+ wxString errorMsg = _("Error copying locked file %x!");
+ errorMsg.Replace(wxT("%x"), wxString(wxT("\"")) + inputFile.c_str() + wxT("\""));
+ throw FileError(errorMsg + wxT("\n\n") + _("Error starting Volume Shadow Copy Service!") + wxT("\n") +
+ _("Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version."));
}
+//---------------------------------------------------------------------------------------------------------
wchar_t volumeNameRaw[1000];
if (!GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName,
@@ -103,7 +164,7 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile)
//release old shadow copy
if (backupHandle != NULL)
{
- ShadowlDllHandler::getInstance().releaseShadowCopy(backupHandle);
+ shadowDll->releaseShadowCopy(backupHandle);
backupHandle = NULL;
}
realVolumeLast.clear(); //...if next call fails...
@@ -114,7 +175,7 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile)
void* backupHandleTmp = NULL;
wchar_t errorMessage[1000];
- if (!ShadowlDllHandler::getInstance().createShadowCopy(
+ if (!shadowDll->createShadowCopy(
volumeNameFormatted.c_str(),
shadowVolName,
1000,
@@ -149,10 +210,3 @@ Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile)
}
-
-
-
-
-
-
-
diff --git a/shared/shadow.h b/shared/shadow.h
index ddb329bd..79e0e59c 100644
--- a/shared/shadow.h
+++ b/shared/shadow.h
@@ -23,7 +23,8 @@ private:
ShadowCopy(const ShadowCopy&);
ShadowCopy& operator=(const ShadowCopy&);
- bool isOkay();
+ class ShadowlDllHandler;
+ const ShadowlDllHandler* shadowDll;
Zstring realVolumeLast; //buffer last volume name
Zstring shadowVolumeLast; //buffer last created shadow volume
diff --git a/shared/standardPaths.cpp b/shared/standardPaths.cpp
index 3d5cfdb5..3c57f5b9 100644
--- a/shared/standardPaths.cpp
+++ b/shared/standardPaths.cpp
@@ -9,7 +9,7 @@ using namespace FreeFileSync;
wxString assembleFileForUserData(const wxString fileName)
{
- static const bool isPortableVersion = !wxFileExists(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("uninstall.exe")); //this check is a bit lame...
+ static const bool isPortableVersion = !wxFileExists(FreeFileSync::getInstallationDir() + wxT("uninstall.exe")); //this check is a bit lame...
if (isPortableVersion) //use current working directory
return wxString(wxT(".")) + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + fileName;
@@ -51,7 +51,7 @@ const wxString& FreeFileSync::getLastErrorTxtFile()
const wxString& FreeFileSync::getInstallationDir()
{
- static wxString instance = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath();
+ static wxString instance = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath() + zToWx(globalFunctions::FILE_NAME_SEPARATOR);
return instance;
}
diff --git a/shared/standardPaths.h b/shared/standardPaths.h
index 34f6ab48..2af802a9 100644
--- a/shared/standardPaths.h
+++ b/shared/standardPaths.h
@@ -12,7 +12,7 @@ namespace FreeFileSync
const wxString& getGlobalConfigFile();
const wxString& getDefaultLogDirectory();
const wxString& getLastErrorTxtFile();
-const wxString& getInstallationDir(); //FreeFileSync installation directory without path separator
+const wxString& getInstallationDir(); //FreeFileSync installation directory WITH path separator at end
const wxString& getConfigDir();
//------------------------------------------------------------------------------
}
diff --git a/shared/zstring.cpp b/shared/zstring.cpp
index 04c79b6f..cb288ea2 100644
--- a/shared/zstring.cpp
+++ b/shared/zstring.cpp
@@ -3,6 +3,7 @@
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include "dllLoader.h"
#endif //FFS_WIN
#ifdef __WXDEBUG__
@@ -46,24 +47,58 @@ AllocationCount& AllocationCount::getInstance()
#ifdef FFS_WIN
+
+#ifndef LOCALE_INVARIANT
+#define LOCALE_INVARIANT 0x007f
+#endif
+
+
inline
int compareStringsWin32(const wchar_t* a, const wchar_t* b, const int aCount = -1, const int bCount = -1)
{
- //DON'T use lstrcmpi() here! It uses word sort, which unfortunately is NOT always a strict weak sorting function for some locales (e.g. swedish)
- //Use CompareString() with "SORT_STRINGSORT" instead!!!
-
- const int rv = CompareString(
- LOCALE_USER_DEFAULT, //locale identifier
- NORM_IGNORECASE | SORT_STRINGSORT, //comparison-style options
- a, //pointer to first string
- aCount, //size, in bytes or characters, of first string
- b, //pointer to second string
- bCount); //size, in bytes or characters, of second string
-
- if (rv == 0)
- throw std::runtime_error("Error comparing strings!");
- else
- return rv - 2; //convert to C-style string compare result
+ //try to call "CompareStringOrdinal" first for low-level string comparison: unfortunately available not before Windows Vista!
+ typedef int (WINAPI *CompareStringOrdinalFunc)(
+ LPCWSTR lpString1,
+ int cchCount1,
+ LPCWSTR lpString2,
+ int cchCount2,
+ BOOL bIgnoreCase);
+ static const CompareStringOrdinalFunc ordinalCompare = Utility::loadDllFunKernel<CompareStringOrdinalFunc>("CompareStringOrdinal");
+
+
+ //we're lucky here! This additional test for "CompareStringOrdinal" has no noticeable performance impact!!
+ if (ordinalCompare != NULL)
+ {
+ const int rv = (*ordinalCompare)(
+ a, //pointer to first string
+ aCount, //size, in bytes or characters, of first string
+ b, //pointer to second string
+ bCount, //size, in bytes or characters, of second string
+ true); //ignore case
+
+ if (rv == 0)
+ throw std::runtime_error("Error comparing strings (ordinal)!");
+ else
+ return rv - 2; //convert to C-style string compare result
+ }
+ else //fallback to "CompareString". Attention: this function is NOT accurate: for example "weiß" == "weiss"!!!
+ {
+ //DON'T use lstrcmpi() here! It uses word sort and is locale dependent!
+ //Use CompareString() with "SORT_STRINGSORT" instead!!!
+
+ const int rv = CompareString(
+ LOCALE_INVARIANT, //locale independent
+ NORM_IGNORECASE | SORT_STRINGSORT, //comparison-style options
+ a, //pointer to first string
+ aCount, //size, in bytes or characters, of first string
+ b, //pointer to second string
+ bCount); //size, in bytes or characters, of second string
+
+ if (rv == 0)
+ throw std::runtime_error("Error comparing strings!");
+ else
+ return rv - 2; //convert to C-style string compare result
+ }
}
#endif
diff --git a/shared/zstring.h b/shared/zstring.h
index 68b72060..d0be30bf 100644
--- a/shared/zstring.h
+++ b/shared/zstring.h
@@ -61,7 +61,7 @@ public:
Zstring BeforeLast( DefaultChar ch) const; //returns empty string if ch not found
Zstring AfterFirst( DefaultChar ch) const; //returns empty string if ch not found
Zstring BeforeFirst(DefaultChar ch) const; //returns the whole string if ch not found
- size_t Find(DefaultChar ch, bool fromEnd) const;
+ size_t Find(DefaultChar ch, bool fromEnd) const; //returns npos if not found
bool Matches(const DefaultChar* mask) const;
static bool Matches(const DefaultChar* name, const DefaultChar* mask);
Zstring& Trim(bool fromRight); //from right or left
@@ -333,6 +333,7 @@ Zstring::~Zstring()
inline
void Zstring::initAndCopy(const DefaultChar* source, size_t sourceLen)
{
+ assert(source);
descr = allocate(sourceLen);
::memcpy(data(), source, sourceLen * sizeof(DefaultChar));
data()[sourceLen] = 0;
bgstack15