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 |
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 |
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 |
Free forum by Nabble | Edit this page |