I've been trying to use the VB code at this Microsoft article support.microsoft.com/kb/185733. I get the protection violation error and I know it's because I'm not calling the RtlMoveMemory function correctly. But I can't figure out how to do it. In the VB code, it uses type long for the parameters but the MSDN article says to use pointers.

Here is my code:

Code:

struct MINMAXINFO,_
ptReserved.x as long,_
ptReserved.y as long,_
ptMaxSize.x as long,_
ptMaxSize.y as long,_
ptMaxPosition.x as long,_
ptMaxPosition.y as long,_
ptMinTrackSize.x as long,_
ptMinTrackSize.y as long,_
ptMaxTrackSize.x as long,_
ptMaxTrackSize.y as long

VB is bad since they use LONG for anything and convert it to the correct data-type behind the scene.
It is always best to translate from an ANSI C code source to LB, since they do have more in common in regard to data-types.

In addition you are missing an argument of the function, which must be present.

Thanks Stefan for your help with the data types. It works great now. Here is the corrected code:

Code:

struct MINMAXINFO,_
ptReserved.x as long,_
ptReserved.y as long,_
ptMaxSize.x as long,_
ptMaxSize.y as long,_
ptMaxPosition.x as long,_
ptMaxPosition.y as long,_
ptMinTrackSize.x as long,_
ptMinTrackSize.y as long,_
ptMaxTrackSize.x as long,_
ptMaxTrackSize.y as long

VB is bad since they use LONG for anything and convert it to the correct data-type behind the scene.
It is always best to translate from an ANSI C code source to LB, since they do have more in common in regard to data-types.

It makes not the slightest difference whether you specify LONG or ULONG in a STRUCT declaration or a CALLDLL statement, so long as the actual value is valid for both (which means it is in the range 0 to +2147483647). Only if the value is negative (in which case you must use LONG) or greater than +2147483647 (in which case you must use ULONG) does it matter.

So for example in the case of the RtlMoveMemory API you can be absolutely certain that the length parameter is valid for both LONG and ULONG, and it makes no difference which you use.

It makes not the slightest difference whether you specify LONG or ULONG in a STRUCT declaration or a CALLDLL statement, so long as the actual value is valid for both
Richard.

That is not correct for Liberty BASIC. You may not know the "actual value" returned from the HWND statement, for instance. If you pass it as a long into an API call it might be misinterpreted. This has happened to folks and caused errors that are hard to nail down.

Stefan is correct when he cautions folks to use C rather than VB for documentation on API functions._________________- Alyce

That is not correct for Liberty BASIC. You may not know the "actual value" returned from the HWND statement, for instance.

It is always correct; the language makes no difference. There are basically three situations that you can encounter in Liberty BASIC:

1. The value that you are storing in a STRUCT, or passing in a CALLDLL statement, is known (for example it may be a constant that you set in your program). In that case you can easily determine what type to use: if it's negative you must declare it as LONG, if it's greater than +2147483647 you must declare it as a ULONG. Otherwise it makes no difference, you can use LONG or ULONG.

2. The value that you are storing in a STRUCT, or passing in a CALLDLL, was itself returned from a previous API call. In that case what matters is that the type you specified for the value returned from the original API is the same as the type you specify in the STRUCT or CALLDLL. It doesn't matter whether it's LONG or ULONG, but they must agree. So for example both these code snippets are perfectly correct:

Code:

calldll #user32, "GetDesktopWindow", hdesk as LONG
calldll #user32, "GetWindowDC", hdesk as LONG, hdc as LONG

A myth has developed at some stage that you must always use ULONG for handles, but that is not true. In a case such as the code above all that matters is that the type specified when the handle is retrieved is the same as that when it is subsequently used.

3. The value is a handle returned from HWND(). When passing the handle to CALLDLL or storing it in a STRUCT you must use whatever type is returned from HWND(). The trouble is that the LB docs don't tell you what that is! I assume that it's a ULONG, in which case that's the type you should specify in the STRUCT or CALLDLL. But it would be a lot more helpful it that was stated somewhere.

What's important to realise is that the type specified in (say) the Microsoft documentation for an API is never important in LB. When LB calls an API it simply passes numbers, there is no way that Windows can tell or care what type was assigned to that number in LB. I read Stefan's comment as implying the contrary - that somehow it can be important to specify in your LB program the type that MSDN specifies rather than the type the VB docs specify. That is not correct and it can lead to a misunderstanding about how the interface between an application and the Windows API works.

A myth has developed at some stage that you must always use ULONG for handles, but that is not true.

The "myth" developed because Carl stated it to be so. Since he is the author of the language, I trust he knows how types are handled behind the scenes.

Quote:

3. The value is a handle returned from HWND(). When passing the handle to CALLDLL or storing it in a STRUCT you must use whatever type is returned from HWND(). The trouble is that the LB docs don't tell you what that is! I assume that it's a ULONG, in which case that's the type you should specify in the STRUCT or CALLDLL. But it would be a lot more helpful it that was stated somewhere.

As I wrote above, it is type ulong. It should be stated in the docs. Considering the fact that Carl must make a living at a full-time job and must develop LB by himself in whatever spare time he can find, I think he does an excellent job. He did a better job when he could devote 100% of his working hours to LB. That has not been the case for years, though.

I don't disagree that you can pass a number as either ulong or long as long as it fits within the values of the type specified. Liberty BASIC is meant to be beginner-friendly, hobbiest-friendly. Since Carl tells us that handles are always to be of type ulong, it is much easier to pass them as ulong than to put in conditional statements to check if they are within a certain range of numbers so that they can be passed as longs._________________- Alyce

The "myth" developed because Carl stated it to be so. Since he is the author of the language, I trust he knows how types are handled behind the scenes.

I don't know the context in which he stated that, but I expect he was referring to the type returned by HWND(), which may well be a ULONG.

Given that being the case, I have no objection to advising users of LB always to use ULONG for handles, because it's a nice easy-to-remember rule, and as you rightly say LB is intended to be simple for beginners.

However I still think it is important to appreciate that it's only essential to use ULONG when the handle was returned from HWND(). When it is returned from an API function all that matters is that the same type (LONG or ULONG) is used consistently for that handle.

I'm not trying to second-guess how LB is implemented, and certainly not suggesting that Carl is mistaken, but simply stating a fundamental fact which follows from the way all applications interface with the Windows API.

Quote:

Considering the fact that Carl must make a living at a full-time job and must develop LB by himself in whatever spare time he can find, I think he does an excellent job.

No criticism of Carl was intended or implied. I would prefer the docs to be more comprehensive and more accurate, but I can understand Carl wishing to concentrate his time on coding rather than writing documentation. The user community can go a long way to address the deficiencies in the docs.

I'm fortunate in having now retired so I don't have to divide my time between paid employment and 'hobby' programming. However for about 25 years I was in exactly the same position as Carl: working full-time for an employer and developing/documenting/marketing BBC BASIC in my spare time. So I know what the pressures are.

The whole thing started out with Windows XP, when more handles were used by the system and they got beyond the positive range of LONG.
This has caused some real trouble, since stable API functions started crashing unexpectedly.

The conclusion was to use ULONG instead of LONG for handles, which resulted in more stable code.

In general a handle can never be a negative number, since it ranges from 0 to 2^32.

One can argue that the binary representation is the same, but we want to develop on the save side.

And if anyone is turning this into a bug of LB and an advantage of any other tool, he should turn his face into the next corner and think about what he has done wrong._________________Stefan

In general a handle can never be a negative number, since it ranges from 0 to 2^32.

A handle is a 32-bit number. As far as Windows and the processor is concerned there is no concept of it being positive or negative.

In the Windows header files HANDLE is defined as void*, i.e. as a pointer to void. It is neither signed nor unsigned, indeed strictly it's not even an integer! That may be why LB supports the undocumented type HANDLE:

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum