This post is a continuation from this thread. I've now managed to build a much reduced, sorta self-contained sample . I agree with Roberto Parisi that it looks like a case of memory that got overwritten as with my reduced sample, space is not replaced by 'N' but some other character. Unfortunately, his tip of using hg_gcall() didn't work for me. Here's the screenshot:
The sample was compiled using BCC5.82 + Harbour rev 17053 + FWH11.8. Download the source here
Just copy the whole thing into fwh\samples and link using buildh.bat or the modified -3.bat supplied.
The bug would go away if I don't call ValidLic32() at all but I can't do that as copy-protection is implemented using it (a SoftwareKey.com product). Any help to resolve this is greatly appreciated.
Here's the test code at a glance for those interested:
- Code: Select all Expand view
#include "fivewin.ch"
// License file defines
#define LF_CREATE_NORMAL 0 //attribute used if License File is created
#define LF_FILE 1 //normal filesystem
#define PP_SUCCESS 1
#define VAR_COMPANY 1
#define VAR_EXPIRE_TYPE 9
memvar zname // Company Name
function bugs()
local i, cStr, cOriStr, cTitle
public zname
if !ValidLic32() // License validation. zname assigned here
return nil
endif
cOriStr := zname
cStr := ""
// copy the string one character at a time
for i := 1 to len(cOriStr)
cStr += substr(cOriStr,i,1)
next
msginfo( "cOriStr: " + cOriStr + CRLF + ;
"cStr : " + cStr,"Copied string: "+if(cOriStr==cStr, "IDENTICAL", "DIFFERENT"))
RETURN NIL
//----------------------------------------------------------------------
function ValidLic32()
local cDataPath := cFilePath(getmodulefilename(getinstance())), nRet, lRet := .t., oSWKey
// turn pp_xxx funcs into a class to avoid a very frequent loading and unloading
// of keylib32.dll in a very short time
if (oSWKey := TValidLic():new()) == nil
return .f.
endif
begin sequence
// open license file
nRet := oSWKey:pp_lfopen(cDataPath+'product.lf', LF_CREATE_NORMAL, LF_FILE, "password")
if nRet != PP_SUCCESS
oSWKey:SayErr(nRet)
break
endif
oSWKey:GetZname() // Read company name from license file
oSWKey:expiryType() // rem-ing this part would make the bug stop to appear
recover
lRet := .f.
end
oSWKey:end()
oSWKey := nil
return ( lRet )
//----------------------------------------------------------------------
class TValidLic
data hDLL, lfHnd, cExpType
method new()
method GetZName()
method expiryType()
method pp_errorstr(errorcode, @buffer )
method pp_lfopen(filename, flags, lfType, password)
method pp_getvarchar(varno, @buffer)
method pp_lfclose()
method SayErr(nRet)
method end()
endclass
//----------------------------------------------------------------------
method new() class TValidLic
local oRet
::hDLL := 0
if abs(::hDLL := LoadLibrary("keylib32.dll")) <= 32
msgalert("Error loading keylib32.dll", "Error "+lstr(::hDLL))
else
oRet := self
endif
return oRet
//----------------------------------------------------------------------
method pp_errorstr( errorcode, buffer) class TValidLic
local nRet, cFarProc
if Abs( ::hDLL ) > 32
cFarProc = GetProcAdd( ::hDLL, "pp_errorstr", .T., 0,7,9 )
nRet := FWCallDLL( cFarProc, errorcode, @buffer )
end
return nRet
//----------------------------------------------------------------------
method pp_getvarchar(varno, buffer) class TValidLic
local nRet, cFarProc
if Abs( ::hDLL ) > 32
cFarProc := GetProcAdd( ::hDLL, "pp_getvarchar", .T., 7,7,7,9 )
nRet := FWCallDLL( cFarProc, ::lfhnd , varno, @buffer )
end
return nRet
//----------------------------------------------------------------------
method pp_lfclose() class TValidLic
local nRet, cFarProc
if Abs( ::hDLL ) > 32
cFarProc = GetProcAdd( ::hDLL, "pp_lfclose", .T., 7,7 )
nRet := FWCallDLL( cFarProc, ::lfhnd )
end
return nRet
//----------------------------------------------------------------------
method pp_lfopen(filename, flags, lfType, password) class TValidLic
local nRet, cFarProc
if Abs( ::hDLL ) > 32
cFarProc = GetProcAdd( ::hDLL, "pp_lfopen", .T., 7,9,7,7,9,7 )
nRet := FWCallDLL( cFarProc, filename, flags, lfType, password, @::lfhnd )
end
return nRet
//----------------------------------------------------------------------
method function getzname() class TValidLic
zname := space(50)
::pp_getvarchar(VAR_COMPANY, @zname)
zname := upper(trim(zname))
if asc(right(zname,1))==0
zname := left(zname, len(zname)-1)
endif
zname := trim(zname)
return nil
//----------------------------------------------------------------------
method expiryType() class TValidLic
local nRet, cExpType := space(1)
nRet := ::pp_getvarchar(VAR_EXPIRE_TYPE, @cExpType)
::cExpType := cExpType
return nRet
//----------------------------------------------------------------------
method SayErr(nRet) class TValidLic
local cStr := space(50),a := procname(1)+" ("+ltrim(str(procline(1)))+")"
::pp_errorstr(nRet, @cStr)
msglist({"License error: "+ltrim(str(nret))+" "+cStr,"Called from "+a},"Error",10,20,18,59.5,"Ok")
return nil
//----------------------------------------------------------------------
method end() class TValidLic
if !empty(::lfhnd)
::pp_lfclose()
endif
if abs(::hDLL) > 32
freeLibrary(::hDLL)
endif
return nil
//----------------------------------------------------------------------
TQVM