windows-afsifs-20050804
[openafs.git] / src / WINNT / afsd / afsdifs.c
index 0efedbe..4875ad5 100644 (file)
 /****************************/
 #define IFSL_SUCCEEDED(st)             (!(st & IFSL_FAIL_BASE))
 #define MAP_RETURN(code)               if (code) return ifs_MapCmError(code);
-                                       /* defined in multiple places (search source) */
-#define BUF_FILEHASH(fidp)             ((((fidp)->vnode+((fidp)->unique << 13) + ((fidp)->unique >> (32-13))   \
-                                                                                +(fidp)->volume+(fidp)->cell)                  \
-                                                                               /*& 0xffffffff*/))
 #define ROOTPATH                       "\\"
-#define TRANSFER_BUF_SIZE              (2*1024*1024)
+#define TRANSFER_BUF_SIZE              (RPC_BUF_SIZE + TRANSFER_CHUNK_SIZE)
 #define SCPL_LOCK                      EnterCriticalSection(&scp_list_lock);
 #define SCPL_UNLOCK                    LeaveCriticalSection(&scp_list_lock);
-#define MAX_USERS                      32
+
 
 /****************************/
 /* structs                  */
 /****************************/
-struct user_map_entry                  /* how we keep users straight.  total of MAX_USERS of these */
+struct user_map_entry                  /* how we keep users straight.  total of MAX_AFS_USERS of these */
 {
-    LARGE_INTEGER id;                  /* internal id created by kernel */
-    cm_user_t *creds;                  /* global (thread-specific) var userp is set to this */
+    LARGE_INTEGER id;                  /* internal id created by kernel */
+    cm_user_t *creds;                  /* global (thread-specific) var userp is set to this */
 };
 
-struct scp_status                      /* one for each unique file in afs */
+struct scp_status                              /* one for each unique file in afs */
 {
-    struct scp_status *next;           /* stored in a global chain in a chain locked by SCPL_[UN]LOCK */
-    cm_scache_t *scp;                  /* file handle used with cm_ fns */
-    ULONG fid;                         /* internal id generated by BUF_FILEHASH from AFS's 128-bit FID */
+    struct scp_status *next;   /* stored in a global chain in a chain locked by SCPL_[UN]LOCK */
+    cm_scache_t *scp;                  /* file handle used with cm_ fns */
+    ULONG fid;                                 /* internal id generated by FID_HASH_FN from AFS's 128-bit FID */
 };
 typedef struct scp_status scp_status_t;
 
@@ -77,11 +73,17 @@ typedef struct readdir_context readdir_context_t;
 /****************************/
 /* global vars              */
 /****************************/
+/* the table user_map is used to store cm_user structs keyed on the calling
+ * process' 64-bit ID token.  the rpc library sets userp to point to this
+ * entry; userp is specific to each thread, and thus may be used securely
+ * as a global.
+ */
 __declspec(thread) cm_user_t *userp;
-struct user_map_entry user_map[MAX_USERS];
+struct user_map_entry user_map[MAX_AFS_USERS];
 
 CRITICAL_SECTION mapLock, scp_list_lock;
 
+/* an event set by the controlling program to cause worker threads to terminate */
 extern HANDLE DoTerminate;
 
 scp_status_t *scp_list_head = NULL;
@@ -154,9 +156,9 @@ unsigned long ifs_MapCmError(unsigned long code)
         return IFSL_SUCCESS;
     case CM_ERROR_NOSUCHCELL:
     case CM_ERROR_NOSUCHVOLUME:
-    case CM_ERROR_NOSUCHFILE:          // x
+    case CM_ERROR_NOSUCHFILE:
         return IFSL_DOES_NOT_EXIST;
-    case CM_ERROR_NOSUCHPATH:          // x
+    case CM_ERROR_NOSUCHPATH:
         return IFSL_PATH_DOES_NOT_EXIST;
     case CM_ERROR_BADNTFILENAME:
         return IFSL_BADFILENAME;
@@ -180,7 +182,7 @@ unsigned long ifs_MapCmError(unsigned long code)
     case CM_ERROR_INVAL:
        case CM_ERROR_UNKNOWN:
     case CM_ERROR_BADSMB:
-        return IFSL_GENERIC_FAILURE;//TODO:? ERR - STATUS_NO_MORE_FILES;
+        return IFSL_GENERIC_FAILURE;
     case CM_ERROR_NOTDIR:
     case CM_ERROR_ISDIR:
     case CM_ERROR_READONLY:
@@ -217,7 +219,7 @@ unsigned long ifs_MapCmError(unsigned long code)
 /****************************/
 /* support fns              */
 /****************************/
-cm_scache_t *ifs_FindScp(ULONG fid)                    /* walk list to find scp<->fid mapping */
+cm_scache_t *ifs_FindScp(ULONG fid)            /* walk list to find scp<->fid mapping */
 {
     scp_status_t *curr;
 
@@ -265,13 +267,13 @@ ifs_CheckAcl(cm_scache_t *scp, ULONG access, ULONG *granted)
     return 0;
 }
 
-/* extract data from scp.  in ifs_ support function to centralize changes. */
+/* extract data from scp.  an ifs_ support function to centralize changes. */
 ifs_CopyInfo(cm_scache_t *scp, ULONG *attribs, LARGE_INTEGER *size,
               LARGE_INTEGER *creation, LARGE_INTEGER *access,
               LARGE_INTEGER *change, LARGE_INTEGER *written)
 {
-    access->QuadPart = 0;                              /* these mappings are not quite correct.  we have the */
-    change->QuadPart = scp->clientModTime;             /* right to leave them zero, if necessary. */
+    access->QuadPart = 0;                                              /* these mappings are not quite correct.  we can */
+    change->QuadPart = scp->clientModTime;             /* leave them zero, if necessary. */
     written->QuadPart = scp->clientModTime;
     creation->QuadPart = scp->serverModTime;
 
@@ -296,20 +298,21 @@ ifs_CopyInfo(cm_scache_t *scp, ULONG *attribs, LARGE_INTEGER *size,
 
 /* close and zero scp pointer.  zeroing pointer should
    help eliminate accessing discarded cache entries. */
-void ifs_InternalClose(cm_scache_t **scp)
+void ifs_InternalClose(cm_scache_t **scpp)
 {
-    osi_assert(scp && *scp);
-    lock_ObtainMutex(&((*scp)->mx));
-    cm_ReleaseSCache(*scp);
-    if ((*scp)->refCount == 0)                 /* we haven't held scache for external use yet */
-       cm_DiscardSCache(*scp);
-    lock_ReleaseMutex(&((*scp)->mx));
-    *scp = NULL;
+    osi_assert(scpp && *scpp);
+
+    lock_ObtainMutex(&((*scpp)->mx));
+    cm_ReleaseSCache(*scpp);
+
+    lock_ReleaseMutex(&((*scpp)->mx));
+    *scpp = NULL;
 }
 
 /* normalizes path by removing trailing slashes.  separates last
-   path component with a null, so that *dirp points to parent path
-   and *filep points to filename.  modifies string path. */
+ * path component with a null, so that *dirp points to parent path
+ * and *filep points to filename.  modifies string path.
+ */
 BOOLEAN ifs_FindComponents(char *path, const char **dirp, const char **filep)
 {
     char *lastSep;
@@ -361,7 +364,7 @@ unsigned long ifs_ConvertFileName(wchar_t *in, unsigned int inchars, char *out,
 }
 
 /* called by rpc_ library to let us initialize environment.
-   call with id of zero to clear current thread auth. */
+ * call with id of zero to clear current thread auth. */
 ifs_ImpersonateClient(LARGE_INTEGER user_id)
 {
     int x, empty;
@@ -374,7 +377,7 @@ ifs_ImpersonateClient(LARGE_INTEGER user_id)
 
     empty = -1;
     EnterCriticalSection(&mapLock);
-    for (x = 0; x < MAX_USERS; x++)
+    for (x = 0; x < MAX_AFS_USERS; x++)
     {
        if (user_map[x].id.QuadPart == 0)
             empty = x;
@@ -403,7 +406,7 @@ ifs_ImpersonateClient(LARGE_INTEGER user_id)
 /****************************/
 uc_namei(WCHAR *name, ULONG *fid)      /* performs name<->fid mapping, and enters it into table */
 {
-    char *buffer;                                      /* we support semi-infinite path lengths */
+    char *buffer;                              /* we support semi-infinite path lengths */
     long code;
     cm_scache_t *scp, *dscp;
     char *dirp, *filep;
@@ -441,15 +444,26 @@ uc_namei(WCHAR *name, ULONG *fid) /* performs name<->fid mapping, and enters it
        MAP_RETURN(code);
     }
 
-    SCPL_LOCK;
-    st = malloc(sizeof(scp_status_t));
-    st->scp = scp;
-    st->fid = BUF_FILEHASH(&scp->fid);
-    st->next = scp_list_head;
-    scp_list_head = st;
-    SCPL_UNLOCK;
+    if (ifs_FindScp(FID_HASH_FN(&scp->fid)))
+       {
+       osi_assertx(ifs_FindScp(FID_HASH_FN(&scp->fid)) == scp, "uc_namei: same fid hash for two files");
+       *fid = FID_HASH_FN(&scp->fid);
+       osi_assert(scp->refCount > 1);
+       cm_ReleaseSCache(scp);
+       }
+    else
+       {
+       SCPL_LOCK;
+       st = malloc(sizeof(scp_status_t));
+       st->scp = scp;
+       st->fid = FID_HASH_FN(&scp->fid);
+       st->next = scp_list_head;
+       scp_list_head = st;
+       SCPL_UNLOCK;
+       osi_assert(scp->refCount == 1);
+       *fid = st->fid;
+       }
 
-    *fid = st->fid;
     free(buffer);
 
     return 0;
@@ -488,13 +502,13 @@ uc_check_access(ULONG fid, ULONG access, ULONG *granted)
        afs_acc |= PRSFS_LOOKUP;
     if (access & FILE_READ_EA || access & FILE_READ_ATTRIBUTES)
        afs_acc |= PRSFS_LOOKUP;
-    if (file && (access & FILE_EXECUTE)) /* look at making this require write access */
+    if (file && (access & FILE_EXECUTE))
        afs_acc |= PRSFS_WRITE;
     if (dir && (access & FILE_TRAVERSE))
        afs_acc |= PRSFS_READ;
     if (dir && (access & FILE_DELETE_CHILD))
        afs_acc |= PRSFS_DELETE;
-    if (/*file && */(access & DELETE))
+    if ((access & DELETE))
        afs_acc |= PRSFS_DELETE;
 
     /* check ACL with server */
@@ -506,7 +520,7 @@ uc_check_access(ULONG fid, ULONG access, ULONG *granted)
     if (afs_gr & PRSFS_READ)
        *granted |= FILE_READ_DATA | FILE_EXECUTE;
     if (afs_gr & PRSFS_WRITE)
-       *granted |= FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE; // last one hack
+       *granted |= FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE;
     if (afs_gr & PRSFS_INSERT)
        *granted |= (dir ? FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY : 0) | (file ? FILE_ADD_SUBDIRECTORY : 0);
     if (afs_gr & PRSFS_LOOKUP)
@@ -568,13 +582,7 @@ uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *
                 code = cm_Lookup(dscp, filep, 0, userp, &req, &scp);
         }
        else
-        {
-            /* for debugging strange error */
-            /*if (!strcmp(filep+strlen(filep)-3, "478") ||
-            !strcmp(filep+strlen(filep)-3, "503"))
-            _asm int 3;*/
-            code = cm_Create(dscp, filep, 0, &attr, &scp, userp, &req);
-        }
+           code = cm_Create(dscp, filep, 0, &attr, &scp, userp, &req);
     }
     cm_ReleaseSCache(dscp);
 
@@ -587,7 +595,7 @@ uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *
     SCPL_LOCK;
     st = malloc(sizeof(scp_status_t));
     st->scp = scp;
-    st->fid = BUF_FILEHASH(&scp->fid);
+    st->fid = FID_HASH_FN(&scp->fid);
     st->next = scp_list_head;
     scp_list_head = st;
     SCPL_UNLOCK;
@@ -595,6 +603,8 @@ uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *
     *fid = st->fid;
     *granted = access;
 
+    free(buffer);
+
     return 0;
 }
 
@@ -636,7 +646,8 @@ uc_setinfo(ULONG fid, ULONG attribs, LARGE_INTEGER creation, LARGE_INTEGER acces
     return IFSL_GENERIC_FAILURE;
 }
 
-//FIX/quota errors
+/* FIXFIX: this code may not catch over-quota errors, because the end
+ * of the file is not written to the server by the time this returns. */
 /* truncate or extend file, in cache and on server */
 uc_trunc(ULONG fid, LARGE_INTEGER size)
 {
@@ -650,11 +661,9 @@ uc_trunc(ULONG fid, LARGE_INTEGER size)
     if (!scp)
        return IFSL_BAD_INPUT;
 
-    /*code = ifs_CheckAcl(scp, FILE_WRITE_DATA, &gr);
-    if (code)
-    return code;
-    if (!(gr & FILE_WRITE_DATA))
-    return IFSL_NO_ACCESS;*/
+    /* we have already checked permissions in the kernel; but, if we do not
+        * have access as this userp, code will fail in rpc layer.
+        */
 
     cm_InitReq(&req);
     lock_ObtainMutex(&(scp->mx));
@@ -676,7 +685,7 @@ uc_trunc(ULONG fid, LARGE_INTEGER size)
     MAP_RETURN(code);*/
 
 #if 0
-    /* attempt to write last byte of file.  fails to help because of delayed writing. */
+    /* attempt to write last byte of file.  fails to bring out quota errors because of delayed writing. */
     if (oldLen.QuadPart < size.QuadPart)
     {
        writePos.QuadPart = size.QuadPart - 1;
@@ -686,9 +695,6 @@ uc_trunc(ULONG fid, LARGE_INTEGER size)
             return IFSL_UNSPEC;
     }
 #endif
-    /*cm_SyncOp(scp, NULL, 
-    cm_Flush(*/
-    //MAP_RETURN(code);
 
     return 0;
 }
@@ -700,8 +706,6 @@ uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data)
     cm_scache_t *scp;
     cm_req_t req;
 
-    //_asm int 3;
-
     *read = 0;
  
     scp = ifs_FindScp(fid);
@@ -717,25 +721,19 @@ uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data)
     return 0;
 }
 
-//FIX/ handle quota errors properly
+/* FIXFIX: this does not catch all overquota errors, because the file
+ * is not necessarily written to the server when this returns. */
 /* write data to a file */
 uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *data)
 {
     ULONG code, gr;
     cm_scache_t *scp;
-    cm_req_t req;
 
     scp = ifs_FindScp(fid);
     if (!scp)
        return IFSL_BAD_INPUT;
 
-    /*code = ifs_CheckAcl(scp, FILE_WRITE_DATA, &gr);
-    if (code)
-    return code;
-    if (!(gr & FILE_WRITE_DATA))
-    return IFSL_NO_ACCESS;*/
-
-    if (offset.QuadPart == -1)                         // perhaps re-stat here?
+    if (offset.QuadPart == -1)
        offset = scp->length;
     code = WriteData(scp, offset, (unsigned long)length, data, userp, written);
     MAP_RETURN(code);
@@ -743,13 +741,10 @@ uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *da
     return 0;
 }
 
-//need downcall for new length
-
 uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fid)
 {
     int code;
     cm_req_t req;
-    //struct vnode *node;
     cm_attr_t attr;
     wchar_t *buf;
     char *curdir, *curfile, *newdir, *newfile;
@@ -770,11 +765,6 @@ uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fi
        ifs_FindComponents(b1, &curdir, &curfile);
        ifs_FindComponents(b2, &newdir, &newfile);
        newdir = b3;
-       /*lock_ReleaseMutex(&scp->mx);
-       cm_FSync(scp, userp, &req);
-       if (scp->refCount != 1)
-        _asm int 3;
-       ifs_InternalClose(&scp);*/
        uc_close(fid);
        code = cm_NameI(cm_data.rootSCachep, curdir, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH, userp, ROOTPATH, &req, &dscp1);
     }
@@ -790,30 +780,45 @@ uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fi
        if (!code)
         {
             code = cm_Rename(dscp1, curfile, dscp2, newfile, userp, &req);
-            //ifs_InternalClose(&dscp2);
-            //cm_InitReq(&req);
-            //code = cm_NameI(cm_rootSCachep, newdir, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH, userp, ROOTPATH, &req, &dscp2);
             if (!code)
             {
+                strcat(b3, "\\");
+                strcat(b3, b2);
+                uc_namei(b3, new_fid);
+            }
+            else
+            {
                 code = ifs_ConvertFileName(curr, -1, b1, MAX_PATH);
                 code = uc_namei(b1, new_fid);
-                //if (fid != fid2)
-                //     _asm int 3;
-                //code = cm_Lookup(dscp2, newfile, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, userp, &req, &node->scp);
             }
             ifs_InternalClose(&dscp2);
         }
        else
         {
-            //code = cm_Lookup(dscp1, curfile, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, userp, &req, &node->scp);
             code = ifs_ConvertFileName(curr, -1, b1, MAX_PATH);
             code = uc_namei(b1, new_fid);
-            //if (fid != fid2)
-            // _asm int 3;
         }
        ifs_InternalClose(&dscp1);
     }
 
+    MAP_RETURN(code);
+    return 0;
+}
+
+uc_flush(ULONG fid)
+{
+    ULONG code;
+    cm_scache_t *scp;
+    cm_req_t req;
+
+    scp = ifs_FindScp(fid);
+    if (!scp)
+       return IFSL_BAD_INPUT;
+
+    cm_InitReq(&req);
+    code = cm_FSync(scp, userp, &req);
+
+    MAP_RETURN(code);
     return 0;
 }
 
@@ -857,17 +862,15 @@ ifs_ReaddirCallback(cm_scache_t *scp, cm_dirEntry_t *entry, void *param, osi_hyp
     child_fid.vnode = ntohl(entry->fid.vnode);
     child_fid.unique = ntohl(entry->fid.unique);
     code = cm_GetSCache(&child_fid, &child_scp, userp, &req);
-    //code = cm_Lookup(scp, entry->name, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, userp, &req, &child_scp);
     if (code || !child_scp)
     {
        cm_ReleaseUser(userp);
        return 0;
     }
 
-    //if (child_scp->refCount == 1)
     {
        lock_ObtainMutex(&child_scp->mx);
-       code = cm_SyncOp(child_scp, NULL, userp, &req, 0, CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);                // do not need callback
+       code = cm_SyncOp(child_scp, NULL, userp, &req, 0, CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
        lock_ReleaseMutex(&child_scp->mx);
     }
 
@@ -878,9 +881,13 @@ ifs_ReaddirCallback(cm_scache_t *scp, cm_dirEntry_t *entry, void *param, osi_hyp
 
     lock_ObtainMutex(&(child_scp->mx));
     code = ifs_CopyInfo(child_scp, &info->attribs, &info->size, &info->creation, &info->access, &info->change, &info->write);
-    //ifs_CheckAcl(child_scp, FILE_WRITE_DATA, &gr);   /* perhaps add flag to not loop, to avoid network traffic if not found*/
-    //if (gr & FILE_READ_DATA && !(gr & FILE_WRITE_DATA))
-    // info->attribs |= FILE_ATTRIBUTE_READONLY;
+#if 0
+       /* make files we do not have write access to read-only */
+       /* this is a handy feature, but it takes a lot of time and traffic to enumerate */
+    ifs_CheckAcl(child_scp, FILE_WRITE_DATA, &gr);     /* perhaps add flag to not loop, to avoid network traffic if not found*/
+    if (gr & FILE_READ_DATA && !(gr & FILE_WRITE_DATA))
+       info->attribs |= FILE_ATTRIBUTE_READONLY;
+#endif
     lock_ReleaseMutex(&(child_scp->mx));
     ifs_InternalClose(&child_scp);
     MAP_RETURN(code);
@@ -932,28 +939,12 @@ uc_readdir(ULONG fid, LARGE_INTEGER cookie_in, WCHAR *filter, ULONG *count, char
     context.count = 0;
     *count = 0;
 
-    //restart:
-
     ((LARGE_INTEGER *)context.buf)->QuadPart = -1;
 
     code = cm_ApplyDir(scp, ifs_ReaddirCallback, &context, &cookie, userp, &req, NULL);
 
     context.buf_pos += sizeof(LARGE_INTEGER);
 
-    if (code != CM_ERROR_STOPNOW)
-       goto done;
-
-    //(*count)++;
-
-    if (code)
-       goto done;
-
-    //goto restart;
-
-    code = 0;
-
-  done:
-
     *count = context.count;
 
     cm_ReleaseUser(userp);
@@ -981,8 +972,6 @@ uc_close(ULONG fid)
 
     lock_ObtainMutex(&(scp->mx));
     cm_ReleaseSCache(scp);
-    if (!scp->refCount)
-       cm_DiscardSCache(scp);
     lock_ReleaseMutex(&(scp->mx));
  
     prev = NULL, curr = scp_list_head;
@@ -1023,16 +1012,16 @@ uc_unlink(WCHAR *name)
     MAP_RETURN(code);
     removed = ifs_FindComponents(buffer, &dirp, &filep);
 
+    if (!(*filep))
+       return IFSL_BADFILENAME;
+
     code = cm_NameI(cm_data.rootSCachep, dirp, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH, userp, ROOTPATH, &req, &dscp);
     MAP_RETURN(code);
-    if (*filep)
-    {
-       code = cm_Unlink(dscp, filep, userp, &req);
-       if (code)
-            code = cm_RemoveDir(dscp, filep, userp, &req);
-    }
-    else
-       ;               /* problem */
+
+    code = cm_Unlink(dscp, filep, userp, &req);
+    if (code)
+       code = cm_RemoveDir(dscp, filep, userp, &req);
+
     cm_ReleaseSCache(dscp);
     MAP_RETURN(code);
 
@@ -1081,10 +1070,9 @@ int ifs_Init(char **reason)
 {
     HANDLE kcom;
 
-    //_asm int 3;
     kcom = CreateFile("\\\\.\\afscom\\upcallhook", GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
-                       /*FILE_FLAG_OVERLAPPED*/0, NULL);
+                       0, NULL);
     if (kcom == INVALID_HANDLE_VALUE)
     {
        *reason = "error creating communications file";
@@ -1092,7 +1080,7 @@ int ifs_Init(char **reason)
     }
     CloseHandle(kcom);
 
-    memset(user_map, 0, 32*sizeof(struct user_map_entry));
+    memset(user_map, 0, MAX_AFS_USERS*sizeof(struct user_map_entry));
     InitializeCriticalSection(&mapLock);
     InitializeCriticalSection(&scp_list_lock);
 
@@ -1132,7 +1120,6 @@ DWORD WINAPI ifs_MainLoop(LPVOID param)
     unsigned char *bufIn, *bufOut;
     DWORD lenIn, lenOut, status;
     DWORD err;
-    OVERLAPPED olp;
     rpc_t rpc;
     BOOL st;
 
@@ -1142,49 +1129,48 @@ DWORD WINAPI ifs_MainLoop(LPVOID param)
     {
        if (bufIn) VirtualFree(bufIn, 0, MEM_RELEASE);
        if (bufOut) VirtualFree(bufOut, 0, MEM_RELEASE);
-       printf("could not allocate transfer bufs\n");
-       PostMessage(NULL, WM_CLOSE, 0, 0);
-       return 1;
+       osi_panic("ifs: allocate transfer buffers", __FILE__, __LINE__);
     }
 
-    //_asm int 3;
     pipe = CreateFile("\\\\.\\afscom\\upcallhook", GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
-                       /*FILE_FLAG_OVERLAPPED*/0, NULL);
+                       0, NULL);
     if (pipe == INVALID_HANDLE_VALUE)
     {
        VirtualFree(bufIn, 0, MEM_RELEASE);
        VirtualFree(bufOut, 0, MEM_RELEASE);
-       printf("error creating communications file\n");
-       PostMessage(NULL, WM_CLOSE, 0, 0);
-       return 1;
+       osi_panic("ifs: creating communications handle", __FILE__, __LINE__);
     }
 
-    //_asm int 3;
     while (1)
     {
+       /* just check if the event is already signalled, do not wait */
        if (WaitForSingleObject(DoTerminate, 0) == WAIT_OBJECT_0)
-            break;
+               break;
+
+       /* read request... */
        st = ReadFile(pipe, bufIn, TRANSFER_BUF_SIZE, &lenIn, NULL);
        if (!st)
-            if (GetLastError() == ERROR_INVALID_HANDLE)
-                break;
-            else
-                continue;
+       if (GetLastError() == ERROR_INVALID_HANDLE)
+               break;
+       else
+               continue;
 
        ZeroMemory(&rpc, sizeof(rpc));
        rpc.in_buf = rpc.in_pos = bufIn;
        rpc.out_buf = rpc.out_pos = bufOut;
 
+       /* ...process it... */
        rpc_parse(&rpc);
 
+       /* ...and write it back */
        st = WriteFile(pipe, rpc.out_buf, rpc.out_pos - rpc.out_buf, &written, NULL);
        if (!st)
-            if (GetLastError() == ERROR_INVALID_HANDLE)
-                break;
-            else
-                continue;
-    }       
+                       if (GetLastError() == ERROR_INVALID_HANDLE)
+                               break;
+                       else
+                               continue;
+       }
 
-    return 1;
+       return 1;
 }