mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-12 10:48:53 +03:00
333 lines
9.5 KiB
C++
333 lines
9.5 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Detours Test Program (setdll.cpp of setdll.exe)
|
|
//
|
|
// Microsoft Research Detours Package
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <detours.h>
|
|
#pragma warning(push)
|
|
#if _MSC_VER > 1400
|
|
#pragma warning(disable:6102 6103) // /analyze warnings
|
|
#endif
|
|
#include <strsafe.h>
|
|
#pragma warning(pop)
|
|
|
|
////////////////////////////////////////////////////////////// Error Messages.
|
|
//
|
|
VOID AssertMessage(PCSTR szMsg, PCSTR szFile, DWORD nLine)
|
|
{
|
|
printf("ASSERT(%s) failed in %s, line %ld.", szMsg, szFile, nLine);
|
|
}
|
|
|
|
#define ASSERT(x) \
|
|
do { if (!(x)) { AssertMessage(#x, __FILE__, __LINE__); DebugBreak(); }} while (0)
|
|
;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
static BOOLEAN s_fRemove = FALSE;
|
|
static CHAR s_szDllPath[MAX_PATH] = "";
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// This code verifies that the named DLL has been configured correctly
|
|
// to be imported into the target process. DLLs must export a function with
|
|
// ordinal #1 so that the import table touch-up magic works.
|
|
//
|
|
static BOOL CALLBACK ExportCallback(_In_opt_ PVOID pContext,
|
|
_In_ ULONG nOrdinal,
|
|
_In_opt_ LPCSTR pszName,
|
|
_In_opt_ PVOID pCode)
|
|
{
|
|
(void)pContext;
|
|
(void)pCode;
|
|
(void)pszName;
|
|
|
|
if (nOrdinal == 1) {
|
|
*((BOOL *)pContext) = TRUE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL DoesDllExportOrdinal1(PCHAR pszDllPath)
|
|
{
|
|
HMODULE hDll = LoadLibraryExA(pszDllPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
|
|
if (hDll == NULL) {
|
|
printf("setdll.exe: LoadLibraryEx(%s) failed with error %ld.\n",
|
|
pszDllPath,
|
|
GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL validFlag = FALSE;
|
|
DetourEnumerateExports(hDll, &validFlag, ExportCallback);
|
|
FreeLibrary(hDll);
|
|
return validFlag;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
static BOOL CALLBACK ListBywayCallback(_In_opt_ PVOID pContext,
|
|
_In_opt_ LPCSTR pszFile,
|
|
_Outptr_result_maybenull_ LPCSTR *ppszOutFile)
|
|
{
|
|
(void)pContext;
|
|
|
|
*ppszOutFile = pszFile;
|
|
if (pszFile) {
|
|
printf(" %s\n", pszFile);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK ListFileCallback(_In_opt_ PVOID pContext,
|
|
_In_ LPCSTR pszOrigFile,
|
|
_In_ LPCSTR pszFile,
|
|
_Outptr_result_maybenull_ LPCSTR *ppszOutFile)
|
|
{
|
|
(void)pContext;
|
|
|
|
*ppszOutFile = pszFile;
|
|
printf(" %s -> %s\n", pszOrigFile, pszFile);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK AddBywayCallback(_In_opt_ PVOID pContext,
|
|
_In_opt_ LPCSTR pszFile,
|
|
_Outptr_result_maybenull_ LPCSTR *ppszOutFile)
|
|
{
|
|
PBOOL pbAddedDll = (PBOOL)pContext;
|
|
if (!pszFile && !*pbAddedDll) { // Add new byway.
|
|
*pbAddedDll = TRUE;
|
|
*ppszOutFile = s_szDllPath;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SetFile(PCHAR pszPath)
|
|
{
|
|
BOOL bGood = TRUE;
|
|
HANDLE hOld = INVALID_HANDLE_VALUE;
|
|
HANDLE hNew = INVALID_HANDLE_VALUE;
|
|
PDETOUR_BINARY pBinary = NULL;
|
|
|
|
CHAR szOrg[MAX_PATH];
|
|
CHAR szNew[MAX_PATH];
|
|
CHAR szOld[MAX_PATH];
|
|
|
|
szOld[0] = '\0';
|
|
szNew[0] = '\0';
|
|
|
|
StringCchCopyA(szOrg, sizeof(szOrg), pszPath);
|
|
StringCchCopyA(szNew, sizeof(szNew), szOrg);
|
|
StringCchCatA(szNew, sizeof(szNew), "#");
|
|
StringCchCopyA(szOld, sizeof(szOld), szOrg);
|
|
StringCchCatA(szOld, sizeof(szOld), "~");
|
|
printf(" %s:\n", pszPath);
|
|
|
|
hOld = CreateFileA(szOrg,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (hOld == INVALID_HANDLE_VALUE) {
|
|
printf("Couldn't open input file: %s, error: %ld\n",
|
|
szOrg, GetLastError());
|
|
bGood = FALSE;
|
|
goto end;
|
|
}
|
|
|
|
hNew = CreateFileA(szNew,
|
|
GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
if (hNew == INVALID_HANDLE_VALUE) {
|
|
printf("Couldn't open output file: %s, error: %ld\n",
|
|
szNew, GetLastError());
|
|
bGood = FALSE;
|
|
goto end;
|
|
}
|
|
|
|
if ((pBinary = DetourBinaryOpen(hOld)) == NULL) {
|
|
printf("DetourBinaryOpen failed: %ld\n", GetLastError());
|
|
goto end;
|
|
}
|
|
|
|
if (hOld != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hOld);
|
|
hOld = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
{
|
|
BOOL bAddedDll = FALSE;
|
|
|
|
DetourBinaryResetImports(pBinary);
|
|
|
|
if (!s_fRemove) {
|
|
if (!DetourBinaryEditImports(pBinary,
|
|
&bAddedDll,
|
|
AddBywayCallback, NULL, NULL, NULL)) {
|
|
printf("DetourBinaryEditImports failed: %ld\n", GetLastError());
|
|
}
|
|
}
|
|
|
|
if (!DetourBinaryEditImports(pBinary, NULL,
|
|
ListBywayCallback, ListFileCallback,
|
|
NULL, NULL)) {
|
|
|
|
printf("DetourBinaryEditImports failed: %ld\n", GetLastError());
|
|
}
|
|
|
|
if (!DetourBinaryWrite(pBinary, hNew)) {
|
|
printf("DetourBinaryWrite failed: %ld\n", GetLastError());
|
|
bGood = FALSE;
|
|
}
|
|
|
|
DetourBinaryClose(pBinary);
|
|
pBinary = NULL;
|
|
|
|
if (hNew != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hNew);
|
|
hNew = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
if (bGood) {
|
|
if (!DeleteFileA(szOld)) {
|
|
DWORD dwError = GetLastError();
|
|
if (dwError != ERROR_FILE_NOT_FOUND) {
|
|
printf("Warning: Couldn't delete %s: %ld\n", szOld, dwError);
|
|
bGood = FALSE;
|
|
}
|
|
}
|
|
if (!MoveFileA(szOrg, szOld)) {
|
|
printf("Error: Couldn't back up %s to %s: %ld\n",
|
|
szOrg, szOld, GetLastError());
|
|
bGood = FALSE;
|
|
}
|
|
if (!MoveFileA(szNew, szOrg)) {
|
|
printf("Error: Couldn't install %s as %s: %ld\n",
|
|
szNew, szOrg, GetLastError());
|
|
bGood = FALSE;
|
|
}
|
|
}
|
|
|
|
DeleteFileA(szNew);
|
|
}
|
|
|
|
|
|
end:
|
|
if (pBinary) {
|
|
DetourBinaryClose(pBinary);
|
|
pBinary = NULL;
|
|
}
|
|
if (hNew != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hNew);
|
|
hNew = INVALID_HANDLE_VALUE;
|
|
}
|
|
if (hOld != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hOld);
|
|
hOld = INVALID_HANDLE_VALUE;
|
|
}
|
|
return bGood;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void PrintUsage(void)
|
|
{
|
|
printf("Usage:\n"
|
|
" setdll [options] binary_files\n"
|
|
"Options:\n"
|
|
" /d:file.dll : Add file.dll binary files\n"
|
|
" /r : Remove extra DLLs from binary files\n"
|
|
" /? : This help screen.\n");
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////// main.
|
|
//
|
|
int CDECL main(int argc, char **argv)
|
|
{
|
|
BOOL fNeedHelp = FALSE;
|
|
PCHAR pszFilePart = NULL;
|
|
|
|
int arg = 1;
|
|
for (; arg < argc; arg++) {
|
|
if (argv[arg][0] == '-' || argv[arg][0] == '/') {
|
|
CHAR *argn = argv[arg] + 1;
|
|
CHAR *argp = argn;
|
|
while (*argp && *argp != ':' && *argp != '=')
|
|
argp++;
|
|
if (*argp == ':' || *argp == '=')
|
|
*argp++ = '\0';
|
|
|
|
switch (argn[0]) {
|
|
|
|
case 'd': // Set DLL
|
|
case 'D':
|
|
if ((strchr(argp, ':') != NULL || strchr(argp, '\\') != NULL) &&
|
|
GetFullPathNameA(argp, sizeof(s_szDllPath), s_szDllPath, &pszFilePart)) {
|
|
}
|
|
else {
|
|
StringCchPrintfA(s_szDllPath, sizeof(s_szDllPath), "%s", argp);
|
|
}
|
|
break;
|
|
|
|
case 'r': // Remove extra set DLLs.
|
|
case 'R':
|
|
s_fRemove = TRUE;
|
|
break;
|
|
|
|
case '?': // Help
|
|
fNeedHelp = TRUE;
|
|
break;
|
|
|
|
default:
|
|
fNeedHelp = TRUE;
|
|
printf("Bad argument: %s:%s\n", argn, argp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (argc == 1) {
|
|
fNeedHelp = TRUE;
|
|
}
|
|
if (!s_fRemove && s_szDllPath[0] == 0) {
|
|
fNeedHelp = TRUE;
|
|
}
|
|
if (fNeedHelp) {
|
|
PrintUsage();
|
|
return 1;
|
|
}
|
|
|
|
|
|
if (s_fRemove) {
|
|
printf("Removing extra DLLs from binary files.\n");
|
|
}
|
|
else {
|
|
if (!DoesDllExportOrdinal1(s_szDllPath)) {
|
|
printf("Error: %hs does not export function with ordinal #1.\n",
|
|
s_szDllPath);
|
|
return 2;
|
|
}
|
|
printf("Adding %hs to binary files.\n", s_szDllPath);
|
|
}
|
|
|
|
for (arg = 1; arg < argc; arg++) {
|
|
if (argv[arg][0] != '-' && argv[arg][0] != '/') {
|
|
SetFile(argv[arg]);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// End of File
|