Skip to content

Commit

Permalink
Provide multilingual support of Kernel32Util.formatMessage()
Browse files Browse the repository at this point in the history
- provided multilingual support of Kernel32Util methods using Kernel32.INSTANCE.FormatMessage()
- overloaded methods
- test is written
  • Loading branch information
overpathz committed Dec 2, 2022
1 parent 529b716 commit e6c6d65
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 6 deletions.
72 changes: 66 additions & 6 deletions contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,43 @@ public static void closeHandle(HANDLE h) {
}
}

/**
* Format a message from a code.
*
* @param code The error code
* @return Formatted message in the default locale.
*/
public static String formatMessage(int code) {
return formatMessage(code, 0, 0);
}

/**
* Format a message from the value obtained from
* {@link Kernel32#GetLastError()} or {@link Native#getLastError()}.
*
* <p>If you pass in zero, FormatMessage looks for a message for LANGIDs in the following order:</p>
* <ol>
* <li>Language neutral</li>
* <li>Thread LANGID, based on the thread's locale value</li>
* <li>User default LANGID, based on the user's default locale value</li>
* <li>System default LANGID, based on the system default locale value</li>
* <li>US English</li>
* </ol>
*
* @param code The error code
* @return Formatted message.
* @param primaryLangId The primary language identifier
* @param sublangId The sublanguage identifier
* @return Formatted message in the specified locale.
*/
public static String formatMessage(int code) {
public static String formatMessage(int code, int primaryLangId, int sublangId) {
PointerByReference buffer = new PointerByReference();
int nLen = Kernel32.INSTANCE.FormatMessage(
WinBase.FORMAT_MESSAGE_ALLOCATE_BUFFER
| WinBase.FORMAT_MESSAGE_FROM_SYSTEM
| WinBase.FORMAT_MESSAGE_IGNORE_INSERTS,
null,
code,
0, // TODO: // MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)
WinNT.LocaleMacros.MAKELANGID(primaryLangId, sublangId),
buffer, 0, null);
if (nLen == 0) {
throw new LastErrorException(Native.getLastError());
Expand All @@ -213,32 +234,71 @@ public static String formatMessage(int code) {
*
* @param code
* HRESULT
* @return Formatted message.
* @return Formatted message in the default locale.
*/
public static String formatMessage(HRESULT code) {
return formatMessage(code.intValue());
}

/**
* Format a message from an HRESULT.
*
* @param code
* HRESULT
* @param primaryLangId
* The primary language identifier
* @param sublangId
* The primary language identifier
* @return Formatted message in the specified locale.
*/
public static String formatMessage(HRESULT code, int primaryLangId, int sublangId) {
return formatMessage(code.intValue(), primaryLangId, sublangId);
}

/**
* Format a system message from an error code.
*
* @param code
* Error code, typically a result of GetLastError.
* @return Formatted message.
* @return Formatted message in the default locale.
*/
public static String formatMessageFromLastErrorCode(int code) {
return formatMessage(W32Errors.HRESULT_FROM_WIN32(code));
}

/**
* Format a system message from an error code.
*
* @param code
* Error code, typically a result of GetLastError.
* @param primaryLangId
* The primary language identifier
* @param sublangId
* The primary language identifier
* @return Formatted message in the specified locale.
*/
public static String formatMessageFromLastErrorCode(int code, int primaryLangId, int sublangId) {
return formatMessage(W32Errors.HRESULT_FROM_WIN32(code), primaryLangId, sublangId);
}

/**
* @return Obtains the human-readable error message text from the last error
* that occurred by invocating {@code Kernel32.GetLastError()}.
* that occurred by invocating {@code Kernel32.GetLastError()} in the default locale.
*/
public static String getLastErrorMessage() {
return Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE
.GetLastError());
}

/**
* @return Obtains the human-readable error message text from the last error
* that occurred by invocating {@code Kernel32.GetLastError()} in the specified locale.
*/
public static String getLastErrorMessage(int primaryLangId, int sublangId) {
return Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE
.GetLastError(), primaryLangId, sublangId);
}

/**
* Return the path designated for temporary files.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ public void testFormatMessageFromHR() {
}
}

public void testFormatMessageFromErrorCodeWithNonEnglishLocale() {
int errorCode = W32Errors.S_OK.intValue();
String formattedMsgInDefaultLocale = Kernel32Util.formatMessage(errorCode);
// primary and sub languages id's of the english locale, because it is present on most machines
String formattedMsgInEnglishLocale = Kernel32Util.formatMessage(errorCode, 9, 1);
if(AbstractWin32TestSupport.isEnglishLocale) {
assertEquals(formattedMsgInDefaultLocale, formattedMsgInEnglishLocale);
} else {
assertNotSame(formattedMsgInDefaultLocale, formattedMsgInEnglishLocale);
}
}

public void testGetTempPath() {
assertTrue(Kernel32Util.getTempPath().length() > 0);
}
Expand Down

0 comments on commit e6c6d65

Please sign in to comment.