blob: 1d61de675f6d5f4044e85415a3e69ffd08df741b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// BrowserClient.cpp : Defines the entry point for the DLL application.
//
// #include "stdafx.h"
#include <windows.h>
#include <wchar.h>
/*
#include <stdio.h>
#include <malloc.h>
#include <ddeml.h>
*/
#include <jni.h>
// ........................................................
extern "C" {
/**********************************************************
* Static variables
*********************************************************/
/** Instance ID for DDE */
static DWORD InstId = 0;
/** counter for topic generation */
static DWORD dwcounter = 0;
/**********************************************************
* Static functions
*********************************************************/
static int InitDDE(void);
static void ClearDde(void);
static HDDEDATA CALLBACK DdeCallback
(UINT Type, UINT Fmt, HCONV ConvHan,
HSZ Str1, HSZ Str2,
HDDEDATA Data, ULONG_PTR Dta1, ULONG_PTR Dta2);
/**********************************************************
* function 'InitDDE' WIN
* desc : Initialize DDE comunication
* returns: 0 <==> OK
* other value <==> an error occured
*********************************************************/
static int InitDDE(void) {
/** is this already initialized? */
// static char Set= 0;
// if(Set && InstId) return(0);
if (InstId) return (0);
if (DdeInitialize(&InstId, DdeCallback,
APPCLASS_STANDARD /* |
APPCMD_FILTERINITS |
CBF_SKIP_ALLNOTIFICATIONS |
CBF_FAIL_ADVISES |
CBF_FAIL_EXECUTES |
CBF_FAIL_SELFCONNECTIONS |
CBF_SKIP_CONNECT_CONFIRMS |
CBF_SKIP_DISCONNECTS*/ |
CBF_SKIP_REGISTRATIONS |
CBF_SKIP_UNREGISTRATIONS, 0) != DMLERR_NO_ERROR) {
printf("Error init DDE\n");
return (-1);
}
// printf("INIT DDE OK\n");
// if(!Set) atexit(ClearDde);
// Set= 1;
return (0);
}
/**********************************************************
* function 'ClearDde' WINDOWS
* desc : quits comunitation through DDE
*********************************************************/
static void ClearDde(void) {
if (!InstId) return;
DdeUninitialize(InstId);
InstId = 0;
}
/**********************************************************
* function 'DDEcallback' WINDOWS
* desc :
*********************************************************/
static HDDEDATA CALLBACK DdeCallback
(UINT Type, UINT Fmt, HCONV ConvHan,
HSZ Str1, HSZ Str2,
HDDEDATA Data, ULONG_PTR Dta1, ULONG_PTR Dta2) {
/** conversation handle */
static HCONV shConv = NULL;
char Item[256];
char Service[256];
char Topic[256];
/* transaction type */
switch (Type) {
/* transaction type */
case XTYP_CONNECT:
if (!(DdeQueryString(InstId, Str1, Topic, 256, CP_WINANSI))) return (FALSE);
if (!(DdeQueryString(InstId, Str2, Service, 256, CP_WINANSI))) return (FALSE);
printf("XTYP_CONNECT >%s< >%s<\n", Service, Topic);
fflush(stdout);
// accept WWW_*Progress* topic
if (!strcmp(Topic, "WWW_BeginProgress")) {
shConv = ConvHan;
dwcounter++;
return (HDDEDATA) TRUE;
}
if (!strcmp(Topic, "WWW_SetProgressRange"))
return (HDDEDATA) TRUE;
if (!strcmp(Topic, "WWW_MakingProgress"))
return (HDDEDATA) TRUE;
if (!strcmp(Topic, "WWW_EndProgress"))
return (HDDEDATA) TRUE;
if (!strcmp(Topic, "WWW_URLEcho"))
return (HDDEDATA) TRUE;
return (FALSE);
case XTYP_POKE:
if (!(DdeQueryString(InstId, Str1, Topic, 256, CP_WINANSI))) return (DDE_FNOTPROCESSED);
if (!(DdeQueryString(InstId, Str2, Item, 256, CP_WINANSI))) return (DDE_FNOTPROCESSED);
printf("XTYP_POKE >%s< >%s<\n", Topic, Item);
fflush(stdout);
if (!strcmp(Topic, "WWW_SetProgressRange")) {
return ((HDDEDATA) DDE_FACK);
}
if (!strcmp(Topic, "WWW_EndProgress")) {
return ((HDDEDATA) DDE_FACK);
}
if (!strcmp(Topic, "WWW_URLEcho")) {
return ((HDDEDATA) DDE_FACK);
}
return (DDE_FNOTPROCESSED);
case XTYP_REQUEST:
if (!(DdeQueryString(InstId, Str1, Topic, 256, CP_WINANSI))) return (DDE_FNOTPROCESSED);
if (!(DdeQueryString(InstId, Str2, Item, 256, CP_WINANSI))) return (DDE_FNOTPROCESSED);
printf("XTYP_REQUEST >%s< >%s<\n", Topic, Item);
fflush(stdout);
if (!strcmp(Topic, "WWW_BeginProgress")) {
HDDEDATA Dta;
if (!(Dta = DdeCreateDataHandle
(InstId, (unsigned char *) &dwcounter, sizeof (DWORD), 0, Str2, CF_TEXT, 0))) {
printf("CANNOT CREATE DATA\n");
return (NULL);
}
return (Dta);
}// www_beginprogress
else if (!strcmp(Topic, "WWW_MakingProgress")) {
HDDEDATA Dta;
char *s = "FALSE";
if (!(Dta = DdeCreateDataHandle
(InstId, (unsigned char*) s, strlen(s), 0, Str2, CF_TEXT, 0))) {
printf("CANNOT CREATE DATA\n");
return (NULL);
}
return (Dta);
} // making progress
return (NULL);
case XTYP_XACT_COMPLETE:
printf("XTYP_XACT_COMPLETE\n");
return ((HDDEDATA) DDE_FACK);
case XTYP_ADVDATA:
printf("XTYP_ADVDATA\n");
return ((HDDEDATA) DDE_FACK);
case XTYP_ERROR:
printf("XTYP_ERROR\n");
break;
#if defined(DEBUG)
case XTYP_CONNECT_CONFIRM:
shConv = ConvHan;
printf("XTYP_CONNECT_CONFIRM\n");
break;
case XTYP_DISCONNECT:
printf("XTYP_DISCONNECT\n");
break;
case XTYP_REGISTER:
printf("XTYP_REGISTER\n");
break;
case XTYP_UNREGISTER:
printf("XTYP_UNREGISTER\n");
break;
default:
if (Type & XCLASS_NOTIFICATION) {
printf("XCLASS_NOTIFICATION\n");
}
if (Type & XCLASS_FLAGS) {
printf("XCLASS_FLAGS\n");
}
if (Type & XCLASS_DATA) {
printf("XCLASS_DATA\n");
}
if (Type & XCLASS_BOOL) {
printf("XCLASS_BOOL\n");
}
printf("type not of interest\n");
#else
default:
#endif /* DEBUG */
break;
}
return (0);
}
/**********************************************************
* function
* desc
*
* param
* returns
* throws
*********************************************************/
JNIEXPORT jbyteArray Java_org_netbeans_modules_extbrowser_NbDdeBrowserImpl_reqDdeMessage
(JNIEnv *env,
jobject obj,
jstring server,
jstring topic,
jstring item,
jint timeout) {
DWORD len = 1024;
char buff[1024];
char msg[1024];
jbyteArray retData = NULL;
const char *Server = env->GetStringUTFChars(server, 0);
const char *Topic = env->GetStringUTFChars(topic, 0);
const char *Item = env->GetStringUTFChars(item, 0);
HCONV Curr = 0;
HSZ StrHproc, StrHitem, StrHtopic;
HDDEDATA TrRes;
DWORD Result; // transaction result
// INIT (REINIT DDE)
if (InitDDE()) {
// printf("Cannot initialize DDE\n");
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Cannot initialize DDE");
return NULL;
}
// create string handles
StrHproc = DdeCreateStringHandle(InstId, Server, CP_WINANSI);
StrHtopic = DdeCreateStringHandle(InstId, Topic, CP_WINANSI);
StrHitem = DdeCreateStringHandle(InstId, Item, CP_WINANSI);
// connect
if (!(Curr = DdeConnect(InstId, StrHproc, StrHtopic, NULL))) {
// printf("Cannot connect to DDE server\n");
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
sprintf(msg, "DdeConnect errno >%X< when connecting to server %s, topic %s.\n", DdeGetLastError(InstId), Server, Topic);
env->ThrowNew(excClass, msg);
DdeFreeStringHandle(InstId, StrHtopic);
DdeFreeStringHandle(InstId, StrHitem);
DdeFreeStringHandle(InstId, StrHproc);
ClearDde();
return NULL;
} else {
// printf("SEND TO >%s< TOPIC >%s< ITEM >%s<\n",
// Server, Topic, Item); fflush (stdout);
if (!(TrRes = DdeClientTransaction
(NULL, 0, Curr, StrHitem, CF_TEXT, XTYP_REQUEST, timeout, &Result))) {
// printf("DDE Tx failed\n");
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
sprintf(msg, "DdeClientTransaction errno >%X<\n", DdeGetLastError(InstId));
fflush(stdout);
env->ThrowNew(excClass, msg);
} else {
// process result
LPBYTE pData = DdeAccessData(TrRes, &len);
memcpy(buff, pData, len);
DdeUnaccessData(TrRes);
DdeFreeDataHandle(TrRes);
retData = env->NewByteArray(len);
for (DWORD i = 0; i < len; i++)
env->SetByteArrayRegion(retData, i, 1, (jbyte*) (buff + i));
}
// release string handles
DdeFreeStringHandle(InstId, StrHtopic);
DdeFreeStringHandle(InstId, StrHitem);
DdeFreeStringHandle(InstId, StrHproc);
DdeDisconnect(Curr);
}
env->ReleaseStringUTFChars(server, Server);
env->ReleaseStringUTFChars(topic, Topic);
env->ReleaseStringUTFChars(item, Item);
ClearDde();
return retData;
}
/**********************************************************
* Reads value from
* HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\Windows\CurrentVersion\\App Paths\\<browser>.exe
* desc
*
* param
* returns
* throws
*********************************************************/
JNIEXPORT jstring Java_org_netbeans_modules_extbrowser_NbDdeBrowserImpl_getBrowserPath
(JNIEnv *env,
jclass cls,
jstring browser) {
DWORD len = 1024;
DWORD type;
char sSubKey[1024];
char sReg[1024];
char sPath[1024];
HKEY hKey = NULL;
jstring path = NULL;
// In the past we used :
// HKEY_CLASSES_ROOT\Applications\\<browser>.exe\shell\open\command key
// It seems to be better to use :
//
const char *b = env->GetStringUTFChars(browser, 0);
sprintf(sSubKey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe", b);
env->ReleaseStringUTFChars(browser, b);
// open registry key
// printf("LOOKING FOR >%s<\n",
// sSubKey); fflush (stdout);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
char msg[1024];
strcpy(msg, "RegOpenKeyEx() failed for ");
strcat(msg, sSubKey);
strcat(msg, ".");
env->ThrowNew(excClass, msg);
return NULL;
}
// query value
if (RegQueryValueEx(hKey, NULL, NULL, &type, (LPBYTE) sReg, &len) != ERROR_SUCCESS) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegQueryValueEx() failed.");
return NULL;
}
// process data
switch (type) {
case REG_EXPAND_SZ:
// expand variables
if (!ExpandEnvironmentStrings(sReg, sPath, 1024)) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "ExpandEnvironmentStrings() failed.");
return NULL;
}
break;
case REG_SZ:
strcpy(sPath, sReg);
break;
default:
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Unsupported registry type.");
return NULL;
}
if (RegCloseKey(hKey) != ERROR_SUCCESS) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegCloseKey() failed.");
return NULL;
}
if ((path = env->NewStringUTF(sPath)) == NULL) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Error when retrieving path to browser.");
return NULL;
}
return path;
}
/**********************************************************
* function
* desc
*
* param
* returns
* throws
*********************************************************/
JNIEXPORT jstring Java_org_netbeans_modules_extbrowser_NbDdeBrowserImpl_getDefaultOpenCommand
(JNIEnv *env,
jclass cls) {
DWORD len = 1024;
DWORD type;
// char sSubKey[1024];
wchar_t sBrowser[1024];
wchar_t sReg[1024];
wchar_t sPath[1024];
HKEY hKey = NULL;
jstring path = NULL;
// find HKEY_CLASSES_ROOT ".html"
sBrowser[0] = '\0';
// open registry key
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L".html", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
// query value
if (RegQueryValueExW(hKey, NULL, NULL, &type, (LPBYTE) sReg, &len) == ERROR_SUCCESS) {
// process data
switch (type) {
case REG_SZ:
wcscpy(sBrowser, sReg);
break;
default:
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Unsupported registry type.");
return NULL;
}
if (RegCloseKey(hKey) != ERROR_SUCCESS) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegCloseKey() failed.");
return NULL;
}
} else {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegQueryValueEx() failed.");
return NULL;
}
} else {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegOpenKeyEx() failed for .html.");
return NULL;
}
if (wcslen(sBrowser) == 0) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Browser not found.");
return NULL;
}
wcscat(sBrowser, L"\\shell\\open\\command");
// now query real command
// open registry key
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, sBrowser, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
// query value
len = 1024;
sReg [0] = '\0';
if (RegQueryValueExW(hKey, NULL, NULL, &type, (BYTE *) & sReg, &len) == ERROR_SUCCESS) {
// process data
switch (type) {
case REG_EXPAND_SZ:
// expand variables
if (!ExpandEnvironmentStringsW(sReg, sPath, 1024)) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "ExpandEnvironmentStrings() failed.");
return NULL;
}
break;
case REG_SZ:
wcscpy(sPath, sReg);
break;
default:
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Unsupported registry type.");
return NULL;
}
if (RegCloseKey(hKey) != ERROR_SUCCESS) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegCloseKey() failed.");
return NULL;
}
} else {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegQueryValueEx() failed.");
return NULL;
}
} else {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "RegOpenKeyEx() failed when trying to open 'browser' key.");
return NULL;
}
// sPath contains command that starts default browser
if ((path = env->NewString((jchar*) sPath, wcslen(sPath))) == NULL) {
jclass excClass = env->FindClass("org/netbeans/modules/extbrowser/NbBrowserException");
env->ThrowNew(excClass, "Error when retrieving path to browser.");
return NULL;
}
return path;
}
} // extern "C"