[FFI newbie] Windows process info from Squeak

"Boris Gärtner" Boris.Gaertner at gmx.net
Thu Feb 2 15:11:52 UTC 2006


"Valdas Bucinskas" <valdas.bucinskas at ipsistemos.lt> wrote:


> Hello,
> 
> Wow, your examples are really interesting and helps incredibly much.
> I modified your your last example slightly, incorporating RAMs used by the
> process. And then tried to find the .exe that calls the process. It
> appears,
> the method GetModuleBaseName from psapi.dll should be used, which is
> described in
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/bas
> e/getmodulebasename.asp.
> It gives the method declaration is
> DWORD GetModuleBaseName(
>   HANDLE hProcess,
>   HMODULE hModule,
>   LPTSTR lpBaseName,
>   DWORD nSize
> );
> What I miss now is the knowledge, how do I convert types from c++ like
> into
> Sueak ones. I guess hProcess corresponds to Win32Handle, lpBaseName
> corresponds  to char*, and nSize corresponds to long. GetModuleBaseName
> returns long.
> 1. But what does hModule correspond to?
> My guess
> 	<apicall: long 'GetModuleBaseName' (Win32Handle Win32Handle char* long)
> module: 'psapi.dll'>

almost correct, but the name of the function is 
    'GetModuleBaseNameA'
where the last character stands for ASCII.
A DLL contents viewer helps a lot to find out such details,
I use this one: http://www.nirsoft.net/utils/dll_export_viewer.html


> throughs Error 13, which is 'The data is invalid.'
> 2. Should a class similar to Win32Handle be created in order to hModule
> typecasting work?
No, that is not needed,  hModule is a handle, Win32Handle is the right
choice.


No please try this:

1. add this api method to Win32Window:

apiGetModuleBaseName: hProcess module: hModule into: lpString bufferSize:
size 
   <apicall: long 'GetModuleBaseNameA' (Win32Handle Win32Handle char* long)
module: 'psapi.dll'>
   ^self externalCallFailed

2. Ensure that you open the process handle with access rights 16r410 (this
is
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, the access
right alone PROCESS_QUERY_INFORMATION does not allow you tho read the name)
(The processes System, Idle and some others will not tell you their
names anyway)

3. Do something like this:

 handleArray do: [:idx |
     processHandle := interface getProcessHandleWithAccessRights: 16r410
                             inherit: true processId: idx.
     processHandle notNil
       ifTrue: 
         [  | buffer processName cnt |
          buffer := ByteArray new: 80.
          interface apiGetModuleBaseName: processHandle 
                    module: nil into: buffer bufferSize: 80. 
          processName := WriteStream on: (String new: 80).
          cnt := 1.
          [i <= 80 and: [(buffer at: cnt) ~= 0]]
             whileTrue:
               [processName nextPut: (Character value: (buffer at: cnt)).
		            cnt := cnt + 1].
          processName := processName contents.
          oc add: 
           (Array with: idx
                     with: (interface apiGetGuiResources: processHandle
                                      type: 0)
                     with: (interface apiGetGuiResources: processHandle
                                      type: 1)
                     with: processName).
              
            interface closeHandle: processHandle.
         ]	  
 ].

When you have to provide buffers that are filled with some information,
it is always a good choice to use ByteArrays of suitable size. You
can always convert a ByteArray into a number or into a string.


Hope this helps,
Boris



More information about the Squeak-dev mailing list