AutoHotkey Community

It is currently May 27th, 2012, 7:28 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: DllCall. Help, anyone?
PostPosted: June 20th, 2006, 4:55 am 
Offline

Joined: February 13th, 2006, 10:40 pm
Posts: 389
Location: Utah
I guess that i dont really have a specific question, mostly just a general how do you use dllcall?

I've read the help files, searched msdn, looked at example scripts, and searched the forum. Still pretty mystified.

I get that dlls are Dynamic Link Librarys. Full of fun code to execute :twisted: :lol: . But what is a type and arg????

is type the type (i get double and uint and blah) that you are passing into the function with arg?
or is type the type of output you want from the dll with parameter arg?

And how do i even get a list of whats inside of a dll? is there some kind of dllcall("/?","HELP ME!!!") ????

Please someone enlighten me. I see great potential with dlls and i really want to learn to use them. Sorry to bother you, if anything, please just give me some links or something. Im really confused.

_________________
Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 10:34 am 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
A vast subject.

If you don't have a base knowledge of C (C++) or similar languages (Pascal...), you will have trouble to understand all the concepts...

I will try to explain the bases concisely... I will skip some finer points (like C functions with variable number of arguments), to avoid diluting the concepts...

In C (and lot of languages), variables have a type: they can be numerical (integer or floating number), a single character or a whole string (ended with a zero byte), or a pointer (a kind of reference).

Integer variables can have various sizes: byte or char (8bit), short (16bit), long (32bits), very long (:-) non standard name: 64bit). This is to allow to make a balance between the memory they use (an array of chars is much smaller than an array of longs) and the values they can hold (from 256 values up to several billions).

That's what is called the type of a variable.
In AHK, the same variable can hold integers, floating numbers, strings, binary blob... In C, the base language of the WinAPI, variables are strongly typed, you cannot store a string in variable declared as integer.

DLLs are collections of C functions.
A C function must be called with a fixed number of parameters, each parameter have a precise type.
For example, if I write:
Code:
hDC := DllCall("CreateDC", "Str", "DISPLAY", "UInt", 0, "UInt", 0, "UInt", 0)
colorBGR := DllCall("GetPixel", "UInt", hDC, "Int", x + offsetX, "Int", y + offsetY)
DllCall("DeleteDC", "UInt", hDC)
I call three different functions with various parameters (or arguments, if you prefer). For CreateDC, the first parameter is a string, the next three are integers. That's the expected types in input.
The function returns an integer (the default type, the most common one), that's the output type.

Veovis wrote:
And how do i even get a list of whats inside of a dll?
The only reliable way is to use the provided documentation. MSDN for the WinAPI, the doc. coming with the library for 3rd party DLLs.

I suggest you are looking for an easy Windows programming tutorial to get the basis you need if you want to explore this field further.

Don't hesitate to ask more (precise) questions, I will try to help.

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Last edited by PhiLho on June 20th, 2006, 12:16 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 11:45 am 
Offline

Joined: February 16th, 2006, 8:29 am
Posts: 42
I don't know a whole lot about it myself, but I'll try to get you started.

As an example I'll show you how to call the MessageBox function.
The MSDN documentation gives the syntax/param order:
Code:
int MessageBox(
  HWND hWnd,
  LPCTSTR lpText,
  LPCTSTR lpCaption,
  UINT uType
);


The capital words like UINT are the param types.
Handles (such as HWND) are usually unsigned integers (Uint).
LPCTSTR means (I think) a pointer to a string (I wont go in to pointers), but using the "Str" type usually works anyway for some reason.

I don't really know what else to say... Just look at the syntax above, then at the equivilent DllCall below, and try to make the connections. If theres something you don't understand, just ask :)
Code:
DllCall("MessageBox"                 ; Name of the function
   ,"Uint",0                         ; Handle of owner window, 0 means no owner.
   ,"Str","This is some text."       ; Message box text
   ,"Str","Title!"                   ; Message box title
   ,"Uint",0)                        ; Options


As for finding functions in a DLL, you can use Dependency Walker. It will only give you the function names, which isn't terribly useful alone.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 4:09 pm 
Offline

Joined: February 13th, 2006, 10:40 pm
Posts: 389
Location: Utah
Thankyou for your replies. PhiLho that helped alot. So (obvisouly) DllCall is a function, just everyother parameter is just declaring what the next parameter is.

Thanks Areilius that comparison helped alot too. I will look into the links and programs you provided.

One more (probably stupid question) is this:

Laszlo had some code that retreives the memory usage via a Kernal32.dll\GlobalMemoryStatus call.

Code:
DllCall("kernel32.dll\GlobalMemoryStatus", "uint",&memorystatus)
mem:=*(&memorystatus+4) ; LS byte is enough, mem = 0..100


from what i understand, hes just calling the function GlobalMemoryStatus, with the parameter "&memorystatus" that is declared as an unsigned int. (wiat, should &memorystatus be in qoutes?) And i looked up globalmemorystatus in msdn here
and found things such as availphys and totalpagefile and stuff so i tried passing those into my dll call like so
Code:
DllCall("kernel32.dll\GlobalMemoryStatus"
       ,"uint",&memoryusage
       ,"uint",&availphys
       ,"unit",&totalpagefile)

msgbox % &memoryusage
msgbox % &availphys
msgbox % &totalpagefile


and all three messageboxes say
Quote:
4673068


I have 392 ish megs of RAM but what is 4.6 million have to do with anything? And why do all three of the args that i passed return the same? or am i doing something wrong?

_________________
Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 4:16 pm 
Offline

Joined: February 13th, 2006, 10:40 pm
Posts: 389
Location: Utah
okay basically what im trying to do is for my SysInfo script i want to be able to retreive someones total RAM and how much they are using so i can display something like "315/392 mg" or maybe a percent would be better anyways, but i figured i have to learn dlls eventually why not right now? So what do i have to pass into the function to get the "availphys" and "totalphys" (i think) values?

_________________
Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 4:25 pm 
@ Veovis
I think that issue has been solved already as I've requested something similar in the past. I might be wrong but I think shimanov (btw. is he still with us?) has provided a working code snippet.

Search term: memory, capacity (?)


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 4:30 pm 
[Here] we go! Laszlo, shimanov & friends - a bunch o geniuses supported me on that :wink:


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 4:38 pm 
Offline

Joined: February 13th, 2006, 10:40 pm
Posts: 389
Location: Utah
Yep i found it at about the same time you did.
for processor
for memory

that is excactly what i wanted!

_________________
Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 20th, 2006, 4:46 pm 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
Awh, you are out of luck, you took a "magical" example that works because Laszlo knows how bytes are physically ordered in memory, so he uses a bad trick to lazily avoid to manage such structure.
I won't even try to explain it for you, it is a bit of advanced stuff (no offence intended! :-)), plus I don't find it is such a good idea because Windows will write stuff in the memory after the variable storage (unless he did a VarSetCapacity that you omitted. I won't search the original post...).

Anyway, if that's the precise DllCall that you need to be working, I can take a look.
Code:
/*
typedef struct _MEMORYSTATUS {
  DWORD dwLength;
  DWORD dwMemoryLoad;
  SIZE_T dwTotalPhys;
  SIZE_T dwAvailPhys;
  SIZE_T dwTotalPageFile;
  SIZE_T dwAvailPageFile;
  SIZE_T dwTotalVirtual;
  SIZE_T dwAvailVirtual;
} MEMORYSTATUS,
 *LPMEMORYSTATUS;

dwLength
    The size of the MEMORYSTATUS data structure, in bytes. You do not need to set this member before calling the GlobalMemoryStatus function; the function sets it.
dwMemoryLoad
    A number between 0 and 100 that specifies the approximate percentage of physical memory that is in use (0 indicates no memory use and 100 indicates full memory use).
        Windows NT:  Percentage of approximately the last 1000 pages of physical memory that is in use.
dwTotalPhys
    The total size of physical memory, in bytes.
dwAvailPhys
    The size of physical memory available, in bytes.
dwTotalPageFile
    The size of the committed memory limit, in bytes.
dwAvailPageFile
    The size of available memory to commit, in bytes.
dwTotalVirtual
    The total size of the user mode portion of the virtual address space of the calling process, in bytes.
dwAvailVirtual
    The size of unreserved and uncommitted memory in the user mode portion of the virtual address space of the calling process, in bytes.

All these types are 32bit long, so the structure is 8*4=32 bytes long.
*/

VarSetCapacity(memoryStatusBuffer, 32, 0)


/*
void GlobalMemoryStatus(
  LPMEMORYSTATUS lpBuffer
);
We have a pointer to a structure (or buffer). It is an integer, we give it the address of our variable.
In a DllCall, past the first parameter, we alternate types and expressions, so quotes around the third param!
*/

DllCall("GlobalMemoryStatus", "UInt", &memoryStatusBuffer)


/*
Now, we need to retreive the values in the structure.
I like to use the simple following function, but you can use the ExtractInteger described in the DllCall manual page.
*/

GetNextUInt(ByRef @struct, _bReset=false)
{
   local addr
   static $offset

   If (_bReset)
   {
      $offset := 0
   }
   addr := &@struct + $offset
   $offset += 4

   Return *addr + (*(addr + 1) << 8) +  (*(addr + 2) << 16) + (*(addr + 3) << 24)
}

skip := GetNextUInt(memoryStatusBuffer)
memoryLoad := GetNextUInt(memoryStatusBuffer)
totalPhys := GetNextUInt(memoryStatusBuffer)
AvailPhys := GetNextUInt(memoryStatusBuffer)
; etc.
MsgBox,
(
Memory load: %memoryLoad%`%
Total size of physical memory: %totalPhys% bytes
Size of physical memory available: %AvailPhys% bytes
)

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 21st, 2006, 3:14 am 
Offline

Joined: February 13th, 2006, 10:40 pm
Posts: 389
Location: Utah
PhiLho wrote:
I won't even try to explain it for you, it is a bit of advanced stuff


No please try.

Tell me if im right but i think its something like

(oh wow that code is pretty foreign... but ill try anyways)

so theres like a string (binary for example)

10001110100111000101100 (which evals to 4.6 million in normal decimal)

so are like the first 8 bits one value and the next 8 something else?

_________________
Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 21st, 2006, 9:08 am 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
OK, you asked for it, but I have to switch from "intuitive" mode to "analytic" mode...
I don't know where you had this code, but I found something similar, and indeed, there is NO memory overwriting as memoryStatus is largely oversized:
Laszlo's code wrote:
VarSetCapacity( memorystatus, 100 )
; [...]
DllCall("kernel32.dll\GlobalMemoryStatus", "uint",&memorystatus)
mem:=*(&memorystatus+4) ; LS byte is enough, mem = 0..100

So the DllCall fills this buffer as expected, and as shown in my previous message, the first two fields are 32bit long.
&memoryStatus gives the address in memory of the buffer. So it is a kind of pointer. &memorystatus+4 skips the first field (4 bytes) so points to the second field. *(&memorystatus+4) retrieves the byte pointed to. Since we are on a little-endian processor, the least signifying byte (LSB) is stored at this address. Since the value is always below 256, fetching just this byte is enough.
That's the trick, and of course it won't work for other values, hence the necessity for a function to fetch the bytes and stitch them together.

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 21st, 2006, 4:53 pm 
Offline

Joined: February 13th, 2006, 10:40 pm
Posts: 389
Location: Utah
ahhhhh that makes much more sense. the statement "LS byte is enough, mem = 0..100" finally makes sense since a byte can be 255, we never need more than a byte.

at first i was confused by all the & signs and mem:=*(&memorystatus+4). At first I thought it had something to do with C or DLLs but i got smart and and looked up expressions in the help files and figured out what the 4.6 million was that i was getting earlier. Its an address. everything makes more sense now. Thank You!

_________________
Image
"Power can be given overnight, but responsibility must be taught. Long years go into its making."


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 21st, 2006, 6:12 pm 
Offline

Joined: June 4th, 2005, 1:30 am
Posts: 113
Location: Stuttgart, Germany
WinHex helped me get started with DllCalls and I am still using it to see what actually is happening in the process memory.
It allows you to open the memory of your running ahk script (Alt-F9) and see what data is present at a certain offset (you can get that offset by evaluating &variable).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 25th, 2006, 12:57 pm 
I have a very "annoying" question about DLLCALLS... I posted this question on MSDN forum too (3 Months) ago, but no one replied :x

In most of the cases, MSDN states the FLAG (or similar) which are in Text format. But If I use them with the type "str" and the literal text, they wont work. For Example, in AHK's help file under Gui, ListvView Example:

Code:
if not DllCall("Shell32\SHGetFileInfoA", "str", FileName, "uint", 0, "str", sfi, "uint", sfi_size, "uint", 0x101)  ; 0x101 is SHGFI_ICON+SHGFI_SMALLICON.


If I use SHGFI_ICON instead of 0x101 (and change the type to "Str"), it wont work. My question is where can I find the "0x" values of these "Text" values.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: June 25th, 2006, 1:08 pm 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
I answered that (or something similar) in a topic you started...
Look at the links I give for ApiViewer or the API-Guide.
In short, these "strings" are actually kinds of variables, and are replaced by the C compiler by their values (provided by the above softwares).
So you can write, to keep these names (more meaningful than raw values):
SHGFI_ICON = 0x100
DllCall("Shell32\SHGetFileInfoA", "str", FileName, "uint", 0, "str", sfi, "uint", sfi_size, "uint", SHGFI_ICON)

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: HotkeyStick, oldbrother, sjc1000, thor and 59 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group