Crash in Unicode mode only [SOLVED]

Windows specific forum
LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Crash in Unicode mode only [SOLVED]

Post by LiK137 »

I am tracking crashes in my program and very tired.
While program is very stable in nonUnicode it is crashing during memory operations.

Code: Select all

Procedure.s EnumDevz()
  
; How to enumerate hardware devices by using SetupDi calls
; mskuma 26 June 2006
; adapted from http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q259695
; (Windows only)


TMPDevicez.s=""         

Structure SP_DEVINFO_DATA
  cbSize.l
  ClassGuid.GUID
  DevInst.l;    // DEVINST handle
  Reserved.l;
EndStructure
  
  hDevInfo.l = 0
  DeviceInfoData.SP_DEVINFO_DATA
  i.l = 0
  sepa.s="!!!"
  ;devicesList.s = ""
  
  ; Create a HDEVINFO with all present devices
  
  hDevInfo = SetupDiGetClassDevs_(#Null,0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)
  
  If hDevInfo = #INVALID_HANDLE_VALUE
    ProcedureReturn "0"
  EndIf
  
  ; Enumerate through all devices in Set
  
  DeviceInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)
    
  While SetupDiEnumDeviceInfo_(hDevInfo, i, @DeviceInfoData) 
     DataT.l
     Protected *buffer = #Null
     buffersize.l = 0
     
     While Not SetupDiGetDeviceRegistryProperty_(hDevInfo,@DeviceInfoData,#SPDRP_DEVICEDESC,@DataT,*buffer,buffersize,@buffersize)
     
         If (GetLastError_() = #ERROR_INSUFFICIENT_BUFFER)
             ; Allocate the buffer size, using twice the size to avoid problems on W2k MBCS systems per KB 888609
               *buffer = AllocateMemory(buffersize*2)  ;Crashes in this line
         Else
             ; Insert error handling here
             Break
         EndIf
     
     Wend
     NexDev.s=PeekS(*buffer)
     If FindString(TMPDevicez.s, NexDev.s, 1, #PB_String_NoCase)=0 
         TMPDevicez.s + sepa.s+NexDev.s  ; just for checking
     EndIf
     
     If (*buffer)
       FreeMemory(*buffer)
     EndIf
     
     i+1  ; increment to next device
     
  Wend
  
  ; finish up
    
  If ( GetLastError_() <> #NO_ERROR And GetLastError_() <> #ERROR_NO_MORE_ITEMS )
     ; Insert error handling here
     ProcedureReturn "0"
  EndIf
  
  ; Cleanup
  SetupDiDestroyDeviceInfoList_(hDevInfo)
  
;  ProcedureReturn MD5Fingerprint(@devicesList,Len(devicesList))
  ;Debug TMPDevicez.s
  ProcedureReturn TMPDevicez.s
EndProcedure

; and

Procedure.s HashString(String2HASH.s)
  String2HASHLen.l=Len(String2HASH.s)
  If String2HASHLen>0
  *MD5Buffer = AllocateMemory(String2HASHLen.l*1.5)                  ; Prepare a buffer with data
  If *MD5Buffer
    PokeS(*MD5Buffer, String2HASH.s)    ; Here also crashes
    Length = MemoryStringLength(*MD5Buffer)
    If String2HASHLen<>Length
      ReAllocateMemory(*MD5Buffer,Length*1.5)
    EndIf
    If ExamineMD5Fingerprint(1)                  ; start the calculation
      MD5$ = MD5Fingerprint(*MD5Buffer, Length)     ; compare to a calculation in 1 step
    EndIf
    FreeMemory(*MD5Buffer)
  EndIf
  EndIf
  ProcedureReturn MD5$
EndProcedure


It would be very good to see PB do this memory allocation itself instead of changing all code such way by adding 2 bytes to memoryallocation manually
Last edited by LiK137 on Tue Jan 10, 2017 10:46 am, edited 1 time in total.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Crash in Unicode mode only

Post by IdeasVacuum »

Take a look at Fred's example here: Get Hardware by SetupDi

I have re-arranged your code a little bit:

Code: Select all

#SPDRP_DEVICEDESC = 0
#ERROR_INSUFFICIENT_BUFFER = 122
#INVALID_HANDLE_VALUE = -1

Structure SP_DEVINFO_DATA
  cbSize.l
  ClassGuid.GUID
  DevInst.l;    // DEVINST handle
  Reserved.l;
EndStructure

Procedure.s EnumDevz()

; How to enumerate hardware devices by using SetupDi calls
; mskuma 26 June 2006
; adapted from https://support.microsoft.com/en-us/kb/259695
; (Windows only)


Protected TMPDevicez.s = ""
Protected NexDev.s
Protected DeviceInfoData.SP_DEVINFO_DATA
Protected i.i = 0
Protected DataT.i
Protected buffersize.i = 1024
Protected      *buffer = AllocateMemory(buffersize)

;Create a HDEVINFO with all present devices
Protected hDevInfo.i = SetupDiGetClassDevs_(#Null, 0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)

  If hDevInfo = #INVALID_HANDLE_VALUE

            ProcedureReturn "0"
  Else
           ;Enumerate through all devices in Set

           DeviceInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)

           While SetupDiEnumDeviceInfo_(hDevInfo, i, @DeviceInfoData)

              While Not SetupDiGetDeviceRegistryProperty_(hDevInfo,@DeviceInfoData,#SPDRP_DEVICEDESC,@DataT,*buffer,buffersize,@buffersize)

                  If (GetLastError_() = #ERROR_INSUFFICIENT_BUFFER)
                       ; Allocate the buffer size, using twice the size to avoid problems on W2k MBCS systems per KB 888609
                        *buffer = AllocateMemory(buffersize * 2)
                  Else
                        ;Insert error handling here
                        Break
                  EndIf

              Wend

              NexDev = PeekS(*buffer, -1, #PB_UTF8)

              If FindString(TMPDevicez.s, NexDev, 1, #PB_String_NoCase) = 0

                         TMPDevicez = TMPDevicez + #CRLF$ + NexDev  ; just for checking
              EndIf

              i = i + 1  ; increment to next device

           Wend

           ;finish up

           If ( GetLastError_() <> #NO_ERROR And GetLastError_() <> #ERROR_NO_MORE_ITEMS )
              ; Insert error handling here
              ProcedureReturn "0"
           EndIf

           ;Cleanup
           SetupDiDestroyDeviceInfoList_(hDevInfo)

           If(MemorySize(*buffer)) : FreeMemory(*buffer) : EndIf
           

           ProcedureReturn TMPDevicez.s
  EndIf

EndProcedure

Debug EnumDevz()
[/size]
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Crash in Unicode mode only

Post by IdeasVacuum »

Code: Select all

Procedure.s HashString(sString2HASH.s)
;#------------------------------------
Protected sMD5.s
Protected *MD5Buffer
Protected iString2HASHLen.i = StringByteLength(sString2HASH)

  If iString2HASHLen > 0

            *MD5Buffer = AllocateMemory(iString2HASHLen)
         If *MD5Buffer

                 PokeS(*MD5Buffer, sString2HASH, iString2HASHLen, #PB_UTF8)
                 
                 sMD5 = MD5Fingerprint(*MD5Buffer, iString2HASHLen)

                 If(MemorySize(*MD5Buffer)) : FreeMemory(*MD5Buffer) : EndIf
         EndIf
  EndIf

  ProcedureReturn sMD5

EndProcedure

Debug HashString("Try this in PB5.31, the cipher library is re-designed in PB5.40")
;23a9c7a1f033f88966539c94e519cb3c
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
GoodNPlenty
Enthusiast
Enthusiast
Posts: 112
Joined: Wed May 13, 2009 8:38 am
Location: Arizona, USA

Re: Crash in Unicode mode only

Post by GoodNPlenty »

For 64-bit I needed to align SP_DEVINFO_DATA structure, change Reserved.l to *Reserved and change NexDev = PeekS(*buffer, -1, #PB_UTF8) to #PB_Unicode.

Code: Select all

EnableExplicit

;#================================================================================================#
;# Unicode Only                                                                                   #
;#================================================================================================#
  CompilerIf #PB_Compiler_Unicode
    CompilerElse
      CompilerError "Requires Unicode Option Set"
  CompilerEndIf
;#================================================================================================#

;#================================================================================================#
;# Windows Only                                                                                   #
;#================================================================================================#
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    CompilerElse
      CompilerError #APE_AppName + "Windows Only"
  CompilerEndIf
;#================================================================================================#

#SPDRP_DEVICEDESC = 0
#ERROR_INSUFFICIENT_BUFFER = 122
#INVALID_HANDLE_VALUE = -1

;# FIXME Change Reserved.l to *Reserved and Align
; Structure SP_DEVINFO_DATA
;   cbSize.l
;   ClassGuid.GUID
;   DevInst.l;    // DEVINST handle
;   Reserved.l;
; EndStructure

Structure SP_DEVINFO_DATA Align #PB_Structure_AlignC
  cbSize.l
  ClassGuid.GUID
  DevInst.l
  *Reserved
EndStructure


Procedure.s EnumDevz()

; How to enumerate hardware devices by using SetupDi calls
; mskuma 26 June 2006
; adapted from https://support.microsoft.com/en-us/kb/259695
; (Windows only)


Protected TMPDevicez.s = ""
Protected NexDev.s
Protected DeviceInfoData.SP_DEVINFO_DATA
Protected i.i = 0
Protected DataT.i
Protected buffersize.i = 1024
Protected      *buffer = AllocateMemory(buffersize)

;Create a HDEVINFO with all present devices
Protected hDevInfo.i = SetupDiGetClassDevs_(#Null, 0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)

  If hDevInfo = #INVALID_HANDLE_VALUE

            ProcedureReturn "0"
  Else
           ;Enumerate through all devices in Set

           DeviceInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)

           While SetupDiEnumDeviceInfo_(hDevInfo, i, @DeviceInfoData)

              While Not SetupDiGetDeviceRegistryProperty_(hDevInfo,@DeviceInfoData,#SPDRP_DEVICEDESC,@DataT,*buffer,buffersize,@buffersize)

                  If (GetLastError_() = #ERROR_INSUFFICIENT_BUFFER)
                       ; Allocate the buffer size, using twice the size to avoid problems on W2k MBCS systems per KB 888609
                        *buffer = AllocateMemory(buffersize * 2)
                  Else
                        ;Insert error handling here
                        Break
                  EndIf

              Wend

              ;FIXME Should be #PB_Unicode
              ;NexDev = PeekS(*buffer, -1, #PB_UTF8)
              NexDev = PeekS(*buffer, -1, #PB_Unicode)
              If FindString(TMPDevicez.s, NexDev, 1, #PB_String_NoCase) = 0

                         TMPDevicez = TMPDevicez + #CRLF$ + NexDev  ; just for checking
              EndIf

              i = i + 1  ; increment to next device

           Wend

           ;finish up

           If ( GetLastError_() <> #NO_ERROR And GetLastError_() <> #ERROR_NO_MORE_ITEMS )
              ; Insert error handling here
              ProcedureReturn "0"
           EndIf

           ;Cleanup
           SetupDiDestroyDeviceInfoList_(hDevInfo)

           If(MemorySize(*buffer)) : FreeMemory(*buffer) : EndIf
           

           ProcedureReturn TMPDevicez.s
  EndIf

EndProcedure

Debug EnumDevz()

LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Re: Crash in Unicode mode only

Post by LiK137 »

thanQ for provided solutions.
So as I understood, instead of Len() StringByteLen() should be used and variables have to be protected.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Crash in Unicode mode only

Post by IdeasVacuum »

That is correct, also note that if compiling in Unicode, then Unicode or UTF8 flags are required by some functions. However, I didn't look into what the code is exactly for - there are many ways to solve the same problems. Concerning the MD5 code, the PB Lib has changed in PB5.40 and is more logical now, but 5.31 and below code will therefore fail in 5.40.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
bbanelli
Enthusiast
Enthusiast
Posts: 544
Joined: Tue May 28, 2013 10:51 pm
Location: Europe
Contact:

Re: Crash in Unicode mode only

Post by bbanelli »

GoodNPlenty wrote:For 64-bit I needed to align SP_DEVINFO_DATA structure
I see you've been using #PB_Structure_AlignC for x64, but reading this article I've merely done this:

Code: Select all

DeviceInfoData.SP_DEVINFO_DATA
DeviceInfoData\cbSize = SizeOf(DeviceInfoData)+4
Is that the same effect (since it seems to be working in my case so far)?
"If you lie to the compiler, it will get its revenge."
Henry Spencer
https://www.pci-z.com/
GoodNPlenty
Enthusiast
Enthusiast
Posts: 112
Joined: Wed May 13, 2009 8:38 am
Location: Arizona, USA

Re: Crash in Unicode mode only

Post by GoodNPlenty »

bbanelli wrote:
GoodNPlenty wrote:For 64-bit I needed to align SP_DEVINFO_DATA structure
I see you've been using #PB_Structure_AlignC for x64, but reading this article I've merely done this:

Code: Select all

DeviceInfoData.SP_DEVINFO_DATA
DeviceInfoData\cbSize = SizeOf(DeviceInfoData)+4
Is that the same effect (since it seems to be working in my case so far)?
I like your solution much better, Thank You for the link.
Post Reply