diff --git a/MemoryModule.c b/MemoryModule.c
index cf38388..817ccef 100644
--- a/MemoryModule.c
+++ b/MemoryModule.c
@@ -27,7 +27,6 @@
 #include <windows.h>
 #include <winnt.h>
 #include <stddef.h>
-#include <tchar.h>
 #ifdef DEBUG_OUTPUT
 #include <stdio.h>
 #endif
@@ -792,28 +791,95 @@ int MemoryCallEntryPoint(HMEMORYMODULE mod)
 
 #define DEFAULT_LANGUAGE        MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
 
-HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type)
+HMEMORYRSRC MemoryFindResourceA(HMEMORYMODULE module, LPCSTR name, LPCSTR type)
 {
-    return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE);
+    return MemoryFindResourceExA(module, name, type, DEFAULT_LANGUAGE);
 }
 
-static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(
+HMEMORYRSRC MemoryFindResourceW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type)
+{
+    return MemoryFindResourceExW(module, name, type, DEFAULT_LANGUAGE);
+}
+
+static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryById(
+    PIMAGE_RESOURCE_DIRECTORY resources,
+    WORD id)
+{
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1);
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;
+    DWORD start = resources->NumberOfNamedEntries;
+    DWORD end = start + resources->NumberOfIdEntries;
+
+    while (end > start) {
+        DWORD middle = (start + end) >> 1;
+        WORD entryName = (WORD) entries[middle].Name;
+        if (id < entryName) {
+            end = (end != middle ? middle : middle-1);
+        } else if (id > entryName) {
+            start = (start != middle ? middle : middle+1);
+        } else {
+            result = &entries[middle];
+            break;
+        }
+    }
+    return result;
+}
+
+static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryByString(
     void *root,
     PIMAGE_RESOURCE_DIRECTORY resources,
-    LPCTSTR key)
+    LPCWSTR key,
+    size_t keylen)
 {
     PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1);
     PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;
-    DWORD start;
-    DWORD end;
-    DWORD middle;
+    DWORD start = 0;
+    DWORD end = resources->NumberOfNamedEntries;
+
+    while (end > start) {
+        DWORD middle = (start + end) >> 1;
+        PIMAGE_RESOURCE_DIR_STRING_U resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF);
+        int cmp = _wcsnicmp(key, resourceString->NameString, resourceString->Length);
+        if (cmp == 0) {
+            // Handle partial match
+            if (keylen > (size_t) resourceString->Length) {
+                cmp = 1;
+            } else if (keylen < (size_t) resourceString->Length) {
+                cmp = -1;
+            }
+        }
+        if (cmp < 0) {
+            end = (middle != end ? middle : middle-1);
+        } else if (cmp > 0) {
+            start = (middle != start ? middle : middle+1);
+        } else {
+            result = &entries[middle];
+            break;
+        }
+    }
+
+    return result;
+}
+
+static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryA(
+    void *root,
+    PIMAGE_RESOURCE_DIRECTORY resources,
+    LPCSTR key)
+{
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;
+    size_t searchKeyLen;
+#define MAX_LOCAL_KEY_LENGTH 2048
+    // In most cases resource names are short, so optimize for that by
+    // using a pre-allocated array.
+    wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1];
+    LPWSTR _searchKey;
 
-    if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) {
+    if (!IS_INTRESOURCE(key) && key[0] == '#') {
         // special case: resource id given as string
-        TCHAR *endpos = NULL;
-        long int tmpkey = (WORD) _tcstol((TCHAR *) &key[1], &endpos, 10);
-        if (tmpkey <= 0xffff && lstrlen(endpos) == 0) {
-            key = MAKEINTRESOURCE(tmpkey);
+        char *endpos = NULL;
+        long int tmpkey = (WORD) strtol(key + 1, &endpos, 10);
+        if (tmpkey <= 0xffff && strlen(endpos) == 0) {
+            key = MAKEINTRESOURCEA(tmpkey);
         }
     }
 
@@ -821,88 +887,112 @@ static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(
     // followed by an ordered list of id entries - we can do
     // a binary search to find faster...
     if (IS_INTRESOURCE(key)) {
-        WORD check = (WORD) (uintptr_t) key;
-        start = resources->NumberOfNamedEntries;
-        end = start + resources->NumberOfIdEntries;
-
-        while (end > start) {
-            WORD entryName;
-            middle = (start + end) >> 1;
-            entryName = (WORD) entries[middle].Name;
-            if (check < entryName) {
-                end = (end != middle ? middle : middle-1);
-            } else if (check > entryName) {
-                start = (start != middle ? middle : middle+1);
-            } else {
-                result = &entries[middle];
-                break;
-            }
+        return _MemorySearchResourceEntryById(resources, (WORD) (uintptr_t) key);
+    }
+
+    // Resource names are always stored using 16bit characters, need to
+    // convert string we search for.
+    searchKeyLen = strlen(key);
+    if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) {
+        size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t);
+        _searchKey = (LPWSTR) malloc(_searchKeySize);
+        if (_searchKey == NULL) {
+            SetLastError(ERROR_OUTOFMEMORY);
+            return NULL;
         }
     } else {
-        LPCWSTR searchKey;
-        size_t searchKeyLen = _tcslen(key);
-#if defined(UNICODE)
-        searchKey = key;
-#else
-        // Resource names are always stored using 16bit characters, need to
-        // convert string we search for.
-#define MAX_LOCAL_KEY_LENGTH 2048
-        // In most cases resource names are short, so optimize for that by
-        // using a pre-allocated array.
-        wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH+1];
-        LPWSTR _searchKey;
-        if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) {
-            size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t);
-            _searchKey = (LPWSTR) malloc(_searchKeySize);
-            if (_searchKey == NULL) {
-                SetLastError(ERROR_OUTOFMEMORY);
-                return NULL;
-            }
-        } else {
-            _searchKey = &_searchKeySpace[0];
-        }
+        _searchKey = &_searchKeySpace[0];
+    }
+    mbstowcs(_searchKey, key, searchKeyLen);
+    _searchKey[searchKeyLen] = 0;
 
-        mbstowcs(_searchKey, key, searchKeyLen);
-        _searchKey[searchKeyLen] = 0;
-        searchKey = _searchKey;
-#endif
-        start = 0;
-        end = resources->NumberOfNamedEntries;
-        while (end > start) {
-            int cmp;
-            PIMAGE_RESOURCE_DIR_STRING_U resourceString;
-            middle = (start + end) >> 1;
-            resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(root, entries[middle].Name & 0x7FFFFFFF);
-            cmp = _wcsnicmp(searchKey, resourceString->NameString, resourceString->Length);
-            if (cmp == 0) {
-                // Handle partial match
-                if (searchKeyLen > resourceString->Length) {
-                    cmp = 1;
-                } else if (searchKeyLen < resourceString->Length) {
-                    cmp = -1;
-                }
-            }
-            if (cmp < 0) {
-                end = (middle != end ? middle : middle-1);
-            } else if (cmp > 0) {
-                start = (middle != start ? middle : middle+1);
-            } else {
-                result = &entries[middle];
-                break;
-            }
+    result = _MemorySearchResourceEntryByString(root, resources, _searchKey, searchKeyLen);
+    if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) {
+        free(_searchKey);
+    }
+#undef MAX_LOCAL_KEY_LENGTH
+    return result;
+}
+
+static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntryW(
+    void *root,
+    PIMAGE_RESOURCE_DIRECTORY resources,
+    LPCWSTR key)
+{
+    if (!IS_INTRESOURCE(key) && key[0] == L'#') {
+        // special case: resource id given as string
+        wchar_t *endpos = NULL;
+        long int tmpkey = (WORD) wcstol(key + 1, &endpos, 10);
+        if (tmpkey <= 0xffff && wcslen(endpos) == 0) {
+            key = MAKEINTRESOURCEW(tmpkey);
         }
-#if !defined(UNICODE)
-        if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) {
-            free(_searchKey);
+    }
+
+    // entries are stored as ordered list of named entries,
+    // followed by an ordered list of id entries - we can do
+    // a binary search to find faster...
+    if (IS_INTRESOURCE(key)) {
+        return _MemorySearchResourceEntryById(resources, (WORD) (uintptr_t) key);
+    }
+
+    return _MemorySearchResourceEntryByString(root, resources, key, wcslen(key));
+}
+
+HMEMORYRSRC MemoryFindResourceExA(HMEMORYMODULE module, LPCSTR name, LPCSTR type, WORD language)
+{
+    unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;
+    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE);
+    PIMAGE_RESOURCE_DIRECTORY rootResources;
+    PIMAGE_RESOURCE_DIRECTORY nameResources;
+    PIMAGE_RESOURCE_DIRECTORY typeResources;
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType;
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName;
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage;
+    if (directory->Size == 0) {
+        // no resource table found
+        SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
+        return NULL;
+    }
+
+    if (language == DEFAULT_LANGUAGE) {
+        // use language from current thread
+        language = LANGIDFROMLCID(GetThreadLocale());
+    }
+
+    // resources are stored as three-level tree
+    // - first node is the type
+    // - second node is the name
+    // - third node is the language
+    rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress);
+    foundType = _MemorySearchResourceEntryA(rootResources, rootResources, type);
+    if (foundType == NULL) {
+        SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
+        return NULL;
+    }
+
+    typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff));
+    foundName = _MemorySearchResourceEntryA(rootResources, typeResources, name);
+    if (foundName == NULL) {
+        SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
+        return NULL;
+    }
+
+    nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff));
+    foundLanguage = _MemorySearchResourceEntryA(rootResources, nameResources, (LPCSTR) (uintptr_t) language);
+    if (foundLanguage == NULL) {
+        // requested language not found, use first available
+        if (nameResources->NumberOfIdEntries == 0) {
+            SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND);
+            return NULL;
         }
-#undef MAX_LOCAL_KEY_LENGTH
-#endif
+
+        foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1);
     }
 
-    return result;
+    return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff));
 }
 
-HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language)
+HMEMORYRSRC MemoryFindResourceExW(HMEMORYMODULE module, LPCWSTR name, LPCWSTR type, WORD language)
 {
     unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;
     PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE);
@@ -928,21 +1018,21 @@ HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR typ
     // - second node is the name
     // - third node is the language
     rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress);
-    foundType = _MemorySearchResourceEntry(rootResources, rootResources, type);
+    foundType = _MemorySearchResourceEntryW(rootResources, rootResources, type);
     if (foundType == NULL) {
         SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
         return NULL;
     }
 
     typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff));
-    foundName = _MemorySearchResourceEntry(rootResources, typeResources, name);
+    foundName = _MemorySearchResourceEntryW(rootResources, typeResources, name);
     if (foundName == NULL) {
         SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
         return NULL;
     }
 
     nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff));
-    foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR) (uintptr_t) language);
+    foundLanguage = _MemorySearchResourceEntryW(rootResources, nameResources, (LPWSTR) (uintptr_t) language);
     if (foundLanguage == NULL) {
         // requested language not found, use first available
         if (nameResources->NumberOfIdEntries == 0) {
@@ -980,49 +1070,103 @@ LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource)
 }
 
 int
-MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize)
+MemoryLoadStringA(HMEMORYMODULE module, UINT id, LPSTR buffer, int maxsize)
 {
-    return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE);
+    return MemoryLoadStringExA(module, id, buffer, maxsize, DEFAULT_LANGUAGE);
 }
 
 int
-MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language)
+MemoryLoadStringW(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize)
+{
+    return MemoryLoadStringExW(module, id, buffer, maxsize, DEFAULT_LANGUAGE);
+}
+
+static BOOL
+MemoryLoadStringData(HMEMORYMODULE module, UINT id, HMEMORYRSRC resource, PIMAGE_RESOURCE_DIR_STRING_U* res)
+{
+    PIMAGE_RESOURCE_DIR_STRING_U data;
+
+    data = (PIMAGE_RESOURCE_DIR_STRING_U) MemoryLoadResource(module, resource);
+    id = id & 0x0f;
+    while (id--) {
+        data = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR));
+    }
+    if (data->Length == 0) {
+        SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
+        return FALSE;
+    }
+
+    *res = data;
+    return TRUE;
+}
+
+int
+MemoryLoadStringExA(HMEMORYMODULE module, UINT id, LPSTR buffer, int maxsize, WORD language)
 {
     HMEMORYRSRC resource;
     PIMAGE_RESOURCE_DIR_STRING_U data;
-    DWORD size;
+    int size;
+
     if (maxsize == 0) {
+        // TODO(fancycode): Should provide pointer to raw data in "buffer".
+        // Check what should be returned in this case (bytes or characters?).
+        buffer[0] = 0;
         return 0;
     }
 
-    resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language);
+    resource = MemoryFindResourceExA(module, MAKEINTRESOURCEA((id >> 4) + 1), (LPCSTR) RT_STRING, language);
     if (resource == NULL) {
         buffer[0] = 0;
         return 0;
     }
 
-    data = (PIMAGE_RESOURCE_DIR_STRING_U) MemoryLoadResource(module, resource);
-    id = id & 0x0f;
-    while (id--) {
-        data = (PIMAGE_RESOURCE_DIR_STRING_U) OffsetPointer(data, (data->Length + 1) * sizeof(WCHAR));
+    if (!MemoryLoadStringData(module, id, resource, &data)) {
+        buffer[0] = 0;
+        return 0;
     }
-    if (data->Length == 0) {
-        SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
+
+    size = data->Length;
+    if (size >= maxsize) {
+        size = maxsize;
+    } else {
+        buffer[size] = 0;
+    }
+    wcstombs(buffer, data->NameString, size);
+    return size;
+}
+
+int
+MemoryLoadStringExW(HMEMORYMODULE module, UINT id, LPWSTR buffer, int maxsize, WORD language)
+{
+    HMEMORYRSRC resource;
+    PIMAGE_RESOURCE_DIR_STRING_U data;
+    int size;
+
+    if (maxsize == 0) {
+        // TODO(fancycode): Should provide pointer to raw data in "buffer".
+        // Check what should be returned in this case (bytes or characters?).
+        buffer[0] = 0;
+        return 0;
+    }
+
+    resource = MemoryFindResourceExW(module, MAKEINTRESOURCEW((id >> 4) + 1), (LPCWSTR) RT_STRING, language);
+    if (resource == NULL) {
+        buffer[0] = 0;
+        return 0;
+    }
+
+    if (!MemoryLoadStringData(module, id, resource, &data)) {
         buffer[0] = 0;
         return 0;
     }
 
     size = data->Length;
-    if (size >= (DWORD) maxsize) {
+    if (size >= maxsize) {
         size = maxsize;
     } else {
         buffer[size] = 0;
     }
-#if defined(UNICODE)
     wcsncpy(buffer, data->NameString, size);
-#else
-    wcstombs(buffer, data->NameString, size);
-#endif
     return size;
 }
 
diff --git a/MemoryModule.h b/MemoryModule.h
index a728f6b..df68957 100644
--- a/MemoryModule.h
+++ b/MemoryModule.h
@@ -39,6 +39,12 @@ typedef void *HCUSTOMMODULE;
 extern "C" {
 #endif
 
+#if defined(UNICODE)
+#define MEMORYMODULE_FUNCTION_AW(func) func##W
+#else
+#define MEMORYMODULE_FUNCTION_AW(func) func##A
+#endif
+
 typedef LPVOID (*CustomAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD, void*);
 typedef BOOL (*CustomFreeFunc)(LPVOID, SIZE_T, DWORD, void*);
 typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void *);
@@ -94,12 +100,16 @@ int MemoryCallEntryPoint(HMEMORYMODULE);
 /**
  * Find the location of a resource with the specified type and name.
  */
-HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR);
+HMEMORYRSRC MemoryFindResourceA(HMEMORYMODULE, LPCSTR, LPCSTR);
+HMEMORYRSRC MemoryFindResourceW(HMEMORYMODULE, LPCWSTR, LPCWSTR);
+#define MemoryFindResource MEMORYMODULE_FUNCTION_AW(MemoryFindResource)
 
 /**
  * Find the location of a resource with the specified type, name and language.
  */
-HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD);
+HMEMORYRSRC MemoryFindResourceExA(HMEMORYMODULE, LPCSTR, LPCSTR, WORD);
+HMEMORYRSRC MemoryFindResourceExW(HMEMORYMODULE, LPCWSTR, LPCWSTR, WORD);
+#define MemoryFindResourceEx MEMORYMODULE_FUNCTION_AW(MemoryFindResourceEx)
 
 /**
  * Get the size of the resource in bytes.
@@ -114,12 +124,16 @@ LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC);
 /**
  * Load a string resource.
  */
-int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
+int MemoryLoadStringA(HMEMORYMODULE, UINT, LPSTR, int);
+int MemoryLoadStringW(HMEMORYMODULE, UINT, LPWSTR, int);
+#define MemoryLoadString MEMORYMODULE_FUNCTION_AW(MemoryLoadString)
 
 /**
  * Load a string resource with a given language.
  */
-int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
+int MemoryLoadStringExA(HMEMORYMODULE, UINT, LPSTR, int, WORD);
+int MemoryLoadStringExW(HMEMORYMODULE, UINT, LPWSTR, int, WORD);
+#define MemoryLoadStringEx MEMORYMODULE_FUNCTION_AW(MemoryLoadStringEx)
 
 /**
 * Default implementation of CustomAllocFunc that calls VirtualAlloc