0
# JNA Windows Integration
1
2
This document covers JNA's Windows-specific functionality including stdcall calling convention support, Win32 API integration, and Windows-specific utilities.
3
4
## Core Imports
5
6
```java { .api }
7
import com.sun.jna.win32.StdCall;
8
import com.sun.jna.win32.StdCallLibrary;
9
import com.sun.jna.win32.W32APIOptions;
10
import com.sun.jna.win32.StdCallFunctionMapper;
11
import com.sun.jna.win32.W32APIFunctionMapper;
12
import com.sun.jna.win32.W32APITypeMapper;
13
```
14
15
## StdCall Interface - Windows Calling Convention
16
17
```java { .api }
18
/**
19
* Marker interface for stdcall calling convention
20
* Used by Windows API functions
21
*/
22
public interface StdCall extends AltCallingConvention {
23
// Marker interface - no methods
24
}
25
26
/**
27
* Base interface for Windows stdcall libraries
28
*/
29
public interface StdCallLibrary extends Library, StdCall {
30
/** Stdcall calling convention constant */
31
int STDCALL_CONVENTION = Function.ALT_CONVENTION;
32
33
/** Auto-lookup of stdcall-decorated names */
34
FunctionMapper FUNCTION_MAPPER = new StdCallFunctionMapper();
35
36
/**
37
* Callback interface using stdcall convention
38
*/
39
public interface StdCallCallback extends Callback, StdCall {
40
// Marker interface for stdcall callbacks
41
}
42
}
43
```
44
45
## Win32 API Options and Configuration
46
47
```java { .api }
48
/**
49
* Standard options for Win32 API usage
50
*/
51
public interface W32APIOptions extends StdCallLibrary {
52
/** Options for Unicode (wide character) Win32 APIs */
53
Map<String, Object> UNICODE_OPTIONS = Collections.unmodifiableMap(new HashMap<String, Object>() {{
54
put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
55
put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
56
}});
57
58
/** Options for ASCII/MBCS Win32 APIs */
59
Map<String, Object> ASCII_OPTIONS = Collections.unmodifiableMap(new HashMap<String, Object>() {{
60
put(OPTION_TYPE_MAPPER, W32APITypeMapper.ASCII);
61
put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.ASCII);
62
}});
63
64
/** Default options based on w32.ascii system property */
65
Map<String, Object> DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii")
66
? ASCII_OPTIONS : UNICODE_OPTIONS;
67
}
68
```
69
70
## Basic Windows Library Definition
71
72
```java { .api }
73
// Simple Windows library interface
74
public interface Kernel32 extends StdCallLibrary {
75
Kernel32 INSTANCE = Native.loadLibrary("kernel32", Kernel32.class);
76
77
/**
78
* Get current process ID
79
* DWORD GetCurrentProcessId(void);
80
*/
81
int GetCurrentProcessId();
82
83
/**
84
* Get handle to current process
85
* HANDLE GetCurrentProcess(void);
86
*/
87
Pointer GetCurrentProcess();
88
89
/**
90
* Sleep for specified milliseconds
91
* void Sleep(DWORD dwMilliseconds);
92
*/
93
void Sleep(int dwMilliseconds);
94
95
/**
96
* Get last Win32 error code
97
* DWORD GetLastError(void);
98
*/
99
int GetLastError();
100
101
/**
102
* Set last error code
103
* void SetLastError(DWORD dwErrCode);
104
*/
105
void SetLastError(int dwErrCode);
106
}
107
108
// Usage
109
int processId = Kernel32.INSTANCE.GetCurrentProcessId();
110
Pointer processHandle = Kernel32.INSTANCE.GetCurrentProcess();
111
Kernel32.INSTANCE.Sleep(1000); // Sleep for 1 second
112
```
113
114
## Unicode vs ASCII API Handling
115
116
```java { .api }
117
// Library supporting both ASCII and Unicode variants
118
public interface User32 extends StdCallLibrary {
119
User32 INSTANCE = Native.loadLibrary("user32", User32.class,
120
W32APIOptions.DEFAULT_OPTIONS);
121
122
/**
123
* Find window by class and window name
124
* Maps to FindWindowA or FindWindowW based on options
125
*/
126
Pointer FindWindow(String lpClassName, String lpWindowName);
127
128
/**
129
* Get window text
130
* Maps to GetWindowTextA or GetWindowTextW
131
*/
132
int GetWindowText(Pointer hWnd, char[] lpString, int nMaxCount);
133
134
/**
135
* Set window text
136
* Maps to SetWindowTextA or SetWindowTextW
137
*/
138
boolean SetWindowText(Pointer hWnd, String lpString);
139
140
/**
141
* Show message box
142
* Maps to MessageBoxA or MessageBoxW
143
*/
144
int MessageBox(Pointer hWnd, String lpText, String lpCaption, int uType);
145
}
146
147
// Explicit Unicode library
148
public interface User32W extends StdCallLibrary {
149
User32W INSTANCE = Native.loadLibrary("user32", User32W.class,
150
W32APIOptions.UNICODE_OPTIONS);
151
152
Pointer FindWindowW(WString lpClassName, WString lpWindowName);
153
int GetWindowTextW(Pointer hWnd, char[] lpString, int nMaxCount);
154
boolean SetWindowTextW(Pointer hWnd, WString lpString);
155
int MessageBoxW(Pointer hWnd, WString lpText, WString lpCaption, int uType);
156
}
157
158
// Explicit ASCII library
159
public interface User32A extends StdCallLibrary {
160
User32A INSTANCE = Native.loadLibrary("user32", User32A.class,
161
W32APIOptions.ASCII_OPTIONS);
162
163
Pointer FindWindowA(String lpClassName, String lpWindowName);
164
int GetWindowTextA(Pointer hWnd, byte[] lpString, int nMaxCount);
165
boolean SetWindowTextA(Pointer hWnd, String lpString);
166
int MessageBoxA(Pointer hWnd, String lpText, String lpCaption, int uType);
167
}
168
```
169
170
## Function Name Mapping
171
172
```java { .api }
173
/**
174
* Maps function names to stdcall-decorated names
175
*/
176
public class StdCallFunctionMapper implements FunctionMapper {
177
/**
178
* Get decorated function name for stdcall convention
179
* @param library Native library
180
* @param method Java method
181
* @return Decorated name (e.g., "_function@12")
182
*/
183
public String getFunctionName(NativeLibrary library, Method method);
184
}
185
186
/**
187
* Function mapper for Win32 API with ASCII/Unicode variants
188
*/
189
public class W32APIFunctionMapper implements FunctionMapper {
190
/** Mapper for Unicode APIs (adds W suffix) */
191
public static final FunctionMapper UNICODE = new W32APIFunctionMapper(true);
192
193
/** Mapper for ASCII APIs (adds A suffix) */
194
public static final FunctionMapper ASCII = new W32APIFunctionMapper(false);
195
196
/**
197
* Get function name with A or W suffix
198
* @param library Native library
199
* @param method Java method
200
* @return Function name with suffix
201
*/
202
public String getFunctionName(NativeLibrary library, Method method);
203
}
204
```
205
206
## Type Mapping for Win32
207
208
```java { .api }
209
/**
210
* Type mapper for Win32 API types (strings and BOOLs)
211
*/
212
public class W32APITypeMapper extends DefaultTypeMapper {
213
/** TypeMapper for Unicode Win32 APIs */
214
public static final TypeMapper UNICODE;
215
216
/** TypeMapper for ASCII/MBCS Win32 APIs */
217
public static final TypeMapper ASCII;
218
219
/** Default TypeMapper based on w32.ascii system property */
220
public static final TypeMapper DEFAULT;
221
222
static {
223
UNICODE = new W32APITypeMapper(true);
224
ASCII = new W32APITypeMapper(false);
225
DEFAULT = Boolean.getBoolean("w32.ascii") ? ASCII : UNICODE;
226
}
227
}
228
```
229
230
## Common Windows Data Types
231
232
```java { .api }
233
// Windows handle types
234
public static class HANDLE extends PointerType {
235
public HANDLE() { }
236
public HANDLE(Pointer p) { setPointer(p); }
237
}
238
239
public static class HWND extends HANDLE {
240
public HWND() { }
241
public HWND(Pointer p) { super(p); }
242
}
243
244
public static class HMODULE extends HANDLE {
245
public HMODULE() { }
246
public HMODULE(Pointer p) { super(p); }
247
}
248
249
// Windows integer types
250
public static class DWORD extends IntegerType {
251
public DWORD() { super(4, true); } // 4-byte unsigned
252
public DWORD(long value) { super(4, value, true); }
253
}
254
255
public static class WORD extends IntegerType {
256
public WORD() { super(2, true); } // 2-byte unsigned
257
public WORD(long value) { super(2, value, true); }
258
}
259
260
public static class BYTE extends IntegerType {
261
public BYTE() { super(1, true); } // 1-byte unsigned
262
public BYTE(long value) { super(1, value, true); }
263
}
264
265
// BOOL type (maps to int)
266
public static class BOOL implements NativeMapped {
267
private final boolean value;
268
269
public BOOL() { this.value = false; }
270
public BOOL(boolean value) { this.value = value; }
271
272
public boolean booleanValue() { return value; }
273
274
@Override
275
public Object fromNative(Object nativeValue, FromNativeContext context) {
276
return new BOOL(((Integer) nativeValue) != 0);
277
}
278
279
@Override
280
public Object toNative() {
281
return value ? 1 : 0;
282
}
283
284
@Override
285
public Class<?> nativeType() {
286
return Integer.class;
287
}
288
}
289
```
290
291
## Windows Structures
292
293
```java { .api }
294
// RECT structure
295
public static class RECT extends Structure {
296
public int left;
297
public int top;
298
public int right;
299
public int bottom;
300
301
public RECT() { }
302
303
public RECT(int left, int top, int right, int bottom) {
304
this.left = left;
305
this.top = top;
306
this.right = right;
307
this.bottom = bottom;
308
write();
309
}
310
311
@Override
312
protected List<String> getFieldOrder() {
313
return Arrays.asList("left", "top", "right", "bottom");
314
}
315
}
316
317
// POINT structure
318
public static class POINT extends Structure {
319
public int x;
320
public int y;
321
322
public POINT() { }
323
324
public POINT(int x, int y) {
325
this.x = x;
326
this.y = y;
327
write();
328
}
329
330
@Override
331
protected List<String> getFieldOrder() {
332
return Arrays.asList("x", "y");
333
}
334
}
335
336
// SYSTEMTIME structure
337
public static class SYSTEMTIME extends Structure {
338
public short wYear;
339
public short wMonth;
340
public short wDayOfWeek;
341
public short wDay;
342
public short wHour;
343
public short wMinute;
344
public short wSecond;
345
public short wMilliseconds;
346
347
@Override
348
protected List<String> getFieldOrder() {
349
return Arrays.asList("wYear", "wMonth", "wDayOfWeek", "wDay",
350
"wHour", "wMinute", "wSecond", "wMilliseconds");
351
}
352
}
353
```
354
355
## Complete Windows API Example
356
357
```java { .api }
358
// Extended Kernel32 interface
359
public interface Kernel32 extends StdCallLibrary {
360
Kernel32 INSTANCE = Native.loadLibrary("kernel32", Kernel32.class,
361
W32APIOptions.DEFAULT_OPTIONS);
362
363
// Process functions
364
int GetCurrentProcessId();
365
Pointer GetCurrentProcess();
366
Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);
367
boolean CloseHandle(Pointer hObject);
368
boolean TerminateProcess(Pointer hProcess, int uExitCode);
369
370
// Memory functions
371
Pointer VirtualAlloc(Pointer lpAddress, int dwSize, int flAllocationType, int flProtect);
372
boolean VirtualFree(Pointer lpAddress, int dwSize, int dwFreeType);
373
374
// Module functions
375
Pointer GetModuleHandle(String lpModuleName);
376
Pointer LoadLibrary(String lpFileName);
377
boolean FreeLibrary(Pointer hModule);
378
Pointer GetProcAddress(Pointer hModule, String lpProcName);
379
380
// System info
381
void GetSystemTime(SYSTEMTIME lpSystemTime);
382
void GetLocalTime(SYSTEMTIME lpSystemTime);
383
int GetTickCount();
384
385
// File functions
386
Pointer CreateFile(String lpFileName, int dwDesiredAccess, int dwShareMode,
387
Pointer lpSecurityAttributes, int dwCreationDisposition,
388
int dwFlagsAndAttributes, Pointer hTemplateFile);
389
boolean ReadFile(Pointer hFile, Pointer lpBuffer, int nNumberOfBytesToRead,
390
IntByReference lpNumberOfBytesRead, Pointer lpOverlapped);
391
boolean WriteFile(Pointer hFile, Pointer lpBuffer, int nNumberOfBytesToWrite,
392
IntByReference lpNumberOfBytesWritten, Pointer lpOverlapped);
393
394
// Constants
395
int PROCESS_ALL_ACCESS = 0x1F0FFF;
396
int MEM_COMMIT = 0x1000;
397
int MEM_RESERVE = 0x2000;
398
int MEM_RELEASE = 0x8000;
399
int PAGE_READWRITE = 0x04;
400
int GENERIC_READ = 0x80000000;
401
int GENERIC_WRITE = 0x40000000;
402
int CREATE_ALWAYS = 2;
403
int OPEN_EXISTING = 3;
404
}
405
406
// Extended User32 interface
407
public interface User32 extends StdCallLibrary {
408
User32 INSTANCE = Native.loadLibrary("user32", User32.class,
409
W32APIOptions.DEFAULT_OPTIONS);
410
411
// Window functions
412
Pointer FindWindow(String lpClassName, String lpWindowName);
413
Pointer GetForegroundWindow();
414
boolean SetForegroundWindow(Pointer hWnd);
415
boolean ShowWindow(Pointer hWnd, int nCmdShow);
416
boolean IsWindowVisible(Pointer hWnd);
417
418
// Window properties
419
int GetWindowText(Pointer hWnd, char[] lpString, int nMaxCount);
420
boolean SetWindowText(Pointer hWnd, String lpString);
421
boolean GetWindowRect(Pointer hWnd, RECT lpRect);
422
boolean SetWindowPos(Pointer hWnd, Pointer hWndInsertAfter,
423
int X, int Y, int cx, int cy, int uFlags);
424
425
// Input functions
426
boolean GetCursorPos(POINT lpPoint);
427
boolean SetCursorPos(int X, int Y);
428
short GetKeyState(int nVirtKey);
429
430
// Message functions
431
int MessageBox(Pointer hWnd, String lpText, String lpCaption, int uType);
432
boolean PostMessage(Pointer hWnd, int Msg, Pointer wParam, Pointer lParam);
433
int SendMessage(Pointer hWnd, int Msg, Pointer wParam, Pointer lParam);
434
435
// Constants
436
int SW_HIDE = 0;
437
int SW_NORMAL = 1;
438
int SW_MAXIMIZE = 3;
439
int SW_MINIMIZE = 6;
440
int MB_OK = 0x00000000;
441
int MB_YESNO = 0x00000004;
442
int WM_CLOSE = 0x0010;
443
int VK_RETURN = 0x0D;
444
int VK_ESCAPE = 0x1B;
445
}
446
```
447
448
## Windows-specific Callback Support
449
450
```java { .api }
451
/**
452
* Callback that can be used in DLL context on Windows
453
*/
454
public interface DLLCallback extends Callback {
455
// Marker interface for DLL-compatible callbacks
456
}
457
458
// Windows callback examples
459
public interface WindowEnumProc extends StdCallLibrary.StdCallCallback {
460
boolean callback(Pointer hWnd, Pointer lParam);
461
}
462
463
public interface HookProc extends StdCallLibrary.StdCallCallback {
464
int callback(int nCode, Pointer wParam, Pointer lParam);
465
}
466
467
// Usage with Win32 APIs
468
public interface User32Extended extends StdCallLibrary {
469
User32Extended INSTANCE = Native.loadLibrary("user32", User32Extended.class);
470
471
/**
472
* Enumerate all top-level windows
473
* BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
474
*/
475
boolean EnumWindows(WindowEnumProc lpEnumFunc, Pointer lParam);
476
477
/**
478
* Install hook procedure
479
* HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
480
*/
481
Pointer SetWindowsHookEx(int idHook, HookProc lpfn, Pointer hMod, int dwThreadId);
482
483
/**
484
* Remove hook procedure
485
* BOOL UnhookWindowsHookEx(HHOOK hhk);
486
*/
487
boolean UnhookWindowsHookEx(Pointer hhk);
488
}
489
490
// Callback implementations
491
WindowEnumProc windowEnumerator = new WindowEnumProc() {
492
@Override
493
public boolean callback(Pointer hWnd, Pointer lParam) {
494
char[] windowText = new char[512];
495
User32.INSTANCE.GetWindowText(hWnd, windowText, windowText.length);
496
String title = new String(windowText).trim();
497
498
if (!title.isEmpty()) {
499
System.out.println("Window: " + title);
500
}
501
return true; // Continue enumeration
502
}
503
};
504
505
// Enumerate all windows
506
User32Extended.INSTANCE.EnumWindows(windowEnumerator, Pointer.NULL);
507
```
508
509
## Practical Windows Usage Examples
510
511
```java { .api }
512
// Get current window information
513
public class WindowInfo {
514
public static void main(String[] args) {
515
// Get foreground window
516
Pointer hwnd = User32.INSTANCE.GetForegroundWindow();
517
if (hwnd != null) {
518
// Get window title
519
char[] titleBuffer = new char[512];
520
int titleLength = User32.INSTANCE.GetWindowText(hwnd, titleBuffer, titleBuffer.length);
521
String title = new String(titleBuffer, 0, titleLength);
522
523
// Get window position
524
RECT rect = new RECT();
525
User32.INSTANCE.GetWindowRect(hwnd, rect);
526
527
System.out.println("Active window: " + title);
528
System.out.println("Position: (" + rect.left + ", " + rect.top +
529
") - (" + rect.right + ", " + rect.bottom + ")");
530
}
531
}
532
}
533
534
// System information
535
public class SystemInfo {
536
public static void main(String[] args) {
537
// Get current time
538
SYSTEMTIME time = new SYSTEMTIME();
539
Kernel32.INSTANCE.GetSystemTime(time);
540
541
System.out.printf("Current UTC time: %04d-%02d-%02d %02d:%02d:%02d.%03d%n",
542
time.wYear, time.wMonth, time.wDay,
543
time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);
544
545
// Get process info
546
int processId = Kernel32.INSTANCE.GetCurrentProcessId();
547
Pointer processHandle = Kernel32.INSTANCE.GetCurrentProcess();
548
549
System.out.println("Process ID: " + processId);
550
System.out.println("Process handle: " + processHandle);
551
}
552
}
553
554
// File operations
555
public class FileOperations {
556
public static void writeFile(String filename, String content) {
557
Pointer hFile = Kernel32.INSTANCE.CreateFile(
558
filename,
559
Kernel32.GENERIC_WRITE,
560
0, // No sharing
561
null, // Default security
562
Kernel32.CREATE_ALWAYS,
563
0, // Normal attributes
564
null // No template
565
);
566
567
if (hFile == null || hFile.equals(Pointer.createConstant(-1))) {
568
throw new RuntimeException("Failed to create file: " +
569
Kernel32.INSTANCE.GetLastError());
570
}
571
572
try {
573
byte[] data = content.getBytes("UTF-8");
574
Memory buffer = new Memory(data.length);
575
buffer.write(0, data, 0, data.length);
576
577
IntByReference bytesWritten = new IntByReference();
578
boolean success = Kernel32.INSTANCE.WriteFile(
579
hFile, buffer, data.length, bytesWritten, null);
580
581
if (!success) {
582
throw new RuntimeException("Failed to write file: " +
583
Kernel32.INSTANCE.GetLastError());
584
}
585
586
System.out.println("Wrote " + bytesWritten.getValue() + " bytes");
587
588
} catch (Exception e) {
589
throw new RuntimeException("Error writing file", e);
590
} finally {
591
Kernel32.INSTANCE.CloseHandle(hFile);
592
}
593
}
594
}
595
```
596
597
## Error Handling with GetLastError
598
599
```java { .api }
600
// Error handling pattern
601
public class Win32ErrorHandler {
602
public static void checkResult(boolean success, String operation) {
603
if (!success) {
604
int errorCode = Kernel32.INSTANCE.GetLastError();
605
throw new Win32Exception(errorCode, operation + " failed");
606
}
607
}
608
609
public static void checkHandle(Pointer handle, String operation) {
610
if (handle == null || handle.equals(Pointer.createConstant(-1))) {
611
int errorCode = Kernel32.INSTANCE.GetLastError();
612
throw new Win32Exception(errorCode, operation + " failed");
613
}
614
}
615
}
616
617
// Custom exception for Win32 errors
618
public class Win32Exception extends RuntimeException {
619
private final int errorCode;
620
621
public Win32Exception(int errorCode, String message) {
622
super(message + " (error code: " + errorCode + ")");
623
this.errorCode = errorCode;
624
}
625
626
public int getErrorCode() {
627
return errorCode;
628
}
629
}
630
631
// Usage
632
try {
633
Pointer handle = Kernel32.INSTANCE.CreateFile(filename, access, share, null, disposition, flags, null);
634
Win32ErrorHandler.checkHandle(handle, "CreateFile");
635
636
boolean success = Kernel32.INSTANCE.WriteFile(handle, buffer, size, bytesWritten, null);
637
Win32ErrorHandler.checkResult(success, "WriteFile");
638
639
} catch (Win32Exception e) {
640
System.err.println("Win32 operation failed: " + e.getMessage());
641
System.err.println("Error code: " + e.getErrorCode());
642
}
643
```
644
645
## Advanced Windows Features
646
647
```java { .api }
648
// Registry access
649
public interface Advapi32 extends StdCallLibrary {
650
Advapi32 INSTANCE = Native.loadLibrary("advapi32", Advapi32.class);
651
652
int RegOpenKeyEx(Pointer hKey, String lpSubKey, int ulOptions, int samDesired, PointerByReference phkResult);
653
int RegQueryValueEx(Pointer hKey, String lpValueName, Pointer lpReserved, IntByReference lpType,
654
Pointer lpData, IntByReference lpcbData);
655
int RegCloseKey(Pointer hKey);
656
657
// Registry constants
658
Pointer HKEY_CURRENT_USER = Pointer.createConstant(0x80000001L);
659
Pointer HKEY_LOCAL_MACHINE = Pointer.createConstant(0x80000002L);
660
int KEY_READ = 0x20019;
661
}
662
663
// Performance counters
664
public interface Pdh extends StdCallLibrary {
665
Pdh INSTANCE = Native.loadLibrary("pdh", Pdh.class);
666
667
int PdhOpenQuery(Pointer szDataSource, Pointer dwUserData, PointerByReference phQuery);
668
int PdhAddCounter(Pointer hQuery, String szFullCounterPath, Pointer dwUserData, PointerByReference phCounter);
669
int PdhCollectQueryData(Pointer hQuery);
670
int PdhGetFormattedCounterValue(Pointer hCounter, int dwFormat, Pointer lpdwType, Pointer pValue);
671
int PdhCloseQuery(Pointer hQuery);
672
}
673
```
674
675
This comprehensive Windows integration provides full access to Win32 APIs with proper calling convention support, automatic function name resolution, type mapping, and error handling for robust Windows application development.