break;
case WM_DESTROY:
-#ifndef AFSIFS
- RpcMgmtStopServerListening(NULL);
-#else
+#ifdef AFSIFS
SetEvent(DoTerminate);
#endif
+ RpcMgmtStopServerListening(NULL);
PostQuitMessage(0);
break;
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;
dwResult = WNetCancelConnection2(szDriveToMapTo, 0, TRUE);
}
#else
- /* FIXFIX */
+ /* FIXFIX: implement */
#endif
}
afsi_log("Disconnect from GlobalAutoMap of %s to %s %s", szDriveToMapTo, szSubMount, dwResult ? "succeeded" : "failed");
}
#else
- /* FIXFIX */
+ /* FIXFIX: implement */
#endif
RegCloseKey(hKey);
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;
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) {
rx_Finalize();
afsi_log("rx finalization complete");
- smb_Shutdown();
+#ifndef AFSIFS
+ smb_Shutdown();
afsi_log("smb shutdown complete");
+#endif
RpcShutdown();
SetEvent(WaitToTerminate);
#else
SetEvent(DoTerminate);
+ dc_release_hooks();
#endif
}
}
/****************************/
#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;
/****************************/
/* 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;
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;
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:
/****************************/
/* 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;
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;
/* 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;
}
/* 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;
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;
/****************************/
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;
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;
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 */
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)
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);
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;
*fid = st->fid;
*granted = access;
+ free(buffer);
+
return 0;
}
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)
{
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));
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;
return IFSL_UNSPEC;
}
#endif
- /*cm_SyncOp(scp, NULL,
- cm_Flush(*/
- //MAP_RETURN(code);
return 0;
}
cm_scache_t *scp;
cm_req_t req;
- //_asm int 3;
-
*read = 0;
scp = ifs_FindScp(fid);
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);
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;
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);
}
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;
}
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);
}
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);
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);
lock_ObtainMutex(&(scp->mx));
cm_ReleaseSCache(scp);
- if (!scp->refCount)
- cm_DiscardSCache(scp);
lock_ReleaseMutex(&(scp->mx));
prev = NULL, curr = scp_list_head;
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);
{
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";
}
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);
unsigned char *bufIn, *bufOut;
DWORD lenIn, lenOut, status;
DWORD err;
- OVERLAPPED olp;
rpc_t rpc;
BOOL st;
{
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;
}
}
}
+ /* 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
#include "afsd.h"
#include <WINNT/syscfg.h>
#include <WINNT/afsreg.h>
+#include <../afsrdr/kif.h>
/*extern void afsi_log(char *pattern, ...);*/
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.
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,
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;
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);
{
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. */
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;
* 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;
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;
}
#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))
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;
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();
#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)*/
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;
/* 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)
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)
{
}
/* 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)
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)
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;
+ }
}
}
}
*/
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)
{
/* 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 */
fcb->fid = fid;
/*fcb->refs = 0;*/
fcb->ccb_list = NULL;
- fcb->IsFastIoPossible = FastIoIsNotPossible;
+ fcb->IsFastIoPossible = FastIoIsPossible;
ExInitializeResourceLite(&fcb->_resource);
ExInitializeResourceLite(&fcb->_pagingIoResource);
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;
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;
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)
{
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
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
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();
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)
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;
}
}
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);
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)
{
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)
{
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)
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;
}
}
else
{
- //UNLOCK_FCB;
if (paging_lock)
UNLOCK_PAGING_FCB;
break;
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;
}
}
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);
ccb->str.Buffer = ccb->name;
FsRtlEnterFileSystem();
- LOCK_FCB; /* FIX: shared lock? */
+ LOCK_FCB;
FsRtlNotifyFullChangeDirectory(rdrExt->notifyList, &rdrExt->listHead,
ccb,
(STRING*)&ccb->str,
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);
}
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)
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;
if (infoDisp->DeleteFile)
{
if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
+ {
+ UNLOCK_FCB;
+ FsRtlExitFileSystem();
SYNC_FAIL(STATUS_ACCESS_DENIED);
+ }
fcb->delPending |= 0x1;
}
else
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;
}
}
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;
}
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));
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));
return 0;
}
+dc_release_hooks()
+{
+ KeSetEvent(&comExt->cancelEvent, 0, FALSE);
+}
+
/**********************************************************
* AfsRdrDeviceControl
* - handle communication requests from fs, etc.
UNICODE_STRING nm;
void *outPtr;
ULONG key, code, length;
+ LARGE_INTEGER wait;
/* utility ioctls */
if (DeviceObject == ComDevice &&
{
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);
{
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,
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);
}
ret = Irp->IoStatus.Status;
- COMPLETE;
+ COMPLETE; /* complete with priority boost */
return ret;
}
#if 0
try {
#endif
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
if (IrpSp->FileObject->FileName.Length == 0)
SYNC_FAIL(STATUS_SUCCESS);
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);
#if 0
} except(EXCEPTION_EXECUTE_HANDLER)
{
- _asm int 3;
STATUS(STATUS_UNSUCCESSFUL, 0);
ExReleaseResourceLite(&ext->fcbLock);
FsRtlExitFileSystem();
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;
{
uc_unlink(ccb->name+2);
}
+ if (fcb->lock)
+ FsRtlFreeFileLock(fcb->lock);
ExDeleteResourceLite(&fcb->_resource);
ExDeleteResourceLite(&fcb->_pagingIoResource);
RtlDeleteElementGenericTable(&rdrExt->fcbTable, &fcb);
**********************************************************/
NTSTATUS AfsRdrShutdown(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
{
- _asm int 3;
STATUS(STATUS_SUCCESS, 0);
COMPLETE;
+ return 0;
}
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;
}
{
NTSTATUS ret;
- /*TRY*/
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
/* complete lock on control device object without processing, as directed */
if (IrpSp->FileObject->FileName.Length == 0)
{
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);*/
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;
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
SYNC_FAIL2(STATUS_SUCCESS, sizeof(*infoVolume) + (infoVolume->VolumeLabelLength - sizeof(WCHAR)));
}
break;
- //case FileFsFullSizeInformation:
- //TODO:
}
EXCEPT(STATUS_UNSUCCESSFUL, 0);
IoDeleteDevice(ComDevice);
IoDeleteDevice(RdrDevice);
-#ifdef RPT_ENA
- rptCliClose(REPORT);
-#endif
-
KdPrint(("RdrUnload exiting.\n"));
}
ULONG len;
ULONG code, read;
PACCESS_TOKEN acc_token;
+ PVOID waitPair[2];
ext = (struct ComExtension *)DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(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);
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);
}
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);
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)
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,
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)
{
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();
}
BOOLEAN ret;
LARGE_INTEGER adj_end;
afs_fcb_t *fcb;
+ LARGE_INTEGER temp;
fcb = FileObject->FsContext;
ASSERT(fcb);
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
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();
}
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");
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++)
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;
/*} except(EXCEPTION_EXECUTE_HANDLER)
{
- _asm int 3;
- //logerror();
return -1;
}*/
struct AfsRdrExtension
{
struct ComExtension *com;
-KMUTEX protectMutex;
PNOTIFY_SYNC notifyList;
LIST_ENTRY listHead;
NPAGED_LOOKASIDE_LIST fcbMemList;
struct AfsRdrExtension *rdr;
LIST_ENTRY outReqList;
KSPIN_LOCK outLock;
-RTL_GENERIC_TABLE inTable;
FAST_MUTEX inLock;
KEVENT outEvent, cancelEvent;
};
--- /dev/null
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* Define VERSIONINFO resource */
+
+#define AFS_VERINFO_FILE_DESCRIPTION "AFS Network Redirector Driver"
+#define AFS_VERINFO_NAME "afsrdr"
+#define AFS_VERINFO_FILENAME "afsrdr.sys"
+
+#include "..\afsd\AFS_component_version_number.h"
+
+#include <winver.h>
+
+1 VERSIONINFO
+ FILEVERSION AFS_VERINFO_FILEVER
+ PRODUCTVERSION AFS_VERINFO_FILEVER
+ FILEOS VOS_NT
+#ifdef AFS_VERINFO_DLL
+ FILETYPE VFT_DLL
+#else
+ FILETYPE VFT_APP
+#endif
+BEGIN
+ BLOCK "StringFileInfo"
+ /* FileVersion must be specified or data won't appear on properties tab */
+ /* Internalname and originalfilename must be specified or explorer won't
+ show version and description */
+ BEGIN
+ BLOCK "000004E4"
+ BEGIN
+ VALUE "CompanyName", "OpenAFS Project", "\0"
+ VALUE "LegalCopyright", "Copyright \251 the Regents of the University of Michigan, 2005.", "\0"
+ VALUE "ProductName", "OpenAFS for Windows", "\0"
+ VALUE "ProductVersion", "1.0", "\0"
+ VALUE "FileVersion", "1.0", "\0"
+ VALUE "FileDescription", AFS_VERINFO_FILE_DESCRIPTION, "\0"
+ VALUE "Build", AFS_VERINFO_BUILD, "\0"
+ VALUE "InternalName", AFS_VERINFO_NAME, "\0"
+ VALUE "OriginalFilename", AFS_VERINFO_FILENAME, "\0"
+ END
+ END
+ /* files in msi's are supposed to have language codes attached to them.
+ this is how they get populated automatically */
+ BLOCK "VarFileInfo"
+ BEGIN
+#ifdef AFS_VERINFO_LANG_CODE
+ VALUE "Translation", AFS_VERINFO_LANG_CODE, AFS_VERINFO_CHARSET
+#else
+/* default to 0, 1252 */
+ VALUE "Translation", 0, 0x4e4
+#endif
+ END
+END
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)
{
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;
}
}
{
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;
}
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
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)
{
NTSTATUS status;
HANDLE token;
+ /* get user's identification from auth token*/
token = rpc_get_context();
ASSERT(token);
status = SeQueryAuthenticationIdToken(token, &auth_id);
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;
}
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);
rpc_t *curr;
int count;
- /*ExFreePoolWithTag(rpc, 0x1234);*/
ifs_lock_rpcs();
if (rpc_upgrade(rpc, -1, 0))
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);
{
if (!rpc)
return;
- //_asm int 3;
free(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
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));
rpc_unmarshal_long(rpc, fid);
rpc_destroy(rpc);
- TIMING_END("namei");
return status;
}
{
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);
rpc_unmarshal_long(rpc, granted);
rpc_destroy(rpc);
- TIMING_END("access");
return status;
}
{
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);
rpc_unmarshal_long(rpc, fid);
rpc_destroy(rpc);
- TIMING_END("create");
return status;
}
{
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);
rpc_unmarshal_longlong(rpc, written);
rpc_destroy(rpc);
- TIMING_END("stat");
return status;
}
{
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);
rpc_unmarshal_long(rpc, &status);
rpc_destroy(rpc);
- TIMING_END("setinfo");
return status;
}
{
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);
rpc_unmarshal_long(rpc, &status);
rpc_destroy(rpc);
- TIMING_END("trunc");
return status;
}
{
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);
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);
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);
rpc_unmarshal_long(rpc, len);
rpc_destroy(rpc);
- TIMING_END("readdir");
return status;
}
{
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);
rpc_unmarshal_long(rpc, &status);
rpc_destroy(rpc);
- TIMING_END("close");
return status;
}
{
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);
rpc_unmarshal_long(rpc, &status);
rpc_destroy(rpc);
- TIMING_END("unlink");
return status;
}
{
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);
rpc_unmarshal_long(rpc, key);
rpc_destroy(rpc);
- TIMING_END("ioctl_write");
return status;
}
{
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);
rpc_unmarshal_long(rpc, length);
rpc_destroy(rpc);
- TIMING_END("ioctl_read");
return status;
}
{
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);
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
ULONG status;
rpc = rpc_create(0);
+ if (!rpc)
+ return IFSL_MEMORY;
rpc_marshal_long(rpc, RPC_BREAK_CALLBACK);
rpc_marshal_long(rpc, 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
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;
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()
{
next = curr->next;
ExFreePoolWithTag(curr, 0x1234);
+ num_rpcs--;
curr = next;
}
rpc_list_head = NULL;
{
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;
}
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)
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
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);
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;
}
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
*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;
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;
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
#include <winioctl.h>
#endif
+
+/* maximum number of users, based on SID, that can access AFS at one time */
+#define MAX_AFS_USERS 20
+
+/* maximum number of threads that can make simultaneous calls into afsrdr,
+ because we maintain a credential set for each thread in a single table. */
+#define MAX_CRED_MAPS 32
+
+/* size if outgoing/incoming RPC buffer (for parameters only, not bulk data) */
+#define RPC_BUF_SIZE 2048
+
+/* max. chunk size for RPC transfers */
+#define TRANSFER_CHUNK_SIZE (1024*1024)
+
+
/* upcalls */
#define RPC_NAMEI 0x10
#define RPC_CHECK_ACCESS 0x11
#define RPC_IOCTL_WRITE 0x1B
#define RPC_IOCTL_READ 0x1C
#define RPC_RENAME 0x1D
-#define RPC_READ_BULK 0x1E
-#define RPC_WRITE_BULK 0x1F
+#define RPC_FLUSH 0x1E
+
/* downcalls */
#define RPC_BREAK_CALLBACK 0x80
+#define RPC_RELEASE_HOOKS 0x81
-#define TRANSFER_CHUNK_SIZE (1024*1024)
+
+/* internal module flags */
#define RPC_TIMEOUT_SHORT 0
#define RPC_TIMEOUT_LONG 1
+
/* internal data struct for both client and server */
struct rpc
{
#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;
* 03-jun 2005 (eric williams) entered into versioning
*/
+
+/* this is based on BUF_FILEHASH, but we were not getting unique hashes */
+#define FID_HASH_FN(fidp) ((((fidp)->vnode + \
+ ((fidp)->unique << 13) + ((fidp)->unique >> (32-13)) + \
+ (fidp)->volume + \
+ (fidp)->cell)))
+
+
+/* dirent information */
+struct readdir_data
+ {
+ LARGE_INTEGER cookie;
+ long offset;
+ LARGE_INTEGER creation, access, write, change, size;
+ ULONG attribs, name_length; /* chars */
+ CCHAR short_name_length; /* chars */
+ WCHAR short_name[14];
+ WCHAR name[];
+ };
+typedef struct readdir_data readdir_data_t;
+
+
/* error codes */
#define IFSL_SUCCESS_BASE 0x00000000
#define IFSL_FAIL_BASE 0x80000000
#define IFSL_NOT_EMPTY (IFSL_FAIL_BASE + 22)
#define IFSL_RPC_TIMEOUT (IFSL_FAIL_BASE + 23)
#define IFSL_OVERQUOTA (IFSL_FAIL_BASE + 24)
-#define IFSL_UNSPEC (IFSL_FAIL_BASE + 25)
+#define IFSL_MEMORY (IFSL_FAIL_BASE + 25)
+#define IFSL_UNSPEC (IFSL_FAIL_BASE + 26)
/* ioctl codes */
-#define IOCTL_AFSRDR_IOCTL CTL_CODE(IOCTL_DISK_BASE, 0x007, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+#define IOCTL_AFSRDR_IOCTL CTL_CODE(IOCTL_DISK_BASE, 0x007, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_AFSRDR_DOWNCALL CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_AFSRDR_GET_PATH CTL_CODE(IOCTL_DISK_BASE, 0x009, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
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();
# * possibility of such damages.
# */
-SOURCES= afsrdr.c ifs_rpc.c
+SOURCES= afsrdr.c ifs_rpc.c afsrdr.rc
TARGETNAME=afsrdr
TARGETPATH=obj
TARGETTYPE=DRIVER
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"