winapi-autorun/

Конечно же, вы видели множество программ, запускающихся автоматически во время загрузки системы. В Windows есть немало способов добавить программу в автозагрузку. Сегодня мы рассмотрим наиболее простой и популярный способ, который заключается в добавлении специальной записи в реестр. Разумеется, как и ранее, мы будем писать программу на Си и Windows API .

Для решения задачи нам понадобятся следующие процедуры.

GetModuleFileName ( hModule , szFileName , dwChars ) ;

GetModuleFileName записывает в буфер szFileName полный путь до файла, содержащего заданный модуль, загруженный текущим процессом. Если hModule == NULL, возвращается полный путь до исполняемого файла текущего процесса. Аргумент dwChars должен быть равен размеру буфера в TCHAR’ах. В случае ошибки процедура возвращает ноль, в случае успеха — значение, отличное от нуля.

GetWindowsDirectory ( szWinPath , dwChars ) ;

GetWindowsDirectory записывает в буфер szWinPath путь до каталога Windows, который «C:WINDOWS», «Z:WINNT» и так далее. Аргумент dwChars должен быть равен размеру буфера в TCHAR’ах. В случае ошибки процедура возвращает ноль, в случае успеха — значение, отличное от нуля.

CopyFile ( szFrom , szTo , bFailIfExists ) ;

Процедура CopyFile копирует файл szFrom в szTo. Если файл с именем szTo уже существует, то процедура перезаписывает его в случае, если bFailIfExists == FALSE, и завершается с ошибкой иначе. В случае ошибки возвращается ноль, в случае успеха — значение, отличное от нуля.

RegOpenKey ( HKEY_LOCAL_MACHINE , szSubKey , & hKey ) ;

RegOpenKey открывает заданный ключ реестра и записывает хэндл открытого ключа в hKey. Первый аргумент — это либо хэндл открытого или созданного ранее ключа, либо одно из предопределенных значений, например, HKEY_USERS, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE и так далее. В аргументе szSubKey передается имя ключа, который требуется открыть. Это должен быть подключ ключа, переданного первым аргументом. В случае успеха процедура возвращает ERROR_SUCCESS. В случае ошибки возвращается одно из значений, определенных в Winerror.h. В отличие от процедур, с которыми мы работали до этого момента, RegOpenKey никак не связана с GetLastError .

RegSetValueEx ( hKey , szName , 0 , REG_SZ , ( PBYTE ) szValue , dwSizeInBytes ) ;

Процедура RegSetValueEx устанавливает значение, а также тип, заданного ключа реестра и принимает следующие аргументы. Слева направо — хэндл ключа реестра, имя устанавливаемого значения, зарезервированный аргумент, тип устанавливаемого значения , указатель на значение, размер значения в байтах, включая завершающий ноль для строк. С возвращаемыми значениями все обстоит так же, как и в случае с RegOpenKey.

RegCloseKey ( hKey ) ;

RegCloseKey закрывает хэндл, соотвествующий ключу реестра. Возвращаемые значения — как у RegOpenKey и RegSetValueEx. Помимо названных процедур для работы с реестром существует великое множество других , но они устроены аналогично и в рамках данной заметки нам не понадобятся.

А теперь — решение:

#include <windows.h>

#define STRLEN(x) (sizeof(x)/sizeof(TCHAR) — 1)

BOOL SelfAutorun ( ) {
HKEY hKey = NULL ;
LONG lResult = 0 ;
TCHAR szExeName [ MAX_PATH + 1 ] ;
TCHAR szWinPath [ MAX_PATH + 1 ] ;
GetModuleFileName ( NULL , szExeName , STRLEN ( szExeName ) ) ;
GetWindowsDirectory ( szWinPath , STRLEN ( szWinPath ) ) ;
lstrcat ( szWinPath , L » \ Autorun.exe» ) ;
if ( 0 == CopyFile ( szExeName , szWinPath , FALSE ) ) {
return FALSE ;
}
lResult = RegOpenKey (
HKEY_LOCAL_MACHINE ,
L «Software \ Microsoft \ Windows \ CurrentVersion \ Run» ,
& hKey ) ;
if ( ERROR_SUCCESS != lResult ) {
return FALSE ;
}
RegSetValueEx ( hKey , L «Autorun» , 0 , REG_SZ , ( PBYTE ) szWinPath ,
lstrlen ( szWinPath ) * sizeof ( TCHAR ) + 1 ) ;
RegCloseKey ( hKey ) ;
return TRUE ;
}

INT main ( ) {
SelfAutorun ( ) ;
MessageBox ( NULL , L «Hello!» , L «Autorun» , 0 ) ;
ExitProcess ( 0 ) ;
}

Если теперь скомпилировать и запустить программу, она будет запускаться при каждой загрузке Windows. При этом в каталоге C:WINDOWS появится файл Autorun.exe, а через regedit.exe будет видна соответствующая запись в реестре. Разумеется, все это будет работать, только если вы сидите под админом. Простой пользователь не имеет прав на запись в C:WINDOWS, а также в ветвь реестра HKLM. Однако ничто не мешает положить программу в любой другой каталог и воспользоваться ветвью реестра HKCU.

В качестве домашнего задания можете погуглить на предмет существования других способов добавления программ в автозагрузку, желательно, через реестр, и автоматизировать один из этих способов. Если хотите, можете даже разместить свой код на каком-нибудь Pastebin , а я его проверю. Ну и, как обычно, не нужно стесняться критиковать мой код, задавать вопросы или же просто делиться возникшими во время прочтения данной заметки мыслями в комментариях!

Дополнение: Пример простейшей многопоточной программы на WinAPI

EnglishRussianUkrainian