AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Windows API Call Question: Structures

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
IsNull



Joined: 10 May 2007
Posts: 112
Location: .switzerland

PostPosted: Tue Sep 16, 2008 3:28 pm    Post subject: Windows API Call Question: Structures Reply with quote

Hi folks,

Well, I havn't problems (at least mostly) to call any dll. But there are some API Calls which require a pointer to a "Structure". And I don't know how to create this information structures.

For example: "AddPrinter" requieres an information buffer

Code:
HANDLE AddPrinter(
  LPTSTR *pName,     // server name
  DWORD Level,      // printer information level
  LPBYTE pPrinter   // printer information buffer
);


Well, this BUffer ist described here Arrow http://msdn.microsoft.com/en-us/library/ms536023(VS.85).aspx


But how can I create this Typedef struct?

This "Information-Buffer" exists in many other cases (required in many api call ), so I have to understand that part well.

Hope someone can explain. Very Happy

greetings
IsNull

[ Moderator!: MSDN link fixed ]
_________________
http://securityvision.ch
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Tue Sep 16, 2008 8:01 pm    Post subject: Re: Windows API Call Question Reply with quote

IsNull wrote:
Hope someone can explain. Very Happy


I have tried my best to explain how the structure stuff works..

Code:

/*

Function DummyDllCall(
  LPBYTE pUserData // user information buffer
);

The USERDATA structure specifies detailed user information

typedef struct USERDATA {
  LPTSTR    pNick;
  LPTSTR    pJoined;
  DWORD     Posts;
  LPTSTR    pLocation;
}   


*/



Nick=IsNull
Joined=10 May 2007
Posts=66
Location=.switzerland

; Items 1,2 & 4 are strings - we have to obtain Pointers to null terminated strings
; Item 3 is already an Integer, so we can feed it into structure as value

pNick     := &Nick     
pJoined   := &Joined
pLocation := &Location

; Lets view the Pointers

; MsgBox,0, Just viewing the Pointers,  % pNick "`n" pJoined "`n" pLocation


; // Encoding structure USERDATA //

; Items 1,2,3,4 - all are now UINTs.
; 1 UINT needs 4 bytes, therefore 4 UINTs need 16 bytes

VarSetCapacity( USERDATA,16,0 ) ; empty structure created - with length of 16 bytes

; Now, put those 4 UINTs into Structure
NumPut( pNick,     USERDATA, 0, "UInt" ) ; Pointer inserted @ offset 0   
NumPut( pJoined,   USERDATA, 4, "UInt" ) ; Pointer inserted @ offset 4
NumPut( Posts,     USERDATA, 8, "UInt" ) ; UINT equals a DWORD - UINT inserted @ offset 8
NumPut( pLocation, USERDATA,12, "UInt" ) ; Pointer inserted @ offset 12

; Therefore -
; Structure USEDATA has been encoded with 4 elements
; 1,2 & 4 are Pointers to null terminated strings
; Item 3 is already a DWORD and so has been fed in directly

; // Lets call the Function DummyDllCall() and pass the structure USERDATA as parameter

DummyDllCall( &USERDATA )


Return                                                 ; // end of auto-execute section //

; The following WORKING FUNCTION will give you a crude idea on how the DLL Funtion would
; retrieve the data from the structure USERDATA
 
DummyDllCall( pUserdata ) {
  pNick     := NumGet( pUserData+0 , 0, "UInt" ) ; Pointer to Null Terminated String     
  pJoined   := NumGet( pUserData+4 , 0, "UInt" ) ; Pointer to Null Terminated String
  Posts     := NumGet( pUserData+8 , 0, "UInt" ) ; is already Integer Data
  pLocation := NumGet( pUserData+12, 0, "UInt" ) ; Pointer to Null Terminated String
 
  VarSetCapacity( Nick    ,20,0 )
  VarSetCapacity( Joined  ,20,0 )
  VarSetCapacity( Location,20,0 )
     
  DllCall( "lstrcpyA", UInt,&Nick    , UInt,pNick )
  DllCall( "lstrcpyA", UInt,&Joined  , UInt,pJoined )
  DllCall( "lstrcpyA", UInt,&Location, UInt,pLocation )

  ; Repair the variables - i.e., Set Internal Variable Length right!
  VarSetCapacity( Nick, -1 ), VarSetCapacity( Joined,-1 ), VarSetCapacity( Location, -1 )
 
  MsgBox,0,DummyDllCall(), % Nick "`n" Joined "`n" Posts "`n" Location
}


Smile
_________________
Back to top
View user's profile Send private message
IsNull



Joined: 10 May 2007
Posts: 112
Location: .switzerland

PostPosted: Wed Sep 17, 2008 6:10 am    Post subject: Reply with quote

wow, many many thanks SKAN, I think I understand most of that! Very Happy
_________________
http://securityvision.ch
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Wed Sep 17, 2008 6:16 am    Post subject: Reply with quote

IsNull wrote:
I think I understand most of that! Very Happy


Do not hesitate to ask questions/clarification.. and BTW,
Are you comfortable with NumGet() and NumPut()?
Do you need explanation on how it works?
Back to top
View user's profile Send private message
IsNull



Joined: 10 May 2007
Posts: 112
Location: .switzerland

PostPosted: Wed Sep 17, 2008 9:05 am    Post subject: Reply with quote

Hey SKAN,

Well I think I understand NUMPUT and NUMGET. Also Pointers and Adresses is clear for me.

Quote:
Do not hesitate to ask questions/clarification..

I will not do so. Very Happy

At the moment I'm writing a Tutorial about this "STRUCT" thing. It is in german, but I can translate it to english. For me, it's the best way to learn such things -writing a Tutorial for others shows my self how certain I am.

Well, there is still one little question:

Strings are normally submittet as "Pointer" (adress) -> uint (4 bytes)
Numbers are normally submittet directly, as DWORD, -> uint (4 bytes)

But, if a Number is too large for the uint, what happens?

Well, maby can use int64, (8 bytes), but you see, the core of the problem persists. What happens when the int64 is too small?
In this case, will the number be submittet as Pointer too?
_________________
http://securityvision.ch
Back to top
View user's profile Send private message
Z_Gecko
Guest





PostPosted: Wed Sep 17, 2008 10:19 am    Post subject: Reply with quote

i might be totally wrong, but
i donīt think integers can be bigger than 64-bit (8-byte).
Quote:
For integers, 64-bit signed values are supported, which range from -9223372036854775808 (-0x8000000000000000) to 9223372036854775807 (0x7FFFFFFFFFFFFFFF).
as i understand this, anything longer will be treated as a string by ahk(and probably by any other 32/64-bit programming language).
So you can probably not submit any number large than 64-bit without using a pointer.
Back to top
IsNull



Joined: 10 May 2007
Posts: 112
Location: .switzerland

PostPosted: Wed Sep 17, 2008 11:49 am    Post subject: Reply with quote

Quote:
So you can probably not submit any number large than 64-bit without using a pointer.

Then, my guess was right. If something ist bigger, I have to handle it with a pointer,too.
_________________
http://securityvision.ch
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Wed Sep 17, 2008 7:04 pm    Post subject: Reply with quote

IsNull wrote:
Strings are normally submittet as "Pointer" (adress) -> uint (4 bytes)
Numbers are normally submittet directly, as DWORD, -> uint (4 bytes)
But, if a Number is too large for the uint, what happens?


The most significant bit/byte is ignored .. and this is documented under NumPut()
Strictly speaking, I have never encountered a neccessity for Large Integer with API till date, expect for File size, for which an UINT offers only 4GB as number.

Note: Natively, the maximum number AHK can handle is (2**63)-1
Code:
MsgBox, % (2**63)-1


In case, one needs to handle large integers, there is always: Machine code functions: Bit Wizardry posted by Laszlo

I repeat, even if one uses 8 byte to store an integer, which would occupy 64 bits, AHK would be able to extract unsigned integer from 63 bits only.

Smile
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group