// PCRawJavaBridge.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。
//

#include "stdafx.h"
#include "windows.h"
#include "winsock2.h"
#include "org_coderepos_nori090_PCRawJavaBridge.h"

HMODULE DLL;
typedef void* (cdecl *PCRawCreate)(const char *url);
typedef void (cdecl *PCRawClose)(void *handle);
typedef int (cdecl *PCRawGetLength)(void *handle);
typedef int (cdecl *PCRawGetData)(void *handle, char *buf, int len);
typedef int (cdecl *PCRawGetLastError)(void *handle);
typedef DWORD (cdecl *PCRawGetUpdateTime)(void *handle);
typedef void (cdecl *PCRawDataLock)(void *handle);
typedef void (cdecl *PCRawDataUnlock)(void *handle);
typedef int (cdecl *PCRawCheckVersion)(LPDWORD lpVersion, DWORD dwAssumedVersion);

PCRawCreate create;
PCRawClose close;
PCRawGetLength getLength;
PCRawGetData getData;
PCRawGetLastError getLastError;
PCRawGetUpdateTime getUpdateTime;
PCRawDataLock dataLock;
PCRawDataUnlock dataUnLock;
PCRawCheckVersion checkVersion;

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    LoadPCRawDLL
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_LoadPCRawDLL
(JNIEnv *env, jclass cls, jstring jstr) {
	if (DLL == NULL) {
		const jchar* cs = env->GetStringChars(jstr, 0);
		DLL = LoadLibrary((LPCWSTR)cs);
		env->ReleaseStringChars(jstr, cs);
		if (DLL == NULL) {
			return -10;
		} else {
			create = (PCRawCreate)GetProcAddress(DLL, (LPCSTR)"PCRawCreate");
			close = (PCRawClose)GetProcAddress(DLL, (LPCSTR)"PCRawClose");
			getLength = (PCRawGetLength)GetProcAddress(DLL, (LPCSTR)"PCRawGetLength");
			getData = (PCRawGetData)GetProcAddress(DLL, (LPCSTR)"PCRawGetData");
			getLastError = (PCRawGetLastError)GetProcAddress(DLL, (LPCSTR)"PCRawGetLastError");
			getUpdateTime = (PCRawGetUpdateTime)GetProcAddress(DLL, (LPCSTR)"PCRawGetUpdateTime");
			dataLock = (PCRawDataLock)GetProcAddress(DLL, (LPCSTR)"PCRawDataLock");
			dataUnLock = (PCRawDataUnlock)GetProcAddress(DLL, (LPCSTR)"PCRawDataUnlock");
			checkVersion = (PCRawCheckVersion)GetProcAddress(DLL, (LPCSTR)"PCRawCheckVersion");
		}
	}
	WSADATA wsaData;
	int ret = WSAStartup(WINSOCK_VERSION, &wsaData);
	if (ret != 0) {
		printf("error!%d", ret);
	}
	return 10;
}

/*
 * Class:     org_coderepos_nori090_PCRawJavaBridge
 * Method:    UnLoadPCRawDLL
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_UnLoadPCRawDLL
(JNIEnv *env, jclass cls) {
	FreeLibrary(DLL);
	create = NULL;
	close = NULL;
	getLength = NULL;
	getData = NULL;
	getLastError = NULL;
	getUpdateTime = NULL;
	dataLock = NULL;
	dataUnLock = NULL;
	checkVersion = NULL;
	WSACleanup();
}

/*
 * Class:     org_coderepos_nori090_PCRawJavaBridge
 * Method:    PCRawCreate
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawCreate1
(JNIEnv *env, jclass cls, jstring jstr) {
	if (create != NULL) {
		const jchar* cs = env->GetStringChars(jstr, 0);
		HANDLE handle = create((char*)cs);
		env->ReleaseStringChars(jstr, cs);
		return (jint)handle;
	}
	return -10;
}

/*
 * Class:     org_coderepos_nori090_PCRawJavaBridge
 * Method:    PCRawCreate2
 * Signature: ([B)I
 */
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawCreate2
(JNIEnv *env, jclass cls, jbyteArray ary) {
	if (create != NULL) {
		jbyte * bs = env->GetByteArrayElements(ary, 0);		
		HANDLE handle = create((char*)bs);
		env->ReleaseByteArrayElements(ary, bs, 0);
		return (jint)handle;
	}
	return -10;
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawClose
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawClose
(JNIEnv *env, jclass cls, jint i) {
	if (close != NULL) {
		close((void*)i);
	}
	FreeLibrary(DLL);
	create = NULL;
	close = NULL;
	getLength = NULL;
	getData = NULL;
	getLastError = NULL;
	getUpdateTime = NULL;
	dataLock = NULL;
	dataUnLock = NULL;
	checkVersion = NULL;
	WSACleanup();
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawGetLength
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawGetLength
(JNIEnv *env, jclass cls, jint i) {
	if (getLength != NULL) {
		int ret = getLength((void*)i);
		return ret;
	}
	return 0;
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawGetData
* Signature: (I[BI)I
*/
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawGetData
(JNIEnv *env, jclass cls, jint i1, jbyteArray ary, jint i2) {
	if (getData != NULL) {
		jbyte *b = env->GetByteArrayElements(ary, 0);
		int size = getData((void*)i1,(char*)b,i2);
		env->ReleaseByteArrayElements(ary, b, 0);
		return size;
	} else {
		return -10;
	}
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawGetLastError
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawGetLastError
(JNIEnv *env, jclass cls, jint i) {
	if (getLastError != NULL) {
		return getLastError((void*)i);
	}
	return -10;
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawGetUpdateTime
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawGetUpdateTime
(JNIEnv *env, jclass cls, jint i) {
	if (getUpdateTime != NULL) {
		return getUpdateTime((void*)i);
	}
	return -10;
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawDataLock
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawDataLock
(JNIEnv *env, jclass cls, jint i) {
	if (dataLock != NULL) {
		dataLock((void*)i);
	}
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawDataUnlock
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawDataUnlock
(JNIEnv *env, jclass cls, jint i) {
	if (dataUnLock != NULL) {
		dataUnLock((void*)i);
	}
}

/*
* Class:     org_coderepos_nori090_PCRawJavaBridge
* Method:    PCRawCheckVersion
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_coderepos_nori090_PCRawJavaBridge_PCRawCheckVersion
(JNIEnv *env, jclass cls) {
	if (checkVersion != NULL) {
		DWORD d = 0;
		checkVersion(&d,0);
		return d;
	}
	return -10;
}
