Index: src/shared/Utils.cpp |
=================================================================== |
--- a/src/shared/Utils.cpp |
+++ b/src/shared/Utils.cpp |
@@ -1,61 +1,109 @@ |
#include <memory> |
#include <stdexcept> |
+#include <vector> |
#include <Windows.h> |
#include <ShlObj.h> |
#include "Utils.h" |
namespace |
{ |
+ // See http://blogs.msdn.com/b/oldnewthing/archive/2004/10/25/247180.aspx |
+ EXTERN_C IMAGE_DOS_HEADER __ImageBase; |
+ |
std::wstring appDataPath; |
bool IsWindowsVistaOrLater() |
{ |
OSVERSIONINFOEX osvi; |
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); |
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); |
GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osvi)); |
return osvi.dwMajorVersion >= 6; |
} |
} |
-std::string ToUtf8String(std::wstring str) |
+std::string ToUtf8String(const std::wstring& str) |
{ |
size_t length = str.size(); |
if (length == 0) |
return std::string(); |
DWORD utf8StringLength = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), length, 0, 0, 0, 0); |
if (utf8StringLength == 0) |
throw std::runtime_error("Failed to determine the required buffer size"); |
std::string utf8String(utf8StringLength, '\0'); |
WideCharToMultiByte(CP_UTF8, 0, str.c_str(), length, &utf8String[0], utf8StringLength, 0, 0); |
return utf8String; |
} |
+std::wstring ToUtf16String(const std::string& str) |
+{ |
+ size_t length = str.size(); |
+ if (length == 0) |
+ return std::wstring(); |
+ |
+ DWORD utf16StringLength = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), length, NULL, 0); |
+ if (utf16StringLength == 0) |
+ throw std::runtime_error("ToUTF16String failed. Can't determine the length of the buffer needed."); |
+ |
+ std::wstring utf16String(utf16StringLength, L'\0'); |
+ MultiByteToWideChar(CP_UTF8, 0, str.c_str(), length, &utf16String[0], utf16StringLength); |
+ return utf16String; |
+} |
+ |
+std::wstring GetDllDir() |
+{ |
+ std::vector<WCHAR> path(MAX_PATH); |
+ DWORD length = GetModuleFileNameW((HINSTANCE)&__ImageBase, &path[0], path.size()); |
+ |
+ while (length == path.size()) |
+ { |
+ // Buffer too small, double buffer size |
+ path.resize(path.size() * 2); |
+ length = GetModuleFileNameW((HINSTANCE)&__ImageBase, &path[0], path.size()); |
+ } |
+ |
+ try |
+ { |
+ if (length == 0) |
+ throw std::runtime_error("Failed determining module path"); |
+ |
+ std::vector<WCHAR>::reverse_iterator it = std::find(path.rbegin(), path.rend(), L'\\'); |
+ if (it == path.rend()) |
+ throw std::runtime_error("Unexpected plugin path, no backslash found"); |
+ |
+ return std::wstring(path.begin(), it.base()); |
+ } |
+ catch (const std::exception&) |
+ { |
+ return std::wstring(); |
+ } |
+} |
+ |
std::wstring GetAppDataPath() |
{ |
if (appDataPath.empty()) |
{ |
if (IsWindowsVistaOrLater()) |
{ |
WCHAR* pathBuffer; |
if (FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, 0, &pathBuffer))) |
throw std::runtime_error("Unable to find app data directory"); |
appDataPath.assign(pathBuffer); |
CoTaskMemFree(pathBuffer); |
} |
else |
{ |
std::auto_ptr<wchar_t> pathBuffer(new wchar_t[MAX_PATH]); |
- if (!SHGetSpecialFolderPath(0, pathBuffer.get(), CSIDL_LOCAL_APPDATA, true)) |
+ if (!SHGetSpecialFolderPathW(0, pathBuffer.get(), CSIDL_LOCAL_APPDATA, true)) |
throw std::runtime_error("Unable to find app data directory"); |
appDataPath.assign(pathBuffer.get()); |
} |
appDataPath += L"\\Adblock Plus for IE"; |
// Ignore errors here, this isn't a critical operation |
::CreateDirectoryW(appDataPath.c_str(), NULL); |
} |