Delphi.int.ru — Портал программистов

Вход Регистрация | Забыли пароль?

События

Сегодня:
Вопросы0    Ответы0    Мини-форумы0


Последние:
Вопрос20.07, 15:06 / #6671
Ответ30.06, 12:52 / #6666
Новости30 апреля 2012


Сейчас онлайн:
На сайте — 12
На IRC-канале — 2

Ссылки

Автор: Iron Monk

Всем привет!

Чем отличается программист от другого типа человека разумного?
Я думаю, постоянным желанием подшутить над братом меньшим - Человеком нормальным, благо способов для этого - великое множество. В реестре Windows неограниченное количество мест для автоматического запуска программ - сейчас нас интересует расширение оболочки - контекстное меню Эксплорера. Займемся созданием +СОМ-сервера который будет запускаться при вызове контекстного меню.
Сразу оговорюсь - на компе потенциального испытуемого должна стоять звуковая карта и, желательно, антивирус Касперского, чтобы испытуемому был хорошо известен вопль AVP при обнаружении вируса.

Для начала, создадим файл ресурса содержащего нужный нам вопль.
Создаем текстовый файл, пишем в нем на одной строке:

MYWAVE RCData C:\Temp\Infected.wav

(вместо C:\Temp\Infected.wav пишете реальный путь к *.wav файлу)
Сохраняем файл с именем WAVE.RC. Далее выполняем команду:

brcc32.exe C:\Temp\Wave.rc

(вместо C:\Temp\Wave.rc пишете реальный путь к Wave.rc файлу)
У нас получился файл ресурсов Wave.res который мы будем использовать дальше.

В примерах Delphi есть почти все, что нам нужно:
..:\Program Files\Borland\Delphi7\Demos\ActiveX\ShellExt\ContextM.pas

Немножко редактируем этот файл (в смысле выбрасываем ненужное - добавляем нужное) и получаем примерно это:

unit Unit1;

interface

uses
  Windows, ActiveX, ComObj, Classes,
  Dialogs, StdCtrls,
  ShlObj;

type
  TInitWormHook = class(TComObject, IShellExtInit, IContextMenu)
  protected
    { IShellExtInit }
    function IShellExtInit.Initialize = SEIInitialize;
    function SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
      hKeyProgID: HKEY): HResult; stdcall;
    { IContextMenu }
    function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast,
      uFlags: UINT): HResult; stdcall;
    function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
    function GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
      pszName: LPSTR; cchMax: UINT): HResult; stdcall;
  end;

  function DllGetClassObject(const CLSID, IID: TGUID; var Obj): HResult; stdcall;
  function DllCanUnloadNow: HResult; stdcall;

const
  Class_ContextMenu: TGUID = '{1A39ADB3-5ED9-44F4-B6BA-5B3D41255033}';

implementation

uses ComServ, SysUtils, ShellApi, Registry, Graphics, mmSystem;

//Цепляем наш ресурс
{$R wave.res}

function TInitWormHook.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
  hKeyProgID: HKEY): HResult;
begin
  Result := NOERROR;
end;

function TInitWormHook.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,
          idCmdLast, uFlags: UINT): HResult;
begin
  Result := 0;
end;

function TInitWormHook.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
begin
  Result := NOERROR;
end;

function TInitWormHook.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
  pszName: LPSTR; cchMax: UINT): HRESULT;
begin
  Result := NOERROR;
end;

type
  TInitWormHookFactory = class(TComObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;
  
//А это - наша процедура по извлечению звука из файла ресурса
procedure RUNWAV;
var
WaveHandle: THandle;
  WavePointer: pointer;
  begin
  WaveHandle:= FindResource(hInstance, 'MYWAVE', RT_RCDATA);
  if WaveHandle <> 0 then
    begin
      WaveHandle := LoadResource(hInstance, WaveHandle);
      if WaveHandle <> 0 then
        begin;
          WavePointer:= LockResource(WaveHandle);
          sndPlaySound(WavePointer, snd_Memory or SND_ASYNC);
          UnlockResource(WaveHandle);
          FreeResource(WaveHandle);
        end;
    end;
end;

procedure TInitWormHookFactory.UpdateRegistry(Register: Boolean);
var
  ClassID: string;
begin
  if Register then begin
    inherited UpdateRegistry(Register);
    ClassID := GUIDToString(Class_ContextMenu);
    CreateRegKey('Directory\shellex\ContextMenuHandlers\WAV', '', ClassID);
    if (Win32Platform = VER_PLATFORM_WIN32_NT) then
      with TRegistry.Create do
        try
          RootKey := HKEY_LOCAL_MACHINE;
          OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions', True);
          OpenKey('Approved', True);
          WriteString(ClassID, 'FTP simple client');
        finally
          Free;
        end;
  end
  else begin
    DeleteRegKey('Directory\shellex\ContextMenuHandlers\WAV');
    inherited UpdateRegistry(Register);
  end;
end;

function DllGetClassObject(const CLSID, IID: TGUID; var Obj): HResult;
begin
  Result:=ComServ.DllGetClassObject(CLSID, IID, Obj);
  if Result = S_OK then begin
    try
     RUNWAV;
    except
    end;
  end;
end;

function DllCanUnloadNow: HResult;
begin
  Result := ComServ.DllCanUnloadNow;
  if Result = S_OK then begin
    try
     RUNWAV;
    except
    end;
  end;
end;

initialization
  TInitWormHookFactory.Create(ComServer, TInitWormHook, Class_ContextMenu,
    '', 'FTP simple client', ciMultiInstance,
    tmApartment);
end.

Теперь нам нужно скомпилировать из этого модуля DLL-ку. Пишем проект ShWave.dpr:

library ShWave;

uses
  ComServ,
  Unit1 in 'Unit1.pas';

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;
begin
end.

После компиляции получаем ShWave.dll

Мы получили +СОМ-сервер, теперь осталось его подключить к контекстному меню. Пишем файл реестра Install.reg:

REGEDIT4

[HKEY_CLASSES_ROOT\CLSID\{1A39ADB3-5ED9-44F4-B6BA-5B3D41255033}\InprocServer32]
@="ShWave.dll"
"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\WAV]
@="{1A39ADB3-5ED9-44F4-B6BA-5B3D41255033}"

[HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers\WAV]
@="{1A39ADB3-5ED9-44F4-B6BA-5B3D41255033}"

Закидываем файл ShWave.dll в %SystemRoot%\System32, запускаем Install.reg и при попытке использования контекстного меню будет звучать вопль AVP или тот, который вы сами зашили в ресурс.

Вместо \*\ можно использовать любое расширение файлов и СОМ-сервер будет активизироваться только при щелчке правой кнопкой мыши на файлах выбранного типа.

Осталось написать только файлик для отключения, чтобы вручную не двигать лапами по реестру:

REGEDIT4

[-HKEY_CLASSES_ROOT\CLSID\{1A39ADB3-5ED9-44F4-B6BA-5B3D41255033}\InprocServer32]

[-HKEY_CLASSES_ROOT\CLSID\{1A39ADB3-5ED9-44F4-B6BA-5B3D41255033}]

[-HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\WAV]

[-HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers\WAV]

Вот и все.

Статья добавлена: 17 ноября 2006

Следующая статья: Основные операции с буфером обмена »

Рейтинг статьи: 5.00 Голосов: 1 Ваша оценка:

Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.


Статьи, похожие по тематике

 

Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:

Ссылка для форумов (BBCode):

Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:23}} (буква a — латинская) — только адрес статьи (URL);
{{статья:23}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).

Поделитесь ссылкой в социальных сетях:


Комментарии читателей к данной статье

Пока нет комментариев к данной статье. Оставьте свой и он будет первым.

Оставлять комментарии к статьям могут только зарегистрированные пользователи.