Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance stability of tests and prepare for inclusion of appveyor #992

Merged
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ dist: trusty
language: java

install:
- '[ "${TRAVIS_OS_NAME}" = "linux" ] && wget http://apache.mirror.iphh.net/ant/binaries/apache-ant-1.9.12-bin.tar.gz && tar xzf apache-ant-1.9.12-bin.tar.gz && sudo mv apache-ant-1.9.12 /usr/local/apache-ant-1.9.12 && sudo rm -f /usr/local/ant && sudo ln -s /usr/local/apache-ant-1.9.12 /usr/local/ant && sudo ln -s /usr/local/apache-ant-1.9.12/bin/ant /usr/local/bin/ant || true'
- '[ "${TRAVIS_OS_NAME}" = "linux" ] && wget http://apache.mirror.iphh.net/ant/binaries/apache-ant-1.9.13-bin.tar.gz && tar xzf apache-ant-1.9.13-bin.tar.gz && sudo mv apache-ant-1.9.13 /usr/local/apache-ant-1.9.13 && sudo rm -f /usr/local/ant && sudo ln -s /usr/local/apache-ant-1.9.13 /usr/local/ant && sudo ln -s /usr/local/apache-ant-1.9.13/bin/ant /usr/local/bin/ant || true'
- '[ "${TRAVIS_OS_NAME}" = "osx" ] && brew update || true'
- '[ "${TRAVIS_OS_NAME}" = "osx" ] && brew uninstall libtool && brew install libtool || true'
- '[ "${TRAVIS_OS_NAME}" = "osx" ] && brew install ant || true'
Expand Down
20 changes: 20 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: 1.0.{build}
image: Visual Studio 2015

install:
- cmd: set PATH=%PATH%;c:\cygwin64;c:\cygwin64\bin
- cmd: choco install -y -f -i ant
- cmd: choco install -y -f -i cygwin
- cmd: C:\cygwin64\cygwinsetup.exe --root C:\cygwin64 --local-package-dir C:\cygwin64\packages --quiet-mode --no-desktop --no-startmenu --packages git,make,automake,automake1.15,libtool,mingw64-x86_64-gcc-g++,mingw64-x86_64-gcc-core,gcc-g++
- cmd: set JAVA_HOME=C:\Program Files\Java\jdk1.8.0
- cmd: set PATH=%JAVA_HOME%\bin;%PATH%
- cmd: set PATH=c:\cygwin64;c:\cygwin64\bin;%PATH%
- cmd: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64'

build_script:
- cmd: ant dist

test_script:
- cmd: net start spooler
- cmd: ant test
- cmd: ant test-platform
8 changes: 6 additions & 2 deletions contrib/platform/src/com/sun/jna/platform/win32/Pdh.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
package com.sun.jna.platform.win32;

import java.util.List;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
Expand Down Expand Up @@ -55,6 +53,12 @@ public interface Pdh extends StdCallLibrary {
/** Maximum full counter log name length. */
int PDH_MAX_DATASOURCE_PATH = 1024;

int PDH_MORE_DATA = 0x800007D2;
int PDH_INVALID_ARGUMENT = 0xC0000BBD;
int PDH_MEMORY_ALLOCATION_FAILURE = 0xC0000BBB;
int PDH_CSTATUS_NO_MACHINE = 0x800007D0;
int PDH_CSTATUS_NO_OBJECT = 0xC0000BB8;

/* TODO
* LPVOID CALLBACK AllocateMemory(_In_ SIZE_T AllocSize,_In_ LPVOID pContext)
* void CALLBACK FreeMemory(LPVOID pBuffer,LPVOID pContext)
Expand Down
203 changes: 116 additions & 87 deletions contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
import java.util.Collections;

/**
* Pdh utility API.
Expand Down Expand Up @@ -61,16 +62,23 @@ public abstract class PdhUtil {
public static String PdhLookupPerfNameByIndex(String szMachineName, int dwNameIndex) {
// Call once to get required buffer size
DWORDByReference pcchNameBufferSize = new DWORDByReference(new DWORD(0));
Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, null, pcchNameBufferSize);

int result = Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, null, pcchNameBufferSize);
if(result != WinError.ERROR_SUCCESS && result != Pdh.PDH_MORE_DATA) {
throw new PdhException(result);
}

// Can't allocate 0 memory
if (pcchNameBufferSize.getValue().intValue() < 1) {
return "";
}
// Allocate buffer and call again
Memory mem = new Memory(pcchNameBufferSize.getValue().intValue() * CHAR_TO_BYTES);
Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, mem, pcchNameBufferSize);
result = Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, mem, pcchNameBufferSize);

if(result != WinError.ERROR_SUCCESS) {
throw new PdhException(result);
}

// Convert buffer to Java String
if (CHAR_TO_BYTES == 1) {
return mem.getString(0);
Expand Down Expand Up @@ -113,9 +121,8 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {

/**
* Utility method to call Pdh's PdhEnumObjectItems that allocates the
* required memory for the mszCounterList parameter based on the type
* mapping used, calls to PdhEnumObjectItems, and returns the received lists
* of strings.
* required memory for the lists parameters based on the type mapping used,
* calls to PdhEnumObjectItems, and returns the received lists of strings.
*
* @param szDataSource
* String that specifies the name of the log file used to
Expand All @@ -137,113 +144,135 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {
* returned.
* @return Returns a List of Strings of the counters for the object.
*/
public static List<String> PdhEnumObjectItemCounters(String szDataSource, String szMachineName, String szObjectName,
public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String szMachineName, String szObjectName,
int dwDetailLevel) {
List<String> counters = new ArrayList<String>();
List<String> instances = new ArrayList<String>();

// Call once to get string lengths
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0));
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0));
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
int result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
pcchInstanceListLength, dwDetailLevel, 0);
if(result != WinError.ERROR_SUCCESS && result != Pdh.PDH_MORE_DATA) {
throw new PdhException(result);
}

// Can't allocate 0 memory if no counters
if (pcchCounterListLength.getValue().intValue() < 1) {
return counters;
Memory mszCounterList = null;
Memory mszInstanceList = null;

if (pcchCounterListLength.getValue().intValue() > 0) {
mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
}

if (pcchInstanceListLength.getValue().intValue() > 0) {
mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
}

result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);

if(result != WinError.ERROR_SUCCESS) {
throw new PdhException(result);
}
// Allocate memory and call again to populate strings
Memory mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
// Don't need the instances
pcchInstanceListLength.getValue().setValue(0);
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, null, pcchInstanceListLength, dwDetailLevel, 0);

// Fetch counters
int offset = 0;
while (offset < mszCounterList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszCounterList.getString(offset);
} else {
s = mszCounterList.getWideString(offset);
if (mszCounterList != null) {
int offset = 0;
while (offset < mszCounterList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszCounterList.getString(offset);
} else {
s = mszCounterList.getWideString(offset);
}
// list ends with double null
if (s.isEmpty()) {
break;
}
counters.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}
// list ends with double null
if (s.isEmpty()) {
break;
}

if(mszInstanceList != null) {
int offset = 0;
while (offset < mszInstanceList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszInstanceList.getString(offset);
} else {
s = mszInstanceList.getWideString(offset);
}
// list ends with double null
if (s.isEmpty()) {
break;
}
instances.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}
counters.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}

return counters;
return new PdhEnumObjectItems(counters, instances);
}


/**
* Utility method to call Pdh's PdhEnumObjectItems that allocates the
* required memory for the mszInstanceList parameters based on the type
* mapping used, calls to PdhEnumObjectItems, and returns the received lists
* of strings.
*
* @param szDataSource
* String that specifies the name of the log file used to
* enumerate the counter and instance names. If NULL, the
* function uses the computer specified in the szMachineName
* parameter to enumerate the names.
* @param szMachineName
* String that specifies the name of the computer that contains
* the counter and instance names that you want to enumerate.
* Include the leading slashes in the computer name, for example,
* \\computername. If the szDataSource parameter is NULL, you can
* set szMachineName to NULL to specify the local computer.
* @param szObjectName
* String that specifies the name of the object whose counter and
* instance names you want to enumerate.
* @param dwDetailLevel
* Detail level of the performance items to return. All items
* that are of the specified detail level or less will be
* returned.
* @return Returns a Lists of Strings of the instances of the object.
* Holder Object for PdhEnumObjectsItems. The embedded lists are modifiable
* lists and can be accessed through the {@link #getCounters()} and
* {@link #getInstances()} accessors.
*/
public static List<String> PdhEnumObjectItemInstances(String szDataSource, String szMachineName,
String szObjectName, int dwDetailLevel) {
List<String> instances = new ArrayList<String>();
public static class PdhEnumObjectItems {
private final List<String> counters;
private final List<String> instances;

// Call once to get string lengths
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0));
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0));
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
pcchInstanceListLength, dwDetailLevel, 0);
public PdhEnumObjectItems(List<String> counters, List<String> instances) {
this.counters = copyAndEmptyListForNullList(counters);
this.instances = copyAndEmptyListForNullList(instances);
}

/**
* @return the embedded counters list, all calls to this function receive
* the same list and thus share modifications
*/
public List<String> getCounters() {
return counters;
}

// Can't allocate 0 memory if no instances
if (pcchInstanceListLength.getValue().intValue() < 1) {
/**
* @return the embedded instances list, all calls to this function receive
* the same list and thus share modifications
*/
public List<String> getInstances() {
return instances;
}
// Allocate memory and call again to populate strings
Memory mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
// Don't need the counters
pcchCounterListLength.getValue().setValue(0);
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength,
mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);

// Fetch instances
int offset = 0;
while (offset < mszInstanceList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszInstanceList.getString(offset);

private List<String> copyAndEmptyListForNullList (List<String> inputList) {
if(inputList == null) {
return new ArrayList<String>();
} else {
s = mszInstanceList.getWideString(offset);
}
// list ends with double null
if (s.isEmpty()) {
break;
return new ArrayList<String>(inputList);
}
instances.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}

return instances;
@Override
public String toString() {
return "PdhEnumObjectItems{" + "counters=" + counters + ", instances=" + instances + '}';
}
}

public static final class PdhException extends RuntimeException {
private final int errorCode;

public PdhException(int errorCode) {
super(String.format("Pdh call failed with error code 0x%08X", errorCode));
this.errorCode = errorCode;
}

public int getErrorCode() {
return errorCode;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,38 @@ public static void killProcessByName(String filename) {
}
Kernel32.INSTANCE.CloseHandle(hSnapShot);
}

/**
* Return true if the supplied uuid can be found in the registry.
*
* @param uuid Format: {&lt;UID&gt;}
*/
public static boolean checkCOMRegistered(String uuid) {
WinReg.HKEYByReference phkKey = null;
try {
phkKey = Advapi32Util.registryGetKey(WinReg.HKEY_CLASSES_ROOT, "Interface\\" + uuid, WinNT.KEY_READ);
if(phkKey != null) {
return true;
}
} catch (Win32Exception ex) {
// Ok - failed ...
} finally {
if(phkKey != null && phkKey.getValue() != null) {
Advapi32Util.registryCloseKey(phkKey.getValue());
}
}
try {
phkKey = Advapi32Util.registryGetKey(WinReg.HKEY_CLASSES_ROOT, "CLSID\\" + uuid, WinNT.KEY_READ);
if(phkKey != null) {
return true;
}
} catch (Win32Exception ex) {
// Ok - failed ...
} finally {
if(phkKey != null && phkKey.getValue() != null) {
Advapi32Util.registryCloseKey(phkKey.getValue());
}
}
return false;
}
}
Loading