]> granicus.if.org Git - nethack/commitdiff
*** empty log message ***
authorjwalz <jwalz>
Sat, 5 Jan 2002 21:06:00 +0000 (21:06 +0000)
committerjwalz <jwalz>
Sat, 5 Jan 2002 21:06:00 +0000 (21:06 +0000)
sys/winnt/mapimail.c [new file with mode: 0644]

diff --git a/sys/winnt/mapimail.c b/sys/winnt/mapimail.c
new file mode 100644 (file)
index 0000000..b991644
--- /dev/null
@@ -0,0 +1,482 @@
+/*      SCCS Id: @(#)mapimail.c 3.3     2000/04/25        */
+/* Copyright (c) Michael Allison, 1997                  */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifdef MAX_BODY_SIZE
+#undef MAX_BODY_SIZE
+#define MAX_BODY_SIZE           2048    /* largest body held in ram in bytes */
+#endif
+
+#include "hack.h"
+# ifdef LAN_MAIL
+#include "win32api.h"
+#include <mapi.h>
+
+#define MAPI_MSGID_SIZE 512     /* as recommended */
+#define MAPI_LIB_FAIL           1
+#define MAPI_FUNC_FAIL          2
+
+HANDLE hLibrary;                        /* Handle for MAPI32.DLL     */
+LHANDLE MAPISession;                    /* Handle for MAPI session   */
+char MAPIMessageID[MAPI_MSGID_SIZE];    /* Msg ID from provider      */
+lpMapiMessage MAPIMessage;              /* Ptr to message from prov  */
+struct lan_mail_struct received_msg;    /* store received msg here   */
+#ifdef MAPI_VERBOSE
+FILE *dbgfile;
+#define MAPIDEBUGFILENAME      "mapidebug.log"
+#endif
+
+/*
+ * Prototypes for functions in this file
+ * (Not in normal NetHack style, but its doubtful that any
+ *  of the code in here is at all portable between platforms)
+ */
+static long __stdcall start_mailthread(LPVOID ThreadParam);
+static boolean MAPI_mail_check(char *);
+static boolean MAPI_mail_fetch(char *);
+static void MAPI_mail_finish(void);
+static int MAPI_mail_context(int *);
+static boolean MAPI_mail_init(char *);
+static int InitMAPI(void);
+static int DeInitMAPI(void);
+static void MAPI_mail_abort(unsigned long);
+
+/*
+ * Declare the function pointers used to access MAPI routines
+ * from the MAPI32.DLL
+ */
+LPMAPILOGON     fpMAPILogon;
+LPMAPILOGOFF    fpMAPILogoff;
+LPMAPIFINDNEXT  fpMAPIFindNext;
+LPMAPIREADMAIL  fpMAPIReadMail;
+LPMAPIFREEBUFFER fpMAPIFreeBuffer;
+
+
+/*
+ * Data requiring synchronized access between the
+ * two thread contexts contained in this file
+ * (nethack thread and the MAPI-mail thread)
+ */
+HANDLE mailthread = 0;          /* handle for the mail-thread       */
+unsigned nhmailthread_ID;       /* thread ID for mail-thread        */
+unsigned long nhmail_param;     /* value passed to mail-thread      */
+long mailthread_continue = 0;   /* nh -> mapi thread: shut down!    */
+long mailthread_stopping = 0;   /* mapi -> nh thread: MAPI is ill!  */
+
+/*
+ * Data updated by the NetHack thread only
+ * but read by the MAPI-mail thread.
+ *
+ */
+char MAPI_username[120];
+boolean debugmapi;
+
+/*
+ * Data updated by the MAPI-mail thread only
+ * but read by the NetHack thread.
+ */
+long mail_fetched = 0;
+
+/*
+ * Data used only by the MAPI-mail thread.
+ */
+long mailpasses;        /* counts the FindNext calls issued to MAPI */
+char msgID[80];         /* message ID of msg under manipulation     */
+
+/*===============================================================
+ * NetHack thread routines
+ *
+ * These routines run in the context of the main NetHack thread.
+ * They are used to provide an interface between the NetHack
+ * LAN_MAIL code and the MAPI-thread code.
+ *
+ * These routines are referenced by shared code in
+ * sys/share/nhlan.c and they are prototyped in include/extern.h
+ *===============================================================
+ */
+boolean mail_check()
+{
+       if (!mailthread_stopping) {
+               if (mail_fetched > 0)
+                       return TRUE;
+       } else lan_mail_terminate();
+       return FALSE;
+}
+
+
+boolean mail_fetch(msg)
+struct lan_mail_struct *msg;
+{
+       /* shouldn't need to check mailthread_stopping here
+          as the data should be valid anyway */
+       *msg = received_msg;
+       iflags.lan_mail_fetched = TRUE;
+       /* clear the marker now so new messages can arrive */
+       InterlockedDecrement(&mail_fetched);
+       /* check to see if the MAPI-mail thread is saying "stop" */
+       if (mailthread_stopping) lan_mail_terminate();
+       return TRUE;
+}
+
+void mail_finish()
+{
+       InterlockedDecrement(&mailthread_continue);
+}
+
+void mail_init(uname)
+char *uname;
+{
+  /* This routine invokes the _beginthreadex()
+   * run-time library call to start the execution
+   * of the MAPI-mail thread.  It also performs
+   * few other preparatory tasks.
+   */
+       if (mailthread_continue) {
+               /* Impossible - something is really messed up */
+               /* We better do some sanity checking */
+               /* Is there a valid thread handle and ID? */
+               if (mailthread && nhmailthread_ID) {
+                       /* TODO: check 'em via WIN32 call */
+                       /* if valid, do something about them */
+                       /* if not, clear them */
+               }
+       }
+       mailthread = 0;
+       nhmailthread_ID = 0;
+       mailthread_continue = 0;  /* no interlock needed yet */
+       mailthread_stopping = 0;  /* no interlock needed yet */
+#ifdef MAPI_VERBOSE
+       if (getenv("DEBUG_MAPI")) debugmapi = TRUE; 
+#endif
+       if (uname)
+               strcpy(MAPI_username, uname);
+       else {
+#ifdef MAPI_VERBOSE
+               if (debugmapi) dbgfile = fopen(MAPIDEBUGFILENAME,"w");
+               if (dbgfile) {
+                      fprintf(dbgfile,
+                             "mapi initialization bypassed because uname not available\n");
+                      fclose(dbgfile);
+               }
+#endif
+               return;
+       }
+       mailthread = (HANDLE)_beginthreadex(
+                       (void *)0,
+                       (unsigned)0,
+                       start_mailthread,
+                       (void *)&nhmail_param,
+                       (unsigned)0, (unsigned *)&nhmailthread_ID);
+#if 0
+       /* TODO: check for failure of the thread. For now nethack
+        *       doesn't care
+        */
+       if (!mailthread) {
+
+       }
+#endif
+}
+
+/*===============================================================
+ * MAPI-mail thread routines
+ *
+ * These routines run in the context of their own
+ * MAPI-mail thread.  They were placed into their own
+ * thread, because MAPI calls can sometimes (often?) take
+ * a horribly long time to return (minutes even).
+ *
+ * Each of the routines below are referenced only by other
+ * routines below, with the exception of start_mailthread(),
+ * of course, which is started by a run-time library call
+ * issued from the main NetHack thread.
+ *===============================================================
+ */
+
+/*
+ * start_mailthread() is the entry point of the MAPI-mail thread.
+ *
+ */
+
+static long __stdcall start_mailthread(LPVOID ThreadParam)
+{
+    char *lu = MAPI_username;
+    if(MAPI_mail_init(lu)) {
+       InterlockedIncrement(&mailthread_continue);
+       while (mailthread_continue) {
+               mailpasses++;
+               if (MAPI_mail_check(msgID)) {
+                       if (MAPI_mail_fetch(msgID)) {
+                               /* getting here means success */
+                       }
+               }
+               Sleep(MAILTHREADFREQ);
+       }
+#ifdef MAPI_VERBOSE
+       if (debugmapi && !mailthread_continue) {
+         fprintf(dbgfile,
+               "MAPI-thread detected mailthread_continue change.\n");
+         fprintf(dbgfile,
+               "NetHack has requested that the MAPI-thread cease.\n");
+       }
+#endif
+    }
+    return 0;
+}
+
+static int
+MAPI_mail_context(mcount)
+int *mcount;
+{
+       unsigned long status;
+       char tmpID[80];
+       int count = 0;
+
+       tmpID[0] = '\0';
+       MAPIMessageID[0] = '\0';
+
+       /* Get the ID of the first unread message */
+       status = fpMAPIFindNext(MAPISession, 0, 0, 0,
+               MAPI_UNREAD_ONLY | MAPI_GUARANTEE_FIFO,
+               0, tmpID);
+       /* Now loop through them all until we have no more */
+       while (status == SUCCESS_SUCCESS) {
+               strcpy(MAPIMessageID, tmpID);
+               count++;
+               status = fpMAPIFindNext(MAPISession, 0,
+                       0, MAPIMessageID,
+                       MAPI_UNREAD_ONLY | MAPI_GUARANTEE_FIFO,
+                       0, tmpID);
+       }
+       if (status == MAPI_E_NO_MESSAGES) {
+               /* context is now at last message */
+               if (mcount) *mcount = count;
+               return SUCCESS_SUCCESS;
+       }
+       return status;
+}
+
+static boolean
+MAPI_mail_check(mID)
+char *mID;
+{
+       unsigned long status;
+       char tmpID[80];
+
+       tmpID[0] = '\0';
+
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile, "MAPI_mail_check() ");
+#endif
+       if (mail_fetched) {
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile, "returning FALSE (buffer occupied)\n");
+#endif
+               return FALSE; /* buffer occupied, don't bother */
+       }
+       /* Get the ID of the next unread message if there is one */
+       status = fpMAPIFindNext(MAPISession, 0, 0, MAPIMessageID,
+               MAPI_UNREAD_ONLY | MAPI_GUARANTEE_FIFO,
+               0, tmpID);
+       if (status == SUCCESS_SUCCESS) {
+               strcpy(mID, tmpID);
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile, "returning TRUE\n");
+#endif
+               return TRUE;
+       }
+       if (status == MAPI_E_NO_MESSAGES) {
+#ifdef MAPI_VERBOSE
+               if (debugmapi) fprintf(dbgfile, "returning FALSE\n");
+#endif
+               return FALSE;
+       }
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile,"Error, check_newmail() status: %d\n", status);
+       MAPI_mail_abort(status);
+#endif
+       return FALSE;
+}
+
+static boolean
+MAPI_mail_fetch(mID)
+char *mID;
+{
+       unsigned long status;
+
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile, "MAPI_mail_fetch() ");
+#endif
+       /*
+        *  Update context right away so we don't loop if there
+        *  was a problem getting the message
+        */
+       strcpy(MAPIMessageID, mID);
+
+       if (mail_fetched) {
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile, "returning FALSE (buffer occupied)\n");
+#endif
+                return FALSE;  /* buffer occupied */
+       }
+
+       status = fpMAPIReadMail(MAPISession, 0, mID,
+                MAPI_SUPPRESS_ATTACH | MAPI_PEEK,
+                0, &MAPIMessage);
+       if (status == SUCCESS_SUCCESS) {
+               strncpy(received_msg.subject,
+                       MAPIMessage->lpszSubject,
+                       sizeof(received_msg.subject) - 1);
+               if((MAPIMessage->lpOriginator->lpszName != (char *)0)
+                && MAPIMessage->lpOriginator->lpszName[0] != '\0')
+                       strncpy(received_msg.sender,
+                               MAPIMessage->lpOriginator->lpszName,
+                               sizeof(received_msg.sender) - 1);
+               else
+                       strncpy(received_msg.sender,
+                               MAPIMessage->lpOriginator->lpszAddress,
+                               sizeof(received_msg.sender) - 1);
+               strncpy(received_msg.body,
+                       MAPIMessage->lpszNoteText,MAX_BODY_SIZE - 1);
+               received_msg.body[MAX_BODY_SIZE - 1] = '\0';
+               received_msg.body_in_ram = TRUE;
+               status = fpMAPIFreeBuffer(MAPIMessage);
+               InterlockedIncrement(&mail_fetched);
+#ifdef MAPI_VERBOSE
+               if (debugmapi) fprintf(dbgfile, "returning TRUE\n");
+#endif
+               return TRUE;
+       }
+#ifdef MAPI_VERBOSE
+       else
+               if (debugmapi) fprintf(dbgfile,"MAPIRead failed, status = %d\n", status);
+       if (debugmapi) fprintf(dbgfile, "returning FALSE (failed)\n");
+#endif
+       return FALSE;
+}
+
+static void
+MAPI_mail_finish()
+{
+       InterlockedIncrement(&mailthread_stopping);
+       (void) fpMAPILogoff(MAPISession,0,0,0);
+       (void) DeInitMAPI();
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fclose(dbgfile);
+#endif
+       (void) _endthreadex(0);
+}
+
+static void
+MAPI_mail_abort(reason)
+unsigned long reason;
+{
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile,
+               "Terminating MAPI-thread due to error %d.\n", reason);
+#endif
+       MAPI_mail_finish();
+}
+
+static boolean
+MAPI_mail_init(uname)
+char *uname;
+{
+       unsigned long status;
+       int count = 0;
+
+#ifdef MAPI_VERBOSE
+       if (debugmapi) dbgfile = fopen(MAPIDEBUGFILENAME,"w");
+       if (debugmapi) fprintf(dbgfile,"Hello %s, NetHack is initializing MAPI.\n",
+               uname);
+#endif
+       status = InitMAPI();
+       if (status) {
+#ifdef MAPI_VERBOSE
+           if (debugmapi) fprintf(dbgfile,"Error initializing MAPI %d\n", status);
+#endif
+           return FALSE;
+       }
+       status = fpMAPILogon(0,uname,0L,0L,0L,(LPLHANDLE)&MAPISession);
+       if (status != SUCCESS_SUCCESS) {
+#ifdef MAPI_VERBOSE
+           if (debugmapi) fprintf(dbgfile,"Status of MAPI logon is %d\n", status);
+#endif
+           return FALSE;
+       }
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile,
+               "Stage 1 of MAPI initialization successful.\n");
+       if (debugmapi) fprintf(dbgfile,"MAPI Session handle: %d\n", MAPISession);
+#endif
+       status = MAPI_mail_context(&count);
+       if (status == SUCCESS_SUCCESS) {
+#ifdef MAPI_VERBOSE
+           if (debugmapi) fprintf(dbgfile,
+                   "Stage 2 of MAPI initialization successful.\n");
+           if (debugmapi) fprintf(dbgfile,"Detected %d old unread messages.\n",
+                   count);
+#endif
+           return TRUE;
+       }
+#ifdef MAPI_VERBOSE
+       if (debugmapi) fprintf(dbgfile,
+               "Error, status of MAPI_mail_context() is %d.\n",
+               status);
+       if (debugmapi) fprintf(dbgfile,
+               "Dismantling MAPI interface and cleaning up.\n");
+#endif
+       MAPI_mail_finish();
+       return FALSE;
+}
+
+int InitMAPI()
+{
+
+    if (!(hLibrary = LoadLibrary("MAPI32.DLL")))
+      return MAPI_LIB_FAIL;
+
+    if ((fpMAPILogon = (LPMAPILOGON)GetProcAddress(hLibrary,"MAPILogon")) == NULL)
+      return MAPI_FUNC_FAIL;
+
+    if ((fpMAPILogoff = (LPMAPILOGOFF)GetProcAddress(hLibrary,"MAPILogoff")) == NULL)
+      return MAPI_FUNC_FAIL;
+
+    if ((fpMAPIFindNext= (LPMAPIFINDNEXT)GetProcAddress(hLibrary,"MAPIFindNext")) == NULL)
+      return MAPI_FUNC_FAIL;
+
+    if ((fpMAPIReadMail= (LPMAPIREADMAIL)GetProcAddress(hLibrary,"MAPIReadMail")) == NULL)
+      return MAPI_FUNC_FAIL;
+
+    if ((fpMAPIFindNext= (LPMAPIFINDNEXT)GetProcAddress(hLibrary,"MAPIFindNext")) == NULL)
+      return MAPI_FUNC_FAIL;
+
+    if ((fpMAPIFreeBuffer= (LPMAPIFREEBUFFER)GetProcAddress(hLibrary,"MAPIFreeBuffer")) == NULL)
+      return MAPI_FUNC_FAIL;
+
+#ifdef MAPI_VERBOSE
+    if (debugmapi) {
+       fprintf(dbgfile,"Entry Points:\n");
+       fprintf(dbgfile,"MAPILogon      = %p\n",fpMAPILogon);
+       fprintf(dbgfile,"MAPILogoff     = %p\n",fpMAPILogoff);
+       fprintf(dbgfile,"MAPIFindNext   = %p\n",fpMAPIFindNext);
+       fprintf(dbgfile,"MAPIFreeBuffer = %p\n",fpMAPIReadMail);
+       fprintf(dbgfile,"MAPIReadMail   = %p\n",fpMAPIFreeBuffer);
+    }
+#endif
+    return 0;
+}
+
+int DeInitMAPI()
+{
+
+    fpMAPILogon = NULL;
+    fpMAPILogoff= NULL;
+    fpMAPIFindNext= NULL;
+    fpMAPIReadMail= NULL;
+    fpMAPIFreeBuffer = NULL;
+    FreeLibrary(hLibrary);
+    return 0;
+}
+
+#endif /*LAN_MAIL*/
+