Skip to content

Commit

Permalink
Fix most Unicode path handling problems except Detours
Browse files Browse the repository at this point in the history
  • Loading branch information
awakecoding committed Dec 1, 2023
1 parent 97d8fb7 commit a6ba60f
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 43 deletions.
4 changes: 2 additions & 2 deletions dll/ApiHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,12 +1088,12 @@ LONG MsRdpEx_AttachHooks()
return NO_ERROR;
}

g_hNtDll = GetModuleHandleA("ntdll.dll");
g_hNtDll = GetModuleHandleW(L"ntdll.dll");
MSRDPEX_GETPROCADDRESS(Real_LdrResolveDelayLoadedAPI, Func_LdrResolveDelayLoadedAPI, g_hNtDll, "LdrResolveDelayLoadedAPI");
MSRDPEX_GETPROCADDRESS(Real_NtCreateFile, Func_NtCreateFile, g_hNtDll, "NtCreateFile");
MSRDPEX_GETPROCADDRESS(Real_NtOpenFile, Func_NtOpenFile, g_hNtDll, "NtOpenFile");

g_hKernelBase = GetModuleHandleA("KernelBase.dll");
g_hKernelBase = GetModuleHandleW(L"KernelBase.dll");
MSRDPEX_GETPROCADDRESS(Real_RegOpenKeyExW, Func_RegOpenKeyExW, g_hKernelBase, "RegOpenKeyExW");
MSRDPEX_GETPROCADDRESS(Real_RegQueryValueExW, Func_RegQueryValueExW, g_hKernelBase, "RegQueryValueExW");
MSRDPEX_GETPROCADDRESS(Real_RegCloseKey, Func_RegCloseKey, g_hKernelBase, "RegCloseKey");
Expand Down
67 changes: 54 additions & 13 deletions dll/Environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,72 @@

bool MsRdpEx_SetEnv(const char* name, const char* value)
{
return SetEnvironmentVariableA(name, value) ? true : false;
bool result = false;
WCHAR* nameW = NULL;
WCHAR* valueW = NULL;

if (!name)
{
goto exit;
}

if (MsRdpEx_ConvertToUnicode(CP_UTF8, 0, name, -1, &nameW, 0) < 1) {
goto exit;
}

if (value) { // optional
if (MsRdpEx_ConvertToUnicode(CP_UTF8, 0, value, -1, &valueW, 0) < 1) {
goto exit;
}
}

result = SetEnvironmentVariableW(nameW, valueW) ? true : false;

exit:
free(nameW);
free(valueW);
return result;
}

char* MsRdpEx_GetEnv(const char* name)
{
uint32_t size;
char* env = NULL;
DWORD nSizeW;
WCHAR* nameW = NULL;
WCHAR* valueW = NULL;
char* value = NULL;

if (!name)
{
goto exit;
}

size = GetEnvironmentVariableA(name, NULL, 0);
if (MsRdpEx_ConvertToUnicode(CP_UTF8, 0, name, -1, &nameW, 0) < 1) {
goto exit;
}

if (!size)
nSizeW = GetEnvironmentVariableW(nameW, NULL, 0);

if (!nSizeW)
return NULL;

env = (char*) malloc(size);
valueW = (WCHAR*) malloc((nSizeW + 1) * 2);

if (!env)
return NULL;
if (!valueW) {
goto exit;
}

if (GetEnvironmentVariableA(name, env, size) != size - 1)
{
free(env);
return NULL;
nSizeW = GetEnvironmentVariableW(nameW, valueW, nSizeW);

valueW[nSizeW] = '\0';

if (MsRdpEx_ConvertFromUnicode(CP_UTF8, 0, valueW, -1, &value, 0, NULL, NULL) < 0) {
goto exit;
}

return env;
exit:
free(nameW);
free(valueW);
return value;
}

bool MsRdpEx_EnvExists(const char* name)
Expand Down
36 changes: 28 additions & 8 deletions dll/File.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,42 +182,62 @@ uint64_t MsRdpEx_FileSize(const char* filename)

bool MsRdpEx_GetFileBuildVersion(const char* filename, uint64_t* version)
{
bool success = false;
DWORD dwHandle = 0;
char* buffer = NULL;
bool success = false;
WCHAR* buffer = NULL;
WCHAR* filenameW = NULL;
VS_FIXEDFILEINFO* pvi = NULL;

if (MsRdpEx_ConvertToUnicode(CP_UTF8, 0, filename, -1, &filenameW, 0) < 1)
{
goto exit;
}

DWORD size = GetFileVersionInfoSizeA(filename, &dwHandle);
DWORD size = GetFileVersionInfoSizeW(filenameW, &dwHandle);

if (size < 1)
goto exit;

buffer = (char*) malloc(size);
buffer = (WCHAR*) malloc(size);

if (!buffer)
goto exit;

if (!GetFileVersionInfoA(filename, 0, size, buffer))
if (!GetFileVersionInfoW(filenameW, 0, size, buffer))
goto exit;

size = sizeof(VS_FIXEDFILEINFO);

if (!VerQueryValueA(buffer, "\\", (LPVOID*) &pvi, (UINT*) &size))
if (!VerQueryValueW(buffer, L"\\", (LPVOID*) &pvi, (UINT*) &size))
goto exit;

*version = (uint64_t)(pvi->dwFileVersionLS >> 16);

success = true;

exit:
free(filenameW);
free(buffer);
return success;
}

bool MsRdpEx_MakePath(const char* path, LPSECURITY_ATTRIBUTES lpAttributes)
{
bool result;
result = SHCreateDirectoryExA(NULL, path, lpAttributes) == ERROR_SUCCESS;
bool result = false;
WCHAR* pathW = NULL;

if (!path)
return false;

if (MsRdpEx_ConvertToUnicode(CP_UTF8, 0, path, -1, &pathW, 0) < 1)
{
goto exit;
}

result = SHCreateDirectoryExW(NULL, pathW, lpAttributes) == ERROR_SUCCESS;

exit:
free(pathW);
return result;
}

Expand Down
2 changes: 1 addition & 1 deletion dll/Log.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ void MsRdpEx_LogOpen()
sprintf_s(g_LogFilePath, MSRDPEX_MAX_PATH, "%s\\MsRdpEx.log", appDataPath);
}

g_LogFile = fopen(g_LogFilePath, "wb");
g_LogFile = MsRdpEx_FileOpen(g_LogFilePath, "wb");
}

void MsRdpEx_LogClose()
Expand Down
132 changes: 118 additions & 14 deletions dll/Paths.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,66 @@ bool MsRdpEx_PathCchRenameExtension(char* pszPath, size_t cchPath, const char* p
return true;
}

DWORD MsRdpEx_GetModuleFileName(HMODULE hModule, LPSTR lpFileName, DWORD nSize)
{
DWORD nStatus = 0;
DWORD errorCode = 0;
LPWSTR lpFileNameW = NULL;

if (nSize < 1)
{
errorCode = ERROR_INSUFFICIENT_BUFFER;
goto exit;
}

lpFileNameW = malloc((nSize + 1) * 2);

if (!lpFileNameW)
{
errorCode = ERROR_INSUFFICIENT_BUFFER;
goto exit;
}

lpFileNameW[nSize] = '\0';

DWORD nStatusW = GetModuleFileNameW(hModule, lpFileNameW, nSize);

if (nStatusW == 0)
{
errorCode = GetLastError();
goto exit;
}

int nStatusA = WideCharToMultiByte(CP_UTF8, 0, lpFileNameW, nStatusW + 1, lpFileName, nSize, NULL, NULL);

if (nStatusA < 2) {
errorCode = ERROR_INSUFFICIENT_BUFFER;
goto exit;
}

nStatus = (nStatusA - 1); // number of TCHARS not including terminating null character

exit:
free(lpFileNameW);
if (errorCode) {
SetLastError(errorCode);
return 0;
}
return nStatus;
}

bool MsRdpEx_PathCchDetect(char* pszPath, size_t cchPath, uint32_t pathId)
{
bool success = true;

switch (pathId)
{
case MSRDPEX_CURRENT_MODULE_PATH:
GetModuleFileNameA(NULL, pszPath, cchPath);
MsRdpEx_GetModuleFileName(NULL, pszPath, cchPath);
break;

case MSRDPEX_CURRENT_LIBRARY_PATH:
GetModuleFileNameA((HINSTANCE)&__ImageBase, pszPath, cchPath);
MsRdpEx_GetModuleFileName((HINSTANCE)&__ImageBase, pszPath, cchPath);
break;

default:
Expand All @@ -60,6 +108,62 @@ bool MsRdpEx_PathCchDetect(char* pszPath, size_t cchPath, uint32_t pathId)
return success;
}

DWORD MsRdpEx_ExpandEnvironmentStrings(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize)
{
DWORD nStatus = 0;
DWORD errorCode = 0;
LPWSTR lpSrcW = NULL;
LPWSTR lpDstW = NULL;

if (MsRdpEx_ConvertToUnicode(CP_UTF8, 0, lpSrc, -1, &lpSrcW, 0) < 1)
{
errorCode = ERROR_INSUFFICIENT_BUFFER;
goto exit;
}

if (!lpDst)
{
nStatus = ExpandEnvironmentStringsW(lpSrcW, NULL, 0);
goto exit;
}

lpDstW = (LPWSTR)malloc((nSize + 1) * 2);

if (!lpDstW)
{
errorCode = ERROR_INSUFFICIENT_BUFFER;
goto exit;
}

lpDstW[nSize] = '\0';

DWORD nStatusW = ExpandEnvironmentStringsW(lpSrcW, lpDstW, nSize);

if (nStatusW == 0)
{
errorCode = GetLastError();
goto exit;
}

int nStatusA = WideCharToMultiByte(CP_UTF8, 0, lpDstW, nStatusW + 1, lpDst, nSize, NULL, NULL);

if (nStatusA < 2) {
errorCode = ERROR_INSUFFICIENT_BUFFER;
goto exit;
}

nStatus = nStatusA; // number of TCHARS including terminating null character

exit:
free(lpSrcW);
free(lpDstW);
if (errorCode) {
SetLastError(errorCode);
return 0;
}
return nStatus;
}

bool MsRdpEx_InitPaths(uint32_t pathIds)
{
pathIds |= (MSRDPEX_CURRENT_MODULE_PATH | MSRDPEX_CURRENT_LIBRARY_PATH);
Expand Down Expand Up @@ -96,36 +200,36 @@ bool MsRdpEx_InitPaths(uint32_t pathIds)
}

if (pathIds & MSRDPEX_APP_DATA_PATH) {
ExpandEnvironmentStringsA("%LocalAppData%\\MsRdpEx", g_MSRDPEX_APP_DATA_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%LocalAppData%\\MsRdpEx", g_MSRDPEX_APP_DATA_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_MakePath(g_MSRDPEX_APP_DATA_PATH, NULL);
}

if (pathIds & MSRDPEX_MSTSC_EXE_PATH) {
ExpandEnvironmentStringsA("%SystemRoot%\\System32\\mstsc.exe", g_MSTSC_EXE_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%SystemRoot%\\System32\\mstsc.exe", g_MSTSC_EXE_PATH, MSRDPEX_MAX_PATH);
}

if (pathIds & MSRDPEX_MSTSCAX_DLL_PATH) {
ExpandEnvironmentStringsA("%SystemRoot%\\System32\\mstscax.dll", g_MSTSCAX_DLL_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%SystemRoot%\\System32\\mstscax.dll", g_MSTSCAX_DLL_PATH, MSRDPEX_MAX_PATH);
}

if (pathIds & MSRDPEX_MSRDC_EXE_PATH) {
ExpandEnvironmentStringsA("%ProgramFiles%\\Remote Desktop\\msrdc.exe", g_MSRDC_EXE_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%ProgramFiles%\\Remote Desktop\\msrdc.exe", g_MSRDC_EXE_PATH, MSRDPEX_MAX_PATH);

if (!MsRdpEx_FileExists(g_MSRDC_EXE_PATH)) {
ExpandEnvironmentStringsA("%LocalAppData%\\Apps\\Remote Desktop\\msrdc.exe", g_MSRDC_EXE_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%LocalAppData%\\Apps\\Remote Desktop\\msrdc.exe", g_MSRDC_EXE_PATH, MSRDPEX_MAX_PATH);
}
}

if (pathIds & MSRDPEX_RDCLIENTAX_DLL_PATH) {
ExpandEnvironmentStringsA("%ProgramFiles%\\Remote Desktop\\rdclientax.dll", g_RDCLIENTAX_DLL_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%ProgramFiles%\\Remote Desktop\\rdclientax.dll", g_RDCLIENTAX_DLL_PATH, MSRDPEX_MAX_PATH);

if (!MsRdpEx_FileExists(g_RDCLIENTAX_DLL_PATH)) {
ExpandEnvironmentStringsA("%LocalAppData%\\Apps\\Remote Desktop\\rdclientax.dll", g_RDCLIENTAX_DLL_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%LocalAppData%\\Apps\\Remote Desktop\\rdclientax.dll", g_RDCLIENTAX_DLL_PATH, MSRDPEX_MAX_PATH);
}
}

if (pathIds & MSRDPEX_DEFAULT_RDP_PATH) {
ExpandEnvironmentStringsA("%UserProfile%\\Documents\\Default.rdp", g_DEFAULT_RDP_PATH, MSRDPEX_MAX_PATH);
MsRdpEx_ExpandEnvironmentStrings("%UserProfile%\\Documents\\Default.rdp", g_DEFAULT_RDP_PATH, MSRDPEX_MAX_PATH);
}

return true;
Expand All @@ -146,12 +250,12 @@ const char* MsRdpEx_GetPath(uint32_t pathId)
break;

case MSRDPEX_EXECUTABLE_PATH:
path = (const char*) g_MSRDPEX_EXE_PATH;
break;
path = (const char*) g_MSRDPEX_EXE_PATH;
break;

case MSRDPEX_LIBRARY_PATH:
path = (const char*) g_MSRDPEX_DLL_PATH;
break;
path = (const char*) g_MSRDPEX_DLL_PATH;
break;

case MSRDPEX_APP_DATA_PATH:
path = (const char*) g_MSRDPEX_APP_DATA_PATH;
Expand Down
Loading

0 comments on commit a6ba60f

Please sign in to comment.