# JNA
<details>
<summary>Оригинальное сообщение</summary>
В Java есть возможность дёргать нативные функции из API операционной системы. В нашем случае, речь идет о win32 api.
[Документация на проект](https://java-native-access.github.io/jna/5.13.0/javadoc/) вроде бы достаточно подробная.
Зависимости для maven:
```xml
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.13.0</version>
</dependency>
```
И пока дело касается примеров из интернета, все нормально работает. По крайней мере, вот этот код нормально печатает две строки, используя функцию printf из msvcrt.dll:
```java
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Main {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.load("msvcrt", CLibrary.class);
void printf(String format,Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Line one\n\t\tLine two\n");
}
}
```
Но как дело касается чего-то внятного, то ничего не работает. В частности, пытаюсь использовать функцию [ADsGetObject](https://learn.microsoft.com/ru-ru/windows/win32/api/adshlp/nf-adshlp-adsgetobject) и даже есть [пример](https://learn.microsoft.com/ru-ru/windows/win32/adsi/binding-with-getobject-and-adsgetobject), но как это перевести в Java? Что такое [HRESULT](https://java-native-access.github.io/jna/5.13.0/javadoc/com/sun/jna/platform/win32/WinNT.HRESULT.html)? Что такое [LPCWSTR](https://java-native-access.github.io/jna/5.8.0/javadoc/com/sun/jna/WString.html) ([тык](https://stackoverflow.com/questions/10319152/jna-call-to-c-function-with-lpcwstr-parameters)), REFIID? Да и возвращаемый VOID не такой уж и пустой, как я понимаю?
В принципе, в документации про это написано, но я ничего не понимаю... Похоже, сначала надо C выучить.
Давайте попробуем вместе это как-то реализовать хотя бы на начальном уровне, переложить на Java вот такой простенький скрипт:
```vb
Set objUser = GetObject("LDAP://CN=Митичев Игорь Владимирович,OU=IT,OU=Security,OU=Departments,DC=teplo,DC=local")
wscript.echo objUser.Get("company")
objUser.put "company","Шараш-Монтаж LTD"
objUser.SetInfo
```
</details>
## Как я понимаю
> Но как дело касается чего-то внятного, то ничего не работает
Кажется, что решения работают. Я думаю, что JNA конкретно в этом случае скорее применим как практика, там чуть ниже у меня есть предложение как чуть проще всё сделать может быть.
> Что такое HRESULT
Это просто [какой-то](https://www.maruf.ca/files/caadoc/CAASysQuickRefs/CAASysHRESULT.htm) int, который возвращает [результат работы](https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values) функции.
> Что такое LPCWSTR
Это Long Pointer WChar String: указатель на начало строки в utf-16. Точнее это я про LPWSTR, а C означает const, в смысле эту строку нельзя будет менять. Поэтому в доке про него ты не нашёл ничего: можно передать LPWSTR и потом через `.getValue()` забрать строку из него. А если его хочется использовать для экспорта функции, то туда можно воткнуть byte[], как это будет в коде ниже, когда я чего-то делал с окошками
> Guid.REFIID
Айдишник интерфейса. Это указатель на IID. Можно создать его на основе, например, [GUID](https://learn.microsoft.com/en-us/windows/win32/wmformat/interface-identifiers)
> VOID не такой уж и пустой
Да, это странная штука, но когда мы возвращаем void - мы имеем в виду, что функция ничего не возвращает.
Но если мы возвращаем void* - это значит, что мы возвращаем указатель на память без какой-то спецификации типа данных по этому указателю
При этом нам хочется передать туда вопреки утверждениям хидера не void**, а, как видишь, некто `IADs *pObject;`
Вот на него [спека](https://learn.microsoft.com/en-us/windows/win32/api/iads/nn-iads-iads), а вот тут в [вопросе](https://stackoverflow.com/questions/44016328/accessing-com-interface-with-jna/44122970) сказано, как с таким объектом работать в JNA
> сначала надо C выучить
Ну тут речь не про C, скорее про WinAPI. Оно пилится уже 30 с лишним лет, там есть много костылей, писало много разного народа, где-то подходы разнятся значительно как результат. C выучить - это прям хорошо, а главное, не очень долго.
> Давайте попробуем вместе это как-то реализовать хотя бы на начальном уровне, переложить на Java вот такой простенький скрипт
Я думаю ближе к вечеру попробую вернуться к этому. Но тут у меня скорее вопрос, почему не хочется использовать [вот это](https://learn.microsoft.com/en-us/windows/win32/adsi/programming-adsi-with-javacom) для того же самого? Гемора меньше, а результат на первый взгляд такой же.
<details>
<summary>Вот тут поделал что-то ещё с WinApi</summary>
Переименовать окошко, перечислить группы пользователя
- [Link](https://hastebin.com/share/kilocejipe.java)
```java
package com.mycompany.app;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.LMAccess.LOCALGROUP_USERS_INFO_0;
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
/**
* Hello world!
*
*/
public class App
{
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.load("user32", User32.class);
interface WNDENUMPROC extends StdCallCallback {
boolean callback(Pointer hWnd, Pointer arg);
}
boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer arg);
int GetWindowTextA(Pointer hWnd, byte[] lpString, int nMaxCount);
boolean SetWindowTextA(Pointer hWnd, byte[] lpString);
}
public interface Netapi32 extends StdCallLibrary {
Netapi32 INSTANCE = (Netapi32) Native.load("netapi32", Netapi32.class);
int NetUserGetLocalGroups(Pointer servername, byte[] username, int level, int flags, Pointer buffer, int prefmaxlen, Pointer entriesread, Pointer totalentries);
}
public static void main(String[] args) {
final User32 user32 = User32.INSTANCE;
user32.EnumWindows(new User32.WNDENUMPROC() {
public boolean callback(Pointer hWnd, Pointer userData) {
byte[] windowText = new byte[512];
user32.GetWindowTextA(hWnd, windowText, 512);
String wText = Native.toString(windowText);
if (wText.isEmpty()) {
return true;
}
System.console().printf("%s - %s\n", wText, wText.compareTo("test"));
if (wText.compareTo("test") == 0) {
byte[] newText = Native.toByteArray("passed");
user32.SetWindowTextA(hWnd, newText);
}
return true;
}
}, null);
LOCALGROUP_USERS_INFO_0 uInfo_0 = new LOCALGROUP_USERS_INFO_0();
WinDef.DWORDByReference entries = new WinDef.DWORDByReference();
WinDef.DWORDByReference entriesTotal = new WinDef.DWORDByReference();
Netapi32.INSTANCE.NetUserGetLocalGroups(null,Native.toByteArray("amitichev") , 0, 1, uInfo_0.getPointer(), -1, entries.getPointer(), entriesTotal.getPointer());
int entriesVal = entries.getValue().intValue();
int entriesTotalVal = entriesTotal.getValue().intValue();
System.console().printf(uInfo_0.toString());
}
}
```
</details>
### Ссылки которые открыл при расследовании
- https://apps.inock.ru/jna.html Оригинальное сообщение
- https://stackoverflow.com/questions/10319152/jna-call-to-c-function-with-lpcwstr-parameters - Ответ про LPWSTR
- https://learn.microsoft.com/en-us/windows/win32/api/adshlp/nf-adshlp-adsgetobject - Спека на ADsGetObject
- https://learn.microsoft.com/en-us/windows/win32/adsi/binding-with-getobject-and-adsgetobject - Пример использования ADsGetObject
- https://java-native-access.github.io/jna/5.13.0/javadoc/com/sun/jna/Pointer.html#field.detail - Дока про Pointer
- https://github.com/nyholku/purejavacomm/blob/master/src/jtermios/windows/WinAPI.java - Пример продуктового использования winapi через JNA
- https://java-native-access.github.io/jna/4.2.0/index.html?com/sun/jna/platform/win32/WTypes.LPWSTR.html - LPWSTR в JNA
- https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values - Тип HRESULT
- http://systemmanager.ru/adam-sdk.en/adsi/adsgetobject.htm - Ещё одно описание ADsGetObject, из которого можно получить название библиотеки
- https://learn.microsoft.com/en-us/windows/win32/adsi/programming-adsi-with-javacom - Правильный путь использования ADSI в Java
- https://stackoverflow.com/a/44122970 - Мапинг COM-объекта в Java
- https://learn.microsoft.com/en-us/windows/win32/api/iads/nn-iads-iads - Спека на IADs интерфейс
- https://learn.microsoft.com/en-us/windows/win32/wmformat/interface-identifiers - Таблица GUID для IID интерфейсов