SF 1794811 Support unicode in COM error messages.

This commit is contained in:
clay_shooter
2007-09-22 16:59:31 +00:00
parent 7f0cb9e0d6
commit 2261c55a11
5 changed files with 110 additions and 49 deletions

View File

@@ -20,15 +20,15 @@
<tr>
<td width="100%" colspan="2"><b>Bugs</b></td>
</tr>
<tr>
<td width="13%" valign="top">1775889</td>
<td width="87%" valign="top">(M4) Fixed leak SafeArray setString(int[],value) and other setString() methods</td>
</tr>
<tr>
<td width="13%" valign="top">1793362</td>
<td width="87%" valign="top">(M5) ERROR_MORE_DATA causes failures. Fix submitted for defect found while porting
Jameleon to use current release of Jacob. </td>
</tr>
<tr>
<td width="13%" valign="top">1775889</td>
<td width="87%" valign="top">(M4) Fixed leak SafeArray setString(int[],value) and other setString() methods</td>
</tr>
<tr>
<td width="13%" valign="top">&nbsp;</td>
<td width="87%" valign="top">&nbsp;</td>
@@ -37,11 +37,12 @@
<td width="100%" colspan="2"><b>Patches</b></td>
</tr>
<tr>
<td width="13%" valign="top">1709841 </td>
<td width="87%" valign="top">(M1) Compiled with Visual Studio 2005. Jacob now requires
2005 or later libraries.
See the UsingJacob.html file for impact this has on NT, 2000 and Server 2003 users.
</td>
<td width="13%" valign="top">1794811 </td>
<td width="87%" valign="top">(M5) Support Unicode strings in COM failure messages</td>
</tr>
<tr>
<td width="13%" valign="top">1793346</td>
<td width="87%" valign="top">(M5) Replaced use of deprecated API and removed unused variables.</td>
</tr>
<tr>
<td width="13%" valign="top">1701995 </td>
@@ -51,8 +52,11 @@
</td>
</tr>
<tr>
<td width="13%" valign="top">1793346</td>
<td width="87%" valign="top">(M5) Replaced use of deprecated API and removed unused variables.</td>
<td width="13%" valign="top">1709841 </td>
<td width="87%" valign="top">(M1) Compiled with Visual Studio 2005. Jacob now requires
2005 or later libraries.
See the UsingJacob.html file for impact this has on NT, 2000 and Server 2003 users.
</td>
</tr>
<tr>
<td width="13%" valign="top">&nbsp;</td>
@@ -61,15 +65,15 @@
<tr>
<td width="100%" colspan="2"><b>Feature Requests</b></td>
</tr>
<tr>
<td width="13%" valign="top">1772783 </td>
<td width="87%" valign="top">(M4) Added VT_DECIMAL support for BigDecimals whose scale less than 28 </td>
</tr>
<tr>
<td width="13%" valign="top">1761727</td>
<td width="87%" valign="top">(M3) unittest directory test programs
converted to JUnit 3.8.1. New ANT target created to run all unit tests. </td>
</tr>
<tr>
<td width="13%" valign="top">1772783 </td>
<td width="87%" valign="top">(M4) Added VT_DECIMAL support for BigDecimals whose scale less than 28 </td>
</tr>
<tr>
<td width="13%" valign="top">&nbsp;</td>
<td width="87%" valign="top">&nbsp;</td>

View File

@@ -322,28 +322,41 @@ static char* BasicToCharString(const BSTR inBasicString)
size_t convertedSize;
::wcstombs_s(&convertedSize, charString, charStrSize, inBasicString, charStrSize);
}
else
else
{
charString = ::_strdup("");
}
return charString;
}
static char* CreateErrorMsgFromResult(HRESULT inResult)
static wchar_t* CreateErrorMsgFromResult(HRESULT inResult)
{
char* msg = NULL;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
wchar_t* msg = NULL;
::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL, inResult,MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL);
SUBLANG_DEFAULT), (LPWSTR) &msg, 0, NULL);
if (msg == NULL)
msg = ::_strdup("An unknown COM error has occured.");
{
const wchar_t* message_text = L"An unknown COM error has occured.";
size_t bufferLength = (wcslen(message_text) + 1) * sizeof(wchar_t);
msg = (wchar_t*) ::LocalAlloc(LPTR, bufferLength);
wcscpy_s(msg, bufferLength, message_text);
}
return msg;
}
static char* CreateErrorMsgFromInfo(HRESULT inResult, EXCEPINFO* ioInfo,
static wchar_t* CreateErrorMsgFromInfo(HRESULT inResult, EXCEPINFO* ioInfo,
const char* methName)
{
char* msg = NULL;
wchar_t* msg = NULL;
size_t methNameWSize = 0;
mbstowcs_s(&methNameWSize, NULL, 0, methName, _TRUNCATE);
wchar_t* methNameW = new wchar_t[methNameWSize];
mbstowcs_s(NULL, methNameW, methNameWSize, methName, _TRUNCATE);
// If this is a dispatch exception (triggered by an Invoke message),
// then we have to take some additional steps to process the error
@@ -356,35 +369,34 @@ static char* CreateErrorMsgFromInfo(HRESULT inResult, EXCEPINFO* ioInfo,
(*(ioInfo->pfnDeferredFillIn))(ioInfo);
// Build the error message from exception information content.
char* source = ::BasicToCharString(ioInfo->bstrSource);
char* desc = ::BasicToCharString(ioInfo->bstrDescription);
const size_t MSG_LEN = ::strlen(methName) + ::strlen(source) + ::strlen(desc) + 128;
msg = new char[MSG_LEN];
::strncpy_s(msg, MSG_LEN, "Invoke of: ", strlen("Invoke of: "));
::strncat_s(msg, MSG_LEN, methName, strlen(methName));
::strncat_s(msg, MSG_LEN, "\nSource: ", strlen("\nSource: "));
::strncat_s(msg, MSG_LEN, source, strlen(source));
::strncat_s(msg, MSG_LEN, "\nDescription: ", strlen("\nDescription: "));
::strncat_s(msg, MSG_LEN, desc, strlen(desc));
::strncat_s(msg, MSG_LEN, "\n", strlen("\n"));
delete source;
delete desc;
int sourceLen = SysStringLen(ioInfo->bstrSource);
int descLen = SysStringLen(ioInfo->bstrDescription);
const size_t MSG_LEN = ::wcslen(methNameW) + sourceLen + descLen + 128;
msg = new wchar_t[MSG_LEN];
::wcsncpy_s(msg, MSG_LEN, L"Invoke of: ", wcslen(L"Invoke of: "));
::wcsncat_s(msg, MSG_LEN, methNameW, wcslen(methNameW));
::wcsncat_s(msg, MSG_LEN, L"\nSource: ", wcslen(L"\nSource: "));
::wcsncat_s(msg, MSG_LEN, ioInfo->bstrSource, sourceLen);
::wcsncat_s(msg, MSG_LEN, L"\nDescription: ", wcslen(L"\nDescription: "));
::wcsncat_s(msg, MSG_LEN, ioInfo->bstrDescription, descLen);
::wcsncat_s(msg, MSG_LEN, L"\n", wcslen(L"\n"));
}
else
{
char* msg2 = CreateErrorMsgFromResult(inResult);
const size_t MSG_LEN = ::strlen(methName) + ::strlen(msg2) + 128;
msg = new char[MSG_LEN];
::strncpy_s(msg, MSG_LEN,
"A COM exception has been encountered:\nAt Invoke of: ",
strlen("A COM exception has been encountered:\nAt Invoke of: "));
::strncat_s(msg, MSG_LEN, methName, strlen(methName));
::strncat_s(msg, MSG_LEN, "\nDescription: ", strlen("\nDescription: "));
::strncat_s(msg, MSG_LEN, msg2, strlen(msg2));
wchar_t* msg2 = CreateErrorMsgFromResult(inResult);
const size_t MSG_LEN = ::wcslen(methNameW) + ::wcslen(msg2) + 256;
msg = new wchar_t[MSG_LEN];
::wcsncpy_s(msg, MSG_LEN,
L"A COM exception has been encountered:\nAt Invoke of: ",
wcslen(L"A COM exception has been encountered:\nAt Invoke of: "));
::wcsncat_s(msg, MSG_LEN, methNameW, wcslen(methNameW));
::wcsncat_s(msg, MSG_LEN, L"\nDescription: ", wcslen(L"\nDescription: "));
::wcsncat_s(msg, MSG_LEN, msg2, wcslen(msg2));
// jacob-msg 1075 - SF 1053872 : Documentation says "use LocalFree"!!
//delete msg2;
LocalFree(msg2);
}
delete methNameW;
return msg;
}
@@ -505,7 +517,7 @@ JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev
// check for error and display a somewhat verbose error message
if (!SUCCEEDED(hr)) {
// two buffers that may have to be freed later
char *buf = NULL;
wchar_t *buf = NULL;
char *dispIdAsName = NULL;
// this method can get called with a name or a dispatch id
// we need to handle both SF 1114159
@@ -534,7 +546,7 @@ JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev
}
}
ThrowComFail(env, buf, hr);
ThrowComFailUnicode(env, buf, hr);
if (buf) delete buf;
if (dispIdAsName) delete dispIdAsName;
return NULL;

View File

@@ -36,12 +36,28 @@ void ThrowComFail(JNIEnv *env, const char* desc, jint hr)
// call the constructor that takes hr and message
jmethodID failCons =
env->GetMethodID(failClass, "<init>", "(ILjava/lang/String;)V");
if (!desc) desc = "Java/COM Error";
if (!desc) {
desc = "Java/COM Error";
}
jstring js = env->NewStringUTF(desc);
jthrowable fail = (jthrowable)env->NewObject(failClass, failCons, hr, js);
env->Throw(fail);
}
void ThrowComFailUnicode(JNIEnv *env, const wchar_t* desc, jint hr)
{
if (!desc) {
ThrowComFail(env, "Java/COM Error", hr);
}
jclass failClass = env->FindClass("com/jacob/com/ComFailException");
// call the constructor that takes hr and message
jmethodID failCons =
env->GetMethodID(failClass, "<init>", "(ILjava/lang/String;)V");
jstring js = env->NewString((const jchar *) desc, wcslen(desc));
jthrowable fail = (jthrowable)env->NewObject(failClass, failCons, hr, js);
env->Throw(fail);
}
// if env's are different throw on the 1st env
int CheckEnv(JNIEnv *env1, JNIEnv *env2)
{

View File

@@ -21,6 +21,7 @@
extern "C" {
VARIANT *extractVariant(JNIEnv *env, jobject arg);
void ThrowComFail(JNIEnv *env, const char* desc, jint hr);
void ThrowComFailUnicode(JNIEnv *env, const wchar_t* desc, jint hr);
IDispatch *extractDispatch(JNIEnv *env, jobject arg);
SAFEARRAY *extractSA(JNIEnv *env, jobject arg);
void setSA(JNIEnv *env, jobject arg, SAFEARRAY *sa, int copy);

View File

@@ -0,0 +1,28 @@
package com.jacob.test.errors;
import com.jacob.test.BaseTestCase;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
/**
* This test verifies patch SF 1794811 .
* It shows how unicode filenames throw exceptions in 1.13M4 and earlier.
* @author justme84
*
*/
public class UnicodeErrorTest extends BaseTestCase {
public void testUnicodeCharactersInErrorMessage() {
ActiveXComponent application = new ActiveXComponent("Word.Application");
ActiveXComponent documents = application.getPropertyAsComponent("Documents");
String fileName = "abc\u0411\u0412\u0413\u0414def";
try {
documents.invoke("Open", fileName);
fail("Should have thrown an exception");
} catch (ComException e) {
assertTrue("Error message should contain file name with unicode " +
"characters in it. "+e.getMessage(),
e.getMessage().indexOf(fileName) > 0);
}
}
}