Skip to content

Commit e4e0968

Browse files
committed
Merge pull request #545 from mlfreeman2/kernel32-additional-2
Added EnumResourceTypes and EnumResourceNames to Kernel32
2 parents 5ec9eeb + b984cf6 commit e4e0968

File tree

6 files changed

+989
-666
lines changed

6 files changed

+989
-666
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Features
1818
* [#535](https://github.com/java-native-access/jna/pull/535): Added `GetDesktopWindow` to `com.sun.jna.platform.win32.User32` - [@mlfreeman2](https://github.com/mlfreeman2).
1919
* [#543](https://github.com/java-native-access/jna/pull/543): Added `ProcessIdToSessionId`, `LoadLibraryEx`, `FreeLibrary` and `Find/Load/Lock/SizeofResource` to `com.sun.jna.platform.win32.Kernel32` - [@mlfreeman2](https://github.com/mlfreeman2).
2020
* [#547](https://github.com/java-native-access/jna/pull/547): Added `GetSystemTimes` to `com.sun.jna.platform.win32.Kernel32` - [@dbwiddis](https://github.com/dbwiddis).
21+
* [#545](https://github.com/java-native-access/jna/pull/545): Added `EnumResourceTypes` and `EnumResourceNames` to `com.sun.jna.platform.win32.Kernel32` - [@mlfreeman2](https://github.com/mlfreeman2).
2122

2223
Bug Fixes
2324
---------

contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java

+67
Original file line numberDiff line numberDiff line change
@@ -3202,4 +3202,71 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName,
32023202
* information, call the GetLastError function.
32033203
*/
32043204
boolean FreeLibrary(HMODULE module);
3205+
3206+
/**
3207+
* Enumerates resource types within a binary module.<br>
3208+
* Starting with Windows Vista, this is typically a language-neutral
3209+
* Portable Executable (LN file), and the enumeration also includes
3210+
* resources from one of the corresponding language-specific resource files
3211+
* (.mui files)-if one exists-that contain localizable language resources.
3212+
* It is also possible to use hModule to specify a .mui file, in which case
3213+
* only that file is searched for resource types.<br>
3214+
* Alternately, applications can call EnumResourceTypesEx, which provides
3215+
* more precise control over which resource files to enumerate.
3216+
*
3217+
* @param hModule
3218+
* A handle to a module to be searched.<br>
3219+
* This handle must be obtained through LoadLibrary or
3220+
* LoadLibraryEx.<br>
3221+
* See Remarks for more information. If this parameter is NULL,
3222+
* that is equivalent to passing in a handle to the module used
3223+
* to create the current process.
3224+
* @param proc
3225+
* A pointer to the callback function to be called for each
3226+
* enumerated resource type.<br>
3227+
* For more information, see the EnumResTypeProc function.
3228+
* @param lParam
3229+
* An application-defined value passed to the callback function.
3230+
* @return Returns TRUE if successful; otherwise, FALSE. To get extended
3231+
* error information, call GetLastError.
3232+
*/
3233+
boolean EnumResourceTypes(HMODULE hModule, WinBase.EnumResTypeProc proc, Pointer lParam);
3234+
3235+
/**
3236+
* Enumerates resources of a specified type within a binary module. <br>
3237+
* For Windows Vista and later, this is typically a language-neutral
3238+
* Portable Executable (LN file), and the enumeration will also include
3239+
* resources from the corresponding language-specific resource files (.mui
3240+
* files) that contain localizable language resources.<br>
3241+
* It is also possible for hModule to specify an .mui file, in which case
3242+
* only that file is searched for resources.
3243+
*
3244+
* @param hModule
3245+
* A handle to a module to be searched. <br>
3246+
* Starting with Windows Vista, if this is an LN file, then
3247+
* appropriate .mui files (if any exist) are included in the
3248+
* search.<br>
3249+
* If this parameter is NULL, that is equivalent to passing in a
3250+
* handle to the module used to create the current process.
3251+
* @param type
3252+
* The type of the resource for which the name is being
3253+
* enumerated.<br>
3254+
* Alternately, rather than a pointer, this parameter can be
3255+
* MAKEINTRESOURCE(ID), where ID is an integer value representing
3256+
* a predefined resource type.<br>
3257+
* For a list of predefined resource types, see Resource Types.
3258+
* For more information, see the Remarks section below.
3259+
* @param proc
3260+
* A pointer to the callback function to be called for each
3261+
* enumerated resource name or ID. For more information, see
3262+
* EnumResNameProc.
3263+
* @param lParam
3264+
* An application-defined value passed to the callback function.
3265+
* This parameter can be used in error checking.
3266+
* @return The return value is TRUE if the function succeeds or FALSE if the
3267+
* function does not find a resource of the type specified, or if
3268+
* the function fails for another reason. To get extended error
3269+
* information, call GetLastError.
3270+
*/
3271+
boolean EnumResourceNames(HMODULE hModule, Pointer type, WinBase.EnumResNameProc proc, Pointer lParam);
32053272
}

contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java

+113-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import java.io.File;
1616
import java.io.FileNotFoundException;
1717
import java.nio.ByteOrder;
18+
import java.util.ArrayList;
19+
import java.util.LinkedHashMap;
1820
import java.util.List;
1921
import java.util.Map;
2022
import java.util.TreeMap;
@@ -702,6 +704,7 @@ public static byte[] getResource(String path, String type, String name) {
702704
Win32Exception err = null;
703705
Pointer start = null;
704706
int length = 0;
707+
byte[] results = null;
705708
try {
706709
Pointer t = null;
707710
try {
@@ -741,6 +744,8 @@ public static byte[] getResource(String path, String type, String name) {
741744
if (start == null) {
742745
throw new IllegalStateException("LockResource returned null.");
743746
}
747+
// have to capture it into a byte array before you free the library, otherwise bad things happen.
748+
results = start.getByteArray(0, length);
744749
} catch (Win32Exception we) {
745750
err = we;
746751
} finally {
@@ -760,7 +765,114 @@ public static byte[] getResource(String path, String type, String name) {
760765
throw err;
761766
}
762767

763-
return start.getByteArray(0, length);
768+
return results;
764769
}
765770

771+
/**
772+
* Gets a list of all resources from the specified executable file
773+
*
774+
* @param path
775+
* The path to the executable file
776+
* @return A map of resource type name/ID => resources.<br>
777+
* A map key + a single list item + the path to the executable can
778+
* be handed off to getResource() to actually get the resource.
779+
*/
780+
public static Map<String, List<String>> getResourceNames(String path) {
781+
HMODULE target = Kernel32.INSTANCE.LoadLibraryEx(path, null, Kernel32.LOAD_LIBRARY_AS_DATAFILE);
782+
783+
if (target == null) {
784+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
785+
}
786+
787+
final List<String> types = new ArrayList<String>();
788+
final Map<String, List<String>> result = new LinkedHashMap<String, List<String>>();
789+
790+
WinBase.EnumResTypeProc ertp = new WinBase.EnumResTypeProc() {
791+
792+
@Override
793+
public boolean invoke(HMODULE module, Pointer type, Pointer lParam) {
794+
// simulate IS_INTRESOURCE macro defined in WinUser.h
795+
// basically that means that if "type" is less than or equal to 65,535
796+
// it assumes it's an ID.
797+
// otherwise it assumes it's a pointer to a string
798+
if (Pointer.nativeValue(type) <= 65535) {
799+
types.add(Pointer.nativeValue(type) + "");
800+
} else {
801+
types.add(type.getWideString(0));
802+
}
803+
return true;
804+
}
805+
};
806+
807+
WinBase.EnumResNameProc ernp = new WinBase.EnumResNameProc() {
808+
809+
@Override
810+
public boolean invoke(HMODULE module, Pointer type, Pointer name, Pointer lParam) {
811+
String typeName = "";
812+
813+
if (Pointer.nativeValue(type) <= 65535) {
814+
typeName = Pointer.nativeValue(type) + "";
815+
} else {
816+
typeName = type.getWideString(0);
817+
}
818+
819+
if (Pointer.nativeValue(name) < 65535) {
820+
result.get(typeName).add(Pointer.nativeValue(name) + "");
821+
} else {
822+
result.get(typeName).add(name.getWideString(0));
823+
}
824+
825+
return true;
826+
}
827+
};
828+
829+
830+
Win32Exception err = null;
831+
try {
832+
if (!Kernel32.INSTANCE.EnumResourceTypes(target, ertp, null)) {
833+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
834+
}
835+
836+
for (final String typeName : types) {
837+
result.put(typeName, new ArrayList<String>());
838+
839+
// simulate MAKEINTRESOURCE macro in WinUser.h
840+
// basically, if the value passed in can be parsed as a number then convert it into one and run with that.
841+
// otherwise, assume it's a string and construct a pointer to said string.
842+
Pointer pointer = null;
843+
try {
844+
pointer = new Pointer(Long.parseLong(typeName));
845+
} catch (NumberFormatException e) {
846+
pointer = new Memory(Native.WCHAR_SIZE * (typeName.length() + 1));
847+
pointer.setWideString(0, typeName);
848+
}
849+
850+
boolean callResult = Kernel32.INSTANCE.EnumResourceNames(target, pointer, ernp, null);
851+
852+
if (!callResult) {
853+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
854+
}
855+
}
856+
} catch (Win32Exception e) {
857+
err = e;
858+
} finally {
859+
// from what I can tell on MSDN, the only thing that needs cleanup
860+
// on this is the HMODULE from LoadLibrary
861+
if (target != null) {
862+
if (!Kernel32.INSTANCE.FreeLibrary(target)) {
863+
Win32Exception we = new Win32Exception(Kernel32.INSTANCE.GetLastError());
864+
if (err != null) {
865+
we.addSuppressed(err);
866+
}
867+
throw we;
868+
}
869+
}
870+
}
871+
872+
if (err != null) {
873+
throw err;
874+
}
875+
return result;
876+
}
877+
766878
}

0 commit comments

Comments
 (0)