// A simple plugin for OllyDbg, written by TQN
library DPlugin;

uses
  Windows, SysUtils, ShellAPI, Plugin;

resourcestring
  VERSION = '0.1';
  AUTHOR  = 'TQN';
  PLUGIN_NAME = 'Delphi Plugin';
  ABOUT   = 'A simple plugin for OllyDbg'#13'Compiled with Borland Delphi 7 - By TQN';

var
  g_hwndOlly: HWND;
  g_hmodOlly: HMODULE;
  SaveDLLProc: TDLLProc;

function GetExePath: string;
var
  pProcess: PChar;
  sExeFName: string;
begin
  pProcess := PChar(Plugingetvalue(VAL_PROCESSNAME));
  if (pProcess = nil) or (pProcess[0] = #0) then
    sExeFName := GetModuleName(g_hmodOlly)
  else
    sExeFName := PChar(Plugingetvalue(VAL_EXEFILENAME));

  Result := ExtractFilePath(sExeFName);
end;

function GetComSpec: string;
var
  sCmd: string;
  pFilePart: PChar;
  szBuf: array[0..MAX_PATH] of Char;
begin
  sCmd := GetEnvironmentVariable('COMSPEC');
  if (sCmd = '') or not FileExists(sCmd) then
  begin
    SetString(sCmd, szBuf, SearchPath(nil, 'cmd.exe', nil, SizeOf(szBuf), szBuf, pFilePart));
    if (sCmd = '') then
      SetString(sCmd, szBuf, SearchPath(nil, 'command.com', nil, SizeOf(szBuf), szBuf, pFilePart));
  end;
  Result := sCmd;
end;

function ODBG_Plugindata(name: PChar): Integer; cdecl;
begin
  StrLCopy(name, PChar(PLUGIN_NAME), 32); // Name of plugin
  Result := PLUGIN_VERSION;
end;

function ODBG_Plugininit(ollydbgversion: Integer; hWndOlly: HWND; features: PULONG): Integer; cdecl;
begin
  if (ollydbgversion < PLUGIN_VERSION) then
  begin
    Result := -1;
    Exit;
  end;

  g_hwndOlly := hWndOlly;
  Addtolist(0, 0, 'Delphi Plugin Example - Ver %s by %s', VERSION, AUTHOR);

  Result := 0;
end;

function ODBG_Pluginmenu(origin: Integer; pData: PChar; pItem: Pointer): Integer; cdecl;
begin
  case origin of
    PM_MAIN:
      begin
        // Plugin menu in main window
        StrCopy(pData, '0 &Calculator, 1 &Explorer, 2 Command &Prompt, 3 &Notepad|4 &About...');
        Result := 1;
      end;
  else
    Result := 0; // Any other window
  end;
end;

procedure ODBG_Pluginaction(origin: Integer; action: Integer; pItem: Pointer); cdecl;
var
  sExePath: string;
begin
  if (origin = PM_MAIN) then
  begin
    sExePath := GetExePath;
    case action of
      0: ShellExecute(0, nil, 'Calc.exe', nil, nil, SW_SHOW);
      1: ShellExecute(0, 'explore', PChar(sExePath), nil, nil, SW_SHOWDEFAULT);
      2: ShellExecute(0, nil, PChar(GetComSpec), PChar('/k cd /d ' + sExePath),
                      PChar(sExePath), SW_SHOWDEFAULT);
      3: ShellExecute(0, nil, 'notepad.exe', nil, PChar(sExePath), SW_SHOWDEFAULT);
      4: MessageBox(g_hwndOlly, PChar(ABOUT), PChar(PLUGIN_NAME), MB_OK);
    end;
  end;
end;

procedure DLLExit(dwReason: DWORD);
begin
  if (dwReason = DLL_PROCESS_DETACH) then
  begin
    // Uninitialize code here
    OutputDebugString('Plugin unloaded by DLL_PROCESS_DETACH');
  end;

  // Call saved entry point procedure
  if Assigned(SaveDLLProc) then
    SaveDLLProc(dwReason);
end;

exports
  ODBG_Plugindata   name '_ODBG_Plugindata',
  ODBG_Plugininit   name '_ODBG_Plugininit',
  ODBG_Pluginmenu   name '_ODBG_Pluginmenu',
  ODBG_Pluginaction name '_ODBG_Pluginaction';

begin
  // Initialize code here
  SaveDLLProc := @DLLProc;
  DLLProc := @DLLExit;

  g_hmodOlly := GetModuleHandle(nil);
end.
