LotusScript 64-bit migration

I’m having trouble converting LotusScript 32-bit code, with DLL calls, to 64-bit code. It’s about this script, which works very well under 32-bit:

There is one point that I do not understand and that I cannot customise. It concerns the call to the ‘Peek/memcpy’ function. Regardless of whether I use ‘double’, ‘any’ or “integer” here, HCL Domino always crashes when I call ‘Peek’:

Option Public
Option Declare
Const wAPIModule = "NNOTES"
Const NOTE_CLASS_FILTER = &H0200

Type AssistInfo
   Version As integer
   TriggerType As Integer  ' 0 none, 1 schedule, 2 new mail, 3 paste, 4 manual, 5 update, 6 router
   SearchType As Integer  ' 0 none, 1 all, 2 new, 3 new/mod, 4 selected, 5 view, 6 unread, 7 prompt, 8 UI
   IntervalType As Integer  ' 0 none, 1 minutes, 2 days, 3 weeks, 4 months
   Interval As Integer
   Time1 As Variant  ' Start time (ms since midnight)
   Time2 As Variant  ' Long (weekday or day of month) or end time (ms since midnight)
   StartTime As Variant  ' Time/Date
   EndTime As Variant  ' Time/Date
   Flags As Long  ' 1 hidden, 2 no weekends, 4 store highlights, 8 mail/paste, 16 choose server
   Spare(15) As Long
End Type

Type BlockID
   hPool As double
   Block As Integer
End Type

Declare Function ConvertTIMEDATEToText Lib wAPIModule Alias "ConvertTIMEDATEToText" _
(  ByVal zI As Long, ByVal zT As Long, ByVal T As Long, ByVal S As String, ByVal nS As Integer, nT As Integer) As Integer
Declare Function ConvertTextToTIMEDATE Lib wAPIModule Alias "ConvertTextToTIMEDATE" _
(  ByVal zI As Long, ByVal zT As Long, pS As Long, ByVal nS As Integer, ByVal T As Long) As Integer
Declare Private Function NIFFindDesignNote Lib wAPIModule Alias "NIFFindDesignNote" _
(  ByVal hDB As double, ByVal S As String, ByVal C As Integer, N As Long) As Integer
Declare Private Function NSFDbOpen Lib wAPIModule Alias "NSFDbOpen" _
(  ByVal PathName As String, DbHandle As double) As Integer
Declare Private Function NSFDbClose Lib wAPIModule Alias "NSFDbClose" _
(  ByVal DbHandle As Double) As Integer
Declare Private Function NSFNoteOpen Lib wAPIModule Alias "NSFNoteOpen" _
(  ByVal hDB As double, ByVal NoteID As Long, ByVal F As Integer, hNT As double) As Integer
Declare Private Function NSFNoteClose Lib wAPIModule Alias "NSFNoteClose" _
(  ByVal hNT As double) As Integer
Declare Function NSFItemInfo Lib wAPIModule Alias "NSFItemInfo" _
(  ByVal hNT As Double, ByVal N As String, ByVal nN As Integer _
,  iB As BlockID, D As Integer, vB As BlockID, nV As Long) As Integer
Declare Private Function NSFNoteUpdate Lib wAPIModule Alias "NSFNoteUpdate" _
(  ByVal hNT As double, ByVal F As Integer) As Integer
Declare Function NSFItemDelete Lib wAPIModule Alias "NSFItemDelete" _
(  ByVal hNT As double, ByVal N As String, ByVal nN As Integer) As Integer
Declare Private Function OSMemAlloc Lib wAPIModule Alias "OSMemAlloc" _
(  ByVal T As Integer, ByVal N As Long, hM As double) As Long
Declare Private Function OSMemFree Lib wAPIModule Alias "OSMemFree" _
(  ByVal hM As double) As Long
Declare Private Function OSLockObject Lib wAPIModule Alias "OSLockObject" _
(  ByVal H As double) As Long
Declare Private Sub OSUnlockObject Lib wAPIModule Alias "OSUnlockObject" _
(  ByVal H As double)
Declare Private Function OSPathNetConstruct Lib wAPIModule Alias "OSPathNetConstruct" _
(  ByVal NullPort As Long, ByVal Server As String, ByVal FIle As String, ByVal PathNet As String) As Integer
Declare Private Sub Peek Lib "MSVCRT" Alias "memcpy" _
(  D As Any, ByVal P As Long, ByVal N As Long)

Sub Initialize
	Dim se As New NotesSession, agent$
	se.Usedoubleaspointer = True

	agent = "Test Agent"	
	Dim info As AssistInfo
	GetAssistInfo se.CurrentDatabase, agent, info
	
	MessageBox "Version: " & CStr(info.Version) _
	& Chr$(10) & "TriggerType: " & CStr(info.TriggerType) _
	& Chr$(10) & "SearchType: " & CStr(info.SearchType) _
	& Chr$(10) & "IntervalType: " & CStr(info.IntervalType) _
	& Chr$(10) & "Interval: " & CStr(info.Interval) _
	& Chr$(10) & "Time1: " & CStr(info.Time1) _
	& Chr$(10) & "Time2: " & CStr(info.Time2) _
	& Chr$(10) & "StartTime: " & CStr(info.StartTime) _
	& Chr$(10) & "EndTime: " & CStr(info.EndTime) _
	& Chr$(10) & "Flags: " & CStr(info.Flags)
End Sub

Sub GetAssistInfo(db As NotesDatabase, agent As String, info As AssistInfo)
	Dim np$, pt&, ti$, dt%, nV&, p&, v&, t$, nt%
	
	np$ = Space(1024)
	OSPathNetConstruct 0, db.Server, db.FilePath, np$
	
	Dim hDB As double
	NSFDbOpen np$, hDB
	If hDB = 0 Then
		MessageBox "Can't open database", 16
		Exit Sub
	End If
	
	pt& = InStr(agent, "|")
	If pt& = 0 Then ti$ = Trim$(agent) Else ti$ = Trim$(Left$(agent, pt& - 1))
	
	Dim nID As Long
	NIFFindDesignNote hDB, ti$, NOTE_CLASS_FILTER, nID
	If nID = 0 Then
		MessageBox "Can't find agent " & ti$, 16
		Exit Sub
	End If
	
	If InStr(db.GetDocumentByID(Hex$(nID)).~$Flags(0), "f") = 0 Then
		MessageBox ti$ & " is not an agent", 16
		Exit Sub
	End If
	
	Dim hNT As double
	NSFNoteOpen hDB, nID, 0, hNT
	
	Dim iB As BlockID, vB As BlockID
	NSFItemInfo hNT#, "$AssistInfo", 11, iB, dt%, vB, nv&
	If Not vB.hPool = 0 Then
		p& = OSLockObject(vB.hPool) + vB.Block
		Peek info.Version, p& + 2, 2
		Peek info.TriggerType, p& + 4, 2
		Peek info.SearchType, p& + 6, 2
		Peek info.IntervalType, p& + 8, 2
		Peek info.Interval, p& + 10, 2
		Peek v&, p& + 12, 4
		If v& <= 31 Then info.Time1 = v& Else info.Time1 = CDat(v&/100/60/60/24)
		Peek v&, p& + 16, 4
		If v& <= 31 Then info.Time2 = v& Else info.Time2 = CDat(v&/100/60/60/24)
		t$ = Space(81)
		ConvertTIMEDATEToText 0, 0, p& + 20, t$, 80, nt%
		If Not nt% = 0 Then info.StartTime = CDat(Left$(t$, nt%))
		t$ = Space(81)
		ConvertTIMEDATEToText 0, 0, p& + 28, t$, 80, nt%
		If Not nt% = 0 Then info.EndTime = CDat(Left$(t$, nt%))
		Peek info.Flags, p& + 36, 4		
		OSUnlockObject vB.hPool
	End If
	
	NSFNoteClose hNT
	NSFDbClose hDB
End Sub

How do I have to adapt this call? Is there a solution for this?

Hi @ErikSchmalz,

I saw that you use the UseDoubleAsPointer (NotesSession - LotusScript ), this allows you to use a Double to handle a 64-bit pointer argument for a C API call.

se.Usedoubleaspointer = True

However, I don’t see that it was set back to false after the API call. As per documentation,

Note: The Notes client runs under a single backend session. If any script sets the value to True , after the C API callout, reset the value to false so that subsequent scripts use the correct Double behavior.

UseDoubleAsPointer (NotesSession - LotusScript )
(UseDoubleAsPointer (NotesSession - LotusScript ))

1 Like

Thank you for this hint.

Since the Notes client crashes every time the NotesAgent is executed, and a reload also creates a new NotesSession, I haven’t noticed any negative effects in this regard yet.
Should it ever go beyond the ‘Peek’ call, I will add a se.Usedoubleaspointer = False.

I have referenced this entry in atnotes. Let’s see if there is someone there who can solve the problem:
atnotes.de