windows-afsifs-20050804
authorEric Williams <ericjw@citi.umich.edu>
Thu, 4 Aug 2005 17:32:32 +0000 (17:32 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 4 Aug 2005 17:32:32 +0000 (17:32 +0000)
addresses:
byte-range locks work (mildly tested)
fixes a reference counting error
can shutdown/restart client
code formatting
major speed improvements
fixes delete operation problem
internal locking in more places

i have reviewed this patch myself carefully.  specifically, please review
the changes to cm_buf.c and cm_callback.c.  in cm_buf, i added the looping
code because i ran into the following assert once.  i am not sure why, and
my attempt to diagnose the problem was not successful.

apart from the byte-range locking code, the code has not change for quite
a bit.

15 files changed:
src/WINNT/afsd/afsd.c
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/afsdifs.c
src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsrdr/afsrdr.c
src/WINNT/afsrdr/afsrdr.h
src/WINNT/afsrdr/afsrdr.rc [new file with mode: 0644]
src/WINNT/afsrdr/ifs_rpc.c
src/WINNT/afsrdr/ifs_rpc.h
src/WINNT/afsrdr/kif.h
src/WINNT/afsrdr/sources
src/WINNT/install/NSIS/OpenAFS.nsi

index 7acd6aa..f977c22 100644 (file)
@@ -276,11 +276,10 @@ LONG APIENTRY MainWndProc(
                break;
 
            case WM_DESTROY:
-#ifndef AFSIFS
-               RpcMgmtStopServerListening(NULL);
-#else
+#ifdef AFSIFS
                SetEvent(DoTerminate);
 #endif
+               RpcMgmtStopServerListening(NULL);
                PostQuitMessage(0);
                break;
 
index fedc01f..51e92ae 100644 (file)
@@ -70,6 +70,9 @@ HANDLE hAFSDMainThread = NULL;
 HANDLE hAFSDWorkerThread[WORKER_THREADS];
 #endif
 
+/* for the IFS version, set the event DoTerminate, on which all
+   worker threads wait.  they will exit, and then everything else
+   can uninitialize. */
 HANDLE WaitToTerminate, DoTerminate;
 
 int GlobalStatus;
@@ -475,7 +478,7 @@ static void MountGlobalDrives(void)
             dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
         }
 #else
-       /* FIXFIX */
+       /* FIXFIX: implement */
 #endif
     }        
 
@@ -522,7 +525,7 @@ static void DismountGlobalDrives()
         afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
     }        
 #else
-       /* FIXFIX */
+       /* FIXFIX: implement */
 #endif
 
     RegCloseKey(hKey);
@@ -1165,6 +1168,14 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         ServiceStatus.dwWaitHint = 0;
         ServiceStatus.dwControlsAccepted = 0;
         SetServiceStatus(StatusHandle, &ServiceStatus);
+
+               {       
+               HANDLE h; char *ptbuf[1];
+               h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+               ptbuf[0] = "Incorrect module versions loaded";
+               ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, ptbuf, NULL);
+               DeregisterEventSource(h);
+               }
                        
         /* exit if initialization failed */
         return;
@@ -1267,6 +1278,9 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
 
+/* the following ifdef chooses the mode of operation for the service.  to enable
+ * a runtime flag (instead of compile-time), pioctl() would need to dynamically
+ * determine the mode, in order to use the correct ioctl special-file path. */
 #ifndef AFSIFS
         code = afsd_InitSMB(&reason, MessageBox);
         if (code != 0) {
@@ -1422,8 +1436,10 @@ afsd_Main(DWORD argc, LPTSTR *argv)
     rx_Finalize();                       
     afsi_log("rx finalization complete");
                                          
-    smb_Shutdown();                      
+#ifndef AFSIFS
+       smb_Shutdown();                      
     afsi_log("smb shutdown complete");   
+#endif
                                          
     RpcShutdown();                       
 
@@ -1509,6 +1525,7 @@ main(int argc, char * argv[])
             SetEvent(WaitToTerminate);
 #else
             SetEvent(DoTerminate);
+                       dc_release_hooks();
 #endif
         }
     }
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;
 }
index 98b63f8..b835f3b 100644 (file)
@@ -685,6 +685,14 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
             }
         }
 
+       /* does this fix the problem below?  it's a simple solution. */
+       if (!cm_data.buf_freeListEndp)
+           {
+           lock_ReleaseWrite(&buf_globalLock);
+           Sleep(200);
+           goto retry;
+           }
+
         /* for debugging, assert free list isn't empty, although we
          * really should try waiting for a running tranasction to finish
          * instead of this; or better, we should have a transaction
index 3076ed8..5e22237 100644 (file)
@@ -27,6 +27,7 @@
 #include "afsd.h"
 #include <WINNT/syscfg.h>
 #include <WINNT/afsreg.h>
+#include <../afsrdr/kif.h>
 
 /*extern void afsi_log(char *pattern, ...);*/
 
@@ -91,12 +92,6 @@ void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
     lock_ReleaseWrite(&cm_callbackLock);
 }
 
-#ifdef AFSIFS
-#define BUF_FILEHASH(fidp)     ((((fidp)->vnode+((fidp)->unique << 13) + ((fidp)->unique >> (32-13))   \
-                                    +(fidp)->volume+(fidp)->cell)                      \
-                                   /*& 0xffffffff*/))
-#endif
-
 /*
  * When we lose a callback, may have to send change notification replies.
  * Do not call with a lock on the scp.
@@ -107,7 +102,8 @@ void cm_CallbackNotifyChange(cm_scache_t *scp)
     HKEY  hKey;
     DWORD dummyLen;
 
-    if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+    /* why does this have to query the registry each time? */
+       if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
                       AFSREG_CLT_OPENAFS_SUBKEY,
                       0,
                       KEY_READ|KEY_QUERY_VALUE,
@@ -128,16 +124,18 @@ void cm_CallbackNotifyChange(cm_scache_t *scp)
     if (dwDelay)
         Sleep(dwDelay);
 
-    if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+    /* for directories, this sends a change notification on the dir itself */
+       if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
 #ifndef AFSIFS
         if (scp->flags & CM_SCACHEFLAG_ANYWATCH)
             smb_NotifyChange(0,
                              FILE_NOTIFY_GENERIC_DIRECTORY_FILTER,
                              scp, NULL, NULL, TRUE);
 #else
-        dc_break_callback(BUF_FILEHASH(&scp->fid));
+        dc_break_callback(FID_HASH_FN(&scp->fid));
 #endif
     } else {
+       /* and for files, this sends a change notification on the file's parent dir */
         cm_fid_t tfid;
         cm_scache_t *dscp;
 
@@ -154,7 +152,7 @@ void cm_CallbackNotifyChange(cm_scache_t *scp)
                               dscp,   NULL, NULL, TRUE);
 #else
         if (dscp)
-            dc_break_callback(BUF_FILEHASH(&dscp->fid));
+            dc_break_callback(FID_HASH_FN(&dscp->fid));
 #endif
         if (dscp) 
             cm_ReleaseSCache(dscp);
index 1d09f9c..1789304 100644 (file)
@@ -145,8 +145,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
 {
     long code, length;
     cm_scache_t *substRootp;
-    char * relativePath = ioctlp->inDatap, absRoot[100];
-       wchar_t absRoot_w[100];
+    char * relativePath = ioctlp->inDatap, absRoot[MAX_PATH];
+       wchar_t absRoot_w[MAX_PATH];
        HANDLE rootDir;
 
     /* This is usually the file name, but for StatMountPoint it is the path. */
@@ -159,32 +159,13 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
     TranslateExtendedChars(relativePath);
 
 #ifdef AFSIFS
-    /* we have passed the whole path, including the afs prefix (pioctl_nt.c modified) */
-#if 0
-    /*_asm int 3; */
-    sprintf(absRoot, "%c:", relativePath[0]);
-    rootDir = CreateFile(absRoot, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
-
-    if (!DeviceIoControl(rootDir, IOCTL_AFSRDR_GET_PATH, NULL, 0, absRoot_w, 100*sizeof(wchar_t), &length, NULL))
-    {
-    CloseHandle(rootDir);
-    return CM_ERROR_NOSUCHPATH;
-    }
-    CloseHandle(rootDir);
-
-    ifs_ConvertFileName(absRoot_w, length/sizeof(wchar_t), absRoot, 100);
-#endif
-#if 0
-    switch (relativePath[0])                                   /* FIXFIX */
-    {
-    case 'y':
-    case 'Y':
-        absRoot = "\\ericjw\\test";                    /* should use drivemap */
-    }
-#endif
+    /* we have passed the whole path, including the afs prefix.
+          when the pioctl call is made, we perform an ioctl to afsrdr
+          and it returns the correct (full) path.  therefore, there is
+          no drive letter, and the path is absolute. */
     code = cm_NameI(cm_data.rootSCachep, relativePath,
                      CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
-                     userp, ""/*absRoot*//*ioctlp->tidPathp*/, reqp, scpp);
+                     userp, "", reqp, scpp);
 
     if (code)
         return code;
@@ -213,7 +194,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
          * since it had better expand into the value of ioctl->tidPathp
          */
         char * p;
-        p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
+        p = relativePath + 2 + strlen(cm_NetbiosName) + 1;                     /* buffer overflow vuln.? */
         if ( !_strnicmp("all", p, 3) )
             p += 4;
 
@@ -1833,7 +1814,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
         uname = tp;
         tp += strlen(tp) + 1;
 
-#ifndef AFSIFS                 /* no SMB username */
+#ifndef AFSIFS                 /* no SMB username, so we cannot log based on this */
         if (flags & PIOCTL_LOGON) {
             /* SMB user name with which to associate tokens */
             smbname = tp;
index 7162e77..669e37e 100644 (file)
@@ -546,7 +546,10 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
             }
 
 #ifdef AFSIFS
-            /* Why was this added for IFS? - jaltman 06/18/2006 */
+                       /* for the IFS version, we bulkstat the dirents because this
+                          routine is used in place of smb_ReceiveCoreSearchDir.  our
+                          other option is to modify smb_ReceiveCoreSearchDir itself, 
+                          but this seems to be the proper use for cm_ApplyDir. */
             lock_ObtainMutex(&scp->mx);
             if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0
                  && (scp->bulkStatProgress.QuadPart <= thyper.QuadPart))
index bc00ec5..03b42d2 100644 (file)
@@ -68,9 +68,10 @@ struct afs_fcb
     ERESOURCE _resource;               /* pointed to by fcb_header->Resource */
     ERESOURCE _pagingIoResource;
     unsigned long fid;                 /* a courtesy from the userland daemon (a good hash function) */
-    UCHAR delPending;                  /* 3 types: FIX */
+    UCHAR delPending;
     struct afs_ccb *ccb_list;          /* list of open instances */
     SHARE_ACCESS share_access;         /* common access control */
+    PFILE_LOCK lock;
 };
 typedef struct afs_fcb afs_fcb_t;
 
@@ -136,7 +137,7 @@ struct ComExtension *comExt;
                COMPLETE; \
                return st; \
                }
-#define SYNC_FAIL_RPC_TIMEOUT  SYNC_FAIL(STATUS_NETWORK_BUSY)
+#define SYNC_FAIL_RPC_TIMEOUT          SYNC_FAIL(STATUS_NETWORK_BUSY)
 
 #define LOCK_FCB_LIST                  FsRtlEnterFileSystem(); ExAcquireFastMutex(&rdrExt->fcbLock);
 #define UNLOCK_FCB_LIST                        ExReleaseFastMutex(&rdrExt->fcbLock); FsRtlExitFileSystem();
@@ -158,9 +159,8 @@ struct ComExtension *comExt;
 #define COMM_DOWNCALL                  (void*)0x02
 #define COMM_UPCALLHOOK                        (void*)0x03
 
-/*#define ACC_READ                     (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_LIST_DIRECTORY
-#define ACC_WRITE                      (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA)*
-
+/* flag to use caching kernel service.  needs to handle cache invalidation in more places.  */
+#define EXPLICIT_CACHING
 
 /* dates from afs are time_t style -- seconds since 1970 */            /* 11644505691.6384 */
 #define AfsTimeToWindowsTime(x)                (((x)+11644505692L)*10000000L)  /*(1970L-1601L)*365.242199*24L*3600L)*/
@@ -246,12 +246,12 @@ afs_fcb_t *find_fcb(ULONG fid)
 NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *_fcb)
 {
     afs_fcb_t *pfcb, *fcb, **fcbp;
-    afs_ccb_t *ccb, *pccb;
+    afs_ccb_t *ccb, *pccb, *curr_ccb;
     ULONG len;
     LONG x, y;
     wchar_t *str, *ptr;
     ULONG fid, access, granted, disp;
-    LARGE_INTEGER size, creation, accesst, change, written, zero;
+    LARGE_INTEGER size, creation, accesst, change, written, zero, wait;
     ULONG attribs;
     ULONG share;
     CC_FILE_SIZES sizes;
@@ -262,7 +262,10 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     /* set rpc security context for current thread */
     acc_token = SeQuerySubjectContextToken(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
     ASSERT(acc_token);
-    rpc_set_context(acc_token);
+
+    wait.QuadPart = -1000;
+    while (rpc_set_context(acc_token) != 0)                            /* if there are no open thread spots... */
+        KeDelayExecutionThread(KernelMode, FALSE, &wait);              /* ...wait */
 
     /* attempt to open afs volume directly */
     if (IrpSp->FileObject->FileName.Length == 0)
@@ -339,7 +342,8 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     size.QuadPart = 0;
     created = 0;
 
-    /* check for file existance.  we jump to creating it if needed */ 
+  open:
+       /* check for file existance.  we jump to creating it if needed */ 
     if (disp == FILE_OPEN || disp == FILE_OPEN_IF || disp == FILE_OVERWRITE ||
          disp == FILE_OVERWRITE_IF || disp == FILE_SUPERSEDE)
     {
@@ -418,9 +422,9 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
         }
 
        /* check for previous open instance(s) of file.  it will be in the fcb chain.
-         * when we have this locked, we cannot make upcalls -- running at APC_LEVEL.
+        * when we have this locked, we cannot make upcalls -- running at APC_LEVEL.
         * lock here (not later) to prevent possible truncation races. 
-         */
+        */
        LOCK_FCB_LIST;
        fcb = find_fcb(fid);
        if (fcb)
@@ -507,7 +511,16 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
                 if (fcb)
                 {
                     fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
-                    CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
+                   curr_ccb = fcb->ccb_list;
+                   while (curr_ccb && curr_ccb->fo)
+                       {
+                       if (CcIsFileCached(curr_ccb->fo))
+                           {
+                           CcSetFileSizes(curr_ccb->fo, (CC_FILE_SIZES*)&fcb->AllocationSize);
+                           break;
+                           }
+                       curr_ccb = curr_ccb->next;
+                       }
                 }
             }
             if (Irp->Overlay.AllocationSize.QuadPart)
@@ -525,7 +538,16 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
                 if (fcb)
                 {
                     fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
-                    CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
+                   curr_ccb = fcb->ccb_list;
+                   while (curr_ccb && curr_ccb->fo)
+                       {
+                       if (CcIsFileCached(curr_ccb->fo))
+                           {
+                           CcSetFileSizes(curr_ccb->fo, (CC_FILE_SIZES*)&fcb->AllocationSize);
+                           break;
+                           }
+                       curr_ccb = curr_ccb->next;
+                       }
                 }
             }
         }
@@ -573,8 +595,18 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
          */
        LOCK_FCB_LIST;
        fcb = find_fcb(fid);
-       if (fcb)
-            _asm int 3;
+       if (fcb)                                /* none of these should happen */
+               if (disp == FILE_CREATE)
+                       {
+                       UNLOCK_FCB_LIST;
+                       SYNC_FAIL2(STATUS_OBJECT_NAME_COLLISION, FILE_EXISTS);
+                       }
+               else
+                       {
+                       fcb = NULL;
+                       UNLOCK_FCB_LIST;
+                       goto open;
+                       }
 
        if (size.QuadPart != 0)
         {
@@ -606,7 +638,6 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     /* OS passed unexpected disposition */
     ExFreePoolWithTag(str, AFS_RDR_TAG);
     SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
-     /*SYNC_FAIL2(STATUS_OBJECT_NAME_NOT_FOUND, FILE_DOES_NOT_EXIST);*/
 
 
     /* allocate nonpaged struct to track this file and all open instances */
@@ -618,7 +649,7 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     fcb->fid = fid;
     /*fcb->refs = 0;*/
     fcb->ccb_list = NULL;
-    fcb->IsFastIoPossible = FastIoIsNotPossible;
+    fcb->IsFastIoPossible = FastIoIsPossible;
 
     ExInitializeResourceLite(&fcb->_resource);
     ExInitializeResourceLite(&fcb->_pagingIoResource);
@@ -633,6 +664,7 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
 
     IoSetShareAccess(access, share, IrpSp->FileObject, &fcb->share_access);
+    fcb->lock = NULL;
 
     /* we store a pointer to the fcb.  the table would want to store a copy otherwise. */
     fcbp = &fcb;
@@ -666,7 +698,6 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     ccb->token = acc_token;    
     /*ObOpenObjectByPointer(acc_token, OBJ_KERNEL_HANDLE, NULL, TOKEN_QUERY, NULL, KernelMode, &ccb->token);*/
 
-    /*fcb->refs++;*/
     if (!fcb->ccb_list)
     {
         ccb->next = NULL;
@@ -681,25 +712,15 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     UNLOCK_PAGING_FCB;
     UNLOCK_FCB_LIST;
 
-    /* how we pack (as it is expected): a) fscontext same for all open instances of a file,
-     * b) fscontext2 unique among each instance, c) private cache map pointer set by cache
-     * manager upon caching, d) so pointers are per-file, as in (a). 
+    /* how we pack (what the cache manager needs): a) fscontext same for all open instances
+     * of a file, b) fscontext2 unique among each instance, c) private cache map pointer set
+     * by cache manager upon caching, d) so pointers are per-file, as in (a). 
      */
     IrpSp->FileObject->FsContext = fcb;
     IrpSp->FileObject->FsContext2 = ccb;
     IrpSp->FileObject->PrivateCacheMap = NULL;
     IrpSp->FileObject->SectionObjectPointer = &(fcb->sectionPtrs);
 
-    /* explicitly start caching on a data file.  caching will still happen upon
-     * paging i/o even if commented out below.  the other option is to cache upon
-     * the first read/write operation.  that code is also in place. 
-     */
-    if (!(attribs & FILE_ATTRIBUTE_DIRECTORY))
-    {
-        /*CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);*/
-        /*CcSetAdditionalCacheAttributes(IrpSp->FileObject, TRUE, TRUE);*/
-    }
-
     /* customize returns; semantics largely derived from output of ifstest.exe */
     switch (disp)
     {
@@ -730,14 +751,9 @@ NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *
     case FILE_CREATE:
         SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED);
     }
-    _asm int 3;
     return 0;
 }
 
-/* experimental; does not work.  need to handle filesizes
- * and cache invalidation in more places. 
- */
-#define EXPLICIT_CACHING
 
 /**********************************************************
  * AfsRdrRead
@@ -759,15 +775,17 @@ NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *Ir
     if (IsDeviceFile(IrpSp->FileObject) || (ccb->attribs & FILE_ATTRIBUTE_DIRECTORY))
        SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
 
-/* the second line disables read ahead and write behind.  since our data is
-   already cached in userland, and there are read-ahead parameters there,
-   we do not use this service. */
+/* the second line enables read ahead and disables write behind.  since our data is
+ * already cached in userland, and there are read-ahead parameters there, these are
+ * not strictly necessary for decent performance.  also, writes-behind may happen on
+ * handles that do not have write access, because the i/o manager picks some handle,
+ * not necessarily the same one that writing was originally done with. */
 #ifdef EXPLICIT_CACHING
     if (!IrpSp->FileObject->PrivateCacheMap)
     {
         CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);
         CcSetAdditionalCacheAttributes(IrpSp->FileObject, FALSE, TRUE);
-        //CcSetReadAheadGranularity
+        /* could do a call to CcSetReadAheadGranularity here */
     }
 #endif
 
@@ -780,20 +798,39 @@ NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *Ir
     offset = IrpSp->Parameters.Read.ByteOffset;
     length = IrpSp->Parameters.Read.Length;
 
-    /* FIX: lock here, before finding end-of-file */
+    FsRtlEnterFileSystem();
+    SLOCK_FCB;
+    if (!(Irp->Flags & IRP_PAGING_IO) && fcb->lock)
+       {
+       if (!FsRtlCheckLockForReadAccess(fcb->lock, Irp))
+           {
+           UNLOCK_FCB;
+           FsRtlExitFileSystem();
+           SYNC_FAIL(STATUS_FILE_LOCK_CONFLICT);
+           }
+       }
 
     /* fast out for reads starting beyond eof */
     if (offset.QuadPart > fcb->ValidDataLength.QuadPart)
+       {
+       UNLOCK_FCB;
+       FsRtlExitFileSystem();
        SYNC_FAIL(STATUS_END_OF_FILE);
+       }
+
     /* pre-truncate reads */
     if (offset.QuadPart + length > fcb->ValidDataLength.QuadPart)
-       length = (ULONG)(fcb->ValidDataLength.QuadPart - offset.QuadPart);
+       length = (ULONG)(fcb->ValidDataLength.QuadPart - offset.QuadPart);
+    UNLOCK_FCB;
+    FsRtlExitFileSystem();
 
     outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
     if (!outPtr)
        SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
 
 #ifdef EXPLICIT_CACHING
+       /* this block is used only when a) caching functionality is compiled in, 
+        * b) this is not a paging i/o request, and c) this is not a no_cache req. */
     if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO)))
     {
        FsRtlEnterFileSystem();
@@ -807,13 +844,15 @@ NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *Ir
                 FsRtlExitFileSystem();
                 SYNC_FAIL(STATUS_UNSUCCESSFUL);
             }
-            // KdPrint(("read  %x at %x cache done %x\n", length, (ULONG)offset.QuadPart, Irp->IoStatus.Information));
             ttlread = Irp->IoStatus.Information;
         }
        except (EXCEPTION_EXECUTE_HANDLER)
         {
             STATUS(STATUS_UNSUCCESSFUL, 0);
         }
+       /* update byteoffset when this is not a paging or async request */
+       if (Irp->IoStatus.Status != STATUS_UNSUCCESSFUL && IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
+           IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlread;
        UNLOCK_PAGING_FCB;
        FsRtlExitFileSystem();
        if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL)
@@ -830,8 +869,8 @@ NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *Ir
             toread = (toread > TRANSFER_CHUNK_SIZE) ? TRANSFER_CHUNK_SIZE : toread;
             curroff.QuadPart = offset.QuadPart + currpos;
             status = uc_read(fcb->fid, curroff, toread, &read, outPtr);
-            // KdPrint(("read  %x at %x done %x\n", length, (ULONG)offset.QuadPart, read));
-            if (status == 0)
+
+           if (status == 0)
             {
                 ttlread += read;
                 currpos += read;
@@ -850,15 +889,14 @@ NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *Ir
             }
         }
       end:
+       /* update byteoffset when this is not a paging or async request */
+       if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
+           IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlread;
        UNLOCK_FCB;
        FsRtlExitFileSystem();
     }
 
-    /* update byteoffset when this is not a paging or async request */
-    if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
-        IrpSp->FileObject->CurrentByteOffset.QuadPart += ttlread;
-
-    if (ttlread == 0 /* was < length*/) {
+    if (ttlread == 0) {
        SYNC_FAIL2(STATUS_END_OF_FILE, ttlread);
     } else {
         SYNC_FAIL2(STATUS_SUCCESS, ttlread);
@@ -888,7 +926,7 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
     if (IsDeviceFile(IrpSp->FileObject) || (ccb->attribs & FILE_ATTRIBUTE_DIRECTORY))
        SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
 
-    /* since we will be performing io on this instance, start caching. */
+    /* since we will be performing io on this instance, start caching (see above). */
 #ifdef EXPLICIT_CACHING
     if (!IrpSp->FileObject->PrivateCacheMap)
     {
@@ -904,21 +942,34 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
     if (!IrpSp->Parameters.Write.Length)
        SYNC_FAIL(STATUS_SUCCESS);
 
+    if (!(outPtr = AfsFindBuffer(Irp)))
+       SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
+
+    FsRtlEnterFileSystem();
+    SLOCK_FCB;
+
+    if (!(Irp->Flags & IRP_PAGING_IO) && fcb->lock)
+       {
+       if (!FsRtlCheckLockForWriteAccess(fcb->lock, Irp))
+           {
+           UNLOCK_FCB;
+           FsRtlExitFileSystem();
+           SYNC_FAIL(STATUS_FILE_LOCK_CONFLICT);
+           }
+       }
+
     if (IrpSp->Parameters.Write.ByteOffset.HighPart == 0xffffffff &&
          IrpSp->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE)
        offset.QuadPart = fcb->FileSize.QuadPart;
     else
        offset = IrpSp->Parameters.Write.ByteOffset;
     length = IrpSp->Parameters.Write.Length;
-
-    if (!(outPtr = AfsFindBuffer(Irp)))
-       SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
+    UNLOCK_FCB;
 
 #ifdef EXPLICIT_CACHING
     if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO)))
     {
        /* extend file for cached writes */
-       FsRtlEnterFileSystem();
        LOCK_PAGING_FCB;
        if (offset.QuadPart + length > fcb->FileSize.QuadPart)
         {
@@ -932,23 +983,28 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
        try
         {
             if (!CcCopyWrite(IrpSp->FileObject, &offset, length, TRUE, outPtr))
+               {
+               UNLOCK_PAGING_FCB;
+               FsRtlExitFileSystem();
                 SYNC_FAIL(STATUS_UNSUCCESSFUL);
+               }
         }
        except (EXCEPTION_EXECUTE_HANDLER)
         {
             STATUS(STATUS_UNSUCCESSFUL, 0);
         }
-        // KdPrint(("write %x at %x cache done\n", length, (ULONG)offset.QuadPart));
+
+       ttlwritten = written = length;
+       if (Irp->IoStatus.Status != STATUS_UNSUCCESSFUL && IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
+           IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlwritten;
        UNLOCK_PAGING_FCB;
        FsRtlExitFileSystem();
-       ttlwritten = written = length;
        if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL)
             SYNC_FAIL(STATUS_UNSUCCESSFUL);
     }
     else
 #endif
     {
-       FsRtlEnterFileSystem();
        while (1)
         {
             if (offset.QuadPart + length > fcb->FileSize.QuadPart)
@@ -962,39 +1018,26 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
             if (paging_lock)
                 LOCK_PAGING_FCB;
             LOCK_FCB;
-            if (offset.QuadPart + length > fcb->FileSize.QuadPart)
+            if (change)
             {
                 if (Irp->Flags & IRP_PAGING_IO)
                 {
                     /* the input buffer and length is for a full page.  ignore this. */
                     if (offset.QuadPart > fcb->FileSize.QuadPart)
                     {
-                        if (paging_lock)
-                        {
-                            _asm int 3;
-                            UNLOCK_PAGING_FCB;
-                        }
+                       /* paging lock cannot be held here, so no need to release */
                         UNLOCK_FCB;
                         FsRtlExitFileSystem();
                         SYNC_FAIL2(STATUS_SUCCESS, length);
                     }
                     length = (ULONG)(fcb->FileSize.QuadPart - offset.QuadPart);
-                    if (paging_lock)
-                    {
-                        _asm int 3;
-                        UNLOCK_PAGING_FCB;
-                    }
                     break;
                 }
                 else
                 {
                     if (!change)
                     {
-                        if (paging_lock)
-                        {
-                            _asm int 3;
-                            UNLOCK_PAGING_FCB;
-                        }
+                       /* paging lock cannot be held here, so no need to release */
                         UNLOCK_FCB;
                         continue;
                     }
@@ -1008,7 +1051,6 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
             }
             else
             {
-                //UNLOCK_FCB;
                 if (paging_lock)
                     UNLOCK_PAGING_FCB;
                 break;
@@ -1021,7 +1063,6 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
             towrite = (towrite > TRANSFER_CHUNK_SIZE) ? TRANSFER_CHUNK_SIZE : towrite;
             curroff.QuadPart = offset.QuadPart + currpos;
             status = uc_write(fcb->fid, curroff, towrite, &written, outPtr);
-            // KdPrint(("write %x at %x done\n", length, (ULONG)offset.QuadPart));
             if (status == 0)
             {
                 ttlwritten += written;
@@ -1041,16 +1082,14 @@ NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
             }
         }
       end:
+       if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
+           IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlwritten;
        UNLOCK_FCB;
        FsRtlExitFileSystem();
     }
 
-    if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
-       IrpSp->FileObject->CurrentByteOffset.QuadPart += ttlwritten;
-
     /* if we failed a write, we would not be here.  so, we must
-     * tell the vmm that all data was written. 
-     */
+     * tell the vmm that all data was written. */
     if (Irp->Flags & IRP_PAGING_IO)
        SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.Write.Length);
     SYNC_FAIL2(STATUS_SUCCESS, ttlwritten);
@@ -1096,7 +1135,7 @@ NTSTATUS AfsRdrDirCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
        ccb->str.Buffer =                       ccb->name;
 
        FsRtlEnterFileSystem();
-       LOCK_FCB;                               /* FIX: shared lock? */
+       LOCK_FCB;
        FsRtlNotifyFullChangeDirectory(rdrExt->notifyList, &rdrExt->listHead,
                                         ccb,
                                         (STRING*)&ccb->str,
@@ -1117,7 +1156,6 @@ NTSTATUS AfsRdrDirCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
          IrpSp->Parameters.QueryDirectory.FileInformationClass != FileDirectoryInformation &&
          IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation)
     {
-       _asm int 3;
        rpt0(("enum", "enum class %d not supported", IrpSp->Parameters.QueryDirectory.FileInformationClass));
        SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
     }
@@ -1142,10 +1180,15 @@ NTSTATUS AfsRdrDirCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
        ccb->cookie.QuadPart = 0;
        if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
             ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
-       buf_size = IrpSp->Parameters.QueryDirectory.FileName->Length+6;
-       ccb->filter = ExAllocatePoolWithTag(NonPagedPool, buf_size, AFS_RDR_TAG);
-       RtlCopyMemory(ccb->filter, IrpSp->Parameters.QueryDirectory.FileName->Buffer, buf_size);
-       ccb->filter[IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR)] = L'\0';
+       if (IrpSp->Parameters.QueryDirectory.FileName)
+           {
+           buf_size = IrpSp->Parameters.QueryDirectory.FileName->Length+6;
+           ccb->filter = ExAllocatePoolWithTag(NonPagedPool, buf_size, AFS_RDR_TAG);
+           RtlCopyMemory(ccb->filter, IrpSp->Parameters.QueryDirectory.FileName->Buffer, buf_size);
+           ccb->filter[IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR)] = L'\0';
+           }
+       else
+           ccb->filter = SEARCH_MATCH_ALL;
     }
 
     if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY)
@@ -1174,7 +1217,7 @@ NTSTATUS AfsRdrDirCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
         info_size = sizeof(FILE_NAMES_INFORMATION);
         break;
     default:
-        KeBugCheckEx(0x12345, 0x98, 0x0, 0x0, 0x0);
+        SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
     }
 
     info = (FILE_BOTH_DIR_INFORMATION *)outPtr;
@@ -1500,7 +1543,11 @@ NTSTATUS AfsRdrSetInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
         if (infoDisp->DeleteFile)
         {
             if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
+               {
+               UNLOCK_FCB;
+               FsRtlExitFileSystem();
                 SYNC_FAIL(STATUS_ACCESS_DENIED);
+               }
             fcb->delPending |= 0x1;
         }
         else
@@ -1556,13 +1603,12 @@ NTSTATUS AfsRdrSetInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
             fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);                      
 
         //null-terminate all strings into uc_rename?
-        //FIX/one rename case not working
 
         if (IrpSp->Parameters.SetFile.FileObject == NULL &&
              infoRename->RootDirectory == NULL)
         {
-            WCHAR fname[300];                  /* FIX: uc_rename needs null-terminated string */
-            StringCchCopyNW(fname, 300-1, infoRename->FileName, infoRename->FileNameLength/sizeof(WCHAR));
+            WCHAR fname[MAX_PATH];
+            StringCchCopyNW(fname, MAX_PATH-1, infoRename->FileName, infoRename->FileNameLength/sizeof(WCHAR));
             uc_rename(fcb->fid, ccb->name+2, NULL, fname, &new_fid);
             fcb->fid = new_fid;
         }
@@ -1576,9 +1622,10 @@ NTSTATUS AfsRdrSetInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
         }
         else
         {
-            _asm int 3;
-            /*fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);
+                       /* FIXFIX: implement this case, although we have never seen it called */
+                       SYNC_RET(STATUS_UNSUCCESSFUL);
 
+                       /*fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);
             p->CurrNameOff = 0;
             StringCbCopyW(buf, size, fcb->name);
             p->NewNameOff = wcslen(buf)+1;
@@ -1625,18 +1672,6 @@ dc_break_callback(ULONG fid)
     }
 
     ASSERT(fcb->ccb_list);
-#if 0
-    pos = wcslen(fcb->ccb_list->name);
-    if (fcb->ccb_list->name[pos-1] == L'\\')
-        pos--;
-    ASSERT(pos);
-    while (pos > 0)
-    {
-        if (fcb->ccb_list->name[pos-1] == L'\\')
-            break;
-        pos--;
-    } 
-    #endif /* 0 */
 
     len = (wcslen(fcb->ccb_list->name) + 10) * sizeof(wchar_t);
     s = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)+len+sizeof(wchar_t));
@@ -1644,11 +1679,14 @@ dc_break_callback(ULONG fid)
     s->MaximumLength = len + sizeof(wchar_t);
     s->Buffer = (PWSTR)(s+1);
 
+    /* we are making a bogus change notification for now, because
+     * it does what we need.
+     */
     StringCbCopyW((PWSTR)(s+1), len, fcb->ccb_list->name);
     if (s->Buffer[wcslen(s->Buffer) - 1] != L'\\')
        StringCbCatW(s->Buffer, len, L"\\");
     pos = wcslen(s->Buffer);
-    StringCbCatW(s->Buffer, len, L"jj");               /* FIX: make bogus change notification */
+    StringCbCatW(s->Buffer, len, L"jj");
 
     KdPrint(("break callback on %d %ws %ws\n", fid, fcb->ccb_list->name, fcb->ccb_list->name+pos));
 
@@ -1661,6 +1699,11 @@ dc_break_callback(ULONG fid)
     return 0;
 }
 
+dc_release_hooks()
+{
+    KeSetEvent(&comExt->cancelEvent, 0, FALSE);
+}
+
 /**********************************************************
  * AfsRdrDeviceControl
  * - handle communication requests from fs, etc.
@@ -1675,6 +1718,7 @@ NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOC
     UNICODE_STRING nm;
     void *outPtr;
     ULONG key, code, length;
+    LARGE_INTEGER wait;
 
     /* utility ioctls */
     if (DeviceObject == ComDevice &&
@@ -1683,12 +1727,14 @@ NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOC
     {
        outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
        if (!outPtr)
-            _asm int 3;
+            SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
 
-       rpc_set_context(IrpSp->FileObject->FsContext);
+       wait.QuadPart = -1000;
+       while (rpc_set_context(IrpSp->FileObject->FsContext) != 0)      /* if there are no open thread spots... */
+           KeDelayExecutionThread(KernelMode, FALSE, &wait);           /* ...wait */
        code = uc_ioctl_write(IrpSp->Parameters.DeviceIoControl.InputBufferLength,
-                               Irp->AssociatedIrp.SystemBuffer,
-                               (ULONG*)&key);
+                              Irp->AssociatedIrp.SystemBuffer,
+                              (ULONG*)&key);
        length = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
        if (!code)              
             code = uc_ioctl_read(key, &length, outPtr);
@@ -1711,9 +1757,11 @@ NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOC
     {       
        outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
        if (!outPtr)
-            _asm int 3;
+            SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
 
-       rpc_set_context(IrpSp->FileObject->FsContext);
+       wait.QuadPart = -1000;
+       while (rpc_set_context(IrpSp->FileObject->FsContext) != 0)      /* if there are no open thread spots... */
+           KeDelayExecutionThread(KernelMode, FALSE, &wait);           /* ...wait */
        code = rpc_call(IrpSp->Parameters.DeviceIoControl.InputBufferLength,
                          Irp->AssociatedIrp.SystemBuffer,
                          IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
@@ -1730,12 +1778,13 @@ NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOC
             break;
         }
     }
+    /* ioctl to get full file afs path (used by pioctl) */
     else if (DeviceObject == RdrDevice &&
               IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_GET_PATH)
     {       
        outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
        if (!outPtr)
-            _asm int 3;
+            SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
 
        StringCbCopyW(outPtr, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, fcb->ccb_list->name+2);
 
@@ -1748,7 +1797,7 @@ NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOC
     }
 
     ret = Irp->IoStatus.Status;
-    COMPLETE;
+    COMPLETE;  /* complete with priority boost */
     return ret;
 }
 
@@ -1766,8 +1815,6 @@ NTSTATUS AfsRdrCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
 #if 0
     try {
 #endif
-        IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
         if (IrpSp->FileObject->FileName.Length == 0)
             SYNC_FAIL(STATUS_SUCCESS);
 
@@ -1778,16 +1825,23 @@ NTSTATUS AfsRdrCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
         LOCK_FCB;
 
         FsRtlNotifyCleanup(ext->notifyList, &ext->listHead, IrpSp->FileObject->FsContext2);
+
+       IoRemoveShareAccess(IrpSp->FileObject, &fcb->share_access);
+
         CcFlushCache(IrpSp->FileObject->SectionObjectPointer, NULL, 0, NULL);
-        if (fcb->delPending && !MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
-            /* yes, moot at this point */
-            STATUS(STATUS_ACCESS_DENIED, 0);
+
+        if (fcb->delPending)
+           {
+           if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
+               /* yes, moot at this point */
+               STATUS(STATUS_ACCESS_DENIED, 0);
+           }
         else
+           {
+           MmFlushImageSection(IrpSp->FileObject->SectionObjectPointer, MmFlushForWrite);
             STATUS(STATUS_SUCCESS, 0);
+           }
 
-        MmFlushImageSection(IrpSp->FileObject->SectionObjectPointer, MmFlushForWrite);
         CcPurgeCacheSection(IrpSp->FileObject->SectionObjectPointer, NULL, 0, TRUE);
         CcUninitializeCacheMap(IrpSp->FileObject, NULL, NULL);
 
@@ -1798,7 +1852,6 @@ NTSTATUS AfsRdrCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
 #if 0
     } except(EXCEPTION_EXECUTE_HANDLER)
     {
-       _asm int 3;
        STATUS(STATUS_UNSUCCESSFUL, 0);
        ExReleaseResourceLite(&ext->fcbLock);
        FsRtlExitFileSystem();
@@ -1831,8 +1884,6 @@ NTSTATUS AfsRdrClose(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
     ccb = IrpSp->FileObject->FsContext2;
     LOCK_FCB_LIST;
 
-    /* set share correctly so future opens can succeed */
-    IoRemoveShareAccess(IrpSp->FileObject, &fcb->share_access);
     ObDereferenceObject(ccb->token);
 
     curr = fcb->ccb_list;
@@ -1856,6 +1907,8 @@ NTSTATUS AfsRdrClose(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
         {
             uc_unlink(ccb->name+2);
         }
+       if (fcb->lock)
+           FsRtlFreeFileLock(fcb->lock);
        ExDeleteResourceLite(&fcb->_resource);
        ExDeleteResourceLite(&fcb->_pagingIoResource);
        RtlDeleteElementGenericTable(&rdrExt->fcbTable, &fcb);
@@ -1879,9 +1932,9 @@ NTSTATUS AfsRdrClose(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *I
  **********************************************************/
 NTSTATUS AfsRdrShutdown(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
 {
-    _asm int 3;
     STATUS(STATUS_SUCCESS, 0);
     COMPLETE;
+    return 0;
 }
 
 
@@ -1894,21 +1947,17 @@ NTSTATUS AfsRdrFlushFile(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATIO
     NTSTATUS ret;
     afs_ccb_t *ccb;
 
-    /*TRY*/
-    IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
-    if (IrpSp->FileObject->FileName.Length == 0)
+    if (IsDeviceFile(IrpSp->FileObject))
        SYNC_RET(STATUS_INVALID_DEVICE_REQUEST);
 
     ccb = IrpSp->FileObject->FsContext2;
 
     CcFlushCache(&fcb->sectionPtrs, NULL, 0, &Irp->IoStatus);
+    uc_flush(fcb->fid);
 
-    //SYNC_FAIL2(/*STATUS_LOCK_NOT_GRANTED*//*STATUS_NOT_IMPLEMENTED*/STATUS_SUCCESS, 0);
-
-    /*EXCEPT(STATUS_UNSUCCESSFUL, 0);*/
+    ret = Irp->IoStatus.Status;
     COMPLETE;
-    return Irp->IoStatus.Status;
+    return ret;
 }
 
 
@@ -1920,9 +1969,6 @@ NTSTATUS AfsRdrLockCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
 {
     NTSTATUS ret;
 
-    /*TRY*/
-    IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
     /* complete lock on control device object without processing, as directed */
     if (IrpSp->FileObject->FileName.Length == 0)
     {
@@ -1930,6 +1976,28 @@ NTSTATUS AfsRdrLockCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
        SYNC_FAIL(STATUS_SUCCESS);
     }
 
+    switch (IrpSp->MinorFunction)
+    {
+       case IRP_MN_LOCK:
+       case IRP_MN_UNLOCK_ALL:
+       case IRP_MN_UNLOCK_ALL_BY_KEY:
+       case IRP_MN_UNLOCK_SINGLE:
+           FsRtlEnterFileSystem();
+           LOCK_PAGING_FCB;
+           LOCK_FCB;
+           if (!fcb->lock)
+               {
+               fcb->lock = FsRtlAllocateFileLock(NULL, NULL);
+               }
+           UNLOCK_FCB;
+           UNLOCK_PAGING_FCB;
+           FsRtlExitFileSystem();
+           FsRtlProcessFileLock(fcb->lock, Irp, NULL);
+           fcb->IsFastIoPossible = fcb->lock->FastIoIsQuestionable ? FastIoIsQuestionable : FastIoIsPossible;
+           return STATUS_PENDING;
+       default:
+           SYNC_FAIL2(STATUS_NOT_IMPLEMENTED, 0);
+    }
     SYNC_FAIL2(/*STATUS_LOCK_NOT_GRANTED*//*STATUS_NOT_IMPLEMENTED*/STATUS_SUCCESS, 0);
 
     /*EXCEPT(STATUS_UNSUCCESSFUL, 0);*/
@@ -1988,7 +2056,8 @@ NTSTATUS AfsRdrQueryVol(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
        case FileFsSizeInformation:
             infoSize = (FILE_FS_SIZE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
             memset(infoSize, 0, sizeof(FILE_FS_SIZE_INFORMATION));
-            infoSize->TotalAllocationUnits.QuadPart =          0x00000000F0000000;             //FIX
+                       /* this data needs to come from an upcall */
+            infoSize->TotalAllocationUnits.QuadPart =          0x00000000F0000000;
             infoSize->AvailableAllocationUnits.QuadPart =      0x00000000E0000000;
             infoSize->SectorsPerAllocationUnit = 1;
             infoSize->BytesPerSector = 1;
@@ -1999,15 +2068,15 @@ NTSTATUS AfsRdrQueryVol(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
        case FileFsVolumeInformation:
             infoVolume = (FILE_FS_VOLUME_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
             memset(infoVolume, 0, sizeof(FILE_FS_VOLUME_INFORMATION));
-            infoVolume->VolumeCreationTime.QuadPart = AfsTimeToWindowsTime(1080000000);//0x43218765);          //TODO:fix
-            infoVolume->VolumeSerialNumber = 0x12345678;                               //TODO:fix
+                       /* this data needs to come from an upcall */
+            infoVolume->VolumeCreationTime.QuadPart = AfsTimeToWindowsTime(1080000000);
+            infoVolume->VolumeSerialNumber = 0x12345678;
             infoVolume->SupportsObjects = FALSE;
             //StringCbCopyLen(infoVolume->VolumeLabel, IrpSp->Parameters.QueryVolume.Length-sizeof(*infoVolume)-2, L"AfsRed", &infoVolume->VolumeLabelLength);
             //IrpSp->Parameters.QueryVolume.Length = 0;
             if (sizeof(*infoVolume) + 12 > IrpSp->Parameters.QueryVolume.Length)
             {
                 infoVolume->VolumeLabelLength = 0;
-                rpt0(("vol", "overflowing buffer %d", IrpSp->Parameters.QueryVolume.Length));
                 SYNC_FAIL2(STATUS_BUFFER_OVERFLOW, sizeof(*infoVolume));
             }
             else
@@ -2017,8 +2086,6 @@ NTSTATUS AfsRdrQueryVol(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION
                 SYNC_FAIL2(STATUS_SUCCESS, sizeof(*infoVolume) + (infoVolume->VolumeLabelLength - sizeof(WCHAR)));
             }          
             break;
-       //case FileFsFullSizeInformation:
-            //TODO:
        }
 
     EXCEPT(STATUS_UNSUCCESSFUL, 0);
@@ -2047,10 +2114,6 @@ VOID AfsRdrUnload(DRIVER_OBJECT *DriverObject)
     IoDeleteDevice(ComDevice);
     IoDeleteDevice(RdrDevice);
 
-#ifdef RPT_ENA
-    rptCliClose(REPORT);
-#endif
-
     KdPrint(("RdrUnload exiting.\n"));
 }
 
@@ -2085,6 +2148,7 @@ NTSTATUS ComDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
     ULONG len;
     ULONG code, read;
     PACCESS_TOKEN acc_token;
+    PVOID waitPair[2];
 
     ext = (struct ComExtension *)DeviceObject->DeviceExtension;
     IrpSp = IoGetCurrentIrpStackLocation(Irp);
@@ -2124,7 +2188,6 @@ NTSTATUS ComDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
 
     case IRP_MJ_WRITE:
         /* we only process MDL writes */
-        //_asm int 3;
         if (!Irp->MdlAddress ||
              !(ptr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)))       /* should be LowPagePriority */
             SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
@@ -2143,25 +2206,31 @@ NTSTATUS ComDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
         break;
     case IRP_MJ_READ:
         if (!Irp->MdlAddress || !(ptr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)))    // should be LowPagePriority
-            _asm int 3;
+            SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
 
         if (IrpSp->FileObject->FsContext2 == COMM_UPCALLHOOK)
         {
-            /*timeout.QuadPart = -10000000L;*/
+           KeClearEvent(&comExt->cancelEvent);
+
             timeout.QuadPart = -100000000L;
-            KeWaitForSingleObject(&comExt->outEvent, Executive, KernelMode, FALSE, &timeout);
+           waitPair[0] = &comExt->outEvent;
+           waitPair[1] = &comExt->cancelEvent;
+            ret = KeWaitForMultipleObjects(2, waitPair, WaitAny, Executive, KernelMode, FALSE, &timeout, NULL);
+
+           if (ret == STATUS_WAIT_1)
+               SYNC_FAIL(STATUS_UNSUCCESSFUL);
 
             if (!rpc_send(ptr, IrpSp->Parameters.Read.Length, &read))
             {
                 KeClearEvent(&comExt->outEvent);
-                KeWaitForSingleObject(&comExt->outEvent, Executive, KernelMode/*UserMode*/, FALSE, &timeout);
+               ret = KeWaitForMultipleObjects(2, waitPair, WaitAny, Executive, KernelMode, FALSE, &timeout, NULL);
                 if (!rpc_send(ptr, IrpSp->Parameters.Read.Length, &read))
                 {
                     KeClearEvent(&comExt->outEvent);
                     SYNC_FAIL(STATUS_UNSUCCESSFUL);
                 }
             }
-            SYNC_FAIL2(STATUS_SUCCESS, read);
+            SYNC_RET2(STATUS_SUCCESS, read);                   /* complete with priority boost */
         }
         else
             STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
@@ -2174,18 +2243,19 @@ NTSTATUS ComDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
     }
 
     ret = Irp->IoStatus.Status;
-    COMPLETE;
+    COMPLETE;                                                  /* complete with priority boost */
     return ret;
 }
 
 
-// handles all irp's for primary (fs) device
+/* handles all irp's for primary (fs) device */
 NTSTATUS Dispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
 {
     IO_STACK_LOCATION *IrpSp;
     NTSTATUS ret;
     afs_fcb_t *fcb;
     afs_ccb_t *ccb;
+    LARGE_INTEGER wait;
 
     if (DeviceObject->DeviceType == FILE_DEVICE_DATALINK)
        return ComDispatch(DeviceObject, Irp);
@@ -2194,14 +2264,16 @@ NTSTATUS Dispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
 
     rpt4(("irp", "%s min %d on %d (%ws) %x %x", IrpMjFuncDesc[IrpSp->MajorFunction], IrpSp->MinorFunction, 0/*ExtractFid(IrpSp->FileObject->FsContext)*/, IrpSp->FileObject->FileName.Buffer, IrpSp->Flags, IrpSp->Parameters.Create.Options));
 
-    fcb = IrpSp->FileObject->FsContext;//FindFcb(IrpSp->FileObject);
+    fcb = IrpSp->FileObject->FsContext;
     if (IrpSp->MajorFunction != IRP_MJ_CREATE)
         ASSERT(fcb);
 
     if (IrpSp->FileObject && IrpSp->FileObject->FsContext2)
     {
        ccb = IrpSp->FileObject->FsContext2;
-       rpc_set_context(ccb->token);
+       wait.QuadPart = -1000;
+       while (rpc_set_context(ccb->token) != 0)                        /* if there are no open thread spots... */
+           KeDelayExecutionThread(KernelMode, FALSE, &wait);           /* ...wait */
     }
 
     switch (IrpSp->MajorFunction)
@@ -2269,6 +2341,35 @@ NTSTATUS Dispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
     return ret;
 }
 
+
+BOOLEAN
+fastIoCheck (
+    IN struct _FILE_OBJECT *FileObject,
+    IN PLARGE_INTEGER FileOffset,
+    IN ULONG Length,
+    IN BOOLEAN Wait,
+    IN ULONG LockKey,
+    IN BOOLEAN CheckForReadOperation,
+    OUT PIO_STATUS_BLOCK IoStatus,
+    IN struct _DEVICE_OBJECT *DeviceObject
+    )
+{
+afs_fcb_t *fcb;
+LARGE_INTEGER temp;
+
+fcb = FileObject->FsContext;
+ASSERT(fcb);
+
+if (!fcb->lock)
+    return TRUE;
+
+temp.QuadPart = Length;
+if (CheckForReadOperation)
+    return FsRtlFastCheckLockForRead(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess());
+return FsRtlFastCheckLockForWrite(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess());
+}
+
+
 BOOLEAN
 fastIoRead (
     IN struct _FILE_OBJECT *FileObject,
@@ -2284,12 +2385,25 @@ fastIoRead (
     BOOLEAN ret;
     ULONG adj_len;
     afs_fcb_t *fcb;
+    LARGE_INTEGER temp;
 
     fcb = FileObject->FsContext;
     ASSERT(fcb);
 
     FsRtlEnterFileSystem();
     LOCK_PAGING_FCB;
+
+    if (fcb->lock)
+    {
+       temp.QuadPart = Length;
+       if (!FsRtlFastCheckLockForRead(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess()))
+       {
+           UNLOCK_PAGING_FCB;
+           FsRtlExitFileSystem();
+           return FALSE;
+       }
+    }
+
     adj_len = Length;
     if (FileOffset->QuadPart > fcb->FileSize.QuadPart)
     {
@@ -2305,11 +2419,8 @@ fastIoRead (
     try
     {
        ret = CcCopyRead(FileObject, FileOffset, adj_len, Wait, Buffer, IoStatus);
-       /*if (IoStatus->Status == STATUS_SUCCESS &&
-        (adj_len < Length))
-        IoStatus->Status = STATUS_END_OF_FILE;*/
-        // KdPrint(("read  %x at %x fast done %x\n", Length, (ULONG)FileOffset->QuadPart, IoStatus->Information));
-       FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
+
+       FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information;
        UNLOCK_PAGING_FCB;
        FsRtlExitFileSystem();
     }
@@ -2337,6 +2448,7 @@ fastIoWrite (
     BOOLEAN ret;
     LARGE_INTEGER adj_end;
     afs_fcb_t *fcb;
+    LARGE_INTEGER temp;
 
     fcb = FileObject->FsContext;
     ASSERT(fcb);
@@ -2344,9 +2456,21 @@ fastIoWrite (
     FsRtlEnterFileSystem();
     LOCK_PAGING_FCB;
 
+    if (fcb->lock)
+    {
+       temp.QuadPart = Length;
+       if (!FsRtlFastCheckLockForWrite(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess()))
+       {
+           UNLOCK_PAGING_FCB;
+           FsRtlExitFileSystem();
+           return FALSE;
+       }
+    }
+
+
     if (FileOffset->QuadPart + Length > fcb->FileSize.QuadPart)
     {
-       adj_end.QuadPart = fcb->FileSize.QuadPart + Length;
+       adj_end.QuadPart = FileOffset->QuadPart + Length;
        fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = adj_end;
        LOCK_FCB;
        try
@@ -2368,8 +2492,8 @@ fastIoWrite (
        ret = CcCopyWrite(FileObject, FileOffset, Length, Wait, Buffer);
        IoStatus->Status = ret?STATUS_SUCCESS:STATUS_UNSUCCESSFUL;
        IoStatus->Information = ret?Length:0;
-        // KdPrint(("write %x at %x fast done\n", Length, (ULONG)FileOffset->QuadPart));
-       FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
+
+       FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information;
        UNLOCK_PAGING_FCB;
        FsRtlExitFileSystem();
     }
@@ -2444,14 +2568,7 @@ NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
     IO_STATUS_BLOCK status;
     FAST_IO_DISPATCH *fastIoDispatch;
 
-    //_asm int 3;
-
     //try {
-#ifdef RPT_ENA
-    REPORT = rptOpen(NULL, "afskern");
-#endif
-    rpt0(("init", "rpt initialized at %x", REPORT));
-
     RtlInitUnicodeString(&rdrName, L"\\Device\\afsrdr");
     RtlInitUnicodeString(&comName, L"\\Device\\afscom");
 
@@ -2462,8 +2579,9 @@ NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
     IoAllocateDriverObjectExtension(DriverObject, (void *)0x394389f7, sizeof(FAST_IO_DISPATCH), &fastIoDispatch);
     RtlZeroMemory(fastIoDispatch, sizeof(FAST_IO_DISPATCH));
     fastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
-    fastIoDispatch->FastIoRead = fastIoRead;
-    fastIoDispatch->FastIoWrite = fastIoWrite;
+    fastIoDispatch->FastIoCheckIfPossible = fastIoCheck;
+    fastIoDispatch->FastIoRead = /*FsRtlCopyRead;*/fastIoRead;
+    fastIoDispatch->FastIoWrite = /*FsRtlCopyWrite;*/fastIoWrite;
     DriverObject->FastIoDispatch = fastIoDispatch;
 
     for (x = 0; x < IRP_MJ_MAXIMUM_FUNCTION; x++)
@@ -2501,12 +2619,10 @@ NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
     comExt = ((struct ComExtension*)ComDevice->DeviceExtension);
     RtlZeroMemory(comExt, sizeof(struct ComExtension));
 
-    //ExInitializeNPagedLookasideList(&comExt->outMemList, NULL, NULL, 0, sizeof(struct KOutEntry)+100, AFS_RDR_TAG, 0);
     InitializeListHead(&comExt->outReqList);
     KeInitializeSpinLock(&comExt->outLock);
     ExInitializeFastMutex(&comExt->inLock);
-    RtlInitializeGenericTable(&comExt->inTable, ReqCompareRoutine, AllocateRoutine, FreeRoutine, NULL);
-    KeInitializeEvent(&comExt->outEvent, NotificationEvent, TRUE);
+    KeInitializeEvent(&comExt->outEvent, SynchronizationEvent/*NotificationEvent*/, TRUE);
     KeInitializeEvent(&comExt->cancelEvent, NotificationEvent, TRUE);
 
     comExt->rdr = rdrExt;
@@ -2521,8 +2637,6 @@ NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
 
     /*} except(EXCEPTION_EXECUTE_HANDLER)
     {
-    _asm int 3;
-    //logerror();
     return -1;
     }*/
 
index 79f9b14..6d70c48 100644 (file)
@@ -40,7 +40,6 @@
 struct AfsRdrExtension
 {
 struct ComExtension *com;
-KMUTEX protectMutex;
 PNOTIFY_SYNC notifyList;
 LIST_ENTRY listHead;
 NPAGED_LOOKASIDE_LIST fcbMemList;
@@ -55,7 +54,6 @@ struct ComExtension
 struct AfsRdrExtension *rdr;
 LIST_ENTRY outReqList;
 KSPIN_LOCK outLock;
-RTL_GENERIC_TABLE inTable;
 FAST_MUTEX inLock;
 KEVENT outEvent, cancelEvent;
 };
diff --git a/src/WINNT/afsrdr/afsrdr.rc b/src/WINNT/afsrdr/afsrdr.rc
new file mode 100644 (file)
index 0000000..e5ef053
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* Define VERSIONINFO resource */
+
+#define  AFS_VERINFO_FILE_DESCRIPTION "AFS Network Redirector Driver"
+#define AFS_VERINFO_NAME "afsrdr"
+#define AFS_VERINFO_FILENAME "afsrdr.sys"
+
+#include "..\afsd\AFS_component_version_number.h"
+
+#include <winver.h>
+
+1 VERSIONINFO
+    FILEVERSION AFS_VERINFO_FILEVER
+    PRODUCTVERSION AFS_VERINFO_FILEVER
+    FILEOS VOS_NT
+#ifdef AFS_VERINFO_DLL
+    FILETYPE VFT_DLL
+#else
+    FILETYPE VFT_APP
+#endif
+BEGIN
+    BLOCK "StringFileInfo"
+    /* FileVersion must be specified or data won't appear on properties tab */
+    /* Internalname and originalfilename must be specified or explorer won't
+       show version and description */
+    BEGIN
+        BLOCK "000004E4"
+        BEGIN
+            VALUE "CompanyName",        "OpenAFS Project", "\0"
+            VALUE "LegalCopyright",     "Copyright \251 the Regents of the University of Michigan, 2005.", "\0"
+            VALUE "ProductName",        "OpenAFS for Windows", "\0"
+            VALUE "ProductVersion",     "1.0", "\0"
+            VALUE "FileVersion",        "1.0", "\0"
+            VALUE "FileDescription",    AFS_VERINFO_FILE_DESCRIPTION, "\0"
+            VALUE "Build",              AFS_VERINFO_BUILD, "\0"
+            VALUE "InternalName",       AFS_VERINFO_NAME, "\0"
+            VALUE "OriginalFilename",   AFS_VERINFO_FILENAME, "\0"
+        END
+    END
+    /* files in msi's are supposed to have language codes attached to them.
+       this is how they get populated automatically */
+    BLOCK "VarFileInfo"
+    BEGIN
+#ifdef AFS_VERINFO_LANG_CODE
+        VALUE "Translation", AFS_VERINFO_LANG_CODE, AFS_VERINFO_CHARSET
+#else
+/* default to 0, 1252 */
+        VALUE "Translation", 0, 0x4e4
+#endif
+    END
+END
index 07139f6..85a20dd 100644 (file)
@@ -60,25 +60,23 @@ rpc_wait(rpc_t *rpc, BOOLEAN long_op);
 rpc_send_mdl(rpc_t *rpc, char *out_buf);
 #endif
 
-/* internal timing functions (not used) */
-#ifdef RPC_KERN
-#define TIMING_START()         LARGE_INTEGER start, stop; \
-                                start.QuadPart = KeQueryInterruptTime();
-#define TIMING_END(name)       stop.QuadPart = KeQueryInterruptTime(); \
-                               rpt5((name, "%s %d", name, (ULONG)(stop.QuadPart - start.QuadPart)));
-#endif
-
 
-/* rpc security kernel functions */
+/****** rpc security kernel functions ******/
+/* before making an upcall from kernel code, set the security context by
+ * passing the access_token to rpc_set_context.  remove the context after all
+ * upcalls are done.  the rpc library automatically checks and sets this
+ * same context on the other end. */
 #ifdef RPC_KERN
 struct rpc_cred_map_entry
 {
     void *token;
     PETHREAD thread;
+    int refs;
 };
 
-struct rpc_cred_map_entry cred_map[20];
+struct rpc_cred_map_entry cred_map[MAX_CRED_MAPS];
 rpc_t *rpc_list_head = NULL;
+long num_rpcs = 0;
 
 rpc_set_context(void *context)
 {
@@ -89,14 +87,16 @@ rpc_set_context(void *context)
     empty = -1;
     ret = 0;
 
-    // LOCKLOCK
-    for (x = 0; x < 20; x++)
+    ifs_lock_rpcs();
+    for (x = 0; x < MAX_CRED_MAPS; x++)
     {
         if (cred_map[x].thread == NULL)
             empty = x;
         if (cred_map[x].thread == thd)
         {
-            cred_map[x].token = context;
+            //////FIX///ASSERT(cred_map[x].token == context);
+           cred_map[x].refs++;
+           //cred_map[x].token = context;
             goto done;
         }
     }
@@ -104,12 +104,13 @@ rpc_set_context(void *context)
     {
         cred_map[empty].thread = thd;
         cred_map[empty].token = context;
+       cred_map[empty].refs = 1;
     }
     else
         ret = -1;
 
   done:
-    // UNLOCKUNLOCK
+    ifs_unlock_rpcs();
     return ret;
 }
 
@@ -121,7 +122,7 @@ void *rpc_get_context()
     thd = PsGetCurrentThread();
 
     // no lock
-    for (x = 0; x < 20; x++)
+    for (x = 0; x < MAX_CRED_MAPS; x++)
         if (cred_map[x].thread == thd)
             return cred_map[x].token;
     // no unlock
@@ -134,22 +135,30 @@ rpc_remove_context()
     PETHREAD thd;
 
     thd = PsGetCurrentThread();
-    // no lock
-    for (x = 0; x < 20; x++)
+    ifs_lock_rpcs();
+    for (x = 0; x < MAX_CRED_MAPS; x++)
         if (cred_map[x].thread == thd)
         {
-            cred_map[x].token = NULL;
-            cred_map[x].thread = NULL;
+           if (cred_map[x].refs > 1)
+               {
+               cred_map[x].refs--;
+               }
+           else
+               {
+               cred_map[x].token = NULL;
+               cred_map[x].thread = NULL;
+               }
+           ifs_unlock_rpcs();
             return 0;
         }
 
-    // no unlock
+    ifs_unlock_rpcs();
     return -1;
 }
 #endif
 
 
-/* rpc internal functions for kernel */
+/* rpc stubs in kernel */
 #ifdef RPC_KERN
 rpc_t *rpc_create(int size_hint)
 {
@@ -162,6 +171,7 @@ rpc_t *rpc_create(int size_hint)
     NTSTATUS status;
     HANDLE token;
 
+    /* get user's identification from auth token*/
     token = rpc_get_context();
     ASSERT(token);
     status = SeQueryAuthenticationIdToken(token, &auth_id);
@@ -173,10 +183,11 @@ rpc_t *rpc_create(int size_hint)
 
     if (!(rpc = rpc_upgrade(NULL, 0, 1)))
     {
-        size = sizeof(rpc_t) + 4096*10;
+        size = sizeof(rpc_t) + 2*RPC_BUF_SIZE;
         rpc = ExAllocatePoolWithTag(NonPagedPool, size, 0x1234);
         if (!rpc)
-            _asm int 3;
+            return NULL;
+       num_rpcs++;
         memset(rpc, 0, size);
         rpc->next = rpc_list_head;
         rpc_list_head = rpc;
@@ -184,23 +195,23 @@ rpc_t *rpc_create(int size_hint)
     }
 
     rpc->out_buf = rpc->out_pos = (char*)(rpc+1);
-    rpc->in_buf = rpc->in_pos = ((char*)(rpc+1))+2048*10;
+    rpc->in_buf = rpc->in_pos = ((char*)(rpc+1))+RPC_BUF_SIZE;
 
     rpc->key = rand() + 10;
     rpc_marshal_long(rpc, rpc->key);
     rpc->bulk_out_len = (ULONG*)rpc->out_pos;
     rpc_marshal_long(rpc, 0);
 
-    /*SeCaptureSubjectContext(&subj_context);
+#if 0
+    /* another way of obtaining credentials, with different effects */
+    SeCaptureSubjectContext(&subj_context);
     acc_token = SeQuerySubjectContextToken(&subj_context);
-    status = SeQueryAuthenticationIdToken(acc_token, &auth_id);*/
-    /**token = rpc_get_context();
-    ASSERT(token);
-    status = SeQueryAuthenticationIdToken(token, &auth_id);
+    status = SeQueryAuthenticationIdToken(acc_token, &auth_id);
 
     user_id.LowPart = auth_id.LowPart;
     user_id.HighPart = auth_id.HighPart;
-    SeReleaseSubjectContext(&subj_context);*/
+    SeReleaseSubjectContext(&subj_context);
+#endif
 
     rpc_marshal_longlong(rpc, user_id);
 
@@ -214,7 +225,6 @@ void rpc_destroy(rpc_t *rpc)
     rpc_t *curr;
     int count;
 
-    /*ExFreePoolWithTag(rpc, 0x1234);*/
     ifs_lock_rpcs();
 
     if (rpc_upgrade(rpc, -1, 0))
@@ -233,14 +243,14 @@ rpc_t *rpc_create(int size_hint)
     rpc_t *rpc;
     ULONG status;
 
-    size = sizeof(rpc_t) + 4096;
+    size = sizeof(rpc_t) + 2*RPC_BUF_SIZE;
     rpc = malloc(size);
     if (!rpc)
-        _asm int 3;
+       osi_panic("ifs_rpc: alloc buffer", __FILE__, __LINE__);
     memset(rpc, 0, size);
 
     rpc->out_buf = rpc->out_pos = (char*)(rpc+1);
-    rpc->in_buf = rpc->in_pos = ((char*)(rpc+1))+2048;
+    rpc->in_buf = rpc->in_pos = ((char*)(rpc+1)) + RPC_BUF_SIZE;
 
     rpc->key = rand() + 10;
     rpc_marshal_long(rpc, rpc->key);
@@ -252,7 +262,6 @@ void rpc_destroy(rpc_t *rpc)
 {
     if (!rpc)
         return;
-    //_asm int 3;
 
     free(rpc);
 }
@@ -269,7 +278,7 @@ rpc_transact(rpc_t *rpc)
 
     header_len = rpc->out_pos - rpc->out_buf;
 
-    read = 2048;
+    read = RPC_BUF_SIZE;
     return ifs_TransactRpc(rpc->out_buf, header_len, rpc->in_buf, &read);
 }
 #endif
@@ -282,10 +291,12 @@ uc_namei(WCHAR *name, ULONG *fid)
     rpc_t *rpc;
     ULONG status;
     MDL *mdl;
-    TIMING_START();
-    /* put namei cache here */
+
+       /* consider putting namei cache here */
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_NAMEI);
     rpc_marshal_long(rpc, wcslen(name));
@@ -303,7 +314,6 @@ uc_namei(WCHAR *name, ULONG *fid)
     rpc_unmarshal_long(rpc, fid);
 
     rpc_destroy(rpc);
-    TIMING_END("namei");
     return status;
 }
 
@@ -311,9 +321,10 @@ uc_check_access(ULONG fid, ULONG access, ULONG *granted)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_CHECK_ACCESS);
     rpc_marshal_long(rpc, fid);
@@ -331,7 +342,6 @@ uc_check_access(ULONG fid, ULONG access, ULONG *granted)
     rpc_unmarshal_long(rpc, granted);
 
     rpc_destroy(rpc);
-    TIMING_END("access");
     return status;
 }
 
@@ -339,9 +349,10 @@ uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_CREATE);
     rpc_marshal_long(rpc, attribs);
@@ -361,7 +372,6 @@ uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *
     rpc_unmarshal_long(rpc, fid);
 
     rpc_destroy(rpc);
-    TIMING_END("create");
     return status;
 }
 
@@ -369,9 +379,10 @@ uc_stat(ULONG fid, ULONG *attribs, LARGE_INTEGER *size, LARGE_INTEGER *creation,
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_STAT);
     rpc_marshal_long(rpc, fid);
@@ -393,7 +404,6 @@ uc_stat(ULONG fid, ULONG *attribs, LARGE_INTEGER *size, LARGE_INTEGER *creation,
     rpc_unmarshal_longlong(rpc, written);
 
     rpc_destroy(rpc);
-    TIMING_END("stat");
     return status;
 }
 
@@ -401,9 +411,10 @@ uc_setinfo(ULONG fid, ULONG attribs, LARGE_INTEGER creation, LARGE_INTEGER acces
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_SETINFO);
     rpc_marshal_long(rpc, fid);
@@ -425,7 +436,6 @@ uc_setinfo(ULONG fid, ULONG attribs, LARGE_INTEGER creation, LARGE_INTEGER acces
     rpc_unmarshal_long(rpc, &status);
 
     rpc_destroy(rpc);
-    TIMING_END("setinfo");
     return status;
 }
 
@@ -433,9 +443,10 @@ uc_trunc(ULONG fid, LARGE_INTEGER size)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_TRUNC);
     rpc_marshal_long(rpc, fid);
@@ -452,7 +463,6 @@ uc_trunc(ULONG fid, LARGE_INTEGER size)
     rpc_unmarshal_long(rpc, &status);
 
     rpc_destroy(rpc);
-    TIMING_END("trunc");
     return status;
 }
 
@@ -460,9 +470,10 @@ uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_READ);
     rpc_marshal_long(rpc, fid);
@@ -481,46 +492,17 @@ uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data)
     rpc_unmarshal_long(rpc, read);
 
     rpc_destroy(rpc);
-    TIMING_END("read");
     return status;
 }
 
-/*uc_read_mdl(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, MDL *data)
-{
-    rpc_t *rpc;
-    ULONG status;
-    TIMING_START();
-
-    rpc = rpc_create(0);
-
-    rpc_marshal_long(rpc, RPC_READ_BULK);
-    rpc_marshal_long(rpc, fid);
-    rpc_marshal_longlong(rpc, offset);
-    rpc_marshal_long(rpc, length);
-
-    rpc_queue_bulk_mdl(rpc, data);
-    if (!rpc_wait(rpc, 1))
-    {
-        rpc_cancel(rpc);
-        rpt0(("cancel", "cancel read mdl"));
-        return IFSL_RPC_TIMEOUT;
-    }
-
-    rpc_unmarshal_long(rpc, &status);
-    rpc_unmarshal_long(rpc, read);
-
-    rpc_destroy(rpc);
-    TIMING_END("read_mdl");
-    return status;
-}*/
-
 uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *data)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_WRITE);
     rpc_marshal_long(rpc, fid);
@@ -539,46 +521,17 @@ uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *da
     rpc_unmarshal_long(rpc, written);
 
     rpc_destroy(rpc);
-    TIMING_END("write");
     return status;
 }
 
-/*uc_write_mdl(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, MDL *data)
-{
-    rpc_t *rpc;
-    ULONG status;
-    TIMING_START();
-
-    rpc = rpc_create(0);
-
-    rpc_marshal_long(rpc, RPC_WRITE_BULK);
-    rpc_marshal_long(rpc, fid);
-    rpc_marshal_longlong(rpc, offset);
-    rpc_marshal_long(rpc, length);
-
-    rpc_queue_bulk_mdl(rpc, data);
-    if (!rpc_wait(rpc, 1))
-    {
-        rpc_cancel(rpc);
-        rpt0(("cancel", "cancel write mdl"));
-        return IFSL_RPC_TIMEOUT;
-    }
-
-    rpc_unmarshal_long(rpc, &status);
-    rpc_unmarshal_long(rpc, written);
-
-    rpc_destroy(rpc);
-    TIMING_END("write_mdl");
-    return status;
-}*/
-
 uc_readdir(ULONG fid, LARGE_INTEGER cookie_in, WCHAR *filter, ULONG *count, char *data, ULONG *len)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_READDIR);
     rpc_marshal_long(rpc, fid);
@@ -599,7 +552,6 @@ uc_readdir(ULONG fid, LARGE_INTEGER cookie_in, WCHAR *filter, ULONG *count, char
     rpc_unmarshal_long(rpc, len);
 
     rpc_destroy(rpc);
-    TIMING_END("readdir");
     return status;
 }
 
@@ -607,9 +559,10 @@ uc_close(ULONG fid)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_CLOSE);
     rpc_marshal_long(rpc, fid);
@@ -625,7 +578,6 @@ uc_close(ULONG fid)
     rpc_unmarshal_long(rpc, &status);
 
     rpc_destroy(rpc);
-    TIMING_END("close");
     return status;
 }
 
@@ -633,9 +585,10 @@ uc_unlink(WCHAR *name)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_UNLINK);
     rpc_marshal_wstr(rpc, name);
@@ -651,7 +604,6 @@ uc_unlink(WCHAR *name)
     rpc_unmarshal_long(rpc, &status);
 
     rpc_destroy(rpc);
-    TIMING_END("unlink");
     return status;
 }
 
@@ -659,9 +611,10 @@ uc_ioctl_write(ULONG length, char *data, ULONG *key)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_IOCTL_WRITE);
     rpc_marshal_long(rpc, length);
@@ -678,7 +631,6 @@ uc_ioctl_write(ULONG length, char *data, ULONG *key)
     rpc_unmarshal_long(rpc, key);
 
     rpc_destroy(rpc);
-    TIMING_END("ioctl_write");
     return status;
 }
 
@@ -686,9 +638,10 @@ uc_ioctl_read(ULONG key, ULONG *length, char *data)
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_IOCTL_READ);
     rpc_marshal_long(rpc, key);
@@ -705,7 +658,6 @@ uc_ioctl_read(ULONG key, ULONG *length, char *data)
     rpc_unmarshal_long(rpc, length);
 
     rpc_destroy(rpc);
-    TIMING_END("ioctl_read");
     return status;
 }
 
@@ -713,9 +665,10 @@ uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fi
 {
     rpc_t *rpc;
     ULONG status;
-    TIMING_START();
 
     rpc = rpc_create(0);
+    if (!rpc)
+       return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_RENAME);
     rpc_marshal_long(rpc, fid);
@@ -735,7 +688,32 @@ uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fi
     rpc_unmarshal_long(rpc, new_fid);
 
     rpc_destroy(rpc);
-    TIMING_END("rename");
+    return status;
+}
+
+uc_flush(ULONG fid)
+{
+    rpc_t *rpc;
+    ULONG status;
+
+    rpc = rpc_create(0);
+    if (!rpc)
+       return IFSL_MEMORY;
+
+    rpc_marshal_long(rpc, RPC_FLUSH);
+    rpc_marshal_long(rpc, fid);
+
+    rpc_queue(rpc);
+    if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
+    {
+        rpc_cancel(rpc);
+        rpt0(("cancel", "cancel flush"));
+        return IFSL_RPC_TIMEOUT;
+    }
+
+    rpc_unmarshal_long(rpc, &status);
+
+    rpc_destroy(rpc);
     return status;
 }
 #endif
@@ -749,6 +727,8 @@ dc_break_callback(ULONG fid)
     ULONG status;
 
     rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
 
     rpc_marshal_long(rpc, RPC_BREAK_CALLBACK);
     rpc_marshal_long(rpc, fid);
@@ -761,6 +741,26 @@ dc_break_callback(ULONG fid)
     rpc_destroy(rpc);
     return status;
 }
+
+dc_release_hooks()
+{
+    rpc_t *rpc;
+    ULONG status;
+
+    rpc = rpc_create(0);
+       if (!rpc)
+               return IFSL_MEMORY;
+
+    rpc_marshal_long(rpc, RPC_RELEASE_HOOKS);
+    if (!rpc_transact(rpc))
+    {
+        rpc_destroy(rpc);
+        return IFSL_GENERIC_FAILURE;
+    }
+    rpc_unmarshal_long(rpc, &status);
+    rpc_destroy(rpc);
+    return status;
+}
 #endif
 
 
@@ -824,6 +824,7 @@ rpc_t *rpc_find(int id)
     curr = rpc_list_head;
     while (curr)
     {
+        /* dead rpc structs should not be returned */
         if (curr->key == id && curr->status != 0)
             return curr;
         curr = curr->next;
@@ -880,13 +881,6 @@ rpc_queue(rpc_t *rpc)
 rpc_cancel(rpc_t *rpc)
 {
     rpc_destroy(rpc);
-    //ExAcquireFastMutex(&ext->inLock);
-    /*ifs_lock_rpcs();
-    if (rpc_upgrade(rpc, -1, 0))
-    rpc_destroy(rpc);
-    ifs_unlock_rpcs();*/
-    //RtlDeleteElementGenericTable(&ext->inTable, (void*)&rpc);
-    //ExReleaseFastMutex(&ext->inLock);
 }
 
 rpc_shutdown()
@@ -900,6 +894,7 @@ rpc_shutdown()
     {
         next = curr->next;
         ExFreePoolWithTag(curr, 0x1234);
+       num_rpcs--;
         curr = next;
     }
     rpc_list_head = NULL;
@@ -911,25 +906,27 @@ rpc_wait(rpc_t *rpc, BOOLEAN long_op)
 {
     NTSTATUS ret;
     LARGE_INTEGER timeout;
-    //p->FsContext = (ULONG)&ev;
 
     if (long_op)
-        timeout.QuadPart = -600000000L;                /* 60 seconds 60L*1000000L */
+        timeout.QuadPart = -600000000L;                /* 60 seconds 60L*10000000L */
     else
-        timeout.QuadPart = -200000000L;                /* 20 seconds 20L*1000000L */
+        timeout.QuadPart = -200000000L;                /* 20 seconds 20L*10000000L */
 
     do
         ret = KeWaitForSingleObject(&rpc->ev, Executive, KernelMode, FALSE, &timeout);
-    while (ret != STATUS_SUCCESS);// && ret != STATUS_TIMEOUT);
+    while (ret != STATUS_SUCCESS && ret != STATUS_TIMEOUT);
 
-    /*if (KeReadStateEvent(&rpc->ev) == 0)
-    _asm int 3;*/
-    if (rpc->status == 5)
+    ifs_lock_rpcs();
+    if (rpc->status == 2 ||                    /* still queued */
+       rpc->status == 5)                       /* send cancelled by library */
+       {
+       ifs_unlock_rpcs();
         return 0;
+       }
 
+    ifs_unlock_rpcs();    
     if (ret == STATUS_SUCCESS)
         return 1;
-    _asm int 3;
     return 0;
 }
 
@@ -942,14 +939,6 @@ rpc_queue_bulk(rpc_t *rpc, char *out_bulk, ULONG out_len, char *in_bulk, ULONG i
     return rpc_queue(rpc);
 }
 
-/*rpc_queue_bulk_mdl(rpc_t *rpc, MDL *bulk)
-{
-    rpc->bulk_mdl = bulk;
-    *rpc->bulk_out_len = 0xFFFFFFFC;
-    rpc->bulk_in = 0;
-    return rpc_queue(rpc);
-}*/
-
 rpc_get_len(rpc_t *rpc)
 {
     if (*rpc->bulk_out_len != 0xFFFFFFFC)
@@ -977,104 +966,23 @@ rpc_send(char *out_buf, int out_len, int *out_written)
 
     if (rpc_get_len(rpc) > out_len)
     {
-        //_asm int 3;
         ifs_unlock_rpcs();
         rpt0(("cancel", "cancel on send"));
         rpc_upgrade(rpc, -1, 5);
-        KeSetEvent(&rpc->ev, IO_NO_INCREMENT, FALSE);  /* move to rpc_ fn */
-        //rpc_cancel(rpc);
-        goto restart;//return 0;
+        KeSetEvent(&rpc->ev, IO_NETWORK_INCREMENT, FALSE);
+        goto restart;
     }
 
-
-
-    /*mdl = (*rpc->bulk_out_len == 0xFFFFFFFC);
-
-    if (mdl)
-    *rpc->bulk_out_len = 0;*/
-
     header_len = rpc->out_pos - rpc->out_buf;
     RtlCopyMemory(out_buf, rpc->out_buf, header_len);
 
-    //if (!mdl)
-    {
-        if (*rpc->bulk_out_len && rpc->bulk_out)
-            RtlCopyMemory(out_buf + header_len, rpc->bulk_out, *rpc->bulk_out_len);
-        *out_written = header_len + *rpc->bulk_out_len;
-    }
-#if 0
-    else
-    {
-        if (rpc->bulk_mdl)
-        {
-            void *ptr;
-            //_asm int 3;
-#if 0
-            try
-            {
-                _asm int 3;
-                MmProbeAndLockPages(rpc->bulk_mdl, UserMode, IoModifyAccess);
-            }
-            except (EXCEPTION_EXECUTE_HANDLER)
-            {
-                _asm int 3;
-            }
-#endif
-            try
-            {
-                rpc->bulk_out = MmMapLockedPagesSpecifyCache(rpc->bulk_mdl, UserMode, MmNonCached, NULL, FALSE, NormalPagePriority);
-            }
-            except (EXCEPTION_EXECUTE_HANDLER)
-            {
-                PMDL remap;
-                void *ptr;
-                _asm int 3;
-                ptr = ExAllocatePool(PagedPool, MmGetMdlByteCount(rpc->bulk_mdl));
-                remap = IoAllocateMdl(ptr, MmGetMdlByteCount(rpc->bulk_mdl), FALSE, TRUE, NULL);
-                MmProbeAndLockPages(remap, UserMode, IoModifyAccess);
-                rpc->bulk_out = MmMapLockedPagesSpecifyCache(remap, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
-                _asm int 3;
-                rpc->bulk_out = MmGetSystemAddressForMdlSafe(rpc->bulk_mdl, NormalPagePriority);
-                MmUnmapLockedPages(rpc->bulk_out, rpc->bulk_mdl);
-                rpc->bulk_out = MmMapLockedPagesSpecifyCache(rpc->bulk_mdl, UserMode, MmNonCached, NULL, FALSE, NormalPagePriority);
-
-                remap = IoAllocateMdl(rpc->bulk_out, MmGetMdlByteCount(rpc->bulk_mdl), FALSE, TRUE, NULL);
-                remap->Process = (void*)PsGetCurrentProcess();
-                MmBuildMdlForNonPagedPool(remap);
-                //MmProbeAndLockPages(remap, UserMode, IoModifyAccess);
-                rpc->bulk_out = MmMapLockedPagesSpecifyCache(remap, UserMode, MmNonCached, (void*)0x01111111, FALSE, NormalPagePriority);
-                /*ifs_unlock_rpcs();
-                rpc_upgrade(rpc, -1, 5);
-                KeSetEvent(&rpc->ev, IO_NO_INCREMENT, FALSE);
-                //rpc_cancel(rpc);
-                goto restart;//return 0;*/
-            }
-            ptr = rpc->bulk_out;
-            RtlCopyMemory(out_buf + header_len, &ptr, sizeof(ptr));
-        }
-
-        *rpc->bulk_out_len = 0xFFFFFFFC;
-        *out_written = header_len + sizeof(void*);
-    }
-#endif
+    if (*rpc->bulk_out_len && rpc->bulk_out)
+        RtlCopyMemory(out_buf + header_len, rpc->bulk_out, *rpc->bulk_out_len);
+    *out_written = header_len + *rpc->bulk_out_len;
 
     ifs_unlock_rpcs();
     return (*out_written != 0);
 }
-
-#if 0
-rpc_send_reg(rpc_t *rpc, char *out_buf)
-{
-    ULONG header_len;
-
-    header_len = rpc->out_pos - rpc->out_buf;
-    RtlCopyMemory(out_buf, rpc->out_buf, header_len);
-
-    if (rpc->bulk_out_len && rpc->bulk_out)
-        RtlCopyMemory(out_buf + header_len, rpc->bulk_out, *rpc->bulk_out_len);
-    return header_len + *rpc->bulk_out_len;
-}
-#endif
 #endif
 
 
@@ -1089,21 +997,12 @@ rpc_recv(char *in_buf, ULONG len)
     ifs_lock_rpcs();
 
     rpc = rpc_find(*(ULONG*)in_buf);
-    if (!rpc)
+    if (!rpc)                          /* rpc was cancelled while waiting */
     {
-        //_asm int 3;
         ifs_unlock_rpcs();
         return -1;
     }
 
-    //_asm int 3;
-    /*if (*rpc->bulk_out_len == 0xFFFFFFFC)
-    {
-    ASSERT(rpc->bulk_out);
-    MmUnmapLockedPages(rpc->bulk_out, rpc->bulk_mdl);
-    // MmUnlockPages(rpc->bulk_mdl);
-    }*/
-
     alloc = rpc->in_buf;
     rpc->in_buf = rpc->in_pos = in_buf;
     rpc_unmarshal_long(rpc, &key);
@@ -1112,19 +1011,16 @@ rpc_recv(char *in_buf, ULONG len)
 
     rpc->in_buf = rpc->in_pos = alloc;
     header_size = len - rpc->bulk_in_len;
-    ASSERT(header_size < 4096);
+    ASSERT(header_size < RPC_BUF_SIZE);
+
     RtlCopyMemory(rpc->in_buf, in_buf + 2*sizeof(ULONG), header_size - 2*sizeof(ULONG));
-    //if (*rpc->bulk_out_len != 0xFFFFFFFC)
+    if (rpc->bulk_in_len && rpc->bulk_in)
     {
-        if (rpc->bulk_in_len && rpc->bulk_in)
-        {
-            ASSERT(rpc->bulk_in_len <= rpc->bulk_in_max);
-            //_asm int 3;
-            RtlCopyMemory(rpc->bulk_in, in_buf + header_size, rpc->bulk_in_len);//len - header_size - 2*sizeof(ULONG));
-        }
+        ASSERT(rpc->bulk_in_len <= rpc->bulk_in_max);
+        RtlCopyMemory(rpc->bulk_in, in_buf + header_size, rpc->bulk_in_len);
     }
 
-    KeSetEvent(&rpc->ev, IO_NO_INCREMENT, FALSE);
+    KeSetEvent(&rpc->ev, IO_NETWORK_INCREMENT, FALSE);         /* priority boost for waiting thread */
     ifs_unlock_rpcs();
     return 0;
 }
@@ -1151,10 +1047,12 @@ rpc_call(ULONG in_len, char *in_buf, ULONG out_max, char *out_buf, ULONG *out_le
         status = dc_break_callback(fid);
         rpc_marshal_long(&rpc, status);
         break;
+    case RPC_RELEASE_HOOKS:
+        status = dc_release_hooks();
+        break;
     }
     *out_len = rpc.out_pos - rpc.out_buf;
     return 0;
-    //ifs_ImpersonateClient(user_id);
 }
 #endif
 
@@ -1256,21 +1154,6 @@ rpc_parse(rpc_t *rpc)
             *rpc->bulk_out_len = read;
         }
         break;
-       /*      case RPC_READ_BULK:
-        {
-        ULONG fid, length, read;
-        LARGE_INTEGER offset;
-        char *data, *save;
-        rpc_unmarshal_long(rpc, &fid);
-        rpc_unmarshal_longlong(rpc, &offset);
-        rpc_unmarshal_long(rpc, &length);
-        data = *((char**)rpc->in_pos);
-        status = uc_read(fid, offset, length, &read, data);
-        rpc_marshal_long(rpc, status);
-        rpc_marshal_long(rpc, read);
-        *rpc->bulk_out_len = 0;
-        }
-        break;*/
     case RPC_WRITE:
         {
             ULONG fid, length, written;
@@ -1285,21 +1168,6 @@ rpc_parse(rpc_t *rpc)
             rpc_marshal_long(rpc, written);
         }
         break;
-       /*      case RPC_WRITE_BULK:
-        {
-        ULONG fid, length, written;
-        LARGE_INTEGER offset;
-        char *data;
-        //_asm int 3;
-        rpc_unmarshal_long(rpc, &fid);
-        rpc_unmarshal_longlong(rpc, &offset);
-        rpc_unmarshal_long(rpc, &length);
-        data = *((char**)rpc->in_pos);
-        status = uc_write(fid, offset, length, &written, data);
-        rpc_marshal_long(rpc, status);
-        rpc_marshal_long(rpc, written);
-        }
-        break;*/
     case RPC_TRUNC:
         {
             ULONG fid;
@@ -1402,6 +1270,14 @@ rpc_parse(rpc_t *rpc)
             rpc_marshal_long(rpc, new_fid);
         }
         break;
+    case RPC_FLUSH:
+        {
+            ULONG fid;
+            rpc_unmarshal_long(rpc, &fid);
+            status = uc_flush(fid);
+            rpc_marshal_long(rpc, status);
+        }
+        break;
     }
 }
 #endif
index 9fa1abb..001eea0 100644 (file)
 #include <winioctl.h>
 #endif
 
+
+/* maximum number of users, based on SID, that can access AFS at one time */
+#define MAX_AFS_USERS                  20
+
+/* maximum number of threads that can make simultaneous calls into afsrdr,
+   because we maintain a credential set for each thread in a single table. */
+#define MAX_CRED_MAPS                  32
+
+/* size if outgoing/incoming RPC buffer (for parameters only, not bulk data) */
+#define RPC_BUF_SIZE                   2048
+
+/* max. chunk size for RPC transfers */
+#define TRANSFER_CHUNK_SIZE    (1024*1024)
+
+
 /* upcalls */
 #define RPC_NAMEI              0x10
 #define RPC_CHECK_ACCESS       0x11
 #define RPC_IOCTL_WRITE                0x1B
 #define RPC_IOCTL_READ         0x1C
 #define RPC_RENAME             0x1D
-#define RPC_READ_BULK          0x1E
-#define RPC_WRITE_BULK         0x1F
+#define RPC_FLUSH              0x1E
+
 
 /* downcalls */
 #define RPC_BREAK_CALLBACK     0x80
+#define RPC_RELEASE_HOOKS      0x81
 
-#define TRANSFER_CHUNK_SIZE    (1024*1024)
+
+/* internal module flags */
 #define RPC_TIMEOUT_SHORT      0
 #define RPC_TIMEOUT_LONG       1
 
+
 /* internal data struct for both client and server */
 struct rpc
        {
@@ -99,15 +117,3 @@ rpc_parse(rpc_t *rpc);
 #endif
 
 
-/* extended information */
-struct readdir_data
-       {
-       LARGE_INTEGER cookie;
-       long offset;
-       LARGE_INTEGER creation, access, write, change, size;
-       ULONG attribs, name_length;                     /* chars */
-       CCHAR short_name_length;                        /* chars */
-       WCHAR short_name[14];
-       WCHAR name[];
-       };
-typedef struct readdir_data readdir_data_t;
index 513f61d..0eac2d7 100644 (file)
  * 03-jun 2005 (eric williams) entered into versioning
  */
 
+
+/* this is based on BUF_FILEHASH, but we were not getting unique hashes */
+#define FID_HASH_FN(fidp)              ((((fidp)->vnode + \
+                                          ((fidp)->unique << 13) + ((fidp)->unique >> (32-13)) + \
+                                          (fidp)->volume + \
+                                          (fidp)->cell)))
+
+
+/* dirent information */
+struct readdir_data
+       {
+       LARGE_INTEGER cookie;
+       long offset;
+       LARGE_INTEGER creation, access, write, change, size;
+       ULONG attribs, name_length;                     /* chars */
+       CCHAR short_name_length;                        /* chars */
+       WCHAR short_name[14];
+       WCHAR name[];
+       };
+typedef struct readdir_data readdir_data_t;
+
+
 /* error codes */
 #define IFSL_SUCCESS_BASE                      0x00000000
 #define IFSL_FAIL_BASE                         0x80000000
 #define IFSL_NOT_EMPTY                         (IFSL_FAIL_BASE + 22)
 #define IFSL_RPC_TIMEOUT                       (IFSL_FAIL_BASE + 23)
 #define IFSL_OVERQUOTA                         (IFSL_FAIL_BASE + 24)
-#define IFSL_UNSPEC                            (IFSL_FAIL_BASE + 25)
+#define IFSL_MEMORY                                    (IFSL_FAIL_BASE + 25)
+#define IFSL_UNSPEC                                    (IFSL_FAIL_BASE + 26)
 
 
 /* ioctl codes */
-#define IOCTL_AFSRDR_IOCTL     CTL_CODE(IOCTL_DISK_BASE, 0x007, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+#define IOCTL_AFSRDR_IOCTL             CTL_CODE(IOCTL_DISK_BASE, 0x007, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 #define IOCTL_AFSRDR_DOWNCALL  CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 #define IOCTL_AFSRDR_GET_PATH  CTL_CODE(IOCTL_DISK_BASE, 0x009, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 
@@ -75,16 +98,15 @@ uc_setinfo(ULONG fid, ULONG attribs, LARGE_INTEGER creation, LARGE_INTEGER acces
 uc_trunc(ULONG fid, LARGE_INTEGER size);
 uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data);
 uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *data);
-/*#ifdef RPC_KERN
-uc_read_mdl(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, MDL *data);
-uc_write_mdl(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, MDL *mdl);
-#endif*/
 uc_readdir(ULONG fid, LARGE_INTEGER cookie_in, WCHAR *filter, ULONG *count, char *data, ULONG *len);
 uc_close(ULONG fid);
 uc_unlink(WCHAR *name);
 uc_ioctl_write(ULONG length, char *data, ULONG *key);
 uc_ioctl_read(ULONG key, ULONG *length, char *data);
 uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fid);
+uc_flush(ULONG fid);
+
 
 /* downcalls */
 dc_break_callback(ULONG fid);
+dc_release_hooks();
index 41abfe9..588c5ad 100644 (file)
@@ -23,7 +23,7 @@
 # * possibility of such damages.
 # */
 
-SOURCES= afsrdr.c ifs_rpc.c
+SOURCES= afsrdr.c ifs_rpc.c afsrdr.rc
 TARGETNAME=afsrdr
 TARGETPATH=obj
 TARGETTYPE=DRIVER
index ab15ed4..e573e30 100644 (file)
@@ -686,7 +686,7 @@ Section "!AFS Client" secClient
   nsExec::Exec '$INSTDIR\Common\Service.exe TransarcAFSDaemon "$INSTDIR\Client\Program\afsd_service.exe" "OpenAFS Client Service"'
   nsExec::Exec '$INSTDIR\Common\Service.exe u AfsRdr'
 !ifdef AFSIFS
-  nsExec::Exec '$INSTDIR\Common\Service.exe AfsRdr "$SYSDIR\DRIVERS\afsrdr.sys" "AFS Redirector"'
+  nsExec::Exec '$INSTDIR\Common\Service.exe AfsRdr "System32\DRIVERS\afsrdr.sys" "AFS Redirector"'
 !endif
 skipremove:
   Delete "$INSTDIR\Common\service.exe"