From fc0ca363da52144628a35abae30315257bbf76a8 Mon Sep 17 00:00:00 2001 From: Eric Williams Date: Thu, 4 Aug 2005 17:32:32 +0000 Subject: [PATCH 1/1] windows-afsifs-20050804 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. --- src/WINNT/afsd/afsd.c | 5 +- src/WINNT/afsd/afsd_service.c | 23 +- src/WINNT/afsd/afsdifs.c | 280 +++++++++++----------- src/WINNT/afsd/cm_buf.c | 8 + src/WINNT/afsd/cm_callback.c | 18 +- src/WINNT/afsd/cm_ioctl.c | 37 +-- src/WINNT/afsd/cm_vnodeops.c | 5 +- src/WINNT/afsrdr/afsrdr.c | 472 +++++++++++++++++++++++-------------- src/WINNT/afsrdr/afsrdr.h | 2 - src/WINNT/afsrdr/afsrdr.rc | 59 +++++ src/WINNT/afsrdr/ifs_rpc.c | 440 +++++++++++++--------------------- src/WINNT/afsrdr/ifs_rpc.h | 36 +-- src/WINNT/afsrdr/kif.h | 34 ++- src/WINNT/afsrdr/sources | 2 +- src/WINNT/install/NSIS/OpenAFS.nsi | 2 +- 15 files changed, 745 insertions(+), 678 deletions(-) create mode 100644 src/WINNT/afsrdr/afsrdr.rc diff --git a/src/WINNT/afsd/afsd.c b/src/WINNT/afsd/afsd.c index 7acd6aa..f977c22 100644 --- a/src/WINNT/afsd/afsd.c +++ b/src/WINNT/afsd/afsd.c @@ -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; diff --git a/src/WINNT/afsd/afsd_service.c b/src/WINNT/afsd/afsd_service.c index fedc01f..51e92ae 100644 --- a/src/WINNT/afsd/afsd_service.c +++ b/src/WINNT/afsd/afsd_service.c @@ -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 } } diff --git a/src/WINNT/afsd/afsdifs.c b/src/WINNT/afsd/afsdifs.c index 0efedbe..4875ad5 100644 --- a/src/WINNT/afsd/afsdifs.c +++ b/src/WINNT/afsd/afsdifs.c @@ -37,30 +37,26 @@ /****************************/ #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; } diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index 98b63f8..b835f3b 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -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 diff --git a/src/WINNT/afsd/cm_callback.c b/src/WINNT/afsd/cm_callback.c index 3076ed8..5e22237 100644 --- a/src/WINNT/afsd/cm_callback.c +++ b/src/WINNT/afsd/cm_callback.c @@ -27,6 +27,7 @@ #include "afsd.h" #include #include +#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); diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 1d09f9c..1789304 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -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; diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 7162e77..669e37e 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -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)) diff --git a/src/WINNT/afsrdr/afsrdr.c b/src/WINNT/afsrdr/afsrdr.c index bc00ec5..03b42d2 100644 --- a/src/WINNT/afsrdr/afsrdr.c +++ b/src/WINNT/afsrdr/afsrdr.c @@ -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; }*/ diff --git a/src/WINNT/afsrdr/afsrdr.h b/src/WINNT/afsrdr/afsrdr.h index 79f9b14..6d70c48 100644 --- a/src/WINNT/afsrdr/afsrdr.h +++ b/src/WINNT/afsrdr/afsrdr.h @@ -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 index 0000000..e5ef053 --- /dev/null +++ b/src/WINNT/afsrdr/afsrdr.rc @@ -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 + +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 diff --git a/src/WINNT/afsrdr/ifs_rpc.c b/src/WINNT/afsrdr/ifs_rpc.c index 07139f6..85a20dd 100644 --- a/src/WINNT/afsrdr/ifs_rpc.c +++ b/src/WINNT/afsrdr/ifs_rpc.c @@ -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 diff --git a/src/WINNT/afsrdr/ifs_rpc.h b/src/WINNT/afsrdr/ifs_rpc.h index 9fa1abb..001eea0 100644 --- a/src/WINNT/afsrdr/ifs_rpc.h +++ b/src/WINNT/afsrdr/ifs_rpc.h @@ -37,6 +37,21 @@ #include #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 @@ -52,16 +67,19 @@ #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; diff --git a/src/WINNT/afsrdr/kif.h b/src/WINNT/afsrdr/kif.h index 513f61d..0eac2d7 100644 --- a/src/WINNT/afsrdr/kif.h +++ b/src/WINNT/afsrdr/kif.h @@ -28,6 +28,28 @@ * 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 @@ -57,11 +79,12 @@ #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(); diff --git a/src/WINNT/afsrdr/sources b/src/WINNT/afsrdr/sources index 41abfe9..588c5ad 100644 --- a/src/WINNT/afsrdr/sources +++ b/src/WINNT/afsrdr/sources @@ -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 diff --git a/src/WINNT/install/NSIS/OpenAFS.nsi b/src/WINNT/install/NSIS/OpenAFS.nsi index ab15ed4..e573e30 100644 --- a/src/WINNT/install/NSIS/OpenAFS.nsi +++ b/src/WINNT/install/NSIS/OpenAFS.nsi @@ -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" -- 1.9.4