Page 1 of 1

Crash in Unicode mode only [SOLVED]

Posted: Wed Oct 07, 2015 2:50 pm
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

Re: Crash in Unicode mode only

Posted: Wed Oct 07, 2015 10:34 pm
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]

Re: Crash in Unicode mode only

Posted: Wed Oct 07, 2015 11:44 pm
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

Re: Crash in Unicode mode only

Posted: Thu Oct 08, 2015 2:33 am
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()


Re: Crash in Unicode mode only

Posted: Thu Oct 08, 2015 10:01 am
by LiK137
thanQ for provided solutions.
So as I understood, instead of Len() StringByteLen() should be used and variables have to be protected.

Re: Crash in Unicode mode only

Posted: Thu Oct 08, 2015 10:11 am
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.

Re: Crash in Unicode mode only

Posted: Thu Oct 08, 2015 12:09 pm
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)?

Re: Crash in Unicode mode only

Posted: Thu Oct 08, 2015 7:27 pm
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.