// Stubs for patching calls into vsdbg.1.dll
extern "C" {
void _0() { _0(); }
void _1() { _0(); }
void _2() { _0(); }
void _3() { _0(); }
void _4() { _0(); }
void _5() { _0(); }
void _6() { _0(); }
void _7() { _0(); }
void _8() { _0(); }
void _9() { _0(); }
void _10() { _0(); }
void _11() { _0(); }
void _12() { _0(); }
}

void (*stuff[])() = {
    &_0, &_1, &_2, &_3, &_4, &_5, &_6, &_7, &_8, &_9, &_10, &_11, &_12,
};

const char *symlist[] = {
    "InitializePAL",
    "WrapICorDebugHandleValue",
    "GetVilValueFieldOffset",
    "Initialize",
    "InitializeSession",
    "RunMainLoop",
    "ShutdownSession",
    "Shutdown",
    "DllGetClassObject",
    "GetUnixDomainSocketSizes",
    "AnalyzeSnapshot",
    "RunDiagnosticAnalysis",
    "OptionalHeader.AddressOfEntryPoint",
};
const char *origDll = "vsdbg.1.dll";
const char *logPath = "A:\\Projects\\vsdbg-fix\\log.txt";

#include "3rdparty/hooker.h"
#include <stdio.h>
#include <windows.h>

FILE *logFile;

void applyPatches(HMODULE module) {
  
}

void loadOrig() { 
  auto lib = LoadLibraryA(origDll);
  applyPatches(lib);

  for (int i = 0; i < sizeof(symlist) / sizeof(symlist[0]); i++) {
    auto sym = GetProcAddress(lib, symlist[i]);
    if (sym) {
      if (!hooker_write_instruction(stuff[i], (void *)sym,
                                    HOOKER_HOOK_FAT | HOOKER_HOOK_JMP, -1)) {
        fprintf(logFile, "Failed to write jmp for %s\n", symlist[i]);
        fflush(logFile);
      } else {
        fprintf(logFile, "Successfully wrote jmp for %s\n", symlist[i]);
        fflush(logFile);
      }
      //   fprintf(logFile, "Failed to hotpatch %s\n", symlist[i]);
      // }
    }
  }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
                      LPVOID lpReserved) {
  switch (ul_reason_for_call) {
  case DLL_PROCESS_ATTACH:
    logFile = fopen(logPath, "w");

    while (!IsDebuggerPresent()) {
      Sleep(100);
      fprintf(logFile, "Waiting for debugger...\n");
      fflush(logFile);
    }

    fprintf(logFile, "Running\n");
    fflush(logFile);

    loadOrig();
    break;
  case DLL_THREAD_ATTACH:
    break;
  case DLL_THREAD_DETACH:
    break;
  case DLL_PROCESS_DETACH:
    break;
  }
  return TRUE;
}
