|
22 | 22 | import com.sun.jna.Structure;
|
23 | 23 | import com.sun.jna.platform.win32.WinDef.USHORT;
|
24 | 24 | import com.sun.jna.ptr.ByReference;
|
| 25 | +import java.io.UnsupportedEncodingException; |
| 26 | +import java.util.logging.Level; |
| 27 | +import java.util.logging.Logger; |
25 | 28 |
|
26 | 29 | /**
|
27 | 30 | * Constant defined in WTypes.h
|
@@ -61,35 +64,80 @@ public interface WTypes {
|
61 | 64 | public static int CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER
|
62 | 65 | | CLSCTX_LOCAL_SERVER;
|
63 | 66 |
|
| 67 | + /** |
| 68 | + * BSTR wrapper. |
| 69 | + * |
| 70 | + * <p>From MSDN:</p> |
| 71 | + * |
| 72 | + * <blockquote>A BSTR (Basic string or binary string) is a string data type |
| 73 | + * that is used by COM, Automation, and Interop functions. Use the BSTR data |
| 74 | + * type in all interfaces that will be accessed from script.</blockquote> |
| 75 | + * |
| 76 | + * <p>The memory structure:</p> |
| 77 | + * |
| 78 | + * <dl> |
| 79 | + * <dt>Length prefix</dt> |
| 80 | + * <dd>Length of the data array holding the string data and does not include |
| 81 | + * the final two NULL characters.</dd> |
| 82 | + * <dt>Data string</dt> |
| 83 | + * <dd>UTF-16LE encoded bytes for the string.</dd> |
| 84 | + * <dt>Terminator</dt> |
| 85 | + * <dd>Two null characters</dd> |
| 86 | + * </dl> |
| 87 | + * |
| 88 | + * <p>The "value" of the BSTR is the pointer to the start of the Data String, |
| 89 | + * the length prefix is the four bytes before that.</p> |
| 90 | + * |
| 91 | + * <p>The MSDN states, that a BSTR derived from a Nullpointer is treated |
| 92 | + * as a string containing zero characters.</p> |
| 93 | + */ |
64 | 94 | public static class BSTR extends PointerType {
|
65 | 95 | public static class ByReference extends BSTR implements
|
66 | 96 | Structure.ByReference {
|
67 | 97 | }
|
68 | 98 |
|
69 | 99 | public BSTR() {
|
70 |
| - super(new Memory(Pointer.SIZE)); |
| 100 | + super(Pointer.NULL); |
71 | 101 | }
|
72 | 102 |
|
73 | 103 | public BSTR(Pointer pointer) {
|
74 | 104 | super(pointer);
|
75 | 105 | }
|
76 | 106 |
|
77 | 107 | public BSTR(String value) {
|
78 |
| - super(new Memory((value.length() + 1L) * Native.WCHAR_SIZE)); |
| 108 | + super(); |
79 | 109 | this.setValue(value);
|
80 | 110 | }
|
81 | 111 |
|
82 | 112 | public void setValue(String value) {
|
83 |
| - this.getPointer().setWideString(0, value); |
| 113 | + if(value == null) { |
| 114 | + value = ""; |
| 115 | + } |
| 116 | + try { |
| 117 | + byte[] encodedValue = value.getBytes("UTF-16LE"); |
| 118 | + // 4 bytes for the length prefix, length for the encoded data, |
| 119 | + // 2 bytes for the two NULL terminators |
| 120 | + Memory mem = new Memory(4 + encodedValue.length + 2); |
| 121 | + mem.clear(); |
| 122 | + mem.setInt(0, encodedValue.length); |
| 123 | + mem.write(4, encodedValue, 0, encodedValue.length); |
| 124 | + this.setPointer(mem.share(4)); |
| 125 | + } catch (UnsupportedEncodingException ex) { |
| 126 | + throw new RuntimeException("UTF-16LE charset is not supported", ex); |
| 127 | + } |
84 | 128 | }
|
85 | 129 |
|
86 | 130 | public String getValue() {
|
87 |
| - Pointer pointer = this.getPointer(); |
88 |
| - String str = null; |
89 |
| - if (pointer != null) |
90 |
| - str = pointer.getWideString(0); |
91 |
| - |
92 |
| - return str; |
| 131 | + try { |
| 132 | + Pointer pointer = this.getPointer(); |
| 133 | + if(pointer == null) { |
| 134 | + return ""; |
| 135 | + } |
| 136 | + int stringLength = pointer.getInt(-4); |
| 137 | + return new String(pointer.getByteArray(0, stringLength), "UTF-16LE"); |
| 138 | + } catch (UnsupportedEncodingException ex) { |
| 139 | + throw new RuntimeException("UTF-16LE charset is not supported", ex); |
| 140 | + } |
93 | 141 | }
|
94 | 142 |
|
95 | 143 | @Override
|
|
0 commit comments