FindClass returns null - c++

I'm having problems with my FindClass call which returns null:
JData::JIgZorroBridgeClass = env->FindClass(JData::IgZorroBridgePath);
Most answers I find about this points to missing package name, or class loader issues.
IgZorroBridgePath here is my class with fully qualified package name, ie. com/igz/Zorro.
Also as you can see I'm initializing the JVM right before this FindClass call, so I think I should be on the correct thread already.
Is there anything else I can check?
#include <assert.h>
#include "JNIHandler.hpp"
#include "JReferences.hpp"
const char* JVMClassPathOption = "-Djava.class.path=Plugin/ig/igplugin-0.1.jar";
const char* IgZorroBridgePath = "com/danlind/igz/ZorroBridge";
void JNIHandler::init()
{
initializeJVM();
initializeJavaReferences();
}
void JNIHandler::initializeJVM()
{
if(isJVMLoaded) return;
JavaVMInitArgs args;
JavaVMOption options[1];
args.version = JData::JNI_VERSION;
args.nOptions = 1;
args.options = options;
options[0].optionString = (char*)JData::JVMClassPathOption;
args.ignoreUnrecognized = JNI_FALSE;
jint res = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
assert(res == JNI_OK);
isJVMLoaded = true;
}
JNIEnv* JNIHandler::getJNIEnvironment(){
return env;
}
JNIEnv* JNIHandler::getEnvForCurrentThread()
{
int envStat = jvm->GetEnv((void **)&env, JData::JNI_VERSION);
if (envStat == JNI_EDETACHED) {
jint res = jvm->AttachCurrentThread((void**)&env, NULL);
assert (res == JNI_OK);
}
return env;
}
void JNIHandler::initializeJavaReferences()
{
if(areJavaReferencesInitialized) return;
initExceptionHandling();
initBridgeObject();
registerNatives();
areJavaReferencesInitialized = true;
}
void JNIHandler::initBridgeObject()
{
JData::JIgZorroBridgeClass = env->FindClass(JData::IgZorroBridgePath);
checkJNIExcpetion(env);
registerClassMethods();
JData::JIgZorroBridgeObject = env->NewObject(JData::JIgZorroBridgeClass, JData::constructor.methodID);
checkJNIExcpetion(env);
}
void JNIHandler::initExceptionHandling()
{
JData::ExceptionClass = env->FindClass(JData::ExcPath);
JData::excGetName.methodID = env->GetMethodID(JData::ExceptionClass, JData::excGetName.name, JData::excGetName.signature);
}
void JNIHandler::registerNatives()
{
JData::JZorroClass = env->FindClass(JData::ZorroPath);
env->RegisterNatives(JData::JZorroClass, JData::nativesTable, JData::nativesTableSize);
checkJNIExcpetion(env);
}
void JNIHandler::registerClassMethods()
{
for(auto *desc : JData::igZorroBridgeMethods)
{
desc->methodID = env->GetMethodID(JData::JIgZorroBridgeClass, desc->name, desc->signature);
checkJNIExcpetion(env);
}
}
void JNIHandler::checkJNIExcpetion(JNIEnv* env)
{
jthrowable exc = env->ExceptionOccurred();
if (!exc) return;
jclass exccls(env->GetObjectClass(exc));
jstring name = static_cast<jstring>(env->CallObjectMethod(exccls, JData::excGetName.methodID));
char const* utfName(env->GetStringUTFChars(name, 0));
JData::excGetMessage.methodID = env->GetMethodID(exccls, JData::excGetMessage.name, JData::excGetMessage.signature);
jstring message = static_cast<jstring>(env->CallObjectMethod(exc, JData::excGetMessage.methodID));
char const* utfMessage(env->GetStringUTFChars(message, 0));
BrokerError(utfName);
BrokerError(utfMessage);
env->ReleaseStringUTFChars(message, utfMessage);
env->ReleaseStringUTFChars(name, utfName);
env->ExceptionClear();
}

I was using the spring boot maven plugin, which reshuffles the package structure. I switched to using the shade plugin instead, which doesn't move packages around. This enabled FindClass to find my java class.

Related

pull using libgit2, c++

I try pull from remote master to local master. In remote master only one not synchronized commit.
Error in method git_annotated_commit_lookup():
Git Error -3 : object not found - no match
for id (08f4a8cc00400100f083caccd755000020299210)
In callback fetchhead_ref_cb never exevute code in "if" block.
int fetchhead_ref_cb(const char *name, const char *url,
const git_oid *oid, unsigned int is_merge, void *payload)
{
qDebug() << "fetchhead_ref_cb";
if (is_merge)
{
qDebug() << "Is merge";
git_oid_cpy((git_oid *)payload, oid);
}
return 0;
}
bool pullBranch()
{
int error;
git_remote *remote;
git_oid branchOidToMerge;
/* lookup the remote */
error = git_remote_lookup(&remote, repo, "origin");
if (!checkForError(error, "Remote lookup")) {
git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
options.callbacks.credentials = cred_acquire_cb;
error = git_remote_fetch(remote,
NULL, /* refspecs, NULL to use the configured ones */
&options, /* options, empty for defaults */
"pull"); /* reflog mesage, usually "fetch" or "pull", you can leave it NULL for "fetch" */
if (!checkForError(error, "Remote fetch")) {
git_repository_fetchhead_foreach(repo, fetchhead_ref_cb, &branchOidToMerge);
git_merge_options merge_options = GIT_MERGE_OPTIONS_INIT;
git_checkout_options checkout_options = GIT_CHECKOUT_OPTIONS_INIT;
git_annotated_commit *commit;
error = git_annotated_commit_lookup(&commit, repo, &branchOidToMerge);
if (!checkForError(error, "Annotated commit lookup")) {
error = git_merge(repo, (const git_annotated_commit **)commit, 1, &merge_options, &checkout_options);
if (!checkForError(error, "Merge")) {
git_annotated_commit_free(commit);
git_repository_state_cleanup(repo);
git_remote_free(remote);
return true;
}
}
}
}
git_remote_free(remote);
return false;
}
Solution for fast-forward merge:
GitPullStatus GitWizard::pullBranch()
{
git_remote *remote;
int error = git_remote_lookup(&remote, repo, "origin");
if (!checkForError(error, "Remote lookup")) {
git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
options.callbacks.credentials = cred_acquire_cb;
error = git_remote_fetch(remote,
NULL, /* refspecs, NULL to use the configured ones */
&options, /* options, empty for defaults */
"pull"); /* reflog mesage, usually "fetch" or "pull", you can leave it NULL for "fetch" */
if (!checkForError(error, "Remote fetch")) {
git_oid branchOidToMerge;
git_repository_fetchhead_foreach(repo, fetchhead_ref_cb, &branchOidToMerge);
git_annotated_commit *their_heads[1];
error = git_annotated_commit_lookup(&their_heads[0], repo, &branchOidToMerge);
checkForError(error, "Annotated commit lookup");
git_merge_analysis_t anout;
git_merge_preference_t pout;
qDebug() << "Try analysis";
error = git_merge_analysis(&anout, &pout, repo, (const git_annotated_commit **) their_heads, 1);
checkForError(error, "Merge analysis");
if (anout & GIT_MERGE_ANALYSIS_UP_TO_DATE) {
qDebug() << "up to date";
git_annotated_commit_free(their_heads[0]);
git_repository_state_cleanup(repo);
git_remote_free(remote);
return GitPullStatus::GIT_UP_TO_DATE;
} else if (anout & GIT_MERGE_ANALYSIS_FASTFORWARD) {
qDebug() << "fast-forwarding";
git_reference *ref;
git_reference *newref;
const char *name = QString("refs/heads/").append(mCurrentBranch).toLocal8Bit().data();
if (git_reference_lookup(&ref, repo, name) == 0)
git_reference_set_target(&newref, ref, &branchOidToMerge, "pull: Fast-forward");
git_reset_from_annotated(repo, their_heads[0], GIT_RESET_HARD, NULL);
git_reference_free(ref);
git_repository_state_cleanup(repo);
}
git_annotated_commit_free(their_heads[0]);
git_repository_state_cleanup(repo);
git_remote_free(remote);
return GitPullStatus::GIT_PULL_OK;
}
}
git_remote_free(remote);
return GitPullStatus::GIT_PULL_ERROR;
}

Passing String argument from c to java using jni

I am trying to call java method from C, but getting below error
Status after JNI_CreateJavaVM=<0>
restCall method found:: Avinash Kumar
Execution error : file ''
error code: 114, pc=0, call=1, seg=0
114 Attempt to access item beyond bounds of memory (Signal 11)
Target is to send String as an argument from C to Java function.
Below is the code :
#include <jni.h>
#define ENV (*env)
enum eConst
{
MAX_Options = 21 ,
MAX_LREF = 120 ,
PARSING_ERROR = -10 ,
ERROR = -999 ,
EXCEPTION_ERROR = -100 ,
OK = 1 ,
YES = 'Y' ,
NO = 'N'
};
int main()
{
jint jRet;
jstring jszRes;
static JavaVM *jvm = NULL;
static JNIEnv *env = NULL ;
JavaVMInitArgs vm_args;
JavaVMOption options[MAX_Options-1];
int optionCount=0;
options[optionCount++].optionString = "-verbose:jni,class,gc";
char *path="user/work/avikumar/";
char *class_path="user/work/avikumar/";
char path_option[2000]={'\n'};
sprintf(path_option,"-Djava.class.path=%s/MyClass.class:%s/jersey-core-1.19.jar:%s/jersey-client-1.19.jar:%s/javax.ws.rs-api-2.0-m02.jar:.",class_path,path,path,path);
options[optionCount++].optionString = path_option;
options[optionCount++].optionString = "-Xms128m";
options[optionCount++].optionString = "-Xmx512m";
options[optionCount++].optionString = "-Xss8m";
vm_args.options = options;
vm_args.nOptions = optionCount;
vm_args.version = JNI_VERSION_1_6;
vm_args.ignoreUnrecognized = JNI_FALSE;
jRet = JNI_CreateJavaVM(&jvm,(void**)&env,(void*)&vm_args);
printf("Status after JNI_CreateJavaVM=<%d>\n",jRet);
if (jRet < 0)
{
return(-4);
}
if( ENV->EnsureLocalCapacity(env, MAX_LREF) < 0)
{
printf( "\n out of memory. Program terminated\n");
(*jvm)->DestroyJavaVM(jvm);
return(-5);
}
jclass jlocClass;
jlocClass= ENV->FindClass(env, "MyClass");
if (jlocClass == NULL || (*env)->ExceptionOccurred(env))
{
printf("Can not load the main class\n");
return (-6);
}
jmethodID restCall_method;
restCall_method = ENV->GetMethodID(env, jlocClass,"restCall","(Ljava/lang/String;)V");
if( restCall_method == NULL)
{
printf("restCall method not found\n");
return (-7);
}
char *inp = "Avinash Kumar";
printf("restCall method found:: %s\n",inp);
//jstring jstr = (*env)->NewStringUTF(env,inp);
jstring jstr1=(*env)->NewStringUTF(env, "Avinash Kumar");
ENV->CallVoidMethod(env, jlocClass, restCall_method,jstr1);
(*jvm)->DestroyJavaVM(jvm);
return 0;
}
MyClass.java
class MyClass
{
public static void main(String args[])
{
System.out.println("Hello Avinash\n");
}
public void restCall(String inp)
{
System.out.println(inp+ " :: Hello Avinash from restCall\n");
}
}
You can't mix static/non-static context inside JNI. You have two choices.
Static method
restCall_method = ENV->GetStaticMethodID(
env, jlocClass, "restCall", "(Ljava/lang/String;)V");
...
...
...
ENV->CallStaticVoidMethod(env, jlocClass, restCall_method,jstr1);
and, inside Java
public static void restCall(String inp)
or non-static method
jmethodID init = ENV->GetMethodID(env,jlocClass, "<init>", "()V");
jobject obj_MyClass = ENV->NewObject(env,jlocClass, init);
jmethodID restCall_method;
restCall_method = ENV->GetMethodID(env, jlocClass,"restCall","(Ljava/lang/String;)V");
...
...
...
ENV->CallVoidMethod(env, obj_MyClass, restCall_method,jstr1);
and, inside Java
public void restCall(String inp)
In first case, you have to use Static family methods to get id and call target method, in second case, you have to create instance of class and use methods for object based context.

Jni C++ findclass function return null

I found a problem with jni about C calling Java code.
Environment WIN10 JDK1.8
Currently I need C++ code to call Java code. At first I wrote a demothat was successful. Code show as below:
public class Sample2 {
public String name;
public static String sayHello(String name) {
return "Hello, " + name + "!";
}
public String sayHello() {
return "Hello, " + name + "!";
}
}
Some of the C++ code is as follows:
int main(){
printf("hello world");
JavaVMOption options[3];
JNIEnv* env;
JavaVM* jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jfieldID fid;
jobject obj;
char opt1[] = "-Djava.compiler=NONE";
char opt2[] = "-Djava.class.path=.";
char opt3[] = "-verbose:NONE";
options[0].optionString = opt1; options[0].extraInfo = NULL;
options[1].optionString = opt2; options[1].extraInfo = NULL;
options[2].optionString = opt3; options[2].extraInfo = NULL;
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = 0;
// 启动虚拟机
status = JNI_CreateJavaVM(&jvm, (void**)& env, &vm_args);
if (status != JNI_ERR){
// 先获得class对象
cls = env->FindClass("Sample2");
}
}
I used Eclipse to compile the Java code into a .class file, copy the .class file into my C++ project, the above DEMO C++ call Java function is successful, and the findclass function returns to normal.
Because I have to introduce a third-party JAR package org.eclipse.paho.client.mqttv3-1.2.0.jar in my own Java, based on the above example, I modified the Java code in DEMO, but when I want to reference the JAR package function, And then run successfully in Eclipse, when I copy the .class file to the C++ project. JNI_CreateJavaVM in the C++ code is returned successfully, but FINDCLASS always returns null, I don't know why. I have not changed the other parts code.
Some Java code:
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class Sample2 {
public String name;
static MqttAsyncClient mqttClient = null;
static String username = "xxx";
static String password = "xxx";
static String broker = "xxx";
public static void main(String[] args) throws InterruptedException {
System.out.print("hello");
}
public static void start() {
String clientId = "mqttserver" + String.valueOf(System.currentTimeMillis());
try {
mqttClient = new MqttAsyncClient(broker, clientId, new MemoryPersistence());
} catch (Exception me) {
me.printStackTrace();
}
}
When in start function is added
mqttClient = new MqttAsyncClient(broker, clientId, new MemoryPersistence()); After the code, there will be problems
Take a look here
char opt1[] = "-Djava.compiler=NONE";
char opt2[] = "-Djava.class.path=.";
char opt3[] = "-verbose:NONE";
options[0].optionString = opt1; options[0].extraInfo = NULL;
options[1].optionString = opt2; options[1].extraInfo = NULL;
options[2].optionString = opt3; options[2].extraInfo = NULL;
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
You are passing three options (array of options with three options defined) but then, you say something like this
vm_args.nOptions = 1;
which means you are passing just one option. It means your options
char opt2[] = "-Djava.class.path=.";
char opt3[] = "-verbose:NONE";
are not even read. You have to change your code to
vm_args.nOptions = 3;
Also, make sure to put on java.class.path all the JARs, folders, where classes required by your code are.

Calling an external function with GetProcAddress crashes the app

I've been trying to call an external function with the GetProcAddress function but everytime i call the function it crashes the console, ive been looking but in every post i get the same final solution but when i try it in my DLL it crashes the app.
Here's the code:
#include <Windows.h>
#include <vector>
#include "SDK\plugin.h"
typedef void (*logprintf_t)(char* format, ...);
logprintf_t logprintf;
// static void* m_AMXExports[44];
typedef bool (PLUGIN_CALL *ServerPluginLoad_t)(void **data);
typedef void (PLUGIN_CALL *ServerPluginUnload_t)();
typedef unsigned int (PLUGIN_CALL *ServerPluginSupports_t)();
typedef void (PLUGIN_CALL *ServerPluginProcessTick_t)();
typedef int (PLUGIN_CALL *ServerPluginAmxLoad_t)(AMX *amx);
typedef int (PLUGIN_CALL *ServerPluginAmxUnload_t)(AMX *amx);
struct Plugins
{
void* AppData[256];
SUPPORTS_FLAGS FlagSupport;
HMODULE Module;
ServerPluginLoad_t LOAD;
ServerPluginUnload_t UNLOAD;
ServerPluginSupports_t SUPPORTS;
ServerPluginProcessTick_t PROCESSTICK;
// AMX Plugin Interface
ServerPluginAmxLoad_t AMXLOAD;
ServerPluginAmxUnload_t AMXUNLOAD;
};
Plugins* ServerPlugins;
void **ppPluginData ;
extern void *pAMXFunctions;
//native LoadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
bool validfunc = false;
char *path;
amx_StrParam(amx, params[1], path);
logprintf("Loading plugin %s", path);
ServerPlugins = new Plugins();
ServerPlugins->Module = LoadLibraryA(path);
if (ServerPlugins->Module == NULL)
{
delete ServerPlugins;
logprintf("Failed loading plugin %s (Error: %d)", path, GetLastError());
return 0;
}
logprintf("NULL");
ServerPlugins->LOAD = (ServerPluginLoad_t)GetProcAddress(ServerPlugins->Module, "Load");
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
ServerPlugins->SUPPORTS = (ServerPluginSupports_t)GetProcAddress(ServerPlugins->Module, "Supports");
if (ServerPlugins->LOAD == NULL || ServerPlugins->SUPPORTS == NULL || ServerPlugins->UNLOAD == NULL)
{
logprintf(" Plugin doesnt conform to architecture");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 1");
ServerPlugins->FlagSupport = (SUPPORTS_FLAGS)ServerPlugins->SUPPORTS();
if ((ServerPlugins->FlagSupport & SUPPORTS_VERSION_MASK) > SUPPORTS_VERSION)
{
logprintf("Unsupported Version; unloading.");
FreeLibrary(ServerPlugins->Module);
delete ServerPlugins;
return false;
}
logprintf("NULL 2");
if ((ServerPlugins->FlagSupport & SUPPORTS_AMX_NATIVES) > SUPPORTS_VERSION)
{
ServerPlugins->AMXLOAD = (ServerPluginAmxLoad_t)GetProcAddress(ServerPlugins->Module, "AmxLoad");
ServerPlugins->AMXUNLOAD = (ServerPluginAmxUnload_t)GetProcAddress(ServerPlugins->Module, "AmxUnload");
}
else
{
ServerPlugins->AMXLOAD = NULL;
ServerPlugins->AMXUNLOAD = NULL;
logprintf("Any Abstract Machine has been loaded");
}
logprintf("NULL 3");
if ((ServerPlugins->FlagSupport & SUPPORTS_PROCESS_TICK) != 0)
{
ServerPlugins->PROCESSTICK = (ServerPluginProcessTick_t)GetProcAddress(ServerPlugins->Module, "ProcessTick");
}
else
{
ServerPlugins->PROCESSTICK = NULL;
}
logprintf("NULL 4"); //debugging
ServerPlugins->AppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ServerPlugins->AppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ServerPlugins->AppData)) //i didnt put it as &ServerPlugins->AppData because it causes an error
{
logprintf("Initialized failed loading plugin %s", path);
FreeLibrary(ServerPlugins->Module);
logprintf("NULL 5");
delete ServerPlugins;
return false;
}
logprintf("Plugin %s loaded", path);
return true;
}
//native UnloadLibrary(libraryname[]);
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
char *path;
amx_StrParam(amx, params[1], path);
ServerPlugins->Module = GetModuleHandle((LPCTSTR)path);
if (ServerPlugins->Module != NULL)
{
ServerPlugins->UNLOAD = (ServerPluginUnload_t)GetProcAddress(ServerPlugins->Module, "Unload");
if (ServerPlugins->UNLOAD != NULL)
{
ServerPlugins->UNLOAD();
FreeLibrary(GetModuleHandleA(path));
logprintf("Library %s has been unloaded correctly", path);
return 1;
}
else
{
logprintf("Unloading library %s failed (Error: %d)", GetLastError());
return 0;
}
}
return 1;
}
PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData)
{
pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
return 1;
}
PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
}
PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports()
{
return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}
AMX_NATIVE_INFO projectNatives[] =
{
{ "LoadLibrary", my_LoadLibrary },
{ "UnloadLibrary", my_UnloadLibrary }
};
PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx)
{
return amx_Register(amx, projectNatives, -1);
}
PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx)
{
return AMX_ERR_NONE;
}
You have a memory leak in convertCharArrayToLPCWSTR(). You are never freeing the wchar_t* that you allocate. The convertCharArrayToLPCWSTR() function itself is not needed, you can simply pass the char* path as-is to LoadLibraryA() instead:
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Module = LoadLibraryA(path);
You are not checking if ServerPlugins->UNLOAD is successfully loaded by GetProcAddress("Unload") or not.
You are using GetProcAddress("Load") for both ServerPlugins->LOAD and ServerPlugins->AMXLOAD, and GetProcAddress("Unload") for both ServerPlugins->UNLOAD and ServerPlugins->AMXUNLOAD. That is very fishy to me. Does the DLL really use the same exports for AMX and non-AMX entry points? If so, that is very bad design, considering that ServerPluginLoad_t has a very different signature than ServerPluginAmxLoad_t, and the same for ServerPlugin(Amx)Unload_t. That is a corrupted call stack waiting to happen. It would be much safer to have the DLL export separate AmxLoad() and AmxUnload() functions instead.
For that matter, the SUPPORTS_AMX_NATIVES and SUPPORTS_PROCESS_TICK flags are redundant, since GetProcAddress() would tell you if those exports are available or not.
As for the crash when calling ServerPlugins->LOAD, I do not see you initializing ppData with any data before passing it to Load(). Certainly not the PLUGIN_DATA_AMX_EXPORTS and PLUGIN_DATA_LOGPRINTF slots, at least:
ppData[PLUGIN_DATA_AMX_EXPORTS] = pAMXFunctions;
ppData[PLUGIN_DATA_LOGPRINTF] = &logprintf;
if (!(ServerPlugins->LOAD)(ppData))
So even if the call to Load() itself did not crash, the DLL would still likely crash at a later time when it tries to use its local pAMXFunctions and logprintf pointers that were assigned in Load().
For that matter, why are you passing things like that as a void* array instead of a struct? That would have been much safer, eg:
struct PluginInitData
{
void* pAMXFunctions;
logprintf_t logprintf;
...
};
typedef bool (__stdcall *ServerPluginLoad_t)(PluginInitData* data);
PluginInitData pInitData;
pInitData.pAMXFunctions = pAMXFunctions;
pInitData.logprintf = &logprintf;
...
if (!(ServerPlugins->LOAD)(&pInitData))
extern "C" bool __stdcall Load(PluginInitData* data)
{
pAMXFunctions = data->pAMXFunctions;
logprintf = data->logprintf;
...
return true;
}
Update: you have fixed most of the issues I mentioned, but now I see that your my_UnloadLibrary() function is implemented wrong. DO NOT call GetModuleHandle() or GetProcAddress() at all, use the existing Module and UNLOAD pointers that were initialized earlier in my_LoadLibrary().
static cell AMX_NATIVE_CALL my_LoadLibrary(AMX* amx, cell* params)
{
char *path;
amx_StrParam(amx, params[1], path);
...
ServerPlugins->Path = path;
...
}
static cell AMX_NATIVE_CALL my_UnloadLibrary(AMX*amx, cell*params)
{
if (ServerPlugins)
{
if (ServerPlugins->UNLOAD != NULL)
ServerPlugins->UNLOAD();
if (ServerPlugins->Module != NULL)
{
FreeLibrary(ServerPlugins->Module);
ServerPlugins->Module = NULL;
}
logprintf("Library %s has been unloaded", ServerPlugins->Path);
delete ServerPlugins;
ServerPlugins = NULL;
}
return 1;
}
If you are still having problems with Load() crashing, then you are just going to have to use your compiler's debugger to find out what is actually happening at run-time. The code shown so far should not be crashing, so either you have a calling convention mismatch, or a data alignment mismatch, or corrupted memory, or something like that. We can't run you debugger for you.

Not able to add certificate policy extension using openssl APIs in c++

I tried using following syntax for the same :
add_ext(x509OutCertificate, NID_certificate_policies, "Policy: 2.16.840.1.113733.1.7.54 ,CPS: https://www.verisign.com/cps");
add_ext(x509OutCertificate, NID_certificate_policies, "2.16.840.1.113733.1.7.54,https://www.verisign.com/cps");
& many more combinations.
but not able to add this extension in certificate. Any clue what is wrong?
Thanks in advance
This is really a comment, but the comment does not have the space.
$ grep -R NID_certificate_policies *crypto/objects/obj_dat.h: NID_certificate_policies,3,&(lvalues[512]),0},
crypto/objects/objects.h:#define NID_certificate_policies 89
crypto/objects/obj_mac.h:#define NID_certificate_policies 89
crypto/x509v3/v3_cpols.c:NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
crypto/x509v3/pcy_cache.c: ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
crypto/x509v3/v3_purp.c: NID_certificate_policies, /* 89 */
Looking at v3_cpols.c, there's an ominous warning:
/* Certificate policies extension support: this one is a bit complex... */
Here's how its declared:
const X509V3_EXT_METHOD v3_cpols = {
NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
0,0,0,0,
0,0,
0,0,
(X509V3_EXT_I2R)i2r_certpol,
(X509V3_EXT_R2I)r2i_certpol,
NULL
};
ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
v3_cpol is then used in ext_dat.h:
static const X509V3_EXT_METHOD *standard_exts[] = {
&v3_nscert,
&v3_ns_ia5_list[0],
&v3_ns_ia5_list[1],
&v3_ns_ia5_list[2],
&v3_ns_ia5_list[3],
&v3_ns_ia5_list[4],
&v3_ns_ia5_list[5],
&v3_ns_ia5_list[6],
...
&v3_cpols,
...
};
There does not appear to be documentation or clear usage. The two books I have on OpenSSL lack a treatment on it. It looks like you are in muddy waters.
Perhaps the folks at the OpenSSL user's list can help out. I suggest it because some folks on the list can probably answer it (SH, DT, VD, etc), but I have not seen them on Stack Overflow's site.
Its been a long time for this question, but i looked into openssl1.0.2k source code, and i found its not support add cps extension directly:
static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, char *value)
{
WriteLogToFile("In r2i_certpol");
STACK_OF(POLICYINFO) *pols = NULL;
char *pstr;
POLICYINFO *pol;
ASN1_OBJECT *pobj;
STACK_OF(CONF_VALUE) *vals;
CONF_VALUE *cnf;
int i, ia5org;
pols = sk_POLICYINFO_new_null();
if (pols == NULL) {
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
return NULL;
}
WriteLogToFile("Before X509V3_parse_list");
vals = X509V3_parse_list(value);
WriteLogToFile("After X509V3_parse_list");
if (vals == NULL) {
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
goto err;
}
ia5org = 0;
for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
cnf = sk_CONF_VALUE_value(vals, i);
if (cnf->value || !cnf->name) {
char str[1000];
sprintf(str, "cnf->value: %s, cnf->name: %s", cnf->value, cnf->name);
WriteLogToFile(str);
X509V3err(X509V3_F_R2I_CERTPOL,
X509V3_R_INVALID_POLICY_IDENTIFIER);
X509V3_conf_err(cnf);
goto err;
}
pstr = cnf->name;
WriteLogToFile(pstr);
if (!strcmp(pstr, "ia5org")) {
ia5org = 1;
continue;
} else if (*pstr == '#') {
STACK_OF(CONF_VALUE) *polsect;
polsect = X509V3_get_section(ctx, pstr + 1);
if (!polsect) {
X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);
X509V3_conf_err(cnf);
goto err;
}
pol = policy_section(ctx, polsect, ia5org);
X509V3_section_free(ctx, polsect);
if (!pol)
goto err;
} else {
if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
X509V3err(X509V3_F_R2I_CERTPOL,
X509V3_R_INVALID_OBJECT_IDENTIFIER);
X509V3_conf_err(cnf);
goto err;
}
pol = POLICYINFO_new();
if (pol == NULL) {
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
goto err;
}
pol->policyid = pobj;
}
if (!sk_POLICYINFO_push(pols, pol)) {
POLICYINFO_free(pol);
X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
goto err;
}
}
sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
return pols;
err:
sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
return NULL;
}
The "CPS" has to be in section part, which is configured by openssl.conf file, so anyone met this problem has to put cps in that configure file, and tell openssl to search that part, like the code below:
bool AddX509ExtensionFromFile(X509* cert, X509* issuer, int nid, char* value,char* extFile)
{
if (extFile)
{
long errorline = -1;
X509V3_CTX ctx2;
CONF* extconf = NCONF_new(NULL);
if (!NCONF_load(extconf, extFile, &errorline))
{
if (errorline <= 0)
{
printf("NCONF_load error\n");
}
else
{
printf("error on line %ld of config file '%s'\n", errorline, extFile);
}
}
char* extsect = "default";
X509V3_set_ctx_test(&ctx2);
X509V3_set_nconf(&ctx2, extconf);
if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
{
printf("error loading extension section %s\n", extsect);
}
X509V3_set_ctx(&ctx2, issuer, cert, NULL, NULL, 0);
X509_EXTENSION* ex = X509V3_EXT_conf_nid(NULL, &ctx2, nid, value);
if (!ex) {
return false;
}
int result = X509_add_ext(cert, ex, -1);
X509_EXTENSION_free(ex);
return (result == 0) ? true : false;
}
return false;
}