diff --git a/hooklib/path.c b/hooklib/path.c index 07647f7..8bcb173 100644 --- a/hooklib/path.c +++ b/hooklib/path.c @@ -11,11 +11,11 @@ #include "hooklib/path.h" +#include + /* Helpers */ static void path_hook_init(void); -static BOOL path_transform_a(char **out, const char *src); -static BOOL path_transform_w(wchar_t **out, const wchar_t *src); /* API hooks */ @@ -97,10 +97,108 @@ static BOOL WINAPI hook_RemoveDirectoryA(const char *lpFileName); static BOOL WINAPI hook_RemoveDirectoryW(const wchar_t *lpFileName); -BOOL WINAPI hook_DeleteFileA(LPCSTR lpFileName); -BOOL WINAPI hook_DeleteFileW(LPWSTR lpFileName); -BOOL WINAPI hook_MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName); -BOOL WINAPI hook_MoveFileW(LPWSTR lpFileName, LPWSTR lpNewFileName); +static BOOL WINAPI hook_PathFileExistsA(LPCSTR pszPath); + +static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath); + +static BOOL WINAPI hook_MoveFileA( + const char *lpExistingFileName, + const char *lpNewFileName); + +static BOOL WINAPI hook_MoveFileW( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName); + +static BOOL WINAPI hook_CopyFileA( + const char *lpExistingFileName, + const char *lpNewFileName, + BOOL bFailIfExists); + +static BOOL WINAPI hook_CopyFileW( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName, + BOOL bFailIfExists); + +static BOOL WINAPI hook_MoveFileExA( + const char *lpExistingFileName, + const char *lpNewFileName, + uint32_t dwFlags); + +static BOOL WINAPI hook_MoveFileExW( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName, + uint32_t dwFlags); + +static BOOL WINAPI hook_CopyFileExA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags +); + +static BOOL WINAPI hook_CopyFileExW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags +); + +static BOOL WINAPI hook_ReplaceFileA( + const char *lpReplacedFileName, + const char *lpReplacementFileName, + const char *lpBackupFileName, + uint32_t dwReplaceFlags, + void *lpExclude, + void *lpReserved); + +static BOOL WINAPI hook_ReplaceFileW( + const wchar_t *lpReplacedFileName, + const wchar_t *lpReplacementFileName, + const wchar_t *lpBackupFileName, + uint32_t dwReplaceFlags, + void *lpExclude, + void *lpReserved); + +static BOOL WINAPI hook_DeleteFileA(const char *lpFileName); + +static BOOL WINAPI hook_DeleteFileW(const wchar_t *lpFileName); + +static DWORD WINAPI hook_GetPrivateProfileStringA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName +); + +static DWORD WINAPI hook_GetPrivateProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +); + +static DWORD WINAPI hook_GetPrivateProfileSectionW( + LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +); + +static UINT WINAPI hook_GetDriveTypeA( + LPCSTR lpRootPathName +); + +static UINT WINAPI hook_GetDriveTypeW( + LPCWSTR lpRootPathName +); /* Link pointers */ @@ -182,10 +280,120 @@ static BOOL (WINAPI *next_RemoveDirectoryA)(const char *lpFileName); static BOOL (WINAPI *next_RemoveDirectoryW)(const wchar_t *lpFileName); -BOOL (WINAPI *next_DeleteFileA)(LPCSTR lpFileName); -BOOL (WINAPI *next_DeleteFileW)(LPWSTR lpFileName); -BOOL (WINAPI *next_MoveFileA)(LPCSTR lpExistingFileName, LPCSTR lpNewFileName); -BOOL (WINAPI *next_MoveFileW)(LPWSTR lpFileName, LPWSTR lpNewFileName); +static BOOL (WINAPI *next_PathFileExistsA)(LPCSTR pszPath); + +static BOOL (WINAPI *next_PathFileExistsW)(LPCWSTR pszPath); + +static BOOL (WINAPI *next_MoveFileA)( + const char *lpExistingFileName, + const char *lpNewFileName); + +static BOOL (WINAPI *next_MoveFileW)( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName); + +static BOOL (WINAPI *next_CopyFileA)( + const char *lpExistingFileName, + const char *lpNewFileName, + BOOL bFailIfExists); + +static BOOL (WINAPI *next_CopyFileW)( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName, + BOOL bFailIfExists); + +static BOOL (WINAPI *next_MoveFileExA)( + const char *lpExistingFileName, + const char *lpNewFileName, + uint32_t dwFlags); + +static BOOL (WINAPI *next_MoveFileExW)( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName, + uint32_t dwFlags); + +static BOOL (WINAPI *next_CopyFileA)( + const LPCSTR lpExistingFileName, + const LPCSTR lpNewFileName, + BOOL bFailIfExists +); + +static BOOL (WINAPI *next_CopyFileW)( + const LPCWSTR lpExistingFileName, + const LPCWSTR lpNewFileName, + BOOL bFailIfExists +); + +static BOOL (WINAPI *next_CopyFileExA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags +); + +static BOOL (WINAPI *next_CopyFileExW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags +); + +static BOOL (WINAPI *next_ReplaceFileA)( + const char *lpReplacedFileName, + const char *lpReplacementFileName, + const char *lpBackupFileName, + uint32_t dwReplaceFlags, + void *lpExclude, + void *lpReserved); + +static BOOL (WINAPI *next_ReplaceFileW)( + const wchar_t *lpReplacedFileName, + const wchar_t *lpReplacementFileName, + const wchar_t *lpBackupFileName, + uint32_t dwReplaceFlags, + void *lpExclude, + void *lpReserved); + +static BOOL (WINAPI *next_DeleteFileA)(const char *lpFileName); + +static BOOL (WINAPI *next_DeleteFileW)(const wchar_t *lpFileName); + +static DWORD (WINAPI *next_GetPrivateProfileStringA)( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName +); + +static DWORD (WINAPI *next_GetPrivateProfileStringW)( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +); + +static DWORD (WINAPI *next_GetPrivateProfileSectionW)( + LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +); + +static UINT (WINAPI *next_GetDriveTypeW)( + LPCWSTR lpRootPathName +); + +static UINT (WINAPI *next_GetDriveTypeA)( + LPCSTR lpRootPathName +); /* Hook table */ @@ -255,13 +463,13 @@ static const struct hook_symbol path_hook_syms[] = { .patch = hook_RemoveDirectoryW, .link = (void **) &next_RemoveDirectoryW, }, { - .name = "DeleteFileA", - .patch = hook_DeleteFileA, - .link = (void **) &next_DeleteFileA, + .name = "PathFileExistsA", + .patch = hook_PathFileExistsA, + .link = (void **) &next_PathFileExistsA, }, { - .name = "DeleteFileW", - .patch = hook_DeleteFileW, - .link = (void **) &next_DeleteFileW, + .name = "PathFileExistsW", + .patch = hook_PathFileExistsW, + .link = (void **) &next_PathFileExistsW, }, { .name = "MoveFileA", .patch = hook_MoveFileA, @@ -270,6 +478,66 @@ static const struct hook_symbol path_hook_syms[] = { .name = "MoveFileW", .patch = hook_MoveFileW, .link = (void **) &next_MoveFileW, + }, { + .name = "MoveFileExA", + .patch = hook_MoveFileExA, + .link = (void **) &next_MoveFileExA, + }, { + .name = "MoveFileExW", + .patch = hook_MoveFileExW, + .link = (void **) &next_MoveFileExW, + }, { + .name = "CopyFileA", + .patch = hook_CopyFileA, + .link = (void **) &next_CopyFileA, + }, { + .name = "CopyFileW", + .patch = hook_CopyFileW, + .link = (void **) &next_CopyFileW, + }, { + .name = "CopyFileExA", + .patch = hook_CopyFileExA, + .link = (void **) &next_CopyFileExA, + }, { + .name = "CopyFileExW", + .patch = hook_CopyFileW, + .link = (void **) &next_CopyFileExW, + }, { + .name = "ReplaceFileA", + .patch = hook_ReplaceFileA, + .link = (void **) &next_ReplaceFileA, + }, { + .name = "ReplaceFileW", + .patch = hook_ReplaceFileW, + .link = (void **) &next_ReplaceFileW, + }, { + .name = "DeleteFileA", + .patch = hook_DeleteFileA, + .link = (void **) &next_DeleteFileA, + }, { + .name = "DeleteFileW", + .patch = hook_DeleteFileW, + .link = (void **) &next_DeleteFileW, + }, { + .name = "GetPrivateProfileStringA", + .patch = hook_GetPrivateProfileStringA, + .link = (void **) &next_GetPrivateProfileStringA, + }, { + .name = "GetPrivateProfileStringW", + .patch = hook_GetPrivateProfileStringW, + .link = (void **) &next_GetPrivateProfileStringW, + }, { + .name = "GetPrivateProfileSectionW", + .patch = hook_GetPrivateProfileSectionW, + .link = (void **) &next_GetPrivateProfileSectionW, + }, { + .name = "GetDriveTypeA", + .patch = hook_GetDriveTypeA, + .link = (void **) &next_GetDriveTypeA, + }, { + .name = "GetDriveTypeW", + .patch = hook_GetDriveTypeW, + .link = (void **) &next_GetDriveTypeW, } }; @@ -334,7 +602,7 @@ void path_hook_insert_hooks(HMODULE target) _countof(path_hook_syms)); } -static BOOL path_transform_a(char **out, const char *src) +BOOL path_transform_a(char **out, const char *src) { wchar_t *src_w; size_t src_c; @@ -403,7 +671,7 @@ end: return ok; } -static BOOL path_transform_w(wchar_t **out, const wchar_t *src) +BOOL path_transform_w(wchar_t **out, const wchar_t *src) { BOOL ok; HRESULT hr; @@ -881,7 +1149,406 @@ static BOOL WINAPI hook_RemoveDirectoryW(const wchar_t *lpFileName) return ok; } -BOOL WINAPI hook_DeleteFileA(LPCSTR lpFileName) +static BOOL WINAPI hook_PathFileExistsA(LPCSTR pszPath) +{ + char *trans; + BOOL ok; + + ok = path_transform_a(&trans, pszPath); + + if (!ok) { + return FALSE; + } + + ok = next_PathFileExistsA(trans ? trans : pszPath); + + free(trans); + + return ok; +} + +static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath) +{ + wchar_t *trans; + BOOL ok; + + ok = path_transform_w(&trans, pszPath); + + if (!ok) { + return FALSE; + } + + ok = next_PathFileExistsW(trans ? trans : pszPath); + + free(trans); + + return ok; +} + +static BOOL WINAPI hook_MoveFileA( + const char *lpExistingFileName, + const char *lpNewFileName) +{ + char *oldTrans; + char *newTrans; + BOOL ok; + + ok = path_transform_a(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_a(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_MoveFileA( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_MoveFileW( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName) +{ + wchar_t *oldTrans; + wchar_t *newTrans; + BOOL ok; + + ok = path_transform_w(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_w(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_MoveFileW( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName); + + free(oldTrans); + free(newTrans); + + return ok; +} + + +static BOOL WINAPI hook_CopyFileA( + const char *lpExistingFileName, + const char *lpNewFileName, + BOOL bFailIfExists) +{ + char *oldTrans; + char *newTrans; + BOOL ok; + + ok = path_transform_a(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_a(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_CopyFileA( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName, + bFailIfExists); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_CopyFileW( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName, + BOOL bFailIfExists) +{ + wchar_t *oldTrans; + wchar_t *newTrans; + BOOL ok; + + ok = path_transform_w(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_w(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_CopyFileW( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName, + bFailIfExists); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_MoveFileExA( + const char *lpExistingFileName, + const char *lpNewFileName, + uint32_t dwFlags) +{ + char *oldTrans; + char *newTrans; + BOOL ok; + + ok = path_transform_a(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_a(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_MoveFileExA( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName, + dwFlags); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_MoveFileExW( + const wchar_t *lpExistingFileName, + const wchar_t *lpNewFileName, + uint32_t dwFlags) +{ + wchar_t *oldTrans; + wchar_t *newTrans; + BOOL ok; + + ok = path_transform_w(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_w(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_MoveFileExW( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName, + dwFlags); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_CopyFileExA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags +) +{ + char *oldTrans; + char *newTrans; + BOOL ok; + + ok = path_transform_a(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_a(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_CopyFileExA( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_CopyFileExW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags +) +{ + wchar_t *oldTrans; + wchar_t *newTrans; + BOOL ok; + + ok = path_transform_w(&oldTrans, lpExistingFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_w(&newTrans, lpNewFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_CopyFileExW( + oldTrans ? oldTrans : lpExistingFileName, + newTrans ? newTrans : lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_ReplaceFileA( + const char *lpReplacedFileName, + const char *lpReplacementFileName, + const char *lpBackupFileName, + uint32_t dwReplaceFlags, + void *lpExclude, + void *lpReserved) +{ + char *oldTrans; + char *newTrans; + BOOL ok; + + ok = path_transform_a(&oldTrans, lpReplacedFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_a(&newTrans, lpReplacementFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_ReplaceFileA( + oldTrans ? oldTrans : lpReplacedFileName, + newTrans ? newTrans : lpReplacementFileName, + lpBackupFileName, + dwReplaceFlags, + lpExclude, + lpReserved); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_ReplaceFileW( + const wchar_t *lpReplacedFileName, + const wchar_t *lpReplacementFileName, + const wchar_t *lpBackupFileName, + uint32_t dwReplaceFlags, + void *lpExclude, + void *lpReserved) +{ + wchar_t *oldTrans; + wchar_t *newTrans; + BOOL ok; + + ok = path_transform_w(&oldTrans, lpReplacedFileName); + + if (!ok) { + return FALSE; + } + + ok = path_transform_w(&newTrans, lpReplacementFileName); + + if (!ok) { + free(oldTrans); + + return FALSE; + } + + ok = next_ReplaceFileW( + oldTrans ? oldTrans : lpReplacedFileName, + newTrans ? newTrans : lpReplacementFileName, + lpBackupFileName, + dwReplaceFlags, + lpExclude, + lpReserved); + + free(oldTrans); + free(newTrans); + + return ok; +} + +static BOOL WINAPI hook_DeleteFileA(const char *lpFileName) { char *trans; BOOL ok; @@ -892,14 +1559,14 @@ BOOL WINAPI hook_DeleteFileA(LPCSTR lpFileName) return FALSE; } - ok = next_DeleteFileA(trans ? trans : lpFileName); + ok = next_DeleteFileA(trans ? trans: lpFileName); free(trans); return ok; } -BOOL WINAPI hook_DeleteFileW(LPWSTR lpFileName) +static BOOL WINAPI hook_DeleteFileW(const wchar_t *lpFileName) { wchar_t *trans; BOOL ok; @@ -910,51 +1577,313 @@ BOOL WINAPI hook_DeleteFileW(LPWSTR lpFileName) return FALSE; } - ok = next_DeleteFileW(trans ? trans : lpFileName); + ok = next_DeleteFileW(trans ? trans: lpFileName); free(trans); return ok; } -BOOL WINAPI hook_MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName) -{ - char *trans1; - char *trans2; +static DWORD WINAPI hook_GetPrivateProfileStringA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName +) { + char *trans; + DWORD result; BOOL ok; - ok = path_transform_a(&trans1, lpExistingFileName); - ok = path_transform_a(&trans2, lpNewFileName); + ok = path_transform_a(&trans, lpFileName); if (!ok) { return FALSE; } - ok = next_MoveFileA(trans1 ? trans1 : lpExistingFileName, trans2 ? trans2 : lpNewFileName); + result = next_GetPrivateProfileStringA( + lpAppName, + lpKeyName, + lpDefault, + lpReturnedString, + nSize, + trans ? trans: lpFileName); - free(trans1); - free(trans2); + free(trans); - return ok; + return result; } -BOOL WINAPI hook_MoveFileW(LPWSTR lpExistingFileName, LPWSTR lpNewFileName) -{ - wchar_t *trans1; - wchar_t *trans2; +static DWORD WINAPI hook_GetPrivateProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +) { + wchar_t *trans; + DWORD result; BOOL ok; - ok = path_transform_w(&trans1, lpExistingFileName); - ok = path_transform_w(&trans2, lpNewFileName); + ok = path_transform_w(&trans, lpFileName); if (!ok) { return FALSE; } - ok = next_MoveFileW(trans1 ? trans1 : lpExistingFileName, trans2 ? trans2 : lpNewFileName); + result = next_GetPrivateProfileStringW( + lpAppName, + lpKeyName, + lpDefault, + lpReturnedString, + nSize, trans ? trans: lpFileName); + + free(trans); - free(trans1); - free(trans2); - - return ok; + return result; } + +static DWORD WINAPI hook_GetPrivateProfileSectionW( + LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +) { + wchar_t *trans; + DWORD result; + BOOL ok; + + ok = path_transform_w(&trans, lpFileName); + + if (!ok) { + return FALSE; + } + + result = next_GetPrivateProfileSectionW( + lpAppName, + lpReturnedString, + nSize, + trans ? trans: lpFileName); + + free(trans); + + return result; +} + + +static UINT WINAPI hook_GetDriveTypeA( + LPCSTR lpRootPathName +) { + char *trans; + UINT result; + BOOL ok; + + ok = path_transform_a(&trans, lpRootPathName); + + if (!ok) { + return FALSE; + } + + result = next_GetDriveTypeA(trans ? trans : lpRootPathName); + + free(trans); + + return result; +} + + +static UINT WINAPI hook_GetDriveTypeW( + LPCWSTR lpRootPathName +) { + wchar_t *trans; + UINT result; + BOOL ok; + + ok = path_transform_w(&trans, lpRootPathName); + + if (!ok) { + return FALSE; + } + + result = next_GetDriveTypeW(trans ? trans : lpRootPathName); + + free(trans); + + return result; +} + +char** str_split_a(char* a_str, const char a_delim) { + char** result = 0; + size_t count = 0; + char* tmp = a_str; + char* last_comma = 0; + char delim[2]; + delim[0] = a_delim; + delim[1] = 0; + + /* Count how many elements will be extracted. */ + while (*tmp) + { + if (a_delim == *tmp) + { + count++; + last_comma = tmp; + } + tmp++; + } + + /* Add space for trailing token. */ + count += last_comma < (a_str + strlen(a_str) - 1); + + /* Add space for terminating null string so caller + knows where the list of returned strings ends. */ + count++; + + result = malloc(sizeof(char*) * count); + + if (result) + { + size_t idx = 0; + char* token = strtok(a_str, delim); + + while (token) + { + assert(idx < count); + *(result + idx++) = strdup(token); + token = strtok(0, delim); + } + assert(idx == count - 1); + *(result + idx) = 0; + } + + return result; +} + +BOOL path_transform_args_a(const char* str, char delimiter, char* buf, size_t size) { + assert(str != NULL); + assert(buf != NULL); + + if (size <= 0) { + return FALSE; + } + + char* copy = strdup(str); + char** tokens = str_split_a(copy, delimiter); + char *trans; + BOOL ok; + BOOL failed = FALSE; + + strcpy(buf, ""); + + if (tokens) { + int j; + for (j = 0; *(tokens + j); j++) { + ok = path_transform_a(&trans, *(tokens + j)); + free(*(tokens + j)); + if (ok) { + strcat_s(buf, size, trans ? trans : *(tokens+j)); + if (*(tokens + j + 1)) { + strcat_s(buf, size, " "); + } + free(trans); + } else { + failed = true; + } + } + free(tokens); + } + + free(copy); + + return !failed; +} + +wchar_t** str_split_w(wchar_t* a_str, const wchar_t a_delim) { + wchar_t** result = 0; + size_t count = 0; + wchar_t* tmp = a_str; + wchar_t* last_comma = 0; + wchar_t delim[2]; + delim[0] = a_delim; + delim[1] = 0; + + /* Count how many elements will be extracted. */ + while (*tmp) + { + if (a_delim == *tmp) + { + count++; + last_comma = tmp; + } + tmp++; + } + + /* Add space for trailing token. */ + count += last_comma < (a_str + wcslen(a_str) - 1); + + /* Add space for terminating null string so caller + knows where the list of returned strings ends. */ + count++; + + result = malloc(sizeof(wchar_t*) * count); + + wchar_t* pt; + + if (result) + { + size_t idx = 0; + wchar_t* token = wcstok_s(a_str, delim, &pt); + + while (token) + { + assert(idx < count); + *(result + idx++) = wcsdup(token); + token = wcstok_s(0, delim, &pt); + } + assert(idx == count - 1); + *(result + idx) = 0; + } + + return result; +} + +BOOL path_transform_args_w(const wchar_t* str, wchar_t delimiter, wchar_t* buf, size_t size) { + assert(str != NULL); + assert(buf != NULL); + + if (size <= 0) { + return FALSE; + } + + wchar_t* copy = wcsdup(str); + wchar_t** tokens = str_split_w(copy, delimiter); + wchar_t *trans; + BOOL ok; + BOOL failed = FALSE; + + wcscpy(buf, L""); + + if (tokens) { + int j; + for (j = 0; *(tokens + j); j++) { + ok = path_transform_w(&trans, *(tokens + j)); + if (ok) { + wcscat_s(buf, size, trans ? trans : *(tokens+j)); + if (*(tokens + j + 1)) { + wcscat_s(buf, size, L" "); + } + free(trans); + } else { + failed = true; + } + free(*(tokens + j)); + } + free(tokens); + } + + free(copy); + + return !failed; +} \ No newline at end of file diff --git a/hooklib/path.h b/hooklib/path.h index 3a58bb7..aca9356 100644 --- a/hooklib/path.h +++ b/hooklib/path.h @@ -13,6 +13,10 @@ typedef HRESULT (*path_hook_t)( HRESULT path_hook_push(path_hook_t hook); void path_hook_insert_hooks(HMODULE target); int path_compare_w(const wchar_t *string1, const wchar_t *string2, size_t count); +BOOL path_transform_a(char **out, const char *src); +BOOL path_transform_w(wchar_t **out, const wchar_t *src); +BOOL path_transform_args_a(const char* str, char delimiter, char* buf, size_t size); +BOOL path_transform_args_w(const wchar_t* str, wchar_t delimiter, wchar_t* buf, size_t size); static inline bool path_is_separator_w(wchar_t c) { diff --git a/platform/vfs.c b/platform/vfs.c index d74172c..83a7e19 100644 --- a/platform/vfs.c +++ b/platform/vfs.c @@ -20,7 +20,6 @@ static DWORD (*next_GetLogicalDrives)(); static UINT (*next_GetDriveTypeA)(LPCSTR lpRootPathName); static void vfs_fixup_path(wchar_t *path, size_t max_count); static HRESULT vfs_mkdir_rec(const wchar_t *path); -static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count); static HRESULT vfs_path_hook_nthome( const wchar_t *src, wchar_t *dest, @@ -290,11 +289,12 @@ end: return hr; } -static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count) +HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count) { const wchar_t *redir; size_t required; size_t redir_len; + size_t src_len; HRESULT hr; assert(src != NULL); @@ -345,10 +345,16 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count) return S_FALSE; } + /* GetFileAttributesW would request the src "E:", so fix the src_len in + in order to redirect the drive letter successfully */ + + src_len = path_is_separator_w(src[2]) ? 3 : 2; + /* Cut off \, replace with redir path, count NUL terminator */ redir_len = wcslen(redir); required = wcslen(src) - 3 + redir_len + 1; + required = wcslen(src) - src_len + redir_len + 1; if (dest != NULL) { if (required > *count) { @@ -356,7 +362,7 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count) } wcscpy_s(dest, *count, redir); - wcscpy_s(dest + redir_len, *count - redir_len, src + 3); + wcscpy_s(dest + redir_len, *count - redir_len, src + src_len); } *count = required; diff --git a/platform/vfs.h b/platform/vfs.h index 56146d6..36724a1 100644 --- a/platform/vfs.h +++ b/platform/vfs.h @@ -18,3 +18,4 @@ struct vfs_config { }; HRESULT vfs_hook_init(const struct vfs_config *config); +HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count);