LPWSTR size on 64-bit Windows

307 views
Skip to first unread message

Daniel Widdis

unread,
Jun 8, 2018, 1:32:44 PM6/8/18
to Java Native Access
This may be a bug (or two), but before filing a report I wanted to check whether I'm just confused.

I am digging around in the registry using HKEY_PERFORMANCE_DATA.  One of the objects required is PERF_OBJECT_TYPE.  It's defined here:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa373160(v=vs.85).aspx

I implemented this structure in JNA using the types exactly as stated at the link (DWORDs and LPWSTRs).

My code on 32-bit Windows 7 works just fine, and Native.getNativeSize(LPWSTR.class) = 4.
My code on 64-bit Windows 10 fails gloriously, because Native.getNativeSize(LPWSTR.class) = 8 and the actual structure/pointer is 32-bit.

I can get my code to work on all platforms by substituting any arbitrary 32-bit class instead of LPWSTR in the structure, like a DWORD.  This is harmless in this particular case, as the LPWSTR fields are reserved/not used, and are null pointers (the DWORD value is 0).  

As an aside and possibly a separate bug, when trying to use toString() on the structure, I get an Invalid Memory Access Error: the getValue() method checks whether the Java-side pointer is null but does not check whether the pointer's value (0) is null on the Native side.

So, questions for those smarter than me:
- Is LPWSTR always 32-bit?   In which case, why is it 64-bit in JNA?
- Should the LPWSTR (and BSTR) getValue() method do something to check for Native null (0 value) pointers?

Matthias Bläsing

unread,
Jun 8, 2018, 2:04:07 PM6/8/18
to jna-...@googlegroups.com
Am Freitag, den 08.06.2018, 10:32 -0700 schrieb Daniel Widdis:
> This may be a bug (or two), but before filing a report I wanted to
> check whether I'm just confused.
>
> I am digging around in the registry using HKEY_PERFORMANCE_DATA. One
> of the objects required is PERF_OBJECT_TYPE. It's defined here:
> https://msdn.microsoft.com/en-us/library/windows/desktop/aa373160(v=v
> s.85).aspx
>
> I implemented this structure in JNA using the types exactly as stated
> at the link (DWORDs and LPWSTRs).
>
> My code on 32-bit Windows 7 works just fine, and
> Native.getNativeSize(LPWSTR.class) = 4.
> My code on 64-bit Windows 10 fails gloriously, because
> Native.getNativeSize(LPWSTR.class) = 8 and the actual
> structure/pointer is 32-bit.

The definition that you see in MSDN does not look right. I looked in
WinPerf.h from one of the Microsoft Windows SDKs and that explains the
problem:

typedef struct _PERF_OBJECT_TYPE {
// ...
#ifdef _WIN64
DWORD ObjectNameTitle; // Should use this as an offset
#else
LPWSTR ObjectNameTitle; // Initially NULL, for use by
// analysis program to point to
// retrieved title string
#endif
// ...
#ifdef _WIN64
DWORD ObjectHelpTitle; // Should use this as an offset
#else
LPWSTR ObjectHelpTitle; // Initially NULL, for use by
// analysis program to point to
// retrieved title string
#endif
// ...
}

So both members are always 32bit -- why MS decided to code it this way
I don't dare to ask, but it explains your explosion.

> I can get my code to work on all platforms by substituting any
> arbitrary 32-bit class instead of LPWSTR in the structure, like a
> DWORD. This is harmless in this particular case, as the LPWSTR
> fields are reserved/not used, and are null pointers (the DWORD value
> is 0).

Code them as int -- as said above they are always 32 Bit long

> As an aside and possibly a separate bug, when trying to use
> toString() on the structure, I get an Invalid Memory Access Error:
> the getValue() method checks whether the Java-side pointer is null
> but does not check whether the pointer's value (0) is null on the
> Native side.
>
> - Should the LPWSTR (and BSTR) getValue() method do something to
> check for Native null (0 value) pointers?

Yes that sounds like a good idea.

Greetings

Matthias

Daniel Widdis

unread,
Jun 8, 2018, 2:09:22 PM6/8/18
to Java Native Access
Ah, should have thought to check the header file.  I'll hardcode an int.  Thanks!

Also I realized that while the 32-bit value is 0, the toString() issue may be picking up the stray second 32 bits from the next structure member and thus failing the "null" check, so that's probably a non-issue.
Reply all
Reply to author
Forward
0 new messages