KernelLibrary

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

KernelLibrary

mario bancos
Problems with kernel32 QueryDosDevice function implementation.

My function method looks like:
 
queryDosDevice: lpDeviceName lpTargetPath: lpTargetPath ucchMax:
ucchMax

        "DWORD QueryDosDevice(
                LPCTSTR  lpDeviceName, // address of MS-DOS device name string
                LPTSTR  lpTargetPath, // address of buffer for storing query results
                DWORD  ucchMax // maximum storage capacity of buffer  
         );"
       
        <stdcall: dword QueryDosDeviceW lpstr lpstr dword>
        ^self invalidCall

So I called like

openDevice: aString

        | linkName nameSize |
       
        linkName := String new: 255.
        nameSize := DWORD fromInteger: linkName size.
        [KernelLibrary default queryDosDevice: aString lpTargetPath: linkName
ucchMax: nameSize asParameter] on: Error do: [^nil].
        ^linkName leftString: nameSize asInteger


So when I passed nil for aString (WIN32 NULL value answer all the
available DOS devices) I get next wallback some seconds after the
execution, I think I'm writting some dolphin process memory location:

Invalid access to memory location. Reading 0x61003C, IP 0x1AC3BE2
(C:\Dolphin Smalltalk 4.0\DolphinVM004.dll)'
ProcessorScheduler>>gpFault:
[] in ProcessorScheduler>>vmi:list:no:with:
BlockClosure>>ifCurtailed:
ProcessorScheduler>>vmi:list:no:with:
SmallInteger(Object)>>primitiveFailed
SmallInteger(MemoryManager)>>primCollectGarbage:
MemoryManager>>collectGarbage
MemoryManager>>aboutToIdle
InputState>>idleWinV5
InputState>>idleLoop
[] in InputState>>forkIdler
ExceptionHandler(ExceptionHandlerAbstract)>>markAndTry
[] in ExceptionHandler(ExceptionHandlerAbstract)>>try:
BlockClosure>>ifCurtailed:
BlockClosure>>ensure:
ExceptionHandler(ExceptionHandlerAbstract)>>try:
BlockClosure>>on:do:
[] in InputState>>forkIdler
BlockClosure>>ifCurtailed:
[] in InputState>>forkIdler
ExceptionHandler(ExceptionHandlerAbstract)>>markAndTry
[] in ExceptionHandler(ExceptionHandlerAbstract)>>try:
BlockClosure>>ifCurtailed:
BlockClosure>>ensure:
ExceptionHandler(ExceptionHandlerAbstract)>>try:
BlockClosure>>on:do:
[] in BlockClosure>>newProcess

Thanks


Reply | Threaded
Open this post in threaded view
|

Re: KernelLibrary

Ian Bartholomew-8
Mario,

Main problem...

You defined the OS function as "QueryDosDeviceW" so it is expecting a wide
(Unicode) string to be passed as the parameter.  Each character in a wide
string needs two bytes so it is expecting linkName to be a buffer able to
contain 255 unicode characters i.e. 510 bytes.  You are actually giving it a
normal string so the buffer is only 255 bytes long and an overflow occurs if
there are more than 128 characters in your device names.

To solve this bit you can either change the function to QueryDosDeviceA
(i.e. expecting a normal ASCII String) or use the existing QueryDosDeviceW
and change the type of String to a UnicodeString - as in

linkName := UnicodeString new: 10000.

The second thing is that the size parameter is  input only (so the DWORD
isn't needed). The function answers the number of bytes read so you need to
use that for your #leftString.  Personally I would answer a collection of
the device names the easy way (using Unicode) ....

linkName := UnicodeString new: 10000.
KernelLibrary default
    queryDosDevice: nil
    lpTargetPath: linkName
    ucchMax: linkName size.
linkName asString subStrings: Character null

Thirdly. The above uses 10000 as the buffer size as my device names take up
6500 odd bytes. If the buffer is not big enough the function just answers 0
and the buffer is invalid.

Ian


Reply | Threaded
Open this post in threaded view
|

Re: KernelLibrary

Ian Bartholomew-8
In reply to this post by mario bancos
Mario,

Main problem...

You defined the OS function as "QueryDosDeviceW" so it is expecting a wide
(Unicode) string to be passed as the parameter.  Each character in a wide
string needs two bytes so it is expecting linkName to be a buffer able to
contain 255 unicode characters i.e. 510 bytes.  You are actually giving it a
normal string so the buffer is only 255 bytes long and an overflow occurs if
there are more than 128 characters in your device names.

To solve this bit you can either change the function to QueryDosDeviceA
(i.e. expecting a normal ASCII String) or use the existing QueryDosDeviceW
and change the type of String to a UnicodeString - as in

linkName := UnicodeString new: 10000.

The second thing is that the size parameter is  input only (so the DWORD
isn't needed). The function answers the number of bytes read so you need to
use that for your #leftString.  Personally I would answer a collection of
the device names the easy way (using Unicode) ....

linkName := UnicodeString new: 10000.
KernelLibrary default
    queryDosDevice: nil
    lpTargetPath: linkName
    ucchMax: linkName size.
linkName asString subStrings: Character null

Thirdly. The above uses 10000 as the buffer size as my device names take up
6500 odd bytes. If the buffer is not big enough the function just answers 0
and the buffer is invalid.

Ian