Exporting nsf objects - deep under the covers

This will dump internal Domino ojects out to disk file for detailed analysis.

This will dump internal Domino ojects out to disk file for detailed analysis. If you've ever wanted to see how Domino stores file attachments, what the ACL really looks like or the inside of a view collection then this script is for you!


Option Public
Option Declare
'Dump objects: 

Const VERSION = 1
Const LOWOBJ = 1 ' No lower than 1
' Just an arbitrary limit. This can be raised (and it is an unsigned value 

so "negative" values are also ok)
Const HIGHOBJ = 65535
Const MAXCHUNK = 32000 ' Domino prefers this size
Const SUCCESS = 0
Declare Function NSFDbOpen Lib "nnotes" (_
Byval PathName As Lmbcs String, _
rethDB As Long _
) As Integer

Declare Function NSFDbClose Lib "nnotes" (_
Byval hDB As Long _
) As Integer

Declare Function NSFDbSessionClose Lib "nnotes" (_
Byval hDB As Long _
) As Integer

Declare Function NSFDbGetObjectSize Lib "nnotes" (_
Byval hDB As Long, _
Byval ObjectID As Long, _
Byval ObjectType As Long, _
retSize As Long, _
retClass As Integer, _
retPrivileges As Integer _
) As Integer

Declare Function NSFDbReadObject Lib "nnotes" (_
Byval hDB As Long, _
Byval ObjectID As Long, _
Byval Offset As Long, _
Byval Length As Long, _
rethBuffer As Long _
) As Integer

Declare Function OSMemFree Lib "nnotes" Alias "OSMemFree" ( _
Byval hObject As Long _
) As Integer

Declare Function OSLockObject Lib "nnotes" Alias "OSLockObject" ( _
Byval hObject As Long _
) As Long

Declare Function OSUnlockObject Lib "nnotes" Alias "OSUnlockObject" ( _
Byval hObject As Long _
) As Integer

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Byval pDest As String, _
Byval pSource As Long, _
Byval dwLength As Long _

Sub Initialize
	Dim result As Long
	Dim hDB As Long
	Dim ObjectID As Long
	Dim ObjectType As Long
	Dim retSize As Long
	Dim retClass As Integer
	Dim retPrivileges As Integer
	Dim rethBuffer As Long
	Dim hLock As Long
	Dim PerlFileH As Long
	Dim BinFileH As Long
	Dim MapFileH As Long
	Dim DbPath As String
	Dim FilePath As String
	Dim Chunk As Long
	Dim Offset As Long
	Dim ObjStr As String
	Messagebox |This script will export information on the first 65535 

objects in a Domino database. There are three important things to keep in 

mind here. #1 The export path must be a directory. A map file, perl script 

and all the objects are placed into this directory. #2 This script scans 

through objects | & LOWOBJ & | to | & HIGHOBJ & |. If you need to change 

these boundaries then change the constants LOWOBJ and HIGHOBJ. I picked 

65535 as an initial default because I just wanted some basic information. 

#3 When LotusScript writes the object files, it pads every byte with 

another null byte (0x00). The perl script will strip that null byte out. 

If you don't have perl (the script will still work) then either you will 

need to strip the nulls yourself or just ignore them. Perl for Windows can 

be installed from http://www.activestate.com for free.|
	DbPath = Inputbox("Enter the path to database. To specify a 

server, prepend <Server> followed by !!. For example, <Server>!!<Filepath> 

or just <Filepath>","Enter the database path", "<Server>!!<Filepath.nsf>")
	FilePath = Inputbox ("Enter directory to export data 

	If Len(FilePath) > 0 And Not Right(FilePath,1) = "" Then
		FilePath = FilePath & ""
	End If
Get a handle to the database
	If Len(DbPath) > 0 Then
		result = NSFDbOpen(DbPath, hDB)
	End If
		Messagebox "The database at " & DbPath & " was not opened"
	End If
Write the null removing perl script out to the directory
	PerlFileH = Freefile
	Open Filepath & "no.pl" For Output As PerlFileH
	Print #PerlFileH, |
use strict;
use warnings;
my $file_name = $ARGV[0];

undef $/;
open IN, $file_name or die "Can't open $file_name: $!";
my $data = <IN>;
close IN or die "Can't close $file_name: $!";

open OUT, ">$file_name" or die "Can't open $file_name: $!";
for (my $offset=0;
     $offset < length $data;
     $offset += 2 ) {
  print OUT substr $data, $offset, 1;
close OUT or die "Can't close $file_name: $!";
	Close PerlFileH
Create a map file. This is a tab delimited file describing the attributes 

of each object. If the
object size is zero, then it will be noted in the log but no object file 

will be saved to disk.
	MapFileH = Freefile
	Open Filepath & "Map.txt" For Output As MapFileH
	Print #MapFileH, "ObjectID	Size	Class	Privileges"
	ObjectID = 0
		' Get the object flags
		If Not SUCCESS = _
		NSFDbGetObjectSize(hDB, ObjectID, 65535, retSize, 

retClass, retPrivileges) Then
			Goto next_Obj
		End If
		' Save the information to the log if nessessary
		If retSize <> 0 Or _
		retClass <> 0 Or _
		retPrivileges <> 0 _
			Print #MapFileH, Hex(ObjectID) & "	" & 

Hex(retSize) & "	" & Hex(retClass) & "	" & Hex(retPrivileges)
			Print ObjectID & "	" & retSize & "	" & 

Hex(retClass) & "	" & Hex(retPrivileges)
		End If
		' If there is something to export, then do that.
		If retSize <> 0 Then
			' Read the object into memory with the handle in 

			If Not SUCCESS = _
			NSFDbReadObject(hDB, ObjectID, 0, retSize, 

rethBuffer) Then
				Goto free_Obj
			End If
			' Lock the object in memory. hLock is now a memory 

address that can be used
			' to access the data
			hLock = OSLockObject (rethBuffeR)
			' Open the output file and write it in MAXCHUNK 

byte chunks
			' Domino appears to prefer this size chunk
			BinFileH = Freefile
			Open Filepath & Hex(ObjectID) & |.obj| For Binary 

Access Write As BinFileH
			Offset = 0
			While Offset < retSize
				Chunk = retSize - Offset
				If (retSize - Offset) > MAXCHUNK Then
					Chunk = MAXCHUNK
				End If
				ObjStr = String(Chunk, "X")
				CopyMemory ObjStr, hLock, Len(ObjStr)
				Put # BinFileH, ,ObjStr ' Remember, each 

byte is null padded
				hLock = hLock + Chunk
				Offset = Offset + Chunk
			Close BinFileH
			' Launch the perl script and who cares if it 

succeeds. If perl is not
			' installed it won't really matter
			If 0 = Shell (|perl | & Filepath & |no.pl | & 

FilePath & Hex(ObjectID) & |.obj|) Then
			End If
			' Unlock the object. The memory is still 

allocated, it may be moved around if the OS wishes
			Call OSUnlockObject (retHBuffer)
			' And now deallocate the memory.
			Call OSMemFree (rethBuffer)
		End If
		ObjectID = ObjectID + 1
	Loop While ObjectID <= 65535
	Close MapFileH
	' Close the handle
	result = NSFDbClose(hDB)
	Messagebox "Done"
End Sub
This was first published in September 2001

Dig Deeper on Domino Resources - Part 6



Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:




  • iSeries tutorials

    Search400.com's tutorials provide in-depth information on the iSeries. Our iSeries tutorials address areas you need to know about...

  • V6R1 upgrade planning checklist

    When upgrading to V6R1, make sure your software will be supported, your programs will function and the correct PTFs have been ...

  • Connecting multiple iSeries systems through DDM

    Working with databases over multiple iSeries systems can be simple when remotely connecting logical partitions with distributed ...