Skip to content

Commit e6c6d65

Browse files
committed
Provide multilingual support of Kernel32Util.formatMessage()
- provided multilingual support of Kernel32Util methods using Kernel32.INSTANCE.FormatMessage() - overloaded methods - test is written
1 parent 529b716 commit e6c6d65

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java

+66-6
Original file line numberDiff line numberDiff line change
@@ -178,22 +178,43 @@ public static void closeHandle(HANDLE h) {
178178
}
179179
}
180180

181+
/**
182+
* Format a message from a code.
183+
*
184+
* @param code The error code
185+
* @return Formatted message in the default locale.
186+
*/
187+
public static String formatMessage(int code) {
188+
return formatMessage(code, 0, 0);
189+
}
190+
181191
/**
182192
* Format a message from the value obtained from
183193
* {@link Kernel32#GetLastError()} or {@link Native#getLastError()}.
184194
*
195+
* <p>If you pass in zero, FormatMessage looks for a message for LANGIDs in the following order:</p>
196+
* <ol>
197+
* <li>Language neutral</li>
198+
* <li>Thread LANGID, based on the thread's locale value</li>
199+
* <li>User default LANGID, based on the user's default locale value</li>
200+
* <li>System default LANGID, based on the system default locale value</li>
201+
* <li>US English</li>
202+
* </ol>
203+
*
185204
* @param code The error code
186-
* @return Formatted message.
205+
* @param primaryLangId The primary language identifier
206+
* @param sublangId The sublanguage identifier
207+
* @return Formatted message in the specified locale.
187208
*/
188-
public static String formatMessage(int code) {
209+
public static String formatMessage(int code, int primaryLangId, int sublangId) {
189210
PointerByReference buffer = new PointerByReference();
190211
int nLen = Kernel32.INSTANCE.FormatMessage(
191212
WinBase.FORMAT_MESSAGE_ALLOCATE_BUFFER
192213
| WinBase.FORMAT_MESSAGE_FROM_SYSTEM
193214
| WinBase.FORMAT_MESSAGE_IGNORE_INSERTS,
194215
null,
195216
code,
196-
0, // TODO: // MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)
217+
WinNT.LocaleMacros.MAKELANGID(primaryLangId, sublangId),
197218
buffer, 0, null);
198219
if (nLen == 0) {
199220
throw new LastErrorException(Native.getLastError());
@@ -213,32 +234,71 @@ public static String formatMessage(int code) {
213234
*
214235
* @param code
215236
* HRESULT
216-
* @return Formatted message.
237+
* @return Formatted message in the default locale.
217238
*/
218239
public static String formatMessage(HRESULT code) {
219240
return formatMessage(code.intValue());
220241
}
221242

243+
/**
244+
* Format a message from an HRESULT.
245+
*
246+
* @param code
247+
* HRESULT
248+
* @param primaryLangId
249+
* The primary language identifier
250+
* @param sublangId
251+
* The primary language identifier
252+
* @return Formatted message in the specified locale.
253+
*/
254+
public static String formatMessage(HRESULT code, int primaryLangId, int sublangId) {
255+
return formatMessage(code.intValue(), primaryLangId, sublangId);
256+
}
257+
222258
/**
223259
* Format a system message from an error code.
224260
*
225261
* @param code
226262
* Error code, typically a result of GetLastError.
227-
* @return Formatted message.
263+
* @return Formatted message in the default locale.
228264
*/
229265
public static String formatMessageFromLastErrorCode(int code) {
230266
return formatMessage(W32Errors.HRESULT_FROM_WIN32(code));
231267
}
232268

269+
/**
270+
* Format a system message from an error code.
271+
*
272+
* @param code
273+
* Error code, typically a result of GetLastError.
274+
* @param primaryLangId
275+
* The primary language identifier
276+
* @param sublangId
277+
* The primary language identifier
278+
* @return Formatted message in the specified locale.
279+
*/
280+
public static String formatMessageFromLastErrorCode(int code, int primaryLangId, int sublangId) {
281+
return formatMessage(W32Errors.HRESULT_FROM_WIN32(code), primaryLangId, sublangId);
282+
}
283+
233284
/**
234285
* @return Obtains the human-readable error message text from the last error
235-
* that occurred by invocating {@code Kernel32.GetLastError()}.
286+
* that occurred by invocating {@code Kernel32.GetLastError()} in the default locale.
236287
*/
237288
public static String getLastErrorMessage() {
238289
return Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE
239290
.GetLastError());
240291
}
241292

293+
/**
294+
* @return Obtains the human-readable error message text from the last error
295+
* that occurred by invocating {@code Kernel32.GetLastError()} in the specified locale.
296+
*/
297+
public static String getLastErrorMessage(int primaryLangId, int sublangId) {
298+
return Kernel32Util.formatMessageFromLastErrorCode(Kernel32.INSTANCE
299+
.GetLastError(), primaryLangId, sublangId);
300+
}
301+
242302
/**
243303
* Return the path designated for temporary files.
244304
*

contrib/platform/test/com/sun/jna/platform/win32/Kernel32UtilTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ public void testFormatMessageFromHR() {
159159
}
160160
}
161161

162+
public void testFormatMessageFromErrorCodeWithNonEnglishLocale() {
163+
int errorCode = W32Errors.S_OK.intValue();
164+
String formattedMsgInDefaultLocale = Kernel32Util.formatMessage(errorCode);
165+
// primary and sub languages id's of the english locale, because it is present on most machines
166+
String formattedMsgInEnglishLocale = Kernel32Util.formatMessage(errorCode, 9, 1);
167+
if(AbstractWin32TestSupport.isEnglishLocale) {
168+
assertEquals(formattedMsgInDefaultLocale, formattedMsgInEnglishLocale);
169+
} else {
170+
assertNotSame(formattedMsgInDefaultLocale, formattedMsgInEnglishLocale);
171+
}
172+
}
173+
162174
public void testGetTempPath() {
163175
assertTrue(Kernel32Util.getTempPath().length() > 0);
164176
}

0 commit comments

Comments
 (0)