Создание COM-сервера
Автор: 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
Следующая статья: Основные операции с буфером обмена »
Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.
Статьи, похожие по тематике
Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:
Ссылка для форумов (BBCode):
Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:23}} (буква a — латинская) — только адрес статьи (URL);
{{статья:23}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).
Поделитесь ссылкой в социальных сетях:
Комментарии читателей к данной статье
Пока нет комментариев к данной статье. Оставьте свой и он будет первым.
Оставлять комментарии к статьям могут только зарегистрированные пользователи.