Subject: Some sample code…
Hi Kevin,
Thanks for your response. I’ve attached the code that I’m using today. There is a lot of unneeded code, it’s just used for testing right now, and I’ve copied most of it from the C API sample “schedule”, and then converted it into some basic C++ class…
Below I have two problems. After calling Schedule_ExtractSchedList() and parsing the result, it only returns SCHED_ENTRY, when it should return SCHED_ENTRY_EXT. The call to SchRetrieve() uses the option SCHRQST_EXTFORMAT to force this format.
The other problem is when I try to call Schedule_GetFirstDetails(), this call just returns error 1006 (invalid schedule object), even though it’s not invalid.
#include “stdafx.h”
#include
#include
#include
#include
#include “lncppapi.h”
#include “schedule.h”
#include <textlist.h>
using namespace std;
#define ERR_BUF_SIZE 512
#define STRING_LENGTH 256
class NotesConnector
{
public:
NotesConnector();
virtual ~NotesConnector();
int Init(int argc, char *argv[]);
STATUS LNPUBLIC LookupSchedules(char *start_date, char *end_date);
void PrintAPIError(STATUS api_error);
int ProgramStatus;
char AUser[STRING_LENGTH];
private:
void ProcessArguments(int argc, char **argv, char **Subject, char **DatabasePath, char **ServerName);
void PrintUsage();
void LNPUBLIC GetTDString(TIMEDATE *ptdModified, char *szTimedate);
STATUS LNPUBLIC FindEntries(char *pSchedList);
char *Subject;
char *DatabasePath;
char *ServerName;
LNNotesSession *Session;
LNDatabase Db;
};
NotesConnector::NotesConnector()
{
ProgramStatus = 0;
AUser[0] = '\0';
Session = new LNNotesSession();
}
NotesConnector::~NotesConnector()
{
delete Session;
Session = NULL;
}
void NotesConnector::PrintUsage()
{
cout << "Usage:" << endl;
cout << "\tmailscan subject [database [server]] " << endl << endl;
cout << "where:" << endl;
cout << "\tsubject Message subject to search for" << endl;
cout << "\tdatabase Optional pathname of database" << endl;
cout << "\tserver Optional server name" << endl;
}
void NotesConnector::ProcessArguments(int argc, char **argv, char **Subject, char **DatabasePath, char **ServerName)
{
int curParam = 0;
int index;
// Set the default values for the arguments (that is, NULL!).
*Subject = NULL; // The logic of the main program depends
*DatabasePath = NULL; // on these pointers being set to NULL if
*ServerName = NULL; // no user input is supplied!
// Check argument count
if (argc < 2)
throw "No subject provided";
if (argc > 4)
throw "Too many arguments";
// Scan the argument list, item by item.
for (index = 1; index < argc; index++)
{
// Check for option switches.
if (('-' == ((argv[index])[0])) || ('/' == ((argv[index])[0])))
{
throw "Unknown switch";
}
else
{
// String argument - assign to
switch (curParam)
{
case 0:
*Subject = argv[index];
break;
case 1:
*DatabasePath = argv[index];
break;
case 2:
*ServerName = argv[index];
break;
default:
throw "More than 3 arguments";
}
curParam++;
}
}
if (((char *) NULL) == (*Subject))
throw "No subject provided";
return;
}
int NotesConnector::Init(int argc, char *argv)
{
// Parse the argument list.
try
{
ProcessArguments(argc, argv, &Subject, &DatabasePath, &ServerName);
}
catch (const char *pErrorMessage)
{
cout << "\nError: " << pErrorMessage << endl << endl;
PrintUsage();
return 1;
}
NotesInit();
/*LNSetThrowAllErrors(TRUE);
if (Session->Init())//(argc, argv))
throw "Unable to initialize the API";
if (DatabasePath == ((char *) NULL))
{
// No database specified; get user's mail database.
Session->GetMailDatabase(&Db);
}
else
{
// Get the specified database.
Session->GetDatabase(DatabasePath, &Db, ServerName);
}
// Open the database.
Db.Open();*/
return 0;
}
STATUS LNPUBLIC NotesConnector::LookupSchedules(char *start_date, char *end_date)
{
STATUS sError = NOERROR;
char *theSchedList;
TIMEDATE_PAIR theApptInterval;
TIMEDATE_PAIR pInterval;
VOID *list_ptr; /* pointer to same list */
WORD list_size; /* total size of list structure */
SCHEDULE *pSchedule;
UNID theApptUnid;
HCNTNR rethCntnr = NULLHANDLE; /* container handle */
DHANDLE list_handle; /* handle to Domino and Notes list structure */
DHANDLE rethSchedList;
HCNTNROBJ hSchedObj, hSchedObj2;
HCNTNROBJ hMoreObj = NULLCNTNROBJ;
DWORD retdwSize;
WORD NumEntries;
SCHED_DETAIL_LIST *sched_details;
/* Create an empty text list data structure. */
sError = ListAllocate(0, 0, FALSE, &list_handle, &list_ptr, &list_size);
NumEntries = ListGetNumEntries(list_ptr, FALSE);
OSUnlockObject(list_handle);
if (sError)
return sError;
/* Add the user we're looking for */
sError = ListAddEntry(list_handle, FALSE, &list_size, NumEntries, AUser, (WORD)strlen(AUser));
if (sError)
return sError;
/* convert start time string to TIMEDATE format */
sError = ConvertTextToTIMEDATE(NULL, NULL, &start_date, (WORD)strlen(start_date), &theApptInterval.Lower);
if (sError)
return sError;
/* convert end time string to TIMEDATE format */
sError = ConvertTextToTIMEDATE(NULL, NULL, &end_date, (WORD)strlen(end_date), &theApptInterval.Upper);
if (sError)
goto Done;
list_ptr = OSLockObject(list_handle);
sError = SchRetrieve(&theApptUnid, NULL, SCHRQST_EACHPERSON|SCHRQST_FORCEREMOTE|SCHRQST_EXTFORMAT, &theApptInterval, (LIST *)list_ptr, &rethCntnr, NULL, NULL, NULL);
if (sError)
goto Done;
/* Get the first schedule */
sError = SchContainer_GetFirstSchedule(rethCntnr, &hSchedObj, &pSchedule);
if (sError)
goto Done;
sError = Schedule_ExtractSchedList(rethCntnr, hSchedObj, &pInterval, (unsigned long *)&retdwSize, &rethSchedList, &hMoreObj);
if (sError)
goto Done;
//sError = Schedule_GetFirstDetails(rethCntnr, hSchedObj, &hSchedObj2, &sched_details);
//if (sError)
// goto Done;
theSchedList = (char *)OSLockObject(rethSchedList);
/* Attempt to find schedule entry in list */
sError = FindEntries(theSchedList);
OSUnlockObject(rethSchedList);
Done:
OSUnlockObject(list_handle);
return sError;
}
STATUS LNPUBLIC NotesConnector::FindEntries(char *pSchedList)
{
int i;
int num;
SCHED_LIST SchedList;
SCHED_ENTRY_EXT SchedEntry;
WORD entry_size = 0;
STATUS sError=0;
char szTemp[MAXALPHATIMEDATE+1];
char szTimedate[MAXALPHATIMEDATE+1];
char szUpperTD[MAXALPHATIMEDATE+1];
/* Get the SCHED_LIST from the location specified by pSchedList */
memcpy((char*)&SchedList, pSchedList, sizeof(SCHED_LIST));
entry_size = SchedList.Spare;
if (entry_size == 0)
entry_size = sizeof(SCHED_ENTRY);
pSchedList += sizeof(SCHED_LIST);
num = SchedList.NumEntries;
for (i=0; i < num; i++)
{
if (entry_size > sizeof(SCHED_ENTRY_EXT))
memcpy((char *)&SchedEntry, pSchedList, sizeof(SCHED_ENTRY_EXT));
else
memcpy((char *)&SchedEntry, pSchedList, entry_size);
GetTDString(&(SchedEntry.Unid).Note, szTemp);
GetTDString(&(SchedEntry).Interval.Lower, szTimedate);
GetTDString(&(SchedEntry).Interval.Upper, szUpperTD);
pSchedList += entry_size;
}
return(sError);
}
void LNPUBLIC NotesConnector::GetTDString(TIMEDATE *ptdModified, char *szTimedate)
{
WORD wLen;
ConvertTIMEDATEToText(NULL, NULL, ptdModified, szTimedate, MAXALPHATIMEDATE, &wLen);
szTimedate[wLen] = '\0';
}
void NotesConnector::PrintAPIError(STATUS api_error)
{
STATUS string_id = ERR(api_error);
char error_text[200];
WORD text_len;
/* Get the message for this Lotus C API for Domino and Notes error code from the resource string table. */
text_len = OSLoadString(NULLHANDLE, string_id, error_text, sizeof(error_text));
/* Print it. */
fprintf(stderr, "\n%s\n", error_text);
}
int main(int argc, char ** argv)
{
STATUS err;
NotesConnector connector;
try
{
connector.ProgramStatus = connector.Init(argc, argv);
if (connector.ProgramStatus)
return connector.ProgramStatus;
SECKFMUserInfo(KFM_ui_GetUserInfo, connector.AUser, NULL);
err = connector.LookupSchedules("2009-10-01 00:00:00", "2010-01-01 00:00:00");
if (err)
connector.PrintAPIError(err);
}
catch (...)
{
return 1;
}
return connector.ProgramStatus;
}