Автозапуск программы на чистом Windows API

18 декабря 2013

Конечно же, вы видели множество программ, запускающихся автоматически во время загрузки системы. В 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

Метки: , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.