Winapi что это
Перейти к содержимому

Winapi что это

  • автор:

Введение в WinAPI: Создание Windows-приложений

WinAPI (Windows Application Programming Interface) является набором функций и процедур, предоставляемых операционной системой Windows для разработки приложений. В этой статье мы рассмотрим основные принципы работы с WinAPI.

WinAPI обеспечивает доступ к функциям операционной системы Windows, таких как создание окон, управление ресурсами, работа с файлами, реагирование на события и еще многое другое. Чтобы начать разработку приложений с использованием WinAPI, необходимо знать несколько основных понятий и функций.

Основным элементом приложения, создаваемого с помощью WinAPI, является окно(не всегда). Для создания окна необходимо определить его характеристики, такие как размер, положение на экране и обработчик событий. Обработчик событий позволяет приложению реагировать на действия пользователя, например, нажатие кнопки мыши или нажатие клавиши.

После создания окна приложение переходит в цикл обработки сообщений, который прослушивает и обрабатывает события которые происходящие в окне. В цикле обработки сообщений мы можем реализовать логику нашего приложения.

WinAPI также предоставляет множество других функций и возможностей, таких как работа с ресурсами (иконки, курсоры, меню), рисование на экране, использование диалоговых окон и многое другое.

В этой статье мы рассмотрели лишь базовые принципы работы с WinAPI. Для изучения более сложных возможностей WinAPI рекомендуется обратиться к официальной документации и руководствам на других сайтах по программированию на WinAPI.

В заключение, WinAPI является мощным инструментом для разработки Windows-приложений. Он предоставляет разработчикам доступ к функциям операционной системы Windows и позволяет создавать приложения для операционных систем Windows в то время как UWP приложения может только на Windows 10+ запускаться.

И кстати: в рамках WinAPI вы также можете создавать приложения с использованием Direct3D , этот графический API разработанным для работы с трехмерной графикой. Direct3D позволяет разработчикам создавать и управлять 3D-графикой в WinApi-приложениях.

Введение в Win32 API

Win32 API (далее WinAPI) – это набор функций (API – Application Programming Interface), работающих под управлением ОС Windows. Они содержатся в библиотеке windows.h .

С помощью WinAPI можно создавать различные оконные процедуры, диалоговые окна, программы и даже игры. Эта, скажем так, библиотека является базовой в освоении программирования Windows Forms, MFC, потому что эти интерфейсы являются надстройками этой библиотеки. Освоив её, Вы без труда будете создавать формы, и понимать, как это происходит.

Не будем внедряться в теорию. Начнём с того, как создать этот проект в MVS, а в конце статьи будет разобран простой пример.

Итак. Сначала открываем Visual Studio, затем, нажимаем на вкладку «Файл», далее «Создать проект»:

1

Безымянный

Затем, в раскрывающемся списке Visual C++ выбираем пункт Win32, там и будет «Проект Win32». Щелкаем по нему: Вводим название проекта, указываем путь и нажимаем «ОК». Далее будет написано: «Добро пожаловать в мастер приложения Win32». Нажимаем далее. По-умолчанию у надписи «Пустой проект» галочка отсутствует. Нам нужно её поставить и убедиться, что у нас «Тип Приложения» — Приложение Windows. Если всё верно, нажимаем – «Готово».

2.

У нас должен быть пустой проект такого вида:

3

Ну а теперь начнём писать простую программу, которая традиционно будет выводить на экран надпись: «Привет, Мир. ».

Естественно, к проекту нужно добавить файл типа «имя».cpp. Кликаем по «Файлы исходного кода» правой кнопкой мыши, в раскрывающемся списке выбираем вкладку – «Добавить», далее «Создать элемент…». В результате у нас должно появиться такое окно:

4

Выбираем «Файл С++», вводим имя, нажимаем «Добавить». Затем открываем этот файл и вставляем в него такой код (подробности далее):

Результат должен быть таким:

5

Теперь остановимся поподробнее на коде программы.

В первой строке мы подключаем заголовочный файл windows.h . В нём содержатся все необходимые «апишные» функции. Здесь всё понятно.

В 4-7 строках у нас описание функции int WINAPI WinMain() .

Квалификатор WINAPI, нужен для функции WinMain всегда. Просто запомните это. WinMain – название функции. Она имеет четыре параметра. Первый из них – HINSTANCE hInstance (строка 4). hInstance является дескриптором экземпляра окна (это некий код оконной процедуры, идентификатор, по которой ОС будет отличать её от остальных окон). Через него можно обращаться к окну в процессе работы в других функциях (об этом позже), что-либо менять в параметрах окна. HINSTANCE является одним из многочисленных типов данных определенных в WinAPI, таким же как int, например. А запись HINSTANCE hInstance говорит нам о том, что мы создаём новую переменную типа HINSTANCE с названием hInstance.

О типах данным мы поговорим позже, поэтому переходим к следующему параметру: HINSTANCE hPrevInstance (строка 5). Как написано в комментариях, в Win32 он не используется, так как он создан для 3.x разрядной системы, из предыдущего понятно, что это дескриптор экземпляра окна. Далее у нас переменная типа LPSTR (строка 6) с именем lpCmdLine . Она используется в том случае, если мы запускаем окно через командную строку с прописью параметров. Очень экзотический способ, поэтому мы не будем на нём задерживаться.

И последний параметр: целочисленный, определяет способ показа окна. Нужен для функции ShowWindow , которая будет описана позже. Например, с помощью него мы можем развернуть окно на весь экран, сделать его определённой высоты, прозрачным или поверх остальных.

Переходим к функции MessageBox() (строка 10). Она имеет четыре параметра и нужна для вывода сообщений о ошибках, например. В данном случае мы использовали её для вывода сообщения. В общем виде описание функции выглядит следующим образом:

В нашем случае, первому параметру присвоен ноль. Всё потому, что у нас нет родительских окон (оно не запущено какой-нибудь программой).

Далее у нас идут две переменные типа LPCTSTR : lpText и lpCaption . Первая сообщает информацию, которая будет выведена в окне в текстовом виде. Вторая сообщает, что будет написано в тексте заголовка к окну. Это аналог char *str , но всё же нет. Для того, чтобы текст выводился корректно, нужно перед строкой поставить букву L (UNICODE строка).

Ну и последний тип данных – UINT – 32-х битное целое без знака. То есть аналог unsigned int . Этому параметру можно передавать некоторые значения (о них тоже позже), за счёт чего можно менять вид кнопки. В нашем случае – это MB_OK — означает, что окно создаёт кнопку с надписью «ОК» и соответствующим действием при её нажатии (закрытием приложения).

В строке 11 мы возвращаем значение функции, так как она имеет не тип void .

Таким образом, общее представление о WinAPI теперь есть. Продолжение в следующих разделах.

Introduction to Windows API

Kavishka Gihan

In this article I will be talking about the well-known Windows API (Win32 API), it’s functionality and how we can implement API calls from different langauges.

Windows API is used to access key components of the Windows operating system. Different application need to modify and change different Windows subsystems and hardware. To perform this in a stealthy way, Windows API is widely used by almost every Windows compatible application.

We call Windows 32 API which then gives out SYSCALLs to the kernel to do the changes we need. When we put this process to a diagram, it would look like this.

Layers of the Windows API

Before we dive right into the functionality of the API, its required to understand the layers of the API and terminologies that we will be referring to

You don’t have to know everything about these layers and terminologies but make sure you get yourself familiar with these terms and basic behaviors of them.

Working with Win32 API, it uses memory addresses. ASLR obscures the process of importing API calls. So there are 2 technologies used to overcome ASLR

  • Windows header files
  • P/Invoke

Windows header files

Header files are included into a program to get different functionalities to the program. These header files will maintain a table of functions and addresses to obtain the required function addresses or pointers to use. You may have seen them included in a C sources like:

For example, windows.h header file is a windows specific header which includes all required child and core header files. This also includes all declarations of the function calls in the Windows 32 API. This is a header file we include in C and C# like languages to get the functionality of the Windows 32 API. This provides various functions and data type declarations like integers and floats.

Child headers

Child headers are the headers that are automatically attached by another header. For example, there are different child header file that are automatically attached by windows.h to get specific functionalities. I.e:

  • winuser.h : User services ( user32.dll )
  • excpt.h : Exception handling

P/Invoke

This stand for Platform Invoke which is used to access structs, callbacks and functions from the code (program). This lets us import desired DLL to the program. This is mainly used in .NET applications.

  • Here, we use the System and System.Runtime.InteropServices namespaces to provide P/invoke to the program. user32.dll DLL is imported using the DLLImport attribute.
  • Now we create an external method to handle the imported DLL. extern keyword is used to provide the runtime of the specific DLL that was imported previously. With this, we can invoke the MessageBox function in a managed method. But still, this is an unmanaged function.

In/Out parameters of API calls

Firstly, let’s discuss what these parameters are and how the are behaved during an API call.

Input parameters : You must set input parameters before calling an API because these parameters pass needed information to the API to enable it to perform its function. For example, if the API is to perform a function on an object, one of the parameters would be the name and library of the object. Input parameters are not changed by the API.

Output parameters: You do not need to set output parameters before calling an API because the API returns information to the application in these parameters. When a return to the application is successful and no errors occur, the application accesses the information returned in output parameters.

All the API calls has a pre-defined structure which defines its own in/out parameters. We can find these structures from Microsoft’s API index

I.e this is the structure for CheckDIgButton call

[in] : data read from
[out] : data written to
[in, out] :data written to and read from (this mean pretty much what it says, both read and written to inside the call. Say you had a very simple function which increments the value of the parameter. It would firstly have to read the value and then use the pointer to set it to value+1)

Here, 3 parameters are passed to the API call:
1. parameter hDlg of data type HWND (A handle to a window)
2. parameter nIDButton of data type int
3. parameter uCheck of data type UINT (An unsigned integer); You can find all the data types from here)

BOOL keyword in the beginning specifies that in a successful API call it will return a boolean value.

This is the structure of WriteProcessMemory function from memoryapi.h ( a system service header file)

  • Notice the asterisk before thelpNumberOfBytesWrittenparameter. It indicates that the parameter is a pointer. This means that the parameter is in fact an address in memory of an int-like variable (int, uint, size_t, etc) Upon a successful call the function will return a BOOL indicating whether the call was successful or not, but it will also set the value of the variable indicated by the pointer to the number of bytes written; sort of side effect from the call.

NOTE: If a certain user has SeDebugPrivilege privileges set, we can get system by using these ReadProcessMemory and WriteProcessMemory functions. I will be covering that in a separate article

API call implementation with C and .NET

Like mentioned above, in order to access the API calls needed to interact with the API we need to include the windows.h header in our program

This is the API call structure to make a windows pop-up

With this, we can create a windows pop-up with the title “Hello kavi”

  • Here the parameters can be filled with values according to our need. l.e the 4th parameter ( dwstyle ) is used to style the windows the way we need. Here in this example its using WS_OVERLAPPEDWINDOW value asthe attributes of the windows. Actually this flag is a combination of several flags which gives the title bar, a border, a menu etc

Well now that we have our API call defined, after we need to implement this to our C program.

  • Here a lot of stuff are happening instead of creating the API call, this is well explained in here
    1. First the variables needed to pass to the API call are created with Create() .
    2. Then we see its declaring a new Windows Class with WNDCLASS wc = <0>;
    3. After we set the corresponding attributes of the window class ( lpfnWndProc : defines the behavior of the windows in relation to WindowProc,hInstance : handle to the application instance, lpszClassName : string that identifies the window class)
    4. After all that, we register the Window with RegisterClass(&wc); by providing the pointer to our windows class ( wc )
    5. Finally all that’s left to do is to create the window with CreateWindowEx

Let’s consider a .NET implementation of an API call. For this example we will be using the GetComputerNameA API call to get the name of the computer.

Just like we discussed earlier, here it’s using P/Invoke to import the kernel32 DLL and use an implemented external method to handle the DLL. After in the Main() function, its calling the API and writing the returned compuer name to the console.

In an upcomming article, I will talk about the ways we can abuse these API calls.

Win32 API Getting started with Win32 API

WinAPI (also known as Win32; officially called the Microsoft Windows API) is an application programming interface written in C by Microsoft to allow access to Windows features. The main components of the WinAPI are:

  • WinBase: The kernel functions, CreateFile, CreateProcess, etc
  • WinUser: The GUI functions, CreateWindow, RegisterClass, etc
  • WinGDI: The graphics functions, Ellipse, SelectObject, etc
  • Common controls: Standard controls, list views, sliders, etc

Versions

Versions of the API are tied to the operating system version. MSDN documentation specifies the minimum supported operating system for each function in the API.

Hello World

Microsoft Windows applications are usually written as either a console application or a windowed application (there are other types such as services and plug-ins). The difference for the programmer is the difference in the interface for the main entry point for the application source provided by the programmer.

When a C or C++ application starts, the executable entry point used by the executable loader is the Runtime that is provided by the compiler. The executable loader reads in the executable, performs any fixup to the image needed, and then invokes the executable entry point which for a C or C++ program is the Runtime provided by the compiler.

The executable entry point invoked by the loader is not the main entry point provided by the application programmer but is instead the Runtime provided by the compiler and the linker which creates the executable. The Runtime sets up the environment for the application and then calls the main entry point provided by the programmer.

A Windows console application may have several slightly different interfaces for the main entry point provided by the programmer. The difference between these is whether the main entry point is the traditional int main (int argc, char *argv[]) or if it is the Windows specific version of int _tmain(int argc, _TCHAR* argv[]) which provides for wide characters in the application parameters. If you generate a Windows Win32 console application project using Visual Studio, the source generated will be the Windows specific version.

A Windows window (GUI) application has a different interface for the main entry point provided by the programmer. This main entry point provided by the programmer has a more complex interface because the Runtime sets up a GUI environment and provides additional information along with the application parameters.

This example explains the Windows window (GUI) main entry point interface. To explore this topics you should have:

  • an IDE with compiler (preferably Visual Studio)
  • C knowledge

Create an empty Win32 windows (GUI, not console) project using the IDE. The project settings must be set for a window application (not a console application) in order for the linker to link with the correct Runtime. Create a main.c file adding it to the project and then type the following code:

This is our Win32 "Hello, world" program. The first step is to include the windows header files. The main header for all of Windows is windows.h , but there are others.

The WinMain is different from a standard int main() used with a console application. There are more parameters used in the interface and more importantly the main entry point for a window application uses a calling convention different from standard C/C++.

The qualifier APIENTRY indicates the calling convention, which is the order in which arguments are pushed on the stack † . By default, the calling convention is the standard C convention indicated by __cdecl . However Microsoft uses a different type of calling convention, the PASCAL convention, for the Windows API functions which is indicated by the __stdcall qualifier. APIENTRY is a defined name for __stdcall in one of the header files included by windows.h (see also What is __stdcall?).

The next arguments to WinMain are as follows:

  • hInst: The instance handle
  • hInstPrev: The previous instance handle. No longer used.
  • cmdline: Command line arguments (see Pass WinMain (or wWinMain) arguments to normal main)
  • cmdshow: indicates if a window should be displayed.

We don't use any of these arguments yet.

Inside of WinMain() , is a call to MessageBox() , which displays a simple dialog with a message, a message box. The first argument is the handle to the owner window. Since we don't have our own window yet, pass NULL . The second argument is the body text. The third argument is the caption, and the fourth argument contains the flags. When 0 is passed, a default message box is shown. The diagram below dissects the message box dialog.

enter image description here

† On 32 bit systems only. Other architectures have different calling conventions.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *