From 8855dc92c8a5004673e1462c48a0d5ad1ff5d717 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Thu, 3 Mar 2016 09:34:55 +0200 Subject: [PATCH] Added Kerne32Util method to facilitate checking that calls to LocalFree/GlobalFree are successful --- CHANGES.md | 7 +- .../sun/jna/platform/win32/Advapi32Util.java | 19 +- .../sun/jna/platform/win32/Crypt32Util.java | 258 ++++++++++-------- .../com/sun/jna/platform/win32/Kernel32.java | 99 +++---- .../sun/jna/platform/win32/Kernel32Util.java | 130 ++++++--- .../sun/jna/platform/win32/Advapi32Test.java | 218 ++++++++------- .../sun/jna/platform/win32/Crypt32Test.java | 95 ++++--- .../sun/jna/platform/win32/VersionTest.java | 34 ++- 8 files changed, 514 insertions(+), 346 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 96d2dfd65a..8ff77416d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,20 +37,21 @@ Features * [#583](https://github.com/java-native-access/jna/pull/583): Added printer attributes and status - [@IvanRF](https://github.com/IvanRF). * [#589](https://github.com/java-native-access/jna/pull/589): Use MethodResultContext in direct mapping (as done in interface mapping) - [@marco2357](https://github.com/marco2357). * [#595](https://github.com/java-native-access/jna/pull/595): Allow calling COM methods/getters requiring hybrid calling (METHOD+PROPERTYGET) - [@matthiasblaesing](https://github.com/matthiasblaesing). -* [#582](https://github.com/java-native-access/jna/pull/582): Mavenize the build process - Phase 1: building the native code via Maven [@lgoldstein](https://github.com/lgoldstein) +* [#582](https://github.com/java-native-access/jna/pull/582): Mavenize the build process - Phase 1: building the native code via Maven [@lgoldstein](https://github.com/lgoldstein). +* [#606](https://github.com/java-native-access/jna/pull/606): Added Kerne32Util method to facilitate checking that calls to LocalFree/GlobalFree are successful [@lgoldstein](https://github.com/lgoldstein). Bug Fixes --------- * [#549](https://github.com/java-native-access/jna/pull/549): Fixed bug in types derived from XID - [@twall](https://github.com/twall). * [#536](https://github.com/java-native-access/jna/pull/536): Fixed bug in determining the Library and options associated with types defined outside of a Library - [@twall](https://github.com/twall). * [#531](https://github.com/java-native-access/jna/pull/531): Ensure direct-mapped callbacks use the right calling convention - [@twall](https://github.com/twall). -* [#566](https://github.com/java-native-access/jna/pull/566): Fix return type of Native#loadLibrary to match unconstrained generic [@lgoldstein](https://github.com/lgoldstein) +* [#566](https://github.com/java-native-access/jna/pull/566): Fix return type of Native#loadLibrary to match unconstrained generic [@lgoldstein](https://github.com/lgoldstein). * [#584](https://github.com/java-native-access/jna/pull/584): Promote float varargs to double - [@marco2357](https://github.com/marco2357). * [#588](https://github.com/java-native-access/jna/pull/588): Fix varargs calls on arm - [@twall](https://github.com/twall). * [#593](https://github.com/java-native-access/jna/pull/593): Improve binding of TypeLib bindings - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#578](https://github.com/java-native-access/jna/pull/578): Fix COM CallbackHandlers, allow usage of VARIANTs directly in c.s.j.p.w.COM.util.ProxyObject and fix native memory leak in c.s.j.p.w.COM.util.ProxyObject - [@matthiasblaesing](https://github.com/matthiasblaesing) * [#601](https://github.com/java-native-access/jna/pull/601): Remove COMThread and COM initialization from objects and require callers to initialize COM themselves. Asserts are added to guard correct usage. - [@matthiasblaesing](https://github.com/matthiasblaesing). -* [#602] https://github.com/java-native-access/jna/pull/602): Make sure SID related memory is properly released once no longer required [@lgoldstein](https://github.com/lgoldstein) +* [#602] https://github.com/java-native-access/jna/pull/602): Make sure SID related memory is properly released once no longer required [@lgoldstein](https://github.com/lgoldstein). Release 4.2.1 ============= diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java index 7103cf51eb..2ab17dfb17 100755 --- a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java @@ -301,7 +301,7 @@ public static String convertSidToStringSid(PSID sid) { try { return ptr.getWideString(0); } finally { - Kernel32.INSTANCE.LocalFree(ptr); + Kernel32Util.validateFreeLocalMemory(ptr); } } @@ -323,7 +323,7 @@ public static byte[] convertStringSidToSid(String sidString) { try { return value.getBytes(); } finally { - Kernel32.INSTANCE.LocalFree(value.getPointer()); + Kernel32Util.validateFreeLocalMemory(value.getPointer()); } } @@ -347,7 +347,7 @@ public static boolean isWellKnownSid(String sidString, int wellKnownSidType) { try { return Advapi32.INSTANCE.IsWellKnownSid(value, wellKnownSidType); } finally { - Kernel32.INSTANCE.LocalFree(value.getPointer()); + Kernel32Util.validateFreeLocalMemory(value.getPointer()); } } @@ -2207,10 +2207,15 @@ public static Memory getSecurityDescriptorForObject(final String absoluteObjectP } int nLength = Advapi32.INSTANCE.GetSecurityDescriptorLength(ppSecurityDescriptor.getValue()); - final Memory memory = new Memory(nLength); - memory.write(0, ppSecurityDescriptor.getValue().getByteArray(0, nLength), 0, nLength); - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); - return memory; + Memory memory = new Memory(nLength); + Pointer secValue = ppSecurityDescriptor.getValue(); + try { + byte[] data = secValue.getByteArray(0, nLength); + memory.write(0, data, 0, nLength); + return memory; + } finally { + Kernel32Util.validateFreeLocalMemory(secValue); + } } /** diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Crypt32Util.java b/contrib/platform/src/com/sun/jna/platform/win32/Crypt32Util.java index 6e7c663cec..834eb42cee 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Crypt32Util.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Crypt32Util.java @@ -1,14 +1,14 @@ /* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna.platform.win32; @@ -22,119 +22,145 @@ */ public abstract class Crypt32Util { - /** - * Protect a blob of data. - * @param data - * Data to protect. - * @return - * Protected data. - */ - public static byte[] cryptProtectData(byte[] data) { - return cryptProtectData(data, 0); - } + /** + * Protect a blob of data. + * @param data + * Data to protect. + * @return + * Protected data. + */ + public static byte[] cryptProtectData(byte[] data) { + return cryptProtectData(data, 0); + } - /** - * Protect a blob of data with optional flags. - * @param data - * Data to protect. - * @param flags - * Optional flags, eg. CRYPTPROTECT_LOCAL_MACHINE | CRYPTPROTECT_UI_FORBIDDEN. - * @return - * Protected data. - */ - public static byte[] cryptProtectData(byte[] data, int flags) { - return cryptProtectData(data, null, flags, "", null); - } - - /** - * Protect a blob of data. - * @param data - * Data to protect. - * @param entropy - * Optional entropy. - * @param flags - * Optional flags. - * @param description - * Optional description. - * @param prompt - * Prompt structure. - * @return - * Protected bytes. - */ - public static byte[] cryptProtectData(byte[] data, byte[] entropy, int flags, - String description, CRYPTPROTECT_PROMPTSTRUCT prompt) { - DATA_BLOB pDataIn = new DATA_BLOB(data); - DATA_BLOB pDataProtected = new DATA_BLOB(); - DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy); - try { - if (! Crypt32.INSTANCE.CryptProtectData(pDataIn, description, - pEntropy, null, prompt, flags, pDataProtected)) { - throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); - } - return pDataProtected.getData(); - } finally { - if (pDataProtected.pbData != null) { - Kernel32.INSTANCE.LocalFree(pDataProtected.pbData); - } - } - } - - /** - * Unprotect a blob of data. - * @param data - * Data to unprotect. - * @return - * Unprotected blob of data. - */ - public static byte[] cryptUnprotectData(byte[] data) { - return cryptUnprotectData(data, 0); - } + /** + * Protect a blob of data with optional flags. + * @param data + * Data to protect. + * @param flags + * Optional flags, eg. CRYPTPROTECT_LOCAL_MACHINE | CRYPTPROTECT_UI_FORBIDDEN. + * @return + * Protected data. + */ + public static byte[] cryptProtectData(byte[] data, int flags) { + return cryptProtectData(data, null, flags, "", null); + } - /** - * Unprotect a blob of data. - * @param data - * Data to unprotect. - * @param flags - * Optional flags, eg. CRYPTPROTECT_UI_FORBIDDEN. - * @return - * Unprotected blob of data. - */ - public static byte[] cryptUnprotectData(byte[] data, int flags) { - return cryptUnprotectData(data, null, flags, null); - } - - /** - * Unprotect a blob of data. - * @param data - * Data to unprotect. - * @param entropy - * Optional entropy. - * @param flags - * Optional flags. - * @param prompt - * Optional prompt structure. - * @return - * Unprotected blob of data. - */ - public static byte[] cryptUnprotectData(byte[] data, byte[] entropy, int flags, - CRYPTPROTECT_PROMPTSTRUCT prompt) { - DATA_BLOB pDataIn = new DATA_BLOB(data); - DATA_BLOB pDataUnprotected = new DATA_BLOB(); - DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy); - PointerByReference pDescription = new PointerByReference(); - try { - if (! Crypt32.INSTANCE.CryptUnprotectData(pDataIn, pDescription, - pEntropy, null, prompt, flags, pDataUnprotected)) { - throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); - } - return pDataUnprotected.getData(); - } finally { - if (pDataUnprotected.pbData != null) { - Kernel32.INSTANCE.LocalFree(pDataUnprotected.pbData); - } - if (pDescription.getValue() != null) { - Kernel32.INSTANCE.LocalFree(pDescription.getValue()); - } - } - } + /** + * Protect a blob of data. + * @param data + * Data to protect. + * @param entropy + * Optional entropy. + * @param flags + * Optional flags. + * @param description + * Optional description. + * @param prompt + * Prompt structure. + * @return + * Protected bytes. + */ + public static byte[] cryptProtectData(byte[] data, byte[] entropy, int flags, + String description, CRYPTPROTECT_PROMPTSTRUCT prompt) { + DATA_BLOB pDataIn = new DATA_BLOB(data); + DATA_BLOB pDataProtected = new DATA_BLOB(); + DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy); + try { + if (! Crypt32.INSTANCE.CryptProtectData(pDataIn, description, + pEntropy, null, prompt, flags, pDataProtected)) { + throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); + } + return pDataProtected.getData(); + } finally { + if (pDataProtected.pbData != null) { + Kernel32Util.validateFreeLocalMemory(pDataProtected.pbData); + } + } + } + + /** + * Unprotect a blob of data. + * @param data + * Data to unprotect. + * @return + * Unprotected blob of data. + */ + public static byte[] cryptUnprotectData(byte[] data) { + return cryptUnprotectData(data, 0); + } + + /** + * Unprotect a blob of data. + * @param data + * Data to unprotect. + * @param flags + * Optional flags, eg. CRYPTPROTECT_UI_FORBIDDEN. + * @return + * Unprotected blob of data. + */ + public static byte[] cryptUnprotectData(byte[] data, int flags) { + return cryptUnprotectData(data, null, flags, null); + } + + /** + * Unprotect a blob of data. + * @param data + * Data to unprotect. + * @param entropy + * Optional entropy. + * @param flags + * Optional flags. + * @param prompt + * Optional prompt structure. + * @return + * Unprotected blob of data. + */ + public static byte[] cryptUnprotectData(byte[] data, byte[] entropy, int flags, + CRYPTPROTECT_PROMPTSTRUCT prompt) { + DATA_BLOB pDataIn = new DATA_BLOB(data); + DATA_BLOB pDataUnprotected = new DATA_BLOB(); + DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy); + PointerByReference pDescription = new PointerByReference(); + Win32Exception err = null; + byte[] unProtectedData = null; + try { + if (! Crypt32.INSTANCE.CryptUnprotectData(pDataIn, pDescription, + pEntropy, null, prompt, flags, pDataUnprotected)) { + err = new Win32Exception(Kernel32.INSTANCE.GetLastError()); + } else { + unProtectedData = pDataUnprotected.getData(); + } + } finally { + if (pDataUnprotected.pbData != null) { + int rc = Kernel32Util.freeLocalMemory(pDataUnprotected.pbData); + if (rc != WinError.ERROR_SUCCESS) { + Win32Exception exc = new Win32Exception(rc); + if (err == null) { + err = exc; + } else { + err.addSuppressed(exc); + } + } + } + + if (pDescription.getValue() != null) { + int rc = Kernel32Util.freeLocalMemory(pDescription.getValue()); + if (rc != WinError.ERROR_SUCCESS) { + Win32Exception exc = new Win32Exception(rc); + if (err == null) { + err = exc; + } else { + err.addSuppressed(exc); + } + } + } + } + + if (err != null) { + throw err; + } + + return unProtectedData; + } } \ No newline at end of file diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java index 40339b1e7e..76c8b10d12 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java @@ -16,8 +16,8 @@ import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; -import com.sun.jna.win32.W32APIOptions; import com.sun.jna.win32.StdCallLibrary; +import com.sun.jna.win32.W32APIOptions; /** * Interface definitions for kernel32.dll. Includes additional @@ -53,7 +53,7 @@ public interface Kernel32 extends StdCallLibrary, WinNT, Wincon { * see Remarks. */ int LOAD_LIBRARY_AS_DATAFILE = 0x2; - + /** * Reads data from the specified file or input/output (I/O) device. Reads * occur at the position specified by the file pointer if supported by the @@ -94,14 +94,16 @@ boolean ReadFile(HANDLE hFile, byte[] lpBuffer, int nNumberOfBytesToRead, /** * Frees the specified local memory object and invalidates its handle. * - * @param hLocal - * A handle to the local memory object. + * @param hMem + * A handle to the local memory object. If the hMem parameter + * is NULL, {@code LocalFree} ignores the parameter and returns NULL. * @return If the function succeeds, the return value is NULL. If the * function fails, the return value is equal to a handle to the * local memory object. To get extended error information, call - * GetLastError. + * {@code GetLastError}. + * @see LocalFree */ - Pointer LocalFree(Pointer hLocal); + Pointer LocalFree(Pointer hMem); /** * Frees the specified global memory object and invalidates its handle. @@ -111,7 +113,8 @@ boolean ReadFile(HANDLE hFile, byte[] lpBuffer, int nNumberOfBytesToRead, * @return If the function succeeds, the return value is NULL If the * function fails, the return value is equal to a handle to the * global memory object. To get extended error information, call - * GetLastError. + * {@code GetLastError}. + * @see GlobalFree */ Pointer GlobalFree(Pointer hGlobal); @@ -183,12 +186,12 @@ boolean ReadFile(HANDLE hFile, byte[] lpBuffer, int nNumberOfBytesToRead, * Retrieves system timing information. On a multiprocessor system, the * values returned are the sum of the designated times across all * processors. - * + * * @param lpIdleTime * A pointer to a {@link WinBase.FILETIME} structure that * receives the amount of time that the system has been idle. * @param lpKernelTime - * A pointer to a {@link WinBase.FILETIME} structure that + * A pointer to a {@link WinBase.FILETIME} structure that * receives the amount of time that the system has spent * executing in Kernel mode (including all threads in all * processes, on all processors). This time value also includes @@ -204,7 +207,7 @@ boolean ReadFile(HANDLE hFile, byte[] lpBuffer, int nNumberOfBytesToRead, * @see GetSystemTimes documentation */ boolean GetSystemTimes(WinBase.FILETIME lpIdleTime, WinBase.FILETIME lpKernelTime, WinBase.FILETIME lpUserTime); - + /** * The GetTickCount function retrieves the number of milliseconds that have * elapsed since the system was started, up to 49.7 days. @@ -1262,23 +1265,23 @@ boolean CreateProcessW(String lpApplicationName, char[] lpCommandLine, * GetLastError. */ HANDLE OpenProcess(int fdwAccess, boolean fInherit, int IDProcess); - + /** * This function retrieves the full path of the executable file of a given process. - * + * * @param hProcess * Handle for the running process * @param dwFlags * 0 - The name should use the Win32 path format. - * 1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format. + * 1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format. * @param lpExeName * pre-allocated character buffer for the returned path * @param lpdwSize * input: the size of the allocated buffer - * output: the length of the returned path in characters - * - * @return true if successful false if not. To get extended error information, - * call GetLastError. + * output: the length of the returned path in characters + * + * @return true if successful false if not. To get extended error information, + * call GetLastError. */ boolean QueryFullProcessImageName(HANDLE hProcess, int dwFlags, char[] lpExeName, IntByReference lpdwSize); @@ -2507,7 +2510,7 @@ boolean SystemTimeToTzSpecificLocalTime(TIME_ZONE_INFORMATION lpTimeZone, /** * Reads data from an area of memory in a specified process. The entire area * to be read must be accessible or the operation fails. - * + * * @see MSDN * @param hProcess * A handle to the process with memory that is being read. The @@ -2815,11 +2818,11 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * @see FindVolumeClose */ boolean FindVolumeClose(HANDLE hFindVolume); - + /** * Retrieves the current control settings for a specified communications * device. - * + * * @param hFile * [in] A handle to the communications device.
* The @@ -2828,37 +2831,37 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * @param lpDCB * [in, out] A pointer to a {@link WinBase.DCB} structure that * receives the control settings information. - * + * * @return If the function succeeds, the return value is nonzero.
* If the function fails, the return value is zero. To get extended * error information, call {@link Kernel32#GetLastError()}. - * + * */ boolean GetCommState(HANDLE hFile, WinBase.DCB lpDCB); /** - * + * * Retrieves the time-out parameters for all read and write operations on a * specified communications device.
*
* For more information about time-out values for communications devices, * see the {@link Kernel32#SetCommTimeouts} function. - * + * * @param hFile * [in] A handle to the communications device. The * {@link com.sun.jna.platform.win32.Kernel32#CreateFile(String, int, int, com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES, int, int, com.sun.jna.platform.win32.WinNT.HANDLE)} * function returns this handle. - * + * * @param lpCommTimeouts * [in] A pointer to a {@link WinBase.COMMTIMEOUTS} structure in * which the time-out information is returned. * @return If the function succeeds, the return value is nonzero. - * + * * If the function fails, the return value is zero. To get extended * error information, call {@link Kernel32#GetLastError()}. - * - * - * + * + * + * */ boolean GetCommTimeouts(HANDLE hFile, WinBase.COMMTIMEOUTS lpCommTimeouts); @@ -2867,7 +2870,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * device-control block (a {@link WinBase.DCB} structure). The function * reinitializes all hardware and control settings, but it does not empty * output or input queues. - * + * * @param hFile * [in] A handle to the communications device. The * {@link com.sun.jna.platform.win32.Kernel32#CreateFile(String, int, int, com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES, int, int, com.sun.jna.platform.win32.WinNT.HANDLE)} @@ -2885,7 +2888,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, /** * Sets the time-out parameters for all read and write operations on a * specified communications device. - * + * * @param hFile * [in] A handle to the communications device. The * {@link com.sun.jna.platform.win32.Kernel32#CreateFile(String, int, int, com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES, int, int, com.sun.jna.platform.win32.WinNT.HANDLE)} @@ -2906,7 +2909,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * process.
*
*
BOOL ProcessIdToSessionId(_In_ DWORD dwProcessId, _Out_ DWORD *pSessionId);

- * + * * @param dwProcessId * Specifies a process identifier.
* Use the GetCurrentProcessId function to retrieve the process @@ -2926,7 +2929,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, /** * Loads the specified module into the address space of the calling process. * The specified module may cause other modules to be loaded. - * + * *
      * 
      * HMODULE WINAPI LoadLibraryEx(
@@ -2936,7 +2939,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName,
      * );
      * 
      * 
- * + * * @param lpFileName * A string that specifies the file name of the module to load. * This name is not related to the name stored in a library @@ -3065,7 +3068,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, *
*
* LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: 0x00000100
- * + * * If this value is used, the directory that contains the DLL is * temporarily added to the beginning of the list of directories * that are searched for the DLL's dependencies. Directories in @@ -3127,7 +3130,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * Determines the location of a resource with the specified type and name in * the specified module.
* To specify a language, use the FindResourceEx function. - * + * * @param hModule * A handle to the module whose portable executable file or an * accompanying MUI file contains the resource.
@@ -3158,7 +3161,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, /** * Retrieves a handle that can be used to obtain a pointer to the first byte * of the specified resource in memory. - * + * * @param hModule * A handle to the module whose executable file contains the * resource.
@@ -3177,7 +3180,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, /** * Retrieves a pointer to the specified resource in memory. - * + * * @param hResource * A handle to the resource to be accessed.
* The LoadResource function returns this handle.
@@ -3204,13 +3207,13 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, */ int SizeofResource(HMODULE hModule, HANDLE hResource); - + /** * Frees the loaded dynamic-link library (DLL) module and, if necessary, * decrements its reference count. When the reference count reaches zero, * the module is unloaded from the address space of the calling process and * the handle is no longer valid. - * + * * @param module * A handle to the loaded library module. The LoadLibrary, * LoadLibraryEx, GetModuleHandle, or GetModuleHandleEx function @@ -3220,7 +3223,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * information, call the GetLastError function. */ boolean FreeLibrary(HMODULE module); - + /** * Enumerates resource types within a binary module.
* Starting with Windows Vista, this is typically a language-neutral @@ -3231,7 +3234,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * only that file is searched for resource types.
* Alternately, applications can call EnumResourceTypesEx, which provides * more precise control over which resource files to enumerate. - * + * * @param hModule * A handle to a module to be searched.
* This handle must be obtained through LoadLibrary or @@ -3249,7 +3252,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * error information, call GetLastError. */ boolean EnumResourceTypes(HMODULE hModule, WinBase.EnumResTypeProc proc, Pointer lParam); - + /** * Enumerates resources of a specified type within a binary module.
* For Windows Vista and later, this is typically a language-neutral @@ -3258,7 +3261,7 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * files) that contain localizable language resources.
* It is also possible for hModule to specify an .mui file, in which case * only that file is searched for resources. - * + * * @param hModule * A handle to a module to be searched.
* Starting with Windows Vista, if this is an LN file, then @@ -3287,10 +3290,10 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, * information, call GetLastError. */ boolean EnumResourceNames(HMODULE hModule, Pointer type, WinBase.EnumResNameProc proc, Pointer lParam); - + /** * Retrieves information about the first module associated with a process. - * + * * @see MSDN * @param hSnapshot * A handle to the snapshot returned from a previous call to the @@ -3308,8 +3311,8 @@ boolean GetVolumePathNamesForVolumeName(String lpszVolumeName, /** * Retrieves information about the next module associated with a process or * thread. - * - * @see MSDN + * + * @see MSDN * @param hSnapshot * A handle to the snapshot returned from a previous call to the * CreateToolhelp32Snapshot function. diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java index f8d9f1cebf..9f23916c63 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java @@ -54,28 +54,95 @@ public static String getComputerName() { return Native.toString(buffer); } + /** + * Makes sure that local memory has been successfully freed + * + * @param ptr The {@link Pointer} to the memory to be released - ignored if NULL + * @see #freeLocalMemory(Pointer) + * @throws Win32Exception if non-{@code ERROR_SUCCESS} code reported + */ + public static void validateFreeLocalMemory(Pointer ptr) { + int rc = freeLocalMemory(ptr); + if (rc != WinError.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Invokes {@link Kernel32#LocalFree(Pointer)} and checks if it succeeded. + * + * @param ptr The {@link Pointer} to the memory to be released - ignored if NULL + * @return {@code ERROR_SUCCESS} or reason for failing to free the memory + * @see Native#getLastError() + */ + public static int freeLocalMemory(Pointer ptr) { + Pointer res = Kernel32.INSTANCE.LocalFree(ptr); + if (res != null) { + return Native.getLastError(); + } else { + return WinError.ERROR_SUCCESS; + } + } + + + /** + * Makes sure that global memory has been successfully freed + * + * @param ptr The {@link Pointer} to the memory to be released - ignored if NULL + * @see #freeGlobalMemory(Pointer) + * @throws Win32Exception if non-{@code ERROR_SUCCESS} code reported + */ + public static void validateFreeGlobalMemory(Pointer ptr) { + int rc = freeGlobalMemory(ptr); + if (rc != WinError.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Invokes {@link Kernel32#GlobalFree(Pointer)} and checks if it succeeded. + * + * @param ptr The {@link Pointer} to the memory to be released - ignored if NULL + * @return {@code ERROR_SUCCESS} or reason for failing to free the memory + * @see Native#getLastError() + */ + public static int freeGlobalMemory(Pointer ptr) { + Pointer res = Kernel32.INSTANCE.GlobalFree(ptr); + if (res != null) { + return Native.getLastError(); + } else { + return WinError.ERROR_SUCCESS; + } + } + /** * Format a message from the value obtained from - * {@link Kernel32#GetLastError} or {@link Native#getLastError}. + * {@link Kernel32#GetLastError()} or {@link Native#getLastError()}. * - * @param code - * int + * @param code The error code * @return Formatted message. */ public static String formatMessage(int code) { PointerByReference buffer = new PointerByReference(); - if (0 == Kernel32.INSTANCE.FormatMessage( + 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) - buffer, 0, null)) { - throw new LastErrorException(Kernel32.INSTANCE.GetLastError()); + | WinBase.FORMAT_MESSAGE_FROM_SYSTEM + | WinBase.FORMAT_MESSAGE_IGNORE_INSERTS, + null, + code, + 0, // TODO: // MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT) + buffer, 0, null); + if (nLen == 0) { + throw new LastErrorException(Native.getLastError()); + } + + Pointer ptr = buffer.getValue(); + try { + String s = ptr.getWideString(0); + return s.trim(); + } finally { + validateFreeLocalMemory(ptr); } - String s = buffer.getValue().getWideString(0); - Kernel32.INSTANCE.LocalFree(buffer.getValue()); - return s.trim(); } /** @@ -94,6 +161,7 @@ public static String formatMessage(HRESULT code) { * @param code error code * @return formatted message */ + @Deprecated public static String formatMessageFromHR(HRESULT code) { return formatMessage(code.intValue()); } @@ -680,19 +748,19 @@ public static final String extractVolumeGUID(String volumeGUIDPath) { return volumeGUIDPath.substring(VOLUME_GUID_PATH_PREFIX.length(), volumeGUIDPath.length() - VOLUME_GUID_PATH_SUFFIX.length()); } - + /** - * + * * This function retrieves the full path of the executable file of a given process. - * + * * @param hProcess * Handle for the running process * @param dwFlags * 0 - The name should use the Win32 path format. - * 1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format. - * - * @return the full path of the process's executable file of null if failed. To get extended error information, - * call GetLastError. + * 1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format. + * + * @return the full path of the process's executable file of null if failed. To get extended error information, + * call GetLastError. */ public static final String QueryFullProcessImageName(HANDLE hProcess, int dwFlags) { char[] path = new char[WinDef.MAX_PATH]; @@ -791,7 +859,7 @@ public static byte[] getResource(String path, String type, String name) { /** * Gets a list of all resources from the specified executable file - * + * * @param path * The path to the executable file * @return A map of resource type name/ID => resources.
@@ -813,7 +881,7 @@ public static Map> getResourceNames(String path) { @Override public boolean invoke(HMODULE module, Pointer type, Pointer lParam) { // simulate IS_INTRESOURCE macro defined in WinUser.h - // basically that means that if "type" is less than or equal to 65,535 + // basically that means that if "type" is less than or equal to 65,535 // it assumes it's an ID. // otherwise it assumes it's a pointer to a string if (Pointer.nativeValue(type) <= 65535) { @@ -830,13 +898,13 @@ public boolean invoke(HMODULE module, Pointer type, Pointer lParam) { @Override public boolean invoke(HMODULE module, Pointer type, Pointer name, Pointer lParam) { String typeName = ""; - + if (Pointer.nativeValue(type) <= 65535) { typeName = Pointer.nativeValue(type) + ""; } else { typeName = type.getWideString(0); } - + if (Pointer.nativeValue(name) < 65535) { result.get(typeName).add(Pointer.nativeValue(name) + ""); } else { @@ -846,7 +914,7 @@ public boolean invoke(HMODULE module, Pointer type, Pointer name, Pointer lParam return true; } }; - + Win32Exception err = null; try { @@ -867,7 +935,7 @@ public boolean invoke(HMODULE module, Pointer type, Pointer name, Pointer lParam pointer = new Memory(Native.WCHAR_SIZE * (typeName.length() + 1)); pointer.setWideString(0, typeName); } - + boolean callResult = Kernel32.INSTANCE.EnumResourceNames(target, pointer, ernp, null); if (!callResult) { @@ -895,10 +963,10 @@ public boolean invoke(HMODULE module, Pointer type, Pointer name, Pointer lParam } return result; } - + /** * Returns all the executable modules for a given process ID.
- * + * * @param processID * The process ID to get executable modules for * @return All the modules in the process. @@ -924,9 +992,9 @@ public static List getModules(int processID) { modules.add(next); next = new Tlhelp32.MODULEENTRY32W(); } - + int lastError = Kernel32.INSTANCE.GetLastError(); - // if we got a false from Module32Next, + // if we got a false from Module32Next, // check to see if it returned false because we're genuinely done // or if something went wrong. if (lastError != W32Errors.ERROR_SUCCESS && lastError != W32Errors.ERROR_NO_MORE_FILES) { @@ -945,7 +1013,7 @@ public static List getModules(int processID) { } } } - + if (we != null) { throw we; } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java index ceeb5cf838..7c3fdb967e 100755 --- a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32Test.java @@ -145,7 +145,8 @@ public void testIsValidSid() { assertTrue("Non positive sid length", sidLength > 0); assertTrue("Invalid sid", Advapi32.INSTANCE.IsValidSid(value)); } finally { - assertNull("Failed to release SID", Kernel32.INSTANCE.LocalFree(value.getPointer())); + assertEquals("Failed to release SID", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(value.getPointer())); } } @@ -158,7 +159,8 @@ public void testGetSidLength() { try { assertEquals("Wrong SID length", 12, Advapi32.INSTANCE.GetLengthSid(value)); } finally { - assertNull("Failed to free SID", Kernel32.INSTANCE.LocalFree(value.getPointer())); + assertEquals("Failed to free SID", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(value.getPointer())); } } @@ -192,7 +194,8 @@ public void testLookupAccountSid() { assertEquals("Everyone", nameString); assertTrue(referencedDomainNameString.length() == 0); } finally { - assertNull("Failed to release sid", Kernel32.INSTANCE.LocalFree(value.getPointer())); + assertEquals("Failed to release sid", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(value.getPointer())); } } @@ -211,10 +214,12 @@ public void testConvertSid() { String convertedSidString = conv.getWideString(0); assertEquals("Mismatched SID string", convertedSidString, sidString); } finally { - assertNull("Failed to release string value", Kernel32.INSTANCE.LocalFree(conv)); + assertEquals("Failed to release string value", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(conv)); } } finally { - assertNull("Failed to release sid", Kernel32.INSTANCE.LocalFree(value.getPointer())); + assertEquals("Failed to release sid", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(value.getPointer())); } } @@ -626,7 +631,8 @@ public void testIsWellKnownSid() { assertTrue("Not a world sid", Advapi32.INSTANCE.IsWellKnownSid(value, WELL_KNOWN_SID_TYPE.WinWorldSid)); assertFalse("Unexpected admin sid", Advapi32.INSTANCE.IsWellKnownSid(value, WELL_KNOWN_SID_TYPE.WinAccountAdministratorSid)); } finally { - assertNull("Failed to release sid", Kernel32.INSTANCE.LocalFree(value.getPointer())); + assertEquals("Failed to release sid", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(value.getPointer())); } } @@ -646,7 +652,8 @@ public void testCreateWellKnownSid() { String convertedSidString = conv.getWideString(0); assertEquals("Mismatched SID string", EVERYONE, convertedSidString); } finally { - assertNull("Failed to release string", Kernel32.INSTANCE.LocalFree(conv)); + assertEquals("Failed to release string", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(conv)); } } @@ -978,8 +985,6 @@ public void testImpersonateSelf() { public void testGetNamedSecurityInfoForFileNoSACL() throws Exception { - // create a temp file - File file = createTempFile(); int infoType = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; @@ -989,18 +994,26 @@ public void testGetNamedSecurityInfoForFileNoSACL() throws Exception { PointerByReference ppDacl = new PointerByReference(); PointerByReference ppSecurityDescriptor = new PointerByReference(); - assertEquals(Advapi32.INSTANCE.GetNamedSecurityInfo( - file.getAbsolutePath(), - AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, - infoType, - ppsidOwner, - ppsidGroup, - ppDacl, - null, - ppSecurityDescriptor), 0); - - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); - file.delete(); + File file = createTempFile(); + try { + try { + assertEquals("GetNamedSecurityInfo(" + file + ")", 0, + Advapi32.INSTANCE.GetNamedSecurityInfo( + file.getAbsolutePath(), + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner, + ppsidGroup, + ppDacl, + null, + ppSecurityDescriptor)); + } finally { + file.delete(); + } + } finally { + assertEquals("Failed to free security descriptor of " + file, + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue())); + } } public void testGetNamedSecurityInfoForFileWithSACL() throws Exception { @@ -1052,24 +1065,27 @@ public void testGetNamedSecurityInfoForFileWithSACL() throws Exception { PointerByReference ppDacl = new PointerByReference(); PointerByReference ppSacl = new PointerByReference(); PointerByReference ppSecurityDescriptor = new PointerByReference(); - // create a temp file + File file = createTempFile(); String filePath = file.getAbsolutePath(); try { - assertEquals("GetNamedSecurityInfo(" + filePath + ")", 0, - Advapi32.INSTANCE.GetNamedSecurityInfo( - filePath, - AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, - infoType, - ppsidOwner, - ppsidGroup, - ppDacl, - ppSacl, - ppSecurityDescriptor)); - // Clean up resources - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); + try { + assertEquals("GetNamedSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.GetNamedSecurityInfo( + filePath, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner, + ppsidGroup, + ppDacl, + ppSacl, + ppSecurityDescriptor)); + } finally { + file.delete(); + } } finally { - file.delete(); + assertEquals("Failed to free security descriptor of " + filePath, + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue())); } if (impersontating) { Advapi32.INSTANCE.SetThreadToken(null, null); @@ -1097,18 +1113,17 @@ public void testSetNamedSecurityInfoForFileNoSACL() throws Exception { File file = createTempFile(); String filePath = file.getAbsolutePath(); try { - assertEquals("GetNamedSecurityInfo(" + filePath + ")", 0, - Advapi32.INSTANCE.GetNamedSecurityInfo( - filePath, - AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, - infoType, - ppsidOwner, - ppsidGroup, - ppDacl, - null, - ppSecurityDescriptor)); - try { + assertEquals("GetNamedSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.GetNamedSecurityInfo( + filePath, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner, + ppsidGroup, + ppDacl, + null, + ppSecurityDescriptor)); assertEquals("SetNamedSecurityInfo(" + filePath + ")", 0, Advapi32.INSTANCE.SetNamedSecurityInfo( filePath, @@ -1119,10 +1134,11 @@ public void testSetNamedSecurityInfoForFileNoSACL() throws Exception { ppDacl.getValue(), null)); } finally { - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); + file.delete(); } } finally { - file.delete(); + assertEquals("Failed to release security descriptor of " + file, + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue())); } } @@ -1183,18 +1199,18 @@ public void testSetNamedSecurityInfoForFileWithSACL() throws Exception { PointerByReference ppSecurityDescriptor = new PointerByReference(); String filePath = file.getAbsolutePath(); try { - assertEquals("GetNamedSecurityInfo(" + filePath + ")", 0, - Advapi32.INSTANCE.GetNamedSecurityInfo( - filePath, - AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, - infoType, - ppsidOwner, - ppsidGroup, - ppDacl, - ppSacl, - ppSecurityDescriptor)); - try { + assertEquals("GetNamedSecurityInfo(" + filePath + ")", 0, + Advapi32.INSTANCE.GetNamedSecurityInfo( + filePath, + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + ppsidOwner, + ppsidGroup, + ppDacl, + ppSacl, + ppSecurityDescriptor)); + // Send the DACL as a SACL assertEquals("SetNamedSecurityInfo(" + filePath + ")", 0, Advapi32.INSTANCE.SetNamedSecurityInfo( @@ -1206,11 +1222,11 @@ public void testSetNamedSecurityInfoForFileWithSACL() throws Exception { ppDacl.getValue(), ppDacl.getValue())); } finally { - // Clean up resources - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); + file.delete(); } } finally { - file.delete(); + assertEquals("Failed to release security descriptor of " + file, + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue())); } if (impersontating) { @@ -1227,51 +1243,67 @@ public void testSetNamedSecurityInfoForFileWithSACL() throws Exception { } public void testGetSecurityDescriptorLength() throws Exception { - // create a temp file - File file = createTempFile(); int infoType = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; PointerByReference ppSecurityDescriptor = new PointerByReference(); - assertEquals(Advapi32.INSTANCE.GetNamedSecurityInfo( - file.getAbsolutePath(), - AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, - infoType, - null, - null, - null, - null, - ppSecurityDescriptor), 0); - - assertTrue(Advapi32.INSTANCE.GetSecurityDescriptorLength(ppSecurityDescriptor.getValue()) > 0); - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); - file.delete(); + File file = createTempFile(); + try { + try { + assertEquals("GetNamedSecurityInfo(" + file + ")", 0, + Advapi32.INSTANCE.GetNamedSecurityInfo( + file.getAbsolutePath(), + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + null, + null, + null, + null, + ppSecurityDescriptor)); + + assertTrue("GetSecurityDescriptorLength(" + file + ")", + Advapi32.INSTANCE.GetSecurityDescriptorLength(ppSecurityDescriptor.getValue()) > 0); + } finally { + file.delete(); + } + } finally { + assertEquals("Failed to release security descriptor of " + file, + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue())); + } } public void testIsValidSecurityDescriptor() throws Exception { - // create a temp file - File file = createTempFile(); int infoType = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; PointerByReference ppSecurityDescriptor = new PointerByReference(); - assertEquals(Advapi32.INSTANCE.GetNamedSecurityInfo( - file.getAbsolutePath(), - AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, - infoType, - null, - null, - null, - null, - ppSecurityDescriptor), 0); - - assertTrue(Advapi32.INSTANCE.IsValidSecurityDescriptor(ppSecurityDescriptor.getValue())); - Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue()); - file.delete(); + File file = createTempFile(); + try { + try { + assertEquals("GetNamedSecurityInfo(" + file + ")", + Advapi32.INSTANCE.GetNamedSecurityInfo( + file.getAbsolutePath(), + AccCtrl.SE_OBJECT_TYPE.SE_FILE_OBJECT, + infoType, + null, + null, + null, + null, + ppSecurityDescriptor), 0); + + assertTrue("IsValidSecurityDescriptor(" + file + ")", + Advapi32.INSTANCE.IsValidSecurityDescriptor(ppSecurityDescriptor.getValue())); + } finally { + file.delete(); + } + } finally { + assertEquals("Failed to release security descriptor of " + file, + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(ppSecurityDescriptor.getValue())); + } } public void testMapGenericReadMask() { @@ -1462,7 +1494,7 @@ public void testReadEncryptedFileRaw() throws Exception { // create an encrypted file File file = createTempFile(); String lpFileName = file.getAbsolutePath(); - assertTrue(Advapi32.INSTANCE.EncryptFile(lpFileName)); + assertTrue("EncryptFile(" + lpFileName + ")", Advapi32.INSTANCE.EncryptFile(lpFileName)); // open file for export ULONG ulFlags = new ULONG(0); diff --git a/contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java b/contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java index ad440d910e..ff8bd1bd3c 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java @@ -1,14 +1,14 @@ /* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna.platform.win32; @@ -26,43 +26,72 @@ public class Crypt32Test extends TestCase { public static void main(String[] args) { junit.textui.TestRunner.run(Crypt32Test.class); } - + public void testCryptProtectUnprotectData() { DATA_BLOB pDataIn = new DATA_BLOB("hello world"); DATA_BLOB pDataEncrypted = new DATA_BLOB(); - assertTrue(Crypt32.INSTANCE.CryptProtectData(pDataIn, "description", - null, null, null, 0, pDataEncrypted)); - PointerByReference pDescription = new PointerByReference(); - DATA_BLOB pDataDecrypted = new DATA_BLOB(); - assertTrue(Crypt32.INSTANCE.CryptUnprotectData(pDataEncrypted, pDescription, - null, null, null, 0, pDataDecrypted)); - assertEquals("description", pDescription.getValue().getWideString(0)); - assertEquals("hello world", pDataDecrypted.pbData.getString(0)); - Kernel32.INSTANCE.LocalFree(pDataEncrypted.pbData); - Kernel32.INSTANCE.LocalFree(pDataDecrypted.pbData); - Kernel32.INSTANCE.LocalFree(pDescription.getValue()); + try { + assertTrue("CryptProtectData(Initial)", + Crypt32.INSTANCE.CryptProtectData(pDataIn, "description", + null, null, null, 0, pDataEncrypted)); + PointerByReference pDescription = new PointerByReference(); + try { + DATA_BLOB pDataDecrypted = new DATA_BLOB(); + try { + assertTrue("CryptProtectData(Crypt)", + Crypt32.INSTANCE.CryptUnprotectData(pDataEncrypted, pDescription, + null, null, null, 0, pDataDecrypted)); + assertEquals("description", pDescription.getValue().getWideString(0)); + assertEquals("hello world", pDataDecrypted.pbData.getString(0)); + } finally { + assertEquals("Failed to free decrypted data", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(pDataDecrypted.pbData)); + } + } finally { + assertEquals("Failed to free description", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(pDescription.getValue())); + } + } finally { + assertEquals("Failed to free encrypted data", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(pDataEncrypted.pbData)); + } } - + public void testCryptProtectUnprotectDataWithEntropy() { DATA_BLOB pDataIn = new DATA_BLOB("hello world"); + DATA_BLOB pEntropy = new DATA_BLOB("entropy"); DATA_BLOB pDataEncrypted = new DATA_BLOB(); - DATA_BLOB pEntropy = new DATA_BLOB("entropy"); - assertTrue(Crypt32.INSTANCE.CryptProtectData(pDataIn, "description", - pEntropy, null, null, 0, pDataEncrypted)); - PointerByReference pDescription = new PointerByReference(); - DATA_BLOB pDataDecrypted = new DATA_BLOB(); - // can't decrypt without entropy - assertFalse(Crypt32.INSTANCE.CryptUnprotectData(pDataEncrypted, pDescription, - null, null, null, 0, pDataDecrypted)); - // decrypt with entropy - assertTrue(Crypt32.INSTANCE.CryptUnprotectData(pDataEncrypted, pDescription, - pEntropy, null, null, 0, pDataDecrypted)); - assertEquals("description", pDescription.getValue().getWideString(0)); - assertEquals("hello world", pDataDecrypted.pbData.getString(0)); - Kernel32.INSTANCE.LocalFree(pDataEncrypted.pbData); - Kernel32.INSTANCE.LocalFree(pDataDecrypted.pbData); - Kernel32.INSTANCE.LocalFree(pDescription.getValue()); - } + try { + assertTrue("CryptProtectData(Initial)", + Crypt32.INSTANCE.CryptProtectData(pDataIn, "description", + pEntropy, null, null, 0, pDataEncrypted)); + PointerByReference pDescription = new PointerByReference(); + try { + DATA_BLOB pDataDecrypted = new DATA_BLOB(); + try { + // can't decrypt without entropy + assertFalse("CryptUnprotectData(NoEntropy)", + Crypt32.INSTANCE.CryptUnprotectData(pDataEncrypted, pDescription, + null, null, null, 0, pDataDecrypted)); + // decrypt with entropy + assertTrue("CryptUnprotectData(WithEntropy)", + Crypt32.INSTANCE.CryptUnprotectData(pDataEncrypted, pDescription, + pEntropy, null, null, 0, pDataDecrypted)); + assertEquals("description", pDescription.getValue().getWideString(0)); + assertEquals("hello world", pDataDecrypted.pbData.getString(0)); + } finally { + assertEquals("Failed to free descrypted data", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(pDataDecrypted.pbData)); + } + } finally { + assertEquals("Failed to free description", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(pDescription.getValue())); + } + } finally { + assertEquals("Failed to free encrypted data", + WinError.ERROR_SUCCESS, Kernel32Util.freeLocalMemory(pDataEncrypted.pbData)); + } + } public void testCertAddEncodedCertificateToSystemStore() { // try to install a non-existent certificate diff --git a/contrib/platform/test/com/sun/jna/platform/win32/VersionTest.java b/contrib/platform/test/com/sun/jna/platform/win32/VersionTest.java index 7c36685240..524dd9f8d4 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/VersionTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/VersionTest.java @@ -15,6 +15,7 @@ import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; + import junit.framework.TestCase; public class VersionTest extends TestCase { @@ -25,33 +26,36 @@ public static void main(String[] args) { public void testGetFileVersion() { String systemRoot = System.getenv("SystemRoot"); - File file = new File(systemRoot + "\\regedit.exe"); + assertNotNull("Missing system root environment variable", systemRoot); + File file = new File(systemRoot + File.separator + "regedit.exe"); if (!file.exists()) { fail("Can't obtain file version, file " + file + " is missing"); } - int size = Version.INSTANCE.GetFileVersionInfoSize(file.getAbsolutePath(), null); - assertTrue(size > 0); + String filePath = file.getAbsolutePath(); + int size = Version.INSTANCE.GetFileVersionInfoSize(filePath, null); + assertTrue("GetFileVersionInfoSize(" + filePath + ")", size > 0); Pointer buffer = Kernel32.INSTANCE.LocalAlloc(WinBase.LMEM_ZEROINIT, size); - assertTrue(!buffer.equals(Pointer.NULL)); + assertTrue("LocalAlloc(" + size + ")", !buffer.equals(Pointer.NULL)); - try - { - assertTrue(Version.INSTANCE.GetFileVersionInfo(file.getAbsolutePath(), 0, size, buffer)); + try { + assertTrue("GetFileVersionInfo(" + filePath + ")", + Version.INSTANCE.GetFileVersionInfo(filePath, 0, size, buffer)); IntByReference outputSize = new IntByReference(); PointerByReference pointer = new PointerByReference(); - assertTrue(Version.INSTANCE.VerQueryValue(buffer, "\\", pointer, outputSize)); + assertTrue("VerQueryValue", + Version.INSTANCE.VerQueryValue(buffer, "\\", pointer, outputSize)); - VerRsrc.VS_FIXEDFILEINFO fixedFileInfo = new VerRsrc.VS_FIXEDFILEINFO(pointer.getValue()); - assertTrue(fixedFileInfo.dwFileVersionLS.longValue() > 0); - assertTrue(fixedFileInfo.dwFileVersionMS.longValue() > 0); - } - finally - { - Kernel32.INSTANCE.GlobalFree(buffer); + VerRsrc.VS_FIXEDFILEINFO fixedFileInfo = + new VerRsrc.VS_FIXEDFILEINFO(pointer.getValue()); + assertTrue("dwFileVersionLS", fixedFileInfo.dwFileVersionLS.longValue() > 0); + assertTrue("dwFileVersionMS", fixedFileInfo.dwFileVersionMS.longValue() > 0); + } finally { + assertEquals("Failed to free buffer", + WinError.ERROR_SUCCESS, Kernel32Util.freeGlobalMemory(buffer)); } } }