I was very wrong. I declare the function in VB code from the .dll I
created. When the dll function calls NotesInit (), it immediatly
consumes 18MB of memory. Even more discouraging is when NotesTerm ()
is called and the function returns, the memory is _still_ being
consumed by the parent VB application!
I'm trying to figure out how to use OSLoadLibrary () with OSFreeLibrary
() to delete this memory footprint when finished, but I'm having alot
of trouble getting it to work. The documentation for this function is
very poor.
Any ideas? Any at all?
After the dll call returns, an extra ~100K remains in the parent
process according to Task Manager, and is added each time the function
is called. If I loop the call, it will crash after a few hundred runs.
The parent app dissapears, and no debugging information is provided. I
cannot find a memory leak in my C code, so I fear it could be a leak in
lotus notes, and is something I cannot fix. Can anybody see the problem
in my code, or suggest a workaround if nnotes.dll is the leak?
I am using Lotus Notes 6.5.4, Windows 2000 sp4, VC++ 6.0, and VB 6.0.
** Visual C++ 6.0 code for Win32 Dynamic-Link Library file main.cpp:
#include <windows.h>
// dynamic function prototypes
typedef WORD (__stdcall *initproc)(void);
typedef void (__stdcall *termproc)(void);
typedef bool (__stdcall *osproc)(const char far *, char far *, int);
typedef WORD (__stdcall *pwproc)(char far *, char far *, char far *);
int __stdcall ChangeNotesPassword(char *OrigPassword, char
*NewPassword, char *stat) {
WORD error; // error code for API calls
char IDFileSpec[256]; // full path to notes .id
// load library at run-time
HINSTANCE dll=LoadLibrary("nnotes.dll");
if (!dll) {
strcpy(stat, "nnotes.dll not found!");
return -1;
}
// map address to functions
initproc Init = (initproc) GetProcAddress(dll, "NotesInit");
termproc Term = (termproc) GetProcAddress(dll, "NotesTerm");
osproc GetEnvironmentString = (osproc) GetProcAddress(dll,
"OSGetEnvironmentString");
pwproc ChangePassword = (pwproc) GetProcAddress(dll,
"SECKFMChangePassword");
if ((!Init) || (!Term) || (!GetEnvironmentString) ||
(!ChangePassword)) {
strcpy(stat, "Could not map entry points to nnotes.dll, version
mismatch?");
FreeLibrary(dll);
return -1;
}
if(error = Init()) {
FreeLibrary(dll);
strcpy(stat, "Could not Initialize notes");
return error;
}
if (!GetEnvironmentString("KeyFileName", IDFileSpec, 256)) {
Term();
FreeLibrary(dll);
strcpy(stat, "Could not find .id file");
return 1337;
}
if (error = ChangePassword(IDFileSpec, OrigPassword, NewPassword)) {
Term();
FreeLibrary(dll);
strcpy(stat, "Password change not successful");
return error;
}
// terminate notes, free library, return success
Term();
FreeLibrary(dll);
strcpy(stat, "Password change A-OK");
return 0;
}
** Visual C++ 6.0 code for Win32 Dynamic-Link Library file exports.def:
EXPORTS
ChangeNotesPassword
** Visual Basic 6.0 test code with button Command1_Click():
Private Declare Function ChangeNotesPassword Lib
"Debug\ChangeNotesPassword.dll" ( _
ByVal OldPassword As String, ByVal NewPassword As String, ByVal
Status As String) _
As Integer
Private Declare Function SetEnvironmentVariable Lib "kernel32.dll"
Alias _
"SetEnvironmentVariableA" (ByVal lpName As String, ByVal lpValue As
String) _
As Long
Private Sub Command1_Click()
Dim E As String * 256 ' holds Error Message
Dim ret As Integer ' error code
ret = ChangeNotesPassword("87654321", "87654321", E)
If ret = 0 Then
Debug.Print E ' success
ElseIf ret = 4103 Then
Debug.Print "Could not Initialize Notes ID"
ElseIf ret = 6408 Then
Debug.Print "Old Password not correct"
ElseIf ret = 8427 Then
Debug.Print "Your new password sucks"
End If
Print Str(ret) + ", " + E
End Sub
Private Sub Form_Load()
Dim newpath As String
newpath = "c:\Program Files\lotus\notes;" + Environ$("PATH")
Call SetEnvironmentVariable("PATH", newpath)
'Debug.Print Environ$("PATH")
End Sub