#  Replaces all http://www.roland.co.uk/cgi-bin/ with
#               http://www.spira.co.uk/roland/new/bin/
#


$exports   = 'exports.txt';
$dllsource = 'wshookvc';
$dll       = 'c:\\\\windows\\\\system\\\\wsock32.dll';


sub main {

  #- Generate C code
  &code_c();

  #- Generate LBC file (Watcom - although Watty's LBC handling doesn't work!)
  &code_lbc();

  #- Generate DEF file (For good ol' visual C)
  &code_def();

}



sub getexports {

  local($line);

  while(@exports) { pop @exports; }

  if(open(EXPORTS, $exports)) {

    while($line = <EXPORTS>) {
      chop $line;
      if($line ne '' && substr($line, 0, 2) ne '//') {
        push(@exports, $line);
      }
    }

    close(EXPORTS);

  } else {
    print "ERROR - Could not open exports file '$exports'";
  }

  @exports = reverse sort @exports;
}



sub getname {
  local($exp) = @_;
  local($ord, $name);

  ($ord, $name) = split(/ /, $exp);

  $ord =~ s/([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9])/pack("I", hex($1))/eg;

  return $name;
}

sub getordinal {
  local($exp) = @_;
  local($ord, $name);

  ($ord, $name) = split(/ /, $exp);

  $ord =~ s/([a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9])/hex($1)/eg;

  return $ord+1;
}



sub code_lbc {
  local($exp);

  &getexports();

  open(LBCFILE, '>'.$dllsource.'.lbc');

  print LBCFILE "OPTION MODNAME=wsock32\n";
  print LBCFILE "OPTION DESCRIPTION 'LKS WinSock Hook DLL'\n";

  print LBCFILE "EXPORT\n";
  print LBCFILE "DllMain='_DllMain\@12',\n";
  print LBCFILE "DllEntryPoint='_DllMain\@12',\n";

  while(@exports) {
    $exp = pop(@exports);
    print LBCFILE &getname($exp).'.'.&getordinal($exp)."='_my_".&getname($exp)."\@0'";
    if(@exports) { print LBCFILE ","; }
    print LBCFILE "\n";
  }

  print LBCFILE "\n";
  print LBCFILE "\n";

  close(LBCFILE);
}



sub code_def {
  local($exp);

  &getexports();

  open(DEFFILE, '>'.$dllsource.'.def');

  print DEFFILE "EXPORTS\n";

  while(@exports) {
    $exp = pop(@exports);
    print DEFFILE &getname($exp).' @'.&getordinal($exp)."\n";
  }

  print DEFFILE "\n";
  print DEFFILE "\n";

  close(DEFFILE);
}



sub code_c {
  local($exp);

  open(CFILE, '>'.$dllsource.'.c');

  print CFILE <<EOR;

#include <stdio.h>
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//#include <winsock.h>



//---- APPLICATION PARAMETERS ------------------------------------------------//

#define SZAPPNAME     "LKS WinSock Hook DLL"
#define SZDESCRIPTION "Logs WinSock calls - just a test at the moment but could be very useful... :)"
#define SZVERSION     "Version 4.0"

#define SZRCOMPANYNAME "LKS Global Takeover Systems"
#define SZRDESCRIPTION "LKS WinSock Hook DLL"
#define SZRVERSION     "v0.01"
#define SZRAPPNAME     "WS_HOOK"
#define SZRCOPYRIGHT   "<c> LKS 1999"
#define SZRTRADEMARK   "-"
#define SZRPRODNAME    "-"
#define SZRPRODVER     "-"



//---- IMPORTED FUNCTIONS ----------------------------------------------------//

EOR

  &getexports();

  while(@exports) {
    $exp = pop @exports;
    print CFILE "static int (WINAPI FAR *real_".&getname($exp).")();  // ".&getordinal($exp)."\n";
  }

  print CFILE <<EOR;



//---- FUNCTION PROTOS -------------------------------------------------------//



//---- DEBUG FUNCTIONS -------------------------------------------------------//

/*

void abc(char * p) {
  FILE *fp=fopen("c:\\z.txt","a+");
  fprintf(fp,"%s\n",p);
  fclose(fp);
}

char aa[1000];

*/

//#define abc(a)

void abc(char * p) {
  HDC dc = GetDC(NULL);
  int i;
  for(i=0; p[i]; i++);
  TextOut(dc, 0, 1000, p, i);
  ReleaseDC(NULL, dc);
}


//---- IMPORT FUNCTION -------------------------------------------------------//

#define SHIM_GETPROCADDRESS(f) real_##f = GetProcAddress(ws_inst, "" #f)

char RealImport_msg[256];
int  RealImport_errors = 0;

FARPROC RealImport(HINSTANCE inst, char *name) {
  FARPROC f;

  f = GetProcAddress(inst, name);

  if(!f) {
    RealImport_errors ++;
    sprintf(RealImport_msg, "Error importing function '%s'", name);
    MessageBox(0, RealImport_msg, "LKS $dll hook", IDOK);
  }

  return f;
}



//---- DLL ENTRY POINT -------------------------------------------------------//

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved) {

  if(reason == DLL_PROCESS_ATTACH) {

    HINSTANCE ws_inst = LoadLibrary("$dll");

    abc("DLL Started for a new process");

    if(!ws_inst) {
      abc("ERROR: Could not load DLL '$dll'");
      return FALSE;
    }

    abc("DLL '$dll' loaded ok");

EOR

  &getexports();

  while(@exports) {
    $exp = pop(@exports);
    print CFILE "    real_".&getname($exp)." = RealImport(ws_inst, \"".&getname($exp)."\");  // ".&getordinal($exp)."\n";
  }

  print CFILE <<EOR;

  if(RealImport_errors == 0) {
      //  All functions imported sucessfully!
      abc("All functions imported sucessfully!");
    } else {
      abc("ERROR - Could not import function(s)!");
      return FALSE;
    }
  }
  return TRUE;
}



//---- MY REPLACEMENT FUNCTIONS ----------------------------------------------//

EOR

  &getexports();

  while(@exports) {
    $exp = pop(@exports);
    print CFILE "__declspec(naked) __declspec(dllexport) WINAPI FAR ".&getname($exp)." () {\n";
    print CFILE "  abc(\"".&getname($exp)."\");\n";
    print CFILE "  _asm jmp[real_".&getname($exp)."];\n";
    print CFILE "}\n\n";
  }

  print CFILE <<EOR;


//---- END OF CODE -----------------------------------------------------------//

//---- Code generated by LKS Makehook.perl :)

EOR

  close(CFILE);
}



{ main(); }


