{ Source code for HOOKIT.EXE }
{ Note: Save the source as HOOKIT.PAS for Pascal or HOOKIT.DPR for Delphi. }

program HookIt;

{$D HookIt!}
{$C MOVEABLE PRELOAD PERMANENT}

{$IFDEF Win32}
{$R HOOKIT32.RES}

uses
  Windows, Messages;

type
  TwMsg = Longint;
  TwParam = Longint;
  TlParam = Longint;

{$ELSE}
{$R HOOKIT16.RES}

uses
 {$IFDEF VER15}
  WinTypes, WinProcs, Win31;
 {$ELSE}
 {$IFDEF VER70}
  WinTypes, WinProcs, Win31;
 {$ELSE}
  WinTypes, WinProcs, Messages;
 {$ENDIF}
 {$ENDIF}

type
  TwMsg = Word;
  TwParam = Word;
  TlParam = Longint;

{$ENDIF}

type
  TWinVersion = record
   WinMajor : Byte;
   WinMinor : Byte;
   DosMajor : Byte;
   DosMinor : Byte;
  end;

  TcbPlaybackFinishedProc = Procedure(AppData: Longint)
                          {$IFDEF Win32} stdcall;
                          {$ELSE}; {$ENDIF}

const
  APPNAME = 'HookIt!';
  CLASSNAME ='HOOKITDIALOGCLASS';
  ID_BTN_START_RECORDING = 101;
  ID_BTN_STOP_RECORDING  =  102;
  ID_BTN_PLAYBACK        = 103;
  ID_BTN_DONE            = IDOK;
  FILENAME  = 'HOOKIT.MAC';

var
  PlaybackFinishedProc :TcbPlaybackFinishedProc;

function StartRecording: Integer
                     {$IFDEF Win32} stdcall;
                     {$ELSE} ; far; {$ENDIF}
                      external 'HOOKLIB' index 2;


function StopRecording(lpFileName: PChar): Integer
                     {$IFDEF Win32} stdcall;
                     {$ELSE} ; far; {$ENDIF}
                      external 'HOOKLIB' index 3;

function Playback(lpFileName: PChar;
                  EndPlayProc: TcbPlaybackFinishedProc;
                  AppData: Longint): Integer
                 {$IFDEF Win32} stdcall;
                 {$ELSE} ; far; {$ENDIF}
                  external 'HOOKLIB' index 5;


procedure PlaybackFinished(AppData: Longint)
                  {$IFDEF Win32} stdcall;
                  {$ELSE} ; export; {$ENDIF}

begin
  EnableWindow(GetDlgItem(hWnd(AppData), ID_BTN_START_RECORDING), True);
  EnableWindow(GetDlgItem(hWnd(AppData), ID_BTN_STOP_RECORDING), False);
  EnableWindow(GetDlgItem(hWnd(AppData), ID_BTN_PLAYBACK), True);
  EnableWindow(GetDlgItem(hWnd(AppData), ID_BTN_DONE), True);
  SetFocus(GetDlgItem(hWnd(AppData),     ID_BTN_PLAYBACK));
end;


function HookitDialogProc(Dialog: HWnd; Msg: TwMsg;
                   WParam: TwParam; LParam: TlParam): Longbool
                         {$IFDEF Win32} stdcall;
                         {$ELSE} ; export; {$ENDIF}
begin
  HookitDialogProc := True;
 {do any default class handling here for HookItDlg}
  HookitDialogProc := Longbool(DefDlgProc(Dialog, Msg, WParam, LParam));
end;


function MainDlgProc(Dialog: HWnd;
                     Msg:TwMsg;
                     WParam:TwParam;
                     LParam:TlParam): Bool
                    {$IFDEF Win32} stdcall; {$ELSE} ; export; {$ENDIF}
begin
  MainDlgProc := True;
  case Msg Of

    WM_INITDIALOG: begin
      EnableWindow(GetDlgItem(Dialog, ID_BTN_START_RECORDING), True);
      EnableWindow(GetDlgItem(Dialog, ID_BTN_STOP_RECORDING), False);
      EnableWindow(GetDlgItem(Dialog, ID_BTN_PLAYBACK), False);
      EnableWindow(GetDlgItem(Dialog, ID_BTN_DONE), True);
      exit;
    end;

    WM_COMMAND: begin

      case WParam of

        ID_BTN_START_RECORDING:
begin
            EnableWindow(GetDlgItem(Dialog, ID_BTN_STOP_RECORDING), True);
            SetFocus    (GetDlgItem(Dialog, ID_BTN_STOP_RECORDING));
            EnableWindow(GetDlgItem(Dialog, ID_BTN_START_RECORDING), False);
            EnableWindow(GetDlgItem(Dialog, ID_BTN_PLAYBACK), False);
            EnableWindow(GetDlgItem(Dialog, ID_BTN_DONE), False);
            if StartRecording = 0 then begin
              EnableWindow(GetDlgItem(Dialog, ID_BTN_START_RECORDING), True);
              SetFocus    (GetDlgItem(Dialog, ID_BTN_START_RECORDING));
              EnableWindow(GetDlgItem(Dialog, ID_BTN_STOP_RECORDING), False);
              EnableWindow(GetDlgItem(Dialog, ID_BTN_PLAYBACK), False);
              EnableWindow(GetDlgItem(Dialog, ID_BTN_DONE), True);
              Messagebox(Dialog, 'Unable to start recording!', APPNAME, MB_OK);
            end;
          exit;
        end;

        ID_BTN_STOP_RECORDING:
begin
          if StopRecording(FILENAME) > 0 then begin
            EnableWindow(GetDlgItem(Dialog, ID_BTN_START_RECORDING), True);
            EnableWindow(GetDlgItem(Dialog, ID_BTN_PLAYBACK), True);
            SetFocus    (GetDlgItem(Dialog, ID_BTN_PLAYBACK));
          end
          else begin
            EnableWindow(GetDlgItem(Dialog, ID_BTN_START_RECORDING), True);
            SetFocus    (GetDlgItem(Dialog, ID_BTN_START_RECORDING));
            EnableWindow(GetDlgItem(Dialog, ID_BTN_PLAYBACK), False);
          end;
          EnableWindow(GetDlgItem(Dialog,   ID_BTN_STOP_RECORDING), False);
          EnableWindow(GetDlgItem(Dialog,   ID_BTN_DONE), True);
          exit;
        end;

        ID_BTN_PLAYBACK: begin
          EnableWindow(GetDlgItem(Dialog,   ID_BTN_START_RECORDING), False);
          EnableWindow(GetDlgItem(Dialog,   ID_BTN_STOP_RECORDING), False);
          EnableWindow(GetDlgItem(Dialog,   ID_BTN_PLAYBACK), False);
          EnableWindow(GetDlgItem(Dialog,   ID_BTN_DONE), False);
          if PlayBack(FILENAME, PlaybackFinishedProc, Dialog) = 0 then begin
            EnableWindow(GetDlgItem(Dialog, ID_BTN_START_RECORDING), True);
            EnableWindow(GetDlgItem(Dialog, ID_BTN_STOP_RECORDING), False);
            EnableWindow(GetDlgItem(Dialog, ID_BTN_PLAYBACK), True);
            EnableWindow(GetDlgItem(Dialog, ID_BTN_DONE), True);
            SetFocus    (GetDlgItem(hWnd(Dialog), ID_BTN_PLAYBACK));
          end;
          exit;
        end;

        ID_BTN_DONE: begin
          EndDialog(Dialog, ID_BTN_DONE);
          exit;
        end;

      end; {wParam}

    end; {WM_COMMAND}

    WM_CLOSE: begin
      FreeProcInstance(@PlaybackFinishedProc);
      EndDialog(Dialog, IDOK);
      exit;
    end;

  end;
  MainDlgProc := False;
end;


procedure Init;
var
  WindowClass: TWndClass;
  WinVer: TWinVersion;
begin
  Longint(WinVer) := GetVersion;
  if ((WinVer.WinMajor < 3) OR
      ((WinVer.WinMajor = 3) AND
       (WinVer.WinMinor < 10)) ) then begin
    Messagebox(0, 'Microsoft Windows 3.10 or greater required!',
               APPNAME, MB_OK);
    halt;
  end;
  @PlaybackFinishedProc := MakeProcInstance(@PlaybackFinished, hInstance);
  If @PlaybackFinishedProc = nil then begin
    Messagebox(0, 'Cannot create instance thunk!', APPNAME, MB_OK);
    halt;
  end;

  if FindWindow(CLASSNAME, APPNAME) <> 0 then begin
    Messagebox(0, 'Multiple Sessions not allowed',
               APPNAME, MB_OK);
    halt;
  end
  else begin
    WindowClass.Style := CS_BYTEALIGNWINDOW;
    WindowClass.lpfnWndProc := @HookItDialogProc;
    WindowClass.cbClsExtra  := 0;
    WindowClass.cbWndExtra  := DLGWINDOWEXTRA;
    WindowClass.hInstance   := hInstance;
    WindowClass.hIcon       := LoadIcon(0, IDI_APPLICATION);
    WindowClass.hCursor     := LoadCursor(0, IDC_ARROW);
    WindowClass.hbrBackground := GetStockObject(WHITE_BRUSH);
    WindowClass.lpszMenuName  := nil;
    WindowClass.lpszClassName := CLASSNAME;
    if not Bool(RegisterClass(WindowClass)) then begin
      Messagebox(0,'RegisterClass Failed!', APPNAME, MB_OK);
      halt;
    end;
  end;
end;

procedure MyWinMain;
var
  WindowProc:TFarProc;
begin
  WindowProc:=MakeProcInstance(@MainDlgProc, hInstance);
  DialogBox(hInstance, 'HOOKIT', 0, WindowProc);
  FreeProcInstance(WindowProc);
end;


{WinMain}
begin
  Init;
  MyWinMain;
end.
