// wcesecurity.cpp : DLL アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
#include "jni.h"

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
  switch (ul_reason_for_call)
  {
    case DLL_PROCESS_ATTACH:
      DisableThreadLibraryCalls((HMODULE) hModule);
      break;
  }

  return TRUE;
}

/**
 * Windows Mobileのエラーコードに対応する詳細メッセージを持つ
 * 例外をthrowする
 */
void throwException(JNIEnv* env, const char* className, const DWORD dwErrorCode)
{
  jobject t;

  // load specified exception class.
  jclass clazz = env->FindClass(className);
  if (! clazz)
  {
    // InternalErrorをthrowする
    char msg[128];
    jclass ieclass = env->FindClass("java/lang/InternalError");
    _snprintf(msg, sizeof(msg)/sizeof(msg[0]), "Failed to load class:%s", className);
    env->ThrowNew(ieclass, msg);
    return;
  }

  // String型の引数を１つとるコンストラクタを探す
  jmethodID mid = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;)V");
  if (! mid)
  {
    // 引数なしのコンストラクタを探す
    mid = env->GetMethodID(clazz, "<init>", "()V");
    if (! mid)
    {
      // InternalErrorをthrowする
      char msg[128];
      jclass ieclass = env->FindClass("java/lang/InternalError");
      _snprintf(msg, sizeof(msg)/sizeof(msg[0]), "Failed to find constructor of class:%s", className);
      env->ThrowNew(ieclass, msg);
      return;
    }

    // メッセージなしの例外を生成
    t = env->NewObject(clazz, mid);
  } else {
    // エラーメッセージを作成する
    _TCHAR* message;
    jstring message_string;
    if (FormatMessage((FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM),
                      NULL,
		      dwErrorCode,
		      LANG_USER_DEFAULT,
		      (LPTSTR) &message,
		      0,
		      NULL))
    {
      const _TCHAR* format = _T("error occurred.(%s)");
      int len = _tcslen(format) + _tcslen(message) + 1;
      _TCHAR* buff = (_TCHAR*) malloc(sizeof(_TCHAR) * (len + 1));
      if (buff)
      {
        _sntprintf(buff, len, format, message);
        message_string = env->NewString((const jchar*) buff, _tcslen(buff));
      }
      free(buff);
      LocalFree(message);
    }
    else
    {
      const _TCHAR* format = _T("error occurred.(0x%x)");
      int len = _tcslen(format) + 10;
      _TCHAR* buff = (_TCHAR*) malloc(sizeof(_TCHAR) * (len + 1));
      if (buff)
      {
        _sntprintf(buff, len, format, dwErrorCode);
        message_string = env->NewString((const jchar*) buff, _tcslen(buff));
      }
      free(buff);
    }
      // 例外を生成
    t = env->NewObject(clazz, mid, message_string);
  }
  if (t)
  {
    // 例外をthrow
    env->Throw((jthrowable) t);
  }
  return;
}

_TCHAR*
getString(JNIEnv* env, jstring str)
{
  if (! str)
  {
    return NULL;
  }
  jsize len = env->GetStringLength(str);
  _TCHAR* result = (_TCHAR*) malloc(sizeof(_TCHAR) * (len + 1));
  if (result)
  {
    const jchar* temp = env->GetStringChars(str, NULL);
    if (temp)
    {
      _tcsncpy(result, reinterpret_cast<const _TCHAR*>(temp), len);
      result[len] = _T('\0');
    }
  }
  return result;
}