I have a Java class calling a native method ACLInfo(String path), this native method should return HashMap to be used in java. Here's the java code.
import java.util.*;
public class test
{
native Map<String, String[]> ACLInfo(String s);
static
{
System.loadLibrary("test");
}
static public void main(String args[])
{
test obj = new test();
Map<String, String[]> map = obj.ACLInfo("C:/Windows/Boot/Resources/bootres.dll");
for (Map.Entry<String, String[]> entry : map.entrySet())
{
String name = entry.getKey();
System.out.println("Name:"+name);
System.out.println("Properties are:");
for(String text : entry.getValue())
{
if(text.equals("Full Control")){
System.out.println(text);
continue;
}
if(text.equals("Read"))
System.out.println(text);
if(text.equals("Write"))
System.out.println(text);
if(text.equals("Execute"))
System.out.println(text);
}
}
}
}
The native code is.
#include <iostream>
#include <jni.h>
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <Lmcons.h>
#include "test.h"
#include "accctrl.h"
#include "aclapi.h"
using namespace std;
JNIEXPORT jobject JNICALL Java_test_ACLInfo(JNIEnv *env, jobject jobj, jstring s)
{
jobjectArray ret;
jstring jstr;
PSID pSidOwner = NULL;
BOOL bRtnBool = TRUE;
DWORD dwRtnCode = 0;
SID_NAME_USE eUse = SidTypeUnknown;
HANDLE hFile;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pOldDACL = NULL;
int i,aceNum;
const char* test;
std::string name,reslt;
const char* nativeString = env->GetStringUTFChars(s, 0);
LPCSTR file = nativeString;
// Get the handle of the file object.
hFile = CreateFile(
file,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// Get the SID of the file.
dwRtnCode = GetSecurityInfo(
hFile,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
&pSidOwner,
NULL,
&pOldDACL,
NULL,
&pSD);
PACL pAcl = pOldDACL;
aceNum = pOldDACL->AceCount;
ret = (jobjectArray)env->NewObjectArray(3, env->FindClass("java/lang/String"), env->NewStringUTF(""));
jclass mapClass = env->FindClass("java/util/HashMap"); //HashMap class in java library
if(mapClass == NULL)
{
return NULL;
}
jsize map_len = aceNum;
jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V"); //constructor of HashMap class
jobject hashMap = env->NewObject(mapClass, init, map_len); //creating a new object for that class
jmethodID put = env->GetMethodID(mapClass, "put", "(Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;");
for (i = 0; i < aceNum; i++)
{
PACCESS_ALLOWED_ACE AceItem;
ACE_HEADER *aceAddr = NULL;
if (GetAce(pOldDACL, i, (LPVOID*)&AceItem) && GetAce(pOldDACL, i, (LPVOID*)&aceAddr))
{
LPTSTR AccountBuff = NULL, DomainBuff = NULL;
DWORD AccountBufflength = 1, DomainBufflength = 1;
PSID_NAME_USE peUse = new SID_NAME_USE;
PSID Sid = &AceItem->SidStart;
LookupAccountSid(NULL, Sid, AccountBuff, (LPDWORD)&AccountBufflength, DomainBuff, (LPDWORD)&DomainBufflength, peUse);
AccountBuff = (LPSTR)malloc(AccountBufflength * sizeof(LPSTR));
DomainBuff = (LPSTR)malloc(DomainBufflength * sizeof(LPSTR));
LookupAccountSid(NULL, Sid, AccountBuff, &AccountBufflength, DomainBuff, &DomainBufflength, peUse);
std::string acc=AccountBuff;
std::string dom=DomainBuff;
name = acc+"\\"+dom;
ACCESS_MASK Mask = AceItem->Mask;
if (((Mask & GENERIC_ALL) == GENERIC_ALL) || ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS)){
reslt="Full Control";
test = reslt.c_str();
env->SetObjectArrayElement(ret,i,env->NewStringUTF(test));
env->CallObjectMethod(hashMap, put, env->NewStringUTF(name.c_str()), ret);
continue;
}
int j=0;
if (((Mask & GENERIC_READ) == GENERIC_READ) || ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ))
{
reslt="Read";
test = reslt.c_str();
env->SetObjectArrayElement(ret,j++,env->NewStringUTF(test));
}
if (((Mask & GENERIC_WRITE) == GENERIC_WRITE) || ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
{
reslt="Write";
test = reslt.c_str();
env->SetObjectArrayElement(ret,j++,env->NewStringUTF(test));
}
if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE) || ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
{
reslt="Execute";
test = reslt.c_str();
env->SetObjectArrayElement(ret,j++,env->NewStringUTF(test));
}
env->CallObjectMethod(hashMap, put, env->NewStringUTF(name.c_str()), ret);
}
}
return hashMap;
}
On running this java class it shows: A fatal error has been detected by the Java Runtime Environment: EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006d6cd4ed, pid=19504, tid=0x0000000000003da0
What's the issue? I have made used of this stackoverflow post for creating hashmap How to create HashMap<String, String> through JNI then parse to java
I have rewritten your code to get rid of the most egregious bugs:
HashMap#put
was wrong.string[]
for every element you put in the hashmap. If you reuse the same object you will get N copies of the same string[]
.I have also removed a lot of the non-JVM cruft. Please try to keep your example code small and to the point.
JNIEXPORT jobject JNICALL Java_test_ACLInfo(JNIEnv *env, jobject jobj, jstring s)
{
// removed stuff
jclass mapClass = env->FindClass("java/util/HashMap"); //HashMap class in java library
jclass stringClass = env->FindClass("java/lang/String");
if(mapClass == NULL)
{
return NULL;
}
jsize map_len = aceNum;
jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V"); //constructor of HashMap class
jobject hashMap = env->NewObject(mapClass, init, map_len); //creating a new object for that class
jmethodID put = env->GetMethodID(mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
for (i = 0; i < aceNum; i++) {
// removed stuff
PACCESS_ALLOWED_ACE AceItem;
ACE_HEADER *aceAddr = NULL;
if (GetAce(pOldDACL, i, (LPVOID*)&AceItem) && GetAce(pOldDACL, i, (LPVOID*)&aceAddr)) {
// removed more stuff
std::string name = std::string(AccountBuff)+"\\"+std::string(DomainBuff);
std::vector<std::string> perms;
ACCESS_MASK Mask = AceItem->Mask;
if (((Mask & GENERIC_ALL) == GENERIC_ALL) || ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS)) {
perms.emplace_back("Full Control");
} else {
if (((Mask & GENERIC_READ) == GENERIC_READ) || ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ)) {
perms.emplace_back("Read");
}
if (((Mask & GENERIC_WRITE) == GENERIC_WRITE) || ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE)) {
perms.emplace_back("Write");
}
if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE) || ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE)) {
perms.emplace_back("Execute");
}
}
env->PushLocalFrame(10);
jobject ret = env->NewObjectArray(perms.size(), stringClass, nullptr);
for (int i = 0; i < perms.size(); i++) {
env->SetObjectArrayElement(ret, i, env->NewStringUTF(perms[i].c_str()));
}
env->CallObjectMethod(hashMap, put, env->NewStringUTF(name.c_str()), ret);
env->PopLocalFrame(nullptr);
}
}
return hashMap;
}
User contributions licensed under CC BY-SA 3.0