Windows: Redirector interface for afsd_service.exe

Over the last three years the afsd_service sources have been
gradually separated into distinct layers for the SMB server
and the AFS cache.  The eventual goal of this work was to
permit the addition of alternative interfaces to the cache
manager in parallel.

This patchset implements the first alternative interface,
a reverse ioctl model that communicates with a native IFS
redirector driver.  The driver will be submitted in a
subsequent patchset.

Although it is possible to run afsd_service with both the
SMB and RDR interfaces active at the same time.  In practice
it is somewhat impractical because it destroys the uniformity
of the \\AFS name space.  The RDR loads at boot time and claims
all of \\AFS.  The SMB interface if active at the same time
must use the old \\%HOSTNAME%-AFS.  As implemented, if the RDR
interface is functional the SMB interface is not started.  Only
if the RDR interface fails will the SMB interface be activated.

The afsd_service.exe maintains all of its primary responsibilities
for communicating with the AFS servers, processing callbacks,
enforcing permissions, handling afs path ioctls, Windows RPC
service simulation, and object management.  The biggest change
is in the cm_buf_t management.  Data is exchanged with the
RDR by passing control over cm_buf_t->data buffers in the form
of Windows File Extents.  This avoids data copies across a
communication channel which significantly improves performance
at a substantial complexity cost.

Credential management is switched from a Windows username binding
to a GUID binding where the GUIDs represent authentication groups
that are managed by the RDR.

This patchset includes additional changes to support integrated
logon in conjunction with the RDR.  In particular, adding support
for authentication groups.

Change-Id: I7135489421c67a429ec3b2acd4c8ae08b8329f6d
Reviewed-on: http://gerrit.openafs.org/5432
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Tested-by: Rod Widdowson <rdw@steadingsoftware.com>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
This commit is contained in:
Jeffrey Altman 2011-09-15 01:11:15 -04:00 committed by Jeffrey Altman
parent f03cef68fb
commit b91d39edec
42 changed files with 12561 additions and 462 deletions

View File

@ -7,7 +7,7 @@
AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" /DSMB_UNICODE -I..\kfw\inc\loadfuncs \
-I..\kfw\inc\krb5 -I..\kfw\inc\leash -I$(DESTDIR)\include\afs \
-I$(DESTDIR)\include\rx
-I$(DESTDIR)\include\rx -I..\afsrdr\common -I..\afsrdr\user
AFSDEV_NETGUI = 1
RELDIR=WINNT\afsd
!INCLUDE ..\..\config\NTMakefile.$(SYS_NAME)
@ -153,10 +153,26 @@ AFSDOBJS=\
$(OUT)\ms-wkssvc_s.obj \
$(OUT)\rpc_wkssvc.obj \
$(OUT)\rpc_srvsvc.obj \
$(OUT)\AFS_component_version_number.obj
$(OUT)\AFS_component_version_number.obj \
$(OUT)\RDRInit.obj \
$(OUT)\RDRFunction.obj \
$(OUT)\RDRIoctl.obj \
$(OUT)\RDRPipe.obj
$(AFSDOBJS):
$(OUT)\RDRInit.obj: ..\afsrdr\user\RDRInit.cpp ..\afsrdr\user\RDRPrototypes.h ..\afsrdr\user\RDRIoctl.h
$(CPP2OBJ) ..\afsrdr\user\RDRInit.cpp
$(OUT)\RDRFunction.obj: ..\afsrdr\user\RDRFunction.c ..\afsrdr\user\RDRPrototypes.h ..\afsrdr\user\RDRIoctl.h
$(C2OBJ) ..\afsrdr\user\RDRFunction.c
$(OUT)\RDRIoctl.obj: ..\afsrdr\user\RDRIoctl.c ..\afsrdr\user\RDRIoctl.h
$(C2OBJ) ..\afsrdr\user\RDRIoctl.c
$(OUT)\RDRPipe.obj: ..\afsrdr\user\RDRPipe.c ..\afsrdr\user\RDRPipe.h
$(C2OBJ) ..\afsrdr\user\RDRPipe.c
$(OUT)\cm_conn.obj: cm_conn.c
$(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
@ -317,7 +333,8 @@ LOGON_DLLSDKLIBS =\
activeds.lib \
user32.lib \
userenv.lib \
shell32.lib
shell32.lib \
rpcrt4.lib
$(LOGON_DLLFILE): $(LOGON_DLLOBJS) $(LOGON_DLLLIBS)
$(DLLGUILINK) $(LOGONLINKFLAGS) -def:afslogon.def $(LOGON_DLLSDKLIBS)
@ -450,12 +467,14 @@ AFSD_EXELIBS =\
$(DESTDIR)\lib\afs\mtafsvldb.lib \
$(DESTDIR)\lib\afs\mtafsint.lib \
$(DESTDIR)\lib\afsrpc.lib \
$(DESTDIR)\lib\afsrxkad.lib \
$(DESTDIR)\lib\afs\mtafsutil.lib \
$(DESTDIR)\lib\afsauthent.lib \
$(DESTDIR)\lib\libafsconf.lib \
$(DESTDIR)\lib\afs\afsreg.lib \
$(DESTDIR)\lib\afspthread.lib \
$(DESTDIR)\lib\afsroken.lib \
$(DESTDIR)\lib\afshcrypto.lib \
$(LANAHELPERLIB)
$(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res $(RXOBJS) $(AFSD_EXELIBS)

View File

@ -60,6 +60,7 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
#include "cm_memmap.h"
#include "cm_freelance.h"
#include "cm_performance.h"
#include "cm_rdr.h"
#include "afsd_init.h"
#include "afsd_eventlog.h"

View File

@ -103,9 +103,10 @@ BOOL reportSessionStartups = FALSE;
cm_initparams_v1 cm_initParams;
clientchar_t *cm_sysName = 0;
unsigned int cm_sysNameCount = 0;
clientchar_t *cm_sysNameList[MAXNUMSYSNAMES];
unsigned int cm_sysName64Count = 0;
clientchar_t *cm_sysName64List[MAXNUMSYSNAMES];
DWORD TraceOption = 0;
@ -917,12 +918,15 @@ afsd_InitCM(char **reasonP)
for ( i=0; i < MAXNUMSYSNAMES; i++ ) {
cm_sysNameList[i] = osi_Alloc(MAXSYSNAME * sizeof(clientchar_t));
cm_sysNameList[i][0] = '\0';
cm_sysName64List[i] = osi_Alloc(MAXSYSNAME * sizeof(clientchar_t));
cm_sysName64List[i][0] = '\0';
}
cm_sysName = cm_sysNameList[0];
/* Process SysName lists from the registry */
{
clientchar_t *p, *q;
clientchar_t * cbuf = (clientchar_t *) buf;
dummyLen = sizeof(buf);
code = RegQueryValueExW(parmKey, L"SysName", NULL, NULL, (LPBYTE) cbuf, &dummyLen);
if (code != ERROR_SUCCESS || !cbuf[0]) {
@ -934,7 +938,7 @@ afsd_InitCM(char **reasonP)
cm_ClientStrCpy(cbuf, lengthof(buf), _C("x86_win32 i386_w2k i386_nt40"));
#endif
}
afsi_log("Sys name %S", cbuf);
afsi_log("Sys name list: %S", cbuf);
/* breakup buf into individual search string entries */
for (p = q = cbuf; p < cbuf + dummyLen; p++) {
@ -944,16 +948,49 @@ afsd_InitCM(char **reasonP)
cm_sysNameCount++;
do {
if (*p == '\0')
goto done_sysname;
goto done_sysname32;
p++;
} while (*p == '\0' || isspace(*p));
q = p;
p--;
}
}
done_sysname32:
;
#ifdef _WIN64
/*
* If there is a 64-bit list, process it. Otherwise, we will leave
* it undefined which implies that the 32-bit list be used for both.
* The 64-bit list is only used for the native file system driver.
* The SMB redirector interface does not provide any means of indicating
* the source of the request.
*/
dummyLen = sizeof(buf);
code = RegQueryValueExW(parmKey, L"SysName64", NULL, NULL, (LPBYTE) cbuf, &dummyLen);
if (code == ERROR_SUCCESS && cbuf[0]) {
afsi_log("Sys name 64 list: %S", cbuf);
/* breakup buf into individual search string entries */
for (p = q = cbuf; p < cbuf + dummyLen; p++) {
if (*p == '\0' || iswspace(*p)) {
memcpy(cm_sysName64List[cm_sysName64Count],q,(p-q) * sizeof(clientchar_t));
cm_sysName64List[cm_sysName64Count][p-q] = '\0';
cm_sysName64Count++;
do {
if (*p == '\0')
goto done_sysname64;
p++;
} while (*p == '\0' || isspace(*p));
q = p;
p--;
}
}
}
done_sysname64:
;
#endif
}
done_sysname:
cm_ClientStrCpy(cm_sysName, MAXSYSNAME, cm_sysNameList[0]);
dummyLen = sizeof(cryptall);
code = RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
@ -1527,11 +1564,11 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
}
if ( smb_Enabled ) {
/* Do this last so that we don't handle requests before init is done.
* Here we initialize the SMB listener.
*/
smb_Init(afsd_logp, smb_UseV3, numSvThreads, aMBfunc);
afsi_log("smb_Init complete");
/* Do this last so that we don't handle requests before init is done.
* Here we initialize the SMB listener.
*/
smb_Init(afsd_logp, smb_UseV3, numSvThreads, aMBfunc);
afsi_log("smb_Init complete");
} else {
afsi_log("smb_Init skipped");
}

View File

@ -1327,6 +1327,21 @@ afsd_Main(DWORD argc, LPTSTR *argv)
/* Notify any volume status handlers that the cache manager has started */
cm_VolStatus_Service_Started();
code = RDR_Initialize();
RDR_Initialized = !code;
afsi_log("RDR_Initialize returned: (code = %d)", code);
if (RDR_Initialized) {
if (cm_sysNameCount)
RDR_SysName( AFS_SYSNAME_ARCH_32BIT, cm_sysNameCount, cm_sysNameList );
#ifdef _WIN64
if (cm_sysName64Count)
RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysName64Count, cm_sysName64List );
else if (cm_sysNameCount)
RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysNameCount, cm_sysNameList );
#endif
}
/*
* Set the default for the SMB interface based upon the state of the
* Redirector interface.
@ -1464,11 +1479,15 @@ afsd_Main(DWORD argc, LPTSTR *argv)
DismountGlobalDrives();
afsi_log("Global Drives dismounted");
if (RDR_Initialized) {
RDR_ShutdownNotify();
cm_VolStatus_SetRDRNotifications(FALSE);
afsi_log("RDR notified of shutdown");
}
smb_Shutdown();
afsi_log("smb shutdown complete");
RpcShutdown();
cm_ReleaseAllLocks();
cm_DaemonShutdown();
@ -1479,8 +1498,15 @@ afsd_Main(DWORD argc, LPTSTR *argv)
afsd_ShutdownCM();
RpcShutdown();
cm_ShutdownMappedMemory();
if (RDR_Initialized) {
RDR_ShutdownFinal();
afsi_log("RDR shutdown complete");
}
rx_Finalize();
afsi_log("rx finalization complete");

View File

@ -11,16 +11,20 @@
#include <afs/param.h>
#include <roken.h>
#include "afslogon.h"
#include <io.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <winsock2.h>
#include <winioctl.h>
#define SECURITY_WIN32
#include <sspi.h>
#include <lm.h>
#include <nb30.h>
#include <sddl.h>
#include "afslogon.h"
#include <afs/stds.h>
#include <afs/pioctl_nt.h>
@ -810,7 +814,8 @@ UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOu
return FALSE;
} // UnicodeStringToANSI
DWORD APIENTRY NPLogonNotify(
DWORD APIENTRY
NPLogonNotify(
PLUID lpLogonId,
LPCWSTR lpAuthentInfoType,
LPVOID lpAuthentInfo,
@ -850,6 +855,8 @@ DWORD APIENTRY NPLogonNotify(
int retryInterval;
int sleepInterval;
CtxtHandle LogonContext;
/* Are we interactive? */
interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
@ -952,7 +959,7 @@ DWORD APIENTRY NPLogonNotify(
/* Get cell name if doing integrated logon.
We might overwrite this if we are logging into an AD realm and we find out that
the user's home dir is in some other cell. */
DebugEvent("About to call cm_GetRootCellName()");
DebugEvent0("About to call cm_GetRootCellName()");
code = cm_GetRootCellName(cell);
if (code < 0) {
DebugEvent0("Unable to obtain Root Cell");
@ -972,7 +979,8 @@ DWORD APIENTRY NPLogonNotify(
}
}
/* loop until AFS is started. */
AFSCreatePAG(lpLogonId);
if (afsWillAutoStart) {
/*
* If the service is configured for auto start but hasn't started yet,
@ -981,12 +989,12 @@ DWORD APIENTRY NPLogonNotify(
if (!(IsServiceRunning() || IsServiceStartPending()))
StartTheService();
/* loop until AFS is started or fails. */
while ( IsServiceStartPending() ) {
Sleep(10);
}
while (IsServiceRunning() && code != KTC_NOCM && code != KTC_NOCMRPC && code != KTC_NOCELL) {
DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
opt.LogonOption,afsWillAutoStart);
@ -1004,6 +1012,9 @@ DWORD APIENTRY NPLogonNotify(
/* if Integrated Logon */
if (ISLOGONINTEGRATED(opt.LogonOption))
{
LogonSSP(lpLogonId, &LogonContext);
ImpersonateSecurityContext(&LogonContext);
if ( KFW_is_available() ) {
SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
if (opt.realm) {
@ -1077,6 +1088,10 @@ DWORD APIENTRY NPLogonNotify(
DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
}
RevertSecurityContext(&LogonContext);
DeleteSecurityContext(&LogonContext);
if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
for ( ctemp = uname; *ctemp ; ctemp++) {
*ctemp = tolower(*ctemp);
@ -1128,8 +1143,8 @@ DWORD APIENTRY NPLogonNotify(
Sleep(sleepInterval * 1000);
retryInterval -= sleepInterval;
}
DebugEvent0("while loop exited");
}
DebugEvent0("while loop exited");
/* remove any kerberos 5 tickets currently held by the SYSTEM account
* for this user

View File

@ -26,7 +26,6 @@ SOFTWARE.
/* We only support VC 1200 and above anyway */
#pragma once
#include <windows.h>
#include <objbase.h>
#include <npapi.h>
#if (_WIN32_WINNT < 0x0501)
@ -132,6 +131,10 @@ DWORD GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonO
DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWSTR domain);
BOOL GetLocalShortDomain(PWSTR Domain, DWORD cbDomain);
void AFSCreatePAG(PLUID lpLogonId);
DWORD LogonSSP(PLUID lpLogonId, PCtxtHandle outCtx);
#ifdef __cplusplus
}
#endif

View File

@ -45,6 +45,7 @@
#define LOCK_HIERARCHY_IGNORE 0
#define LOCK_HIERARCHY_RDR_GLOBAL 10
#define LOCK_HIERARCHY_SMB_STARTED 20
#define LOCK_HIERARCHY_SMB_LISTENER 30
#define LOCK_HIERARCHY_SMB_DIRWATCH 40
@ -87,5 +88,8 @@
#define LOCK_HIERARCHY_AFSDBSBMT_GLOBAL 1000
#define LOCK_HIERARCHY_TOKEN_EVENT_GLOBAL 2000
#define LOCK_HIERARCHY_SYSCFG_GLOBAL 3000
#define LOCK_HIERARCHY_RDR_EXTENTS 0
#endif /* OPENAFS_WINNT_AFSD_CM_H */

View File

@ -338,6 +338,9 @@ void cm_InvalidateACLUser(cm_scache_t *scp, cm_user_t *userp)
aclp->userp = NULL;
aclp->backp = (struct cm_scache *) 0;
found = 1;
if (RDR_Initialized && cm_HaveCallback(scp))
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_CREDS);
break;
}
}
@ -351,6 +354,7 @@ void cm_InvalidateACLUser(cm_scache_t *scp, cm_user_t *userp)
void
cm_ResetACLCache(cm_cell_t *cellp, cm_user_t *userp)
{
cm_volume_t *volp, *nextVolp;
cm_scache_t *scp, *nextScp;
afs_uint32 hash;
@ -369,6 +373,40 @@ cm_ResetACLCache(cm_cell_t *cellp, cm_user_t *userp)
}
}
lock_ReleaseRead(&cm_scacheLock);
if (RDR_Initialized) {
lock_ObtainRead(&cm_volumeLock);
for (hash = 0; hash < cm_data.volumeHashTableSize; hash++) {
for ( volp = cm_data.volumeRWIDHashTablep[hash]; volp; volp = nextVolp) {
nextVolp = volp->vol[RWVOL].nextp;
if ((cellp == NULL || cellp->cellID == volp->cellp->cellID) &&
volp->vol[RWVOL].ID) {
lock_ReleaseRead(&cm_volumeLock);
RDR_InvalidateVolume(volp->cellp->cellID, volp->vol[RWVOL].ID, AFS_INVALIDATE_CREDS);
lock_ObtainRead(&cm_volumeLock);
}
}
for ( volp = cm_data.volumeROIDHashTablep[hash]; volp; volp = nextVolp) {
nextVolp = volp->vol[ROVOL].nextp;
if ((cellp == NULL || cellp->cellID == volp->cellp->cellID) &&
volp->vol[ROVOL].ID) {
lock_ReleaseRead(&cm_volumeLock);
RDR_InvalidateVolume(volp->cellp->cellID, volp->vol[ROVOL].ID, AFS_INVALIDATE_CREDS);
lock_ObtainRead(&cm_volumeLock);
}
}
for ( volp = cm_data.volumeBKIDHashTablep[hash]; volp; volp = nextVolp) {
nextVolp = volp->vol[BACKVOL].nextp;
if ((cellp == NULL || cellp->cellID == volp->cellp->cellID) &&
volp->vol[BACKVOL].ID) {
lock_ReleaseRead(&cm_volumeLock);
RDR_InvalidateVolume(volp->cellp->cellID, volp->vol[BACKVOL].ID, AFS_INVALIDATE_CREDS);
lock_ObtainRead(&cm_volumeLock);
}
}
}
lock_ReleaseRead(&cm_volumeLock);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,8 @@ extern int buf_cacheType;
/* represents a single buffer */
typedef struct cm_buf {
osi_queue_t q; /* queue of all zero-refcount buffers */
afs_uint32 qFlags; /* queue/hash state flags - buf_globalLock */
osi_queue_t q; /* queue: buf_freeList and buf_redirList */
afs_uint32 qFlags; /* queue/hash state flags - buf_globalLock */
afs_uint32 magic;
struct cm_buf *allp; /* next in all list */
struct cm_buf *hashp; /* hash bucket pointer */
@ -77,7 +77,7 @@ typedef struct cm_buf {
afs_uint32 waitRequests; /* num of thread wait requests */
afs_uint32 dirty_offset; /* offset from beginning of buffer containing dirty bytes */
afs_uint32 dirty_length; /* number of dirty bytes within the buffer */
afs_uint32 dirty_length; /* number of dirty bytes within the buffer */
#ifdef DISKCACHE95
cm_diskcache_t *dcp; /* diskcache structure */
@ -88,8 +88,17 @@ typedef struct cm_buf {
#else
void * dummy;
#endif
/* redirector state - protected by buf_globalLock */
osi_queue_t redirq; /* queue: cm_scache_t redirList */
time_t redirLastAccess;/* last time redir accessed the buffer */
time_t redirReleaseRequested;
unsigned char md5cksum[16]; /* md5 checksum of the block pointed to by datap */
} cm_buf_t;
#define redirq_to_cm_buf_t(q) ((q) ? (cm_buf_t *)((char *) (q) - offsetof(cm_buf_t, redirq)) : NULL)
/* values for cmFlags */
#define CM_BUF_CMFETCHING 1 /* fetching this buffer */
#define CM_BUF_CMSTORING 2 /* storing this buffer */
@ -132,8 +141,6 @@ extern long buf_Init(int newFile, cm_buf_ops_t *, afs_uint64 nbuffers);
extern void buf_Shutdown(void);
extern long buf_CountFreeList(void);
#ifdef DEBUG_REFCOUNT
extern void buf_ReleaseDbg(cm_buf_t *, char *, long);
@ -212,10 +219,51 @@ extern long buf_DirtyBuffersExist(cm_fid_t * fidp);
extern long buf_CleanDirtyBuffers(cm_scache_t *scp);
extern long buf_RDRBuffersExist(cm_fid_t *fidp);
extern long buf_ClearRDRFlag(cm_scache_t *scp, char * reason);
extern long buf_ForceDataVersion(cm_scache_t * scp, afs_uint64 fromVersion, afs_uint64 toVersion);
extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
extern void buf_ComputeCheckSum(cm_buf_t *bp);
extern int buf_ValidateCheckSum(cm_buf_t *bp);
extern const char *buf_HexCheckSum(cm_buf_t * bp);
extern afs_uint32
buf_RDRShakeSomeExtentsFree(cm_req_t *reqp, afs_uint32 oneFid, afs_uint32 minage);
extern afs_uint32
buf_RDRShakeAnExtentFree(cm_buf_t *bufp, cm_req_t *reqp);
extern afs_uint32
buf_RDRShakeFileExtentsFree(cm_scache_t *scp, cm_req_t *reqp);
extern void
buf_InsertToRedirQueue(cm_scache_t *scp, cm_buf_t *bufp);
extern void
buf_RemoveFromRedirQueue(cm_scache_t *scp, cm_buf_t *bufp);
extern void
buf_MoveToHeadOfRedirQueue(cm_scache_t *scp, cm_buf_t *bufp);
#ifdef _M_IX86
#define buf_IncrementRedirCount() InterlockedIncrement(&cm_data.buf_redirCount)
#define buf_DecrementRedirCount() InterlockedDecrement(&cm_data.buf_redirCount)
#define buf_IncrementFreeCount() InterlockedIncrement(&cm_data.buf_freeCount)
#define buf_DecrementFreeCount() InterlockedDecrement(&cm_data.buf_freeCount)
#else
#define buf_IncrementRedirCount() InterlockedIncrement64(&cm_data.buf_redirCount)
#define buf_DecrementRedirCount() InterlockedDecrement64(&cm_data.buf_redirCount)
#define buf_IncrementFreeCount() InterlockedIncrement64(&cm_data.buf_freeCount)
#define buf_DecrementFreeCount() InterlockedDecrement64(&cm_data.buf_freeCount)
#endif
/* error codes */
#define CM_BUF_EXISTS 1 /* buffer exists, and shouldn't */
#endif /* OPENAFS_WINNT_AFSD_BUF_H */

View File

@ -197,6 +197,10 @@ void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
osi_Log4(afsd_logp, "RevokeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
lock_ObtainWrite(&scp->rw);
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
@ -241,7 +245,7 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
cm_scache_t *scp;
cm_fid_t tfid;
osi_Log1(afsd_logp, "RevokeVolumeCallback vol %d", fidp->Volume);
osi_Log1(afsd_logp, "RevokeVolumeCallback vol %u", fidp->Volume);
/* do this first, so that if we're executing a callback granting call
* at this moment, we kill it before it can be merged in. Otherwise,
@ -251,7 +255,6 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
tfid.cell = cellp ? cellp->cellID : 0;
tfid.volume = fidp->Volume;
tfid.vnode = tfid.unique = 0;
cm_RecordRacingRevoke(&tfid, CM_RACINGFLAG_CANCELVOL);
lock_ObtainWrite(&cm_scacheLock);
@ -265,11 +268,19 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainWrite(&scp->rw);
osi_Log4(afsd_logp, "RevokeVolumeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
osi_Log5(afsd_logp, "RevokeVolumeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
osi_Log2(afsd_logp, ".... dv 0x%x:%x",
(afs_uint32)((scp->dataVersion >> 32) & 0xFFFFFFFF),
(afs_uint32)(scp->dataVersion & 0xFFFFFFFF));
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
cm_CallbackNotifyChange(scp);
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
@ -281,6 +292,9 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
lock_ReleaseWrite(&cm_scacheLock);
if (cellp && RDR_Initialized)
RDR_InvalidateVolume(cellp->cellID, fidp->Volume, AFS_INVALIDATE_CALLBACK);
osi_Log1(afsd_logp, "RevokeVolumeCallback Complete vol %d", fidp->Volume);
}
@ -1063,8 +1077,12 @@ SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
}
}
lock_ReleaseWrite(&scp->rw);
if (discarded)
if (discarded) {
cm_CallbackNotifyChange(scp);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
}
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
@ -1557,7 +1575,8 @@ int cm_HaveCallback(cm_scache_t *scp)
break;
}
}
if (!haveCB &&
if (cm_readonlyVolumeVersioning &&
!haveCB &&
volp->creationDateRO == scp->volumeCreationDate &&
volp->cbServerpRO != NULL) {
haveCB = 1;
@ -1699,6 +1718,9 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
cm_CallbackNotifyChange(scp);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
lock_ObtainWrite(&scp->rw);
} else {
if (scp && scp->flags & CM_SCACHEFLAG_PURERO) {
@ -1993,6 +2015,10 @@ void cm_CheckCBExpiration(void)
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
cm_CallbackNotifyChange(scp);
scp_complete:

View File

@ -79,4 +79,5 @@ extern afs_int32 cm_OfflineROIsValid;
extern afs_int32 cm_giveUpAllCBs;
extern afs_int32 cm_shutdown;
#endif /* OPENAFS_WINNT_AFSD_CM_CALLBACK_H */

View File

@ -156,7 +156,7 @@ void cm_InitConn(void)
if (HardDeadtimeout == 0) {
HardDeadtimeout = (unsigned short) (RDRtimeout > 125 ? 120 : (RDRtimeout - 5));
afsi_log("HardDeadTimeout is %d", HardDeadtimeout);
}
}
if (IdleDeadtimeout == 0) {
IdleDeadtimeout = (unsigned short) ConnDeadtimeout;
afsi_log("IdleDeadTimeout is %d", IdleDeadtimeout);
@ -696,15 +696,23 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
lock_ReleaseWrite(&cm_scacheLock);
cm_LockMarkSCacheLost(scp);
lock_ReleaseWrite(&scp->rw);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_DELETED);
cm_ReleaseSCache(scp);
if (pscp) {
if (cm_HaveCallback(pscp)) {
lock_ObtainWrite(&pscp->rw);
cm_DiscardSCache(pscp);
lock_ReleaseWrite(&pscp->rw);
}
cm_ReleaseSCache(pscp);
lock_ReleaseWrite(&pscp->rw);
if (RDR_Initialized)
RDR_InvalidateObject(pscp->fid.cell, pscp->fid.volume, pscp->fid.vnode, pscp->fid.unique,
pscp->fid.hash, pscp->fileType, AFS_INVALIDATE_EXPIRED);
}
cm_ReleaseSCache(pscp);
}
}
} else {

View File

@ -53,8 +53,8 @@ typedef struct cm_conn {
* to the cache manager functions.
*/
typedef struct cm_req {
DWORD startTime; /* Quit before RDR times us out */
int rpcError; /* RPC error code */
DWORD startTime; /* GetTickCount() when this struct was initialized */
int rpcError; /* RPC error code */
int volumeError; /* volume error code */
int accessError; /* access error code */
struct cm_server * tokenIdleErrorServp; /* server that reported a token/idle error other than expired */

View File

@ -40,6 +40,7 @@ long cm_daemonTokenCheckInterval = 180;
long cm_daemonCheckOfflineVolInterval = 600;
long cm_daemonPerformanceTuningInterval = 0;
long cm_daemonRankServerInterval = 600;
long cm_daemonRDRShakeExtentsInterval = 0;
osi_rwlock_t cm_daemonLock;
@ -164,7 +165,8 @@ void cm_BkgDaemon(void * parm)
case CM_ERROR_ALLDOWN:
case CM_ERROR_ALLOFFLINE:
case CM_ERROR_PARTIALWRITE:
if (rp->procp == cm_BkgStore) {
if (rp->procp == cm_BkgStore ||
rp->procp == RDR_BkgFetch) {
osi_Log2(afsd_logp,
"cm_BkgDaemon re-queueing failed request 0x%p code 0x%x",
rp, code);
@ -349,6 +351,13 @@ cm_DaemonCheckInit(void)
cm_daemonCheckOfflineVolInterval = dummy;
afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval);
dummyLen = sizeof(DWORD);
code = RegQueryValueEx(parmKey, "daemonRDRShakeExtentsInterval", NULL, NULL,
(BYTE *) &dummy, &dummyLen);
if (code == ERROR_SUCCESS && dummy)
cm_daemonRDRShakeExtentsInterval = dummy;
afsi_log("daemonRDRShakeExtentsInterval is %d", cm_daemonRDRShakeExtentsInterval);
dummyLen = sizeof(DWORD);
code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL,
(BYTE *) &dummy, &dummyLen);
@ -418,6 +427,7 @@ void cm_Daemon(long parm)
time_t lastBusyVolCheck;
time_t lastPerformanceCheck;
time_t lastServerRankCheck;
time_t lastRDRShakeExtents;
char thostName[200];
unsigned long code;
struct hostent *thp;
@ -472,6 +482,8 @@ void cm_Daemon(long parm)
if (cm_daemonPerformanceTuningInterval)
lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
if (cm_daemonRDRShakeExtentsInterval)
lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
while (daemon_ShutdownFlag == 0) {
if (powerStateSuspended) {
@ -624,6 +636,20 @@ void cm_Daemon(long parm)
now = osi_Time();
}
if (cm_daemonRDRShakeExtentsInterval &&
now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
daemon_ShutdownFlag == 0 &&
powerStateSuspended == 0) {
cm_req_t req;
cm_InitReq(&req);
lastRDRShakeExtents = now;
if (cm_data.buf_redirCount > cm_data.buf_freeCount)
buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
if (daemon_ShutdownFlag == 1)
break;
now = osi_Time();
}
/* allow an exit to be called prior to stopping the service */
hHookDll = cm_LoadAfsdHookLib();
if (hHookDll)

View File

@ -22,6 +22,7 @@
#include <osi.h>
#include "afsd.h"
#include "smb.h"
#ifdef DEBUG
extern void afsi_log(char *pattern, ...);
@ -732,12 +733,12 @@ cm_BkgStore(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_u
osi_hyper_t toffset;
long length;
long code = 0;
afs_uint32 req_flags = reqp->flags;
if (scp->flags & CM_SCACHEFLAG_DELETED) {
osi_Log4(afsd_logp, "Skipping BKG store - Deleted scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
} else {
/* Retries will be performed by the BkgDaemon thread if appropriate */
afs_uint32 req_flags = reqp->flags;
reqp->flags |= CM_REQ_NORETRY;
toffset.LowPart = p1;
@ -1420,6 +1421,7 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, long code, int scp_locked)
osi_queueData_t *qdp;
osi_queueData_t *nqdp;
int flags;
int reportErrorToRedir = 0;
/* Give back reserved buffers */
if (biop->reserved)
@ -1477,6 +1479,7 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, long code, int scp_locked)
bufp->error = code;
bufp->dataVersion = CM_BUF_VERSION_BAD;
bufp->dirtyCounter++;
reportErrorToRedir = 1;
break;
case CM_ERROR_TIMEDOUT:
case CM_ERROR_ALLDOWN:
@ -1501,6 +1504,12 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, long code, int scp_locked)
buf_Release(bufp);
bufp = NULL;
}
if (RDR_Initialized && reportErrorToRedir) {
DWORD status;
smb_MapNTError(cm_MapRPCError(code, biop->reqp), &status, TRUE);
RDR_SetFileStatus( &scp->fid, status);
}
} else {
if (!scp_locked)
lock_ObtainWrite(&scp->rw);

View File

@ -397,6 +397,15 @@ int cm_noteLocalMountPointChange(afs_int32 locked) {
lock_ObtainMutex(&cm_Freelance_Lock);
cm_data.fakeDirVersion++;
cm_localMountPointChangeFlag = 1;
if (RDR_Initialized) {
cm_fid_t fid;
cm_FakeRootFid(&fid);
RDR_InvalidateObject( fid.cell, fid.volume, fid.vnode, fid.unique, fid.hash,
CM_SCACHETYPE_DIRECTORY,
AFS_INVALIDATE_DATA_VERSION);
}
if (!locked)
lock_ReleaseMutex(&cm_Freelance_Lock);
return 1;
@ -459,6 +468,11 @@ int cm_reInitLocalMountPoints() {
lock_ReleaseWrite(&scp->rw);
lock_ReleaseWrite(&cm_scacheLock);
cm_CallbackNotifyChange(scp);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
lock_ObtainMutex(&cm_Freelance_Lock);

View File

@ -78,7 +78,12 @@ cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
{
long code;
code = cm_FSync(scp, userp, reqp, FALSE);
if (RDR_Initialized &&
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_FLUSHED))
code = CM_ERROR_WOULDBLOCK;
else
code = cm_FSync(scp, userp, reqp, FALSE);
if (!code) {
lock_ObtainWrite(&scp->rw);
cm_DiscardSCache(scp);
@ -104,7 +109,16 @@ cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
}
#endif
code = buf_FlushCleanPages(scp, userp, reqp);
/*
* The file system will forget all knowledge of the object
* when it receives this message.
*/
if (RDR_Initialized &&
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_FLUSHED))
code = CM_ERROR_WOULDBLOCK;
else
code = buf_FlushCleanPages(scp, userp, reqp);
if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
lock_ObtainWrite(&scp->dirlock);
@ -530,6 +544,10 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
lock_ObtainWrite(&scp->rw);
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
if (RDR_Initialized)
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_CREDS);
}
return code;
@ -1185,6 +1203,11 @@ cm_IoctlDeleteMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
if (RDR_Initialized &&
!RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_DELETED))
buf_ClearRDRFlag(scp, "deleted mp");
done3:
if (originalName != NULL)
free(originalName);
@ -1409,7 +1432,7 @@ cm_IoctlGetCacheParms(struct cm_ioctl *ioctlp, struct cm_user *userp)
/* and then the actual # of buffers in use (not in the free list, I guess,
* will be what we do).
*/
parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
parms.parms[1] = (cm_data.buf_nbuffers - cm_data.buf_freeCount) * (cm_data.buf_blockSize / 1024);
memcpy(ioctlp->outDatap, &parms, sizeof(parms));
ioctlp->outDatap += sizeof(parms);
@ -1679,6 +1702,13 @@ cm_IoctlGetWsCell(cm_ioctl_t *ioctlp, cm_user_t *userp)
* VIOC_AFS_SYSNAME internals.
*
* Assumes that pioctl path has been parsed or skipped.
*
* In order to support both 32-bit and 64-bit sysname lists
* we will treat bit-31 of the setSysName value as a flag
* indicating which architecture is being indicated. If unset
* the architecture is 32-bit and if set the architecture is
* 64-bit. This change is backward compatible with cache
* managers that do not support this extension.
*/
afs_int32
cm_IoctlSysName(struct cm_ioctl *ioctlp, struct cm_user *userp)
@ -1688,10 +1718,14 @@ cm_IoctlSysName(struct cm_ioctl *ioctlp, struct cm_user *userp)
clientchar_t *inname = NULL;
int t;
unsigned int count;
int arch64 = 0;
memcpy(&setSysName, ioctlp->inDatap, sizeof(afs_uint32));
ioctlp->inDatap += sizeof(afs_uint32);
arch64 = (setSysName & 0x8000000) ? 1 : 0;
setSysName &= 0x7FFFFFF;
if (setSysName) {
/* check my args */
if ( setSysName < 0 || setSysName > MAXNUMSYSNAMES )
@ -1716,46 +1750,57 @@ cm_IoctlSysName(struct cm_ioctl *ioctlp, struct cm_user *userp)
}
/* Not xlating, so local case */
if (!cm_sysName)
osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
if (setSysName) {
/* Local guy; only root can change sysname */
/* clear @sys entries from the dnlc, once afs_lookup can
* do lookups of @sys entries and thinks it can trust them */
/* privs ok, store the entry, ... */
cm_ClientStrCpy(cm_sysName, lengthof(cm_sysName), inname);
cm_ClientStrCpy(cm_sysNameList[0], MAXSYSNAME, inname);
cm_ClientStrCpy(arch64 ? cm_sysName64List[0] : cm_sysNameList[0], MAXSYSNAME, inname);
if (setSysName > 1) { /* ... or list */
for (count = 1; count < setSysName; ++count) {
clientchar_t * newsysname;
if (!cm_sysNameList[count])
if (!(arch64 ? cm_sysName64List[count] : cm_sysNameList[count]))
osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
__FILE__, __LINE__);
newsysname = cm_ParseIoctlStringAlloc(ioctlp, NULL);
cm_ClientStrCpy(cm_sysNameList[count], MAXSYSNAME, newsysname);
cm_ClientStrCpy(arch64 ? cm_sysName64List[count] : cm_sysNameList[count], MAXSYSNAME, newsysname);
free(newsysname);
}
}
cm_sysNameCount = setSysName;
if ( arch64 ) {
cm_sysName64Count = setSysName;
if (cm_sysName64Count)
RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysName64Count, cm_sysName64List );
else if (cm_sysNameCount)
RDR_SysName( AFS_SYSNAME_ARCH_64BIT, cm_sysNameCount, cm_sysNameList );
} else {
cm_sysNameCount = setSysName;
RDR_SysName( AFS_SYSNAME_ARCH_32BIT, cm_sysNameCount, cm_sysNameList );
}
} else {
afs_uint32 i32;
/* return the sysname to the caller */
i32 = cm_sysNameCount;
/* return the sysname list to the caller.
* if there is no 64-bit list and 64-bit is requested, use the 32-bit list.
*/
if ( arch64 && cm_sysName64Count == 0 )
arch64 = 0;
i32 = arch64 ? cm_sysName64Count : cm_sysNameCount;
memcpy(ioctlp->outDatap, &i32, sizeof(afs_int32));
ioctlp->outDatap += sizeof(afs_int32); /* skip found flag */
if (cm_sysNameCount) {
for ( count=0; count < cm_sysNameCount ; ++count) { /* ... or list */
if ( !cm_sysNameList[count] || *cm_sysNameList[count] == _C('\0'))
if (i32) {
for ( count=0; count < i32 ; ++count) { /* ... or list */
if ( !(arch64 ? cm_sysName64List[count] : cm_sysNameList[count]) ||
*(arch64 ? cm_sysName64List[count] : cm_sysNameList[count]) == _C('\0'))
osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n",
__FILE__, __LINE__);
cm_UnparseIoctlString(ioctlp, NULL, cm_sysNameList[count], -1);
cm_UnparseIoctlString(ioctlp, NULL, arch64 ? cm_sysName64List[count] : cm_sysNameList[count], -1);
}
}
}
@ -2346,6 +2391,11 @@ cm_IoctlDeletelink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
if (RDR_Initialized &&
!RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fid.hash, scp->fileType, AFS_INVALIDATE_DELETED))
buf_ClearRDRFlag(scp, "deleted link");
done3:
free(clientp);
@ -2529,8 +2579,14 @@ cm_IoctlSetToken(struct cm_ioctl *ioctlp, struct cm_user *userp)
}
if (flags & PIOCTL_LOGON) {
userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
clientchar_t *cname;
cname = cm_FsStringToClientStringAlloc(smbname, -1, NULL);
userp = smb_FindCMUserByName(cname, ioctlp->fidp->vcp->rname,
SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
if (cname)
free(cname);
release_userp = 1;
}

View File

@ -118,9 +118,10 @@ typedef struct cm_IoctlQueryOptions {
#define MAXNUMSYSNAMES 16 /* max that current constants allow */
#define MAXSYSNAME 128 /* max sysname (i.e. @sys) size */
extern clientchar_t *cm_sysName;
extern unsigned int cm_sysNameCount;
extern clientchar_t *cm_sysNameList[MAXNUMSYSNAMES];
extern unsigned int cm_sysName64Count;
extern clientchar_t *cm_sysName64List[MAXNUMSYSNAMES];
/* Paths that are passed into pioctl calls can be specified using
UTF-8. These strings are prefixed with UTF8_PREFIX defined below.

View File

@ -266,15 +266,15 @@ cm_ShutdownMappedMemory(void)
HeapDestroy(hCacheHeap);
afsi_log("Memory Heap has been destroyed");
} else {
if (cm_ValidateCache == 2)
dirty = !cm_IsCacheValid();
if (cm_ValidateCache == 2)
dirty = !cm_IsCacheValid();
*config_data_p = cm_data;
config_data_p->dirty = dirty;
UnmapViewOfFile(config_data_p);
CloseHandle(hMemoryMappedFile);
hMemoryMappedFile = NULL;
afsi_log("Memory Mapped File has been closed");
*config_data_p = cm_data;
config_data_p->dirty = dirty;
UnmapViewOfFile(config_data_p);
CloseHandle(hMemoryMappedFile);
hMemoryMappedFile = NULL;
afsi_log("Memory Mapped File has been closed");
}
return 0;
}
@ -794,44 +794,44 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD max
CloseHandle(hm);
}
hm = CreateFileMapping( hf,
NULL,
PAGE_READWRITE,
(DWORD)(mappingSize >> 32),
(DWORD)(mappingSize & 0xFFFFFFFF),
NULL);
if (hm == NULL) {
if (GetLastError() == ERROR_DISK_FULL) {
afsi_log("Error creating file mapping for \"%s\": disk full [2]",
cachePath);
return CM_ERROR_TOOMANYBUFS;
}
afsi_log("Error creating file mapping for \"%s\": %d",
cachePath, GetLastError());
return CM_ERROR_INVAL;
}
baseAddress = MapViewOfFileEx( hm,
FILE_MAP_ALL_ACCESS,
0,
0,
(SIZE_T)mappingSize,
baseAddress );
if (baseAddress == NULL) {
afsi_log("Error mapping view of file: %d", GetLastError());
baseAddress = MapViewOfFile( hm,
FILE_MAP_ALL_ACCESS,
0,
0,
(SIZE_T)mappingSize);
if (baseAddress == NULL) {
if (hf != INVALID_HANDLE_VALUE)
CloseHandle(hf);
CloseHandle(hm);
hm = CreateFileMapping( hf,
NULL,
PAGE_READWRITE,
(DWORD)(mappingSize >> 32),
(DWORD)(mappingSize & 0xFFFFFFFF),
NULL);
if (hm == NULL) {
if (GetLastError() == ERROR_DISK_FULL) {
afsi_log("Error creating file mapping for \"%s\": disk full [2]",
cachePath);
return CM_ERROR_TOOMANYBUFS;
}
afsi_log("Error creating file mapping for \"%s\": %d",
cachePath, GetLastError());
return CM_ERROR_INVAL;
}
baseAddress = MapViewOfFileEx( hm,
FILE_MAP_ALL_ACCESS,
0,
0,
(SIZE_T)mappingSize,
baseAddress );
if (baseAddress == NULL) {
afsi_log("Error mapping view of file: %d", GetLastError());
baseAddress = MapViewOfFile( hm,
FILE_MAP_ALL_ACCESS,
0,
0,
(SIZE_T)mappingSize);
if (baseAddress == NULL) {
if (hf != INVALID_HANDLE_VALUE)
CloseHandle(hf);
CloseHandle(hm);
return CM_ERROR_INVAL;
}
newCache = 1;
}
CloseHandle(hm);
}
CloseHandle(hm);
hMemoryMappedFile = hf;
}
@ -936,10 +936,18 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD max
cm_data.bufEndOfData = (char *) baseAddress;
cm_data.buf_dirtyListp = NULL;
cm_data.buf_dirtyListEndp = NULL;
cm_data.fakeDirVersion = 0x8;
/* Make sure the fakeDirVersion is always increasing */
cm_data.fakeDirVersion = time(NULL);
cm_data.fakeUnique = 0;
UuidCreate((UUID *)&cm_data.Uuid);
cm_data.volSerialNumber = volumeSerialNumber;
memcpy(cm_data.Sid, machineSid, sizeof(machineSid));
/*
* make sure that the file is fully allocated
* by writing a non-zero byte to the end
*/
cm_data.baseAddress[mappingSize-1] = 0xFF;
} else {
int gennew = 0;

View File

@ -83,17 +83,30 @@ typedef struct cm_config_data {
cm_buf_t * buf_freeListEndp;
cm_buf_t * buf_dirtyListp;
cm_buf_t * buf_dirtyListEndp;
cm_buf_t * buf_redirListp;
cm_buf_t * buf_redirListEndp;
cm_buf_t ** buf_scacheHashTablepp;
cm_buf_t ** buf_fileHashTablepp;
cm_buf_t * buf_allp;
afs_uint64 buf_nbuffers;
afs_uint32 buf_blockSize;
afs_uint32 buf_hashSize;
#ifdef _M_IX86
afs_uint32 buf_nbuffers;
afs_uint32 buf_nOrigBuffers;
afs_uint32 buf_reservedBufs;
afs_uint32 buf_maxReservedBufs;
afs_uint32 buf_reserveWaiting;
afs_uint32 buf_freeCount;
afs_uint32 buf_redirCount;
#else
afs_uint64 buf_nbuffers;
afs_uint64 buf_nOrigBuffers;
afs_uint64 buf_reservedBufs;
afs_uint64 buf_maxReservedBufs;
afs_uint64 buf_reserveWaiting;
afs_uint64 buf_freeCount;
afs_uint64 buf_redirCount;
#endif
time_t mountRootGen;
afsUUID Uuid;
DWORD volSerialNumber;

View File

@ -537,7 +537,7 @@ void cm_PerformancePrintReport(void)
"SIZEs- 0kb=%u 1kb=%u 4kb=%u 64kb=%u 1mb=%u 20m=%u 100mb=%u 1gb=%u 2gb=%u larger=%u\r\n\r\n",
t,
cm_data.currentSCaches, cm_data.maxSCaches, cm_data.currentVolumes, cm_data.maxVolumes,
cm_data.buf_nbuffers - buf_CountFreeList(), cm_data.buf_nbuffers,
cm_data.buf_nbuffers - cm_data.buf_freeCount, cm_data.buf_nbuffers,
fid_cnt, fid_w_vol, fid_w_scache, fid_w_callbacks, fid_w_buffers,
fid_w_scache_no_vol, fid_w_vol_no_scache, fid_w_scache_no_buf, fid_w_buf_no_scache,
rw_vols, ro_vols, bk_vols,

41
src/WINNT/afsd/cm_rdr.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 Secure Endpoints Inc.
* Copyright (c) 2009-2011 Your File System Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Secure Endpoints Inc nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission from Secure Endpoints Inc and
* Your File System Inc.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef CM_RDR_H
#define CM_RDR_H
#include <..\afsrdr\common\AFSUserDefines.h>
#include <..\afsrdr\common\AFSUserStructs.h>
#include <..\afsrdr\common\AFSUserPrototypes.h>
#endif /* CM_RDR_H */

View File

@ -23,6 +23,7 @@
#include "afsd.h"
#include "cm_btree.h"
#include <afs/unified_afs.h>
/*extern void afsi_log(char *pattern, ...);*/
@ -154,6 +155,11 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
return -1;
}
if (scp->redirBufCount != 0) {
return -1;
}
cm_RemoveSCacheFromHashTable(scp);
/* invalidate so next merge works fine;
* also initialize some flags */
@ -233,36 +239,64 @@ cm_scache_t *cm_GetNewSCache(void)
/* There were no deleted scache objects that we could use. Try to find
* one that simply hasn't been used in a while.
*/
for ( scp = cm_data.scacheLRULastp;
scp;
scp = (cm_scache_t *) osi_QPrev(&scp->q))
{
/* It is possible for the refCount to be zero and for there still
* to be outstanding dirty buffers. If there are dirty buffers,
* we must not recycle the scp. */
if (scp->refCount == 0 && scp->bufReadsp == NULL && scp->bufWritesp == NULL) {
if (!buf_DirtyBuffersExist(&scp->fid)) {
if (!lock_TryWrite(&scp->rw))
continue;
for (retry = 0 ; retry < 2; retry++) {
for ( scp = cm_data.scacheLRULastp;
scp;
scp = (cm_scache_t *) osi_QPrev(&scp->q))
{
/* It is possible for the refCount to be zero and for there still
* to be outstanding dirty buffers. If there are dirty buffers,
* we must not recycle the scp.
*
* If the object is in use by the redirector, then avoid recycling
* it unless we have to.
*/
if (scp->refCount == 0 && scp->bufReadsp == NULL && scp->bufWritesp == NULL) {
if (!buf_DirtyBuffersExist(&scp->fid) && !buf_RDRBuffersExist(&scp->fid)) {
cm_fid_t fid;
afs_uint32 fileType;
if (!cm_RecycleSCache(scp, 0)) {
/* we found an entry, so return it */
/* now remove from the LRU queue and put it back at the
* head of the LRU queue.
*/
cm_AdjustScacheLRU(scp);
if (!lock_TryWrite(&scp->rw))
continue;
/* and we're done */
return scp;
/* Found a likely candidate. Save type and fid in case we succeed */
fid = scp->fid;
fileType = scp->fileType;
if (!cm_RecycleSCache(scp, 0)) {
/* we found an entry, so return it.
* remove from the LRU queue and put it back at the
* head of the LRU queue.
*/
cm_AdjustScacheLRU(scp);
if (RDR_Initialized) {
/*
* We drop the cm_scacheLock because it may be required to
* satisfy an ioctl request from the redirector. It should
* be safe to hold the scp->rw lock here because at this
* point (a) the object has just been recycled so the fid
* is nul and there are no requests that could possibly
* be issued by the redirector that would depend upon it.
*/
lock_ReleaseWrite(&cm_scacheLock);
RDR_InvalidateObject( fid.cell, fid.volume, fid.vnode,
fid.unique, fid.hash,
fileType, AFS_INVALIDATE_EXPIRED);
lock_ObtainWrite(&cm_scacheLock);
}
/* and we're done */
return scp;
}
lock_ReleaseWrite(&scp->rw);
} else {
osi_Log1(afsd_logp,"GetNewSCache dirty buffers exist scp 0x%p", scp);
}
lock_ReleaseWrite(&scp->rw);
} else {
osi_Log1(afsd_logp,"GetNewSCache dirty buffers exist scp 0x%x", scp);
}
}
osi_Log1(afsd_logp, "GetNewSCache all scache entries in use (retry = %d)", retry);
}
osi_Log1(afsd_logp, "GetNewSCache all scache entries in use (retry = %d)", retry);
return NULL;
}
@ -567,7 +601,11 @@ void cm_InitSCache(int newFile, long maxSCaches)
scp->dirDataVersion = CM_SCACHE_VERSION_BAD;
#endif
scp->waitQueueT = NULL;
_InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_WAITING);
_InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_CALLBACK | CM_SCACHEFLAG_WAITING | CM_SCACHEFLAG_RDR_IN_USE));
scp->redirBufCount = 0;
scp->redirQueueT = NULL;
scp->redirQueueH = NULL;
}
}
cm_allFileLocks = NULL;
@ -981,6 +1019,9 @@ int cm_SyncOpCheckContinue(cm_scache_t * scp, afs_int32 flags, cm_buf_t * bufp)
* possibly resulting in a bogus truncation. The simplest way to avoid this
* is to serialize all StoreData RPC's. This is the reason we defined
* CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING.
*
* CM_SCACHESYNC_BULKREAD is used to permit synchronization of multiple bulk
* readers which may be requesting overlapping ranges.
*/
long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *reqp,
afs_uint32 rights, afs_uint32 flags)
@ -1208,6 +1249,14 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
}
}
if (flags & CM_SCACHESYNC_BULKREAD) {
/* Don't allow concurrent fiddling with lock lists */
if (scp->flags & CM_SCACHEFLAG_BULKREADING) {
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is BULKREADING want BULKREAD", scp);
goto sleep;
}
}
/* if we get here, we're happy */
break;
@ -1276,6 +1325,8 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_ASYNCSTORING);
if (flags & CM_SCACHESYNC_LOCK)
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_LOCKING);
if (flags & CM_SCACHESYNC_BULKREAD)
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_BULKREADING);
/* now update the buffer pointer */
if (bufp && (flags & CM_SCACHESYNC_FETCHDATA)) {
@ -1347,6 +1398,8 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags)
_InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_ASYNCSTORING);
if (flags & CM_SCACHESYNC_LOCK)
_InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_LOCKING);
if (flags & CM_SCACHESYNC_BULKREAD)
_InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_BULKREADING);
/* now update the buffer pointer */
if (bufp && (flags & CM_SCACHESYNC_FETCHDATA)) {
@ -1468,10 +1521,20 @@ void cm_MergeStatus(cm_scache_t *dscp,
#endif /* AFS_FREELANCE_CLIENT */
if (statusp->errorCode != 0) {
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_EACCESS);
osi_Log2(afsd_logp, "Merge, Failure scp 0x%p code 0x%x", scp, statusp->errorCode);
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_EACCESS);
switch (statusp->errorCode) {
case EACCES:
case UAEACCES:
case EPERM:
case UAEPERM:
_InterlockedOr(&scp->flags, CM_SCACHEFLAG_EACCESS);
}
osi_Log2(afsd_logp, "Merge, Failure scp 0x%p code 0x%x", scp, statusp->errorCode);
scp->fileType = 0; /* unknown */
if (scp->fid.vnode & 0x1)
scp->fileType = CM_SCACHETYPE_DIRECTORY;
else
scp->fileType = 0; /* unknown */
scp->serverModTime = 0;
scp->clientModTime = 0;
@ -1634,7 +1697,8 @@ void cm_MergeStatus(cm_scache_t *dscp,
if (cm_FidCmp(&scp->fid, &bp->fid) == 0 &&
lock_TryMutex(&bp->mx)) {
if (bp->refCount == 0 &&
!(bp->flags & CM_BUF_READING | CM_BUF_WRITING | CM_BUF_DIRTY)) {
!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING | CM_BUF_DIRTY)) &&
!(bp->qFlags & CM_BUF_QREDIR)) {
prevBp = bp->fileHashBackp;
bp->fileHashBackp = bp->fileHashp = NULL;
if (prevBp)
@ -1671,9 +1735,19 @@ void cm_MergeStatus(cm_scache_t *dscp,
* does not update a mountpoint or symlink by altering the contents of
* the file data; but the Unix CM does.
*/
if (scp->dataVersion != dataVersion && !(flags & CM_MERGEFLAG_FETCHDATA))
if (scp->dataVersion != dataVersion && !(flags & CM_MERGEFLAG_FETCHDATA)) {
scp->mountPointStringp[0] = '\0';
osi_Log5(afsd_logp, "cm_MergeStatus data version change scp 0x%p cell %u vol %u vn %u uniq %u",
scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
osi_Log4(afsd_logp, ".... oldDV 0x%x:%x -> newDV 0x%x:%x",
(afs_uint32)((scp->dataVersion >> 32) & 0xFFFFFFFF),
(afs_uint32)(scp->dataVersion & 0xFFFFFFFF),
(afs_uint32)((dataVersion >> 32) & 0xFFFFFFFF),
(afs_uint32)(dataVersion & 0xFFFFFFFF));
}
/* We maintain a range of buffer dataVersion values which are considered
* valid. This avoids the need to update the dataVersion on each buffer
* object during an uncontested storeData operation. As a result this
@ -1685,6 +1759,19 @@ void cm_MergeStatus(cm_scache_t *dscp,
scp->bufDataVersionLow == 0)
scp->bufDataVersionLow = dataVersion;
if (RDR_Initialized && scp->dataVersion != CM_SCACHE_VERSION_BAD) {
if ( ( !(reqp->flags & CM_REQ_SOURCE_REDIR) || !(flags & (CM_MERGEFLAG_DIROP|CM_MERGEFLAG_STOREDATA))) &&
scp->dataVersion != dataVersion ) {
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode,
scp->fid.unique, scp->fid.hash,
scp->fileType, AFS_INVALIDATE_DATA_VERSION);
} else if ( (reqp->flags & CM_REQ_SOURCE_REDIR) && (flags & (CM_MERGEFLAG_DIROP|CM_MERGEFLAG_STOREDATA)) &&
dataVersion - scp->dataVersion > 1) {
RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode,
scp->fid.unique, scp->fid.hash,
scp->fileType, AFS_INVALIDATE_DATA_VERSION);
}
}
scp->dataVersion = dataVersion;
/*
@ -1735,7 +1822,7 @@ void cm_DiscardSCache(cm_scache_t *scp)
}
scp->cbExpires = 0;
scp->volumeCreationDate = 0;
_InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_CALLBACK | CM_SCACHEFLAG_LOCAL));
_InterlockedAnd(&scp->flags, ~(CM_SCACHEFLAG_CALLBACK | CM_SCACHEFLAG_LOCAL | CM_SCACHEFLAG_RDR_IN_USE));
cm_dnlcPurgedp(scp);
cm_dnlcPurgevp(scp);
cm_FreeAllACLEnts(scp);
@ -1965,7 +2052,7 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock)
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (q = scp->fileLocksH; q; q = osi_QNext(q)) {
cm_file_lock_t * lockp = (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
cm_file_lock_t * lockp = fileq_to_cm_file_lock_t(q);
sprintf(output, " %s lockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x "
"key=0x%I64x flags=0x%x update=0x%I64u\r\n",
cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length,

View File

@ -62,6 +62,8 @@ typedef struct cm_file_lock {
* cm_scacheLock] */
} cm_file_lock_t;
#define fileq_to_cm_file_lock_t(q) ((cm_file_lock_t *)((char *) (q) - offsetof(cm_file_lock_t, fileq)))
#define CM_FILELOCK_FLAG_DELETED 0x01
#define CM_FILELOCK_FLAG_LOST 0x02
@ -223,8 +225,16 @@ typedef struct cm_scache {
Holds queue of
cm_scache_waiter_t
objects. Protected by
cm_cacheLock. */
cm_scacheLock. */
osi_queue_t * waitQueueT; /* locked by cm_scacheLock */
/* redirector state - protected by scp->rw */
osi_queue_t * redirQueueH; /* LRU queue of buffers for this
file that are assigned to the
afsredir kernel module. */
osi_queue_t * redirQueueT;
afs_uint32 redirBufCount; /* Number of buffers held by the redirector */
time_t redirLastAccess; /* last time redir accessed the vnode */
} cm_scache_t;
/* dataVersion */
@ -277,6 +287,8 @@ typedef struct cm_scache {
#define CM_SCACHEFLAG_EACCESS 0x200000 /* Bulk Stat returned EACCES */
#define CM_SCACHEFLAG_SMB_FID 0x400000
#define CM_SCACHEFLAG_LOCAL 0x800000 /* Locally modified */
#define CM_SCACHEFLAG_BULKREADING 0x1000000/* Bulk read in progress */
#define CM_SCACHEFLAG_RDR_IN_USE 0x2000000/* in use by Redirector; advisory */
/* sync flags for calls to the server. The CM_SCACHEFLAG_FETCHING,
* CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
@ -314,6 +326,8 @@ typedef struct cm_scache {
#define CM_SCACHESYNC_FORCECB 0x200000/* when calling cm_GetCallback()
* set the force flag */
#define CM_SCACHESYNC_BULKREAD 0x400000/* reading many buffers */
/* flags for cm_RecycleSCache */
#define CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS 0x1

View File

@ -172,13 +172,14 @@ cm_PingServer(cm_server_t *tsp)
} /* got an unauthenticated connection to this server */
lock_ObtainMutex(&tsp->mx);
if (code >= 0 || code == RXGEN_OPCODE) {
if (code >= 0 || code == RXGEN_OPCODE || code == CM_RX_RETRY_BUSY_CALL) {
/* mark server as up */
_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
tsp->downTime = 0;
/* we currently handle 32-bits of capabilities */
if (code != RXGEN_OPCODE && caps.Capabilities_len > 0) {
if (code != RXGEN_OPCODE && code != CM_RX_RETRY_BUSY_CALL &&
caps.Capabilities_len > 0) {
tsp->capabilities = caps.Capabilities_val[0];
xdr_free((xdrproc_t) xdr_Capabilities, &caps);
caps.Capabilities_len = 0;
@ -455,13 +456,15 @@ static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp)
lock_ObtainMutex(&tsp->mx);
wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
if (results[i] >= 0 || results[i] == RXGEN_OPCODE) {
if (results[i] >= 0 || results[i] == RXGEN_OPCODE ||
results[i] == CM_RX_RETRY_BUSY_CALL) {
/* mark server as up */
_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
tsp->downTime = 0;
/* we currently handle 32-bits of capabilities */
if (results[i] != RXGEN_OPCODE && caps[i].Capabilities_len > 0) {
if (results[i] != RXGEN_OPCODE && results[i] != CM_RX_RETRY_BUSY_CALL &&
caps[i].Capabilities_len > 0) {
tsp->capabilities = caps[i].Capabilities_val[0];
xdr_free((xdrproc_t) xdr_Capabilities, &caps[i]);
caps[i].Capabilities_len = 0;
@ -620,7 +623,7 @@ static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp)
lock_ObtainMutex(&tsp->mx);
wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
if (results[i] >= 0) {
if (results[i] >= 0 || results[i] == CM_RX_RETRY_BUSY_CALL) {
/* mark server as up */
_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
tsp->downTime = 0;

View File

@ -197,6 +197,10 @@ long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
if (desiredAccess == DELETE)
goto done_2;
/* Always allow reading attributes (Hidden, System, Readonly, ...) */
if (desiredAccess == FILE_READ_ATTRIBUTES)
goto done_2;
if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
rights |= (scp->fileType == CM_SCACHETYPE_DIRECTORY ? PRSFS_LOOKUP : PRSFS_READ);
@ -1327,10 +1331,16 @@ notfound:
return code;
}
int cm_ExpandSysName(clientchar_t *inp, clientchar_t *outp, long outSizeCch, unsigned int index)
int cm_ExpandSysName(cm_req_t * reqp, clientchar_t *inp, clientchar_t *outp, long outSizeCch, unsigned int index)
{
clientchar_t *tp;
int prefixCount;
#ifdef _WIN64
int use_sysname64 = 0;
if (cm_sysName64Count > 0 && reqp && (reqp->flags & CM_REQ_WOW64) && (reqp->flags & CM_REQ_SOURCE_REDIR))
use_sysname64 = 1;
#endif
tp = cm_ClientStrRChr(inp, '@');
if (tp == NULL)
@ -1343,6 +1353,11 @@ int cm_ExpandSysName(clientchar_t *inp, clientchar_t *outp, long outSizeCch, uns
if (outp == NULL)
return 1;
#ifdef _WIN64
if (use_sysname64 && index >= cm_sysName64Count)
return -1;
else
#endif
if (index >= cm_sysNameCount)
return -1;
@ -1350,8 +1365,14 @@ int cm_ExpandSysName(clientchar_t *inp, clientchar_t *outp, long outSizeCch, uns
prefixCount = (int)(tp - inp);
cm_ClientStrCpyN(outp, outSizeCch, inp, prefixCount); /* copy out "a." from "a.@sys" */
outp[prefixCount] = 0; /* null terminate the "a." */
cm_ClientStrCat(outp, outSizeCch, cm_sysNameList[index]);/* append i386_nt40 */
outp[prefixCount] = 0; /* null terminate the "a." */
#ifdef _WIN64
if (use_sysname64)
cm_ClientStrCat(outp, outSizeCch, cm_sysName64List[index]);
else
#endif
cm_ClientStrCat(outp, outSizeCch, cm_sysNameList[index]);
return 1;
}
@ -1494,9 +1515,9 @@ long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *us
return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outScpp);
}
if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) {
if (cm_ExpandSysName(reqp, namep, NULL, 0, 0) > 0) {
for ( sysNameIndex = 0; sysNameIndex < MAXNUMSYSNAMES; sysNameIndex++) {
code = cm_ExpandSysName(namep, tname, lengthof(tname), sysNameIndex);
code = cm_ExpandSysName(reqp, namep, tname, lengthof(tname), sysNameIndex);
if (code > 0) {
code = cm_LookupInternal(dscp, tname, flags, userp, reqp, &scp);
#ifdef DEBUG_REFCOUNT
@ -1654,6 +1675,11 @@ long cm_Unlink(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t * cnamep,
cm_dnlcRemove(dscp, cnamep);
if (code == 0) {
cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
if (RDR_Initialized &&
scp->fileType != CM_SCACHETYPE_FILE && scp->fileType != CM_SCACHETYPE_DIRECTORY)
RDR_InvalidateObject(dscp->fid.cell, dscp->fid.volume, dscp->fid.vnode,
dscp->fid.unique, dscp->fid.hash,
dscp->fileType, AFS_INVALIDATE_DATA_VERSION);
} else if (code == CM_ERROR_NOSUCHFILE) {
/* windows would not have allowed the request to delete the file
* if it did not believe the file existed. therefore, we must
@ -1685,6 +1711,11 @@ long cm_Unlink(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t * cnamep,
}
cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
if (RDR_Initialized && !(reqp->flags & CM_REQ_SOURCE_REDIR) &&
!RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode,
scp->fid.unique, scp->fid.hash,
scp->fileType, AFS_INVALIDATE_DELETED))
buf_ClearRDRFlag(scp, "unlink");
}
}
@ -2789,7 +2820,7 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
if (cm_ExpandSysName(cnamep, NULL, 0, 0)) {
if (cm_ExpandSysName(NULL, cnamep, NULL, 0, 0)) {
return CM_ERROR_ATSYS;
}
@ -2973,7 +3004,7 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
if (cm_ExpandSysName(cnamep, NULL, 0, 0)) {
if (cm_ExpandSysName(NULL, cnamep, NULL, 0, 0)) {
return CM_ERROR_ATSYS;
}
@ -3171,6 +3202,10 @@ long cm_Link(cm_scache_t *dscp, clientchar_t *cnamep, cm_scache_t *sscp, long fl
lock_ObtainWrite(&dscp->rw);
if (code == 0) {
cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
if (RDR_Initialized)
RDR_InvalidateObject(dscp->fid.cell, dscp->fid.volume, dscp->fid.vnode,
dscp->fid.unique, dscp->fid.hash,
dscp->fileType, AFS_INVALIDATE_DATA_VERSION);
}
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
lock_ReleaseWrite(&dscp->rw);
@ -3452,6 +3487,11 @@ long cm_RemoveDir(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t *cnamep, cm_
cm_RemoveSCacheFromHashTable(scp);
lock_ReleaseWrite(&cm_scacheLock);
lock_ReleaseWrite(&scp->rw);
if (RDR_Initialized && !(reqp->flags & CM_REQ_SOURCE_REDIR) &&
!RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode,
scp->fid.unique, scp->fid.hash,
scp->fileType, AFS_INVALIDATE_DELETED))
buf_ClearRDRFlag(scp, "rmdir");
}
}
@ -3830,6 +3870,9 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
cm_DiscardSCache(oldScp);
lock_ReleaseWrite(&oldScp->rw);
if (RDR_Initialized)
RDR_InvalidateObject(oldScp->fid.cell, oldScp->fid.volume, oldScp->fid.vnode, oldScp->fid.unique,
oldScp->fid.hash, oldScp->fileType, AFS_INVALIDATE_CALLBACK);
done:
if (oldScp)
cm_ReleaseSCache(oldScp);
@ -5108,6 +5151,12 @@ long cm_UnlockByKey(cm_scache_t * scp,
fileLock->flags |= CM_FILELOCK_FLAG_DELETED;
cm_ReleaseUser(fileLock->userp);
cm_ReleaseSCacheNoLock(scp);
fileLock->userp = NULL;
fileLock->scp = NULL;
n_unlocks++;
}
}
@ -5122,9 +5171,9 @@ long cm_UnlockByKey(cm_scache_t * scp,
return 0;
}
osi_Log1(afsd_logp, "cm_UnlockByKey done with %d locks", n_unlocks);
code = cm_IntUnlock(scp, userp, reqp);
osi_Log1(afsd_logp, "cm_UnlockByKey code 0x%x", code);
osi_Log4(afsd_logp, " Leaving scp with excl[%d], shared[%d], client[%d], serverLock[%d]",
scp->exclusiveLocks, scp->sharedLocks, scp->clientLocks,
(int)(signed char) scp->serverLock);
@ -5132,6 +5181,7 @@ long cm_UnlockByKey(cm_scache_t * scp,
return code;
}
/* Called with scp->rw held */
long cm_Unlock(cm_scache_t *scp,
unsigned char sLockType,
LARGE_INTEGER LOffset, LARGE_INTEGER LLength,
@ -5234,8 +5284,20 @@ long cm_Unlock(cm_scache_t *scp,
}
fileLock->flags |= CM_FILELOCK_FLAG_DELETED;
if (userp != NULL) {
cm_ReleaseUser(fileLock->userp);
} else {
userp = fileLock->userp;
release_userp = TRUE;
}
cm_ReleaseSCacheNoLock(scp);
fileLock->userp = NULL;
fileLock->scp = NULL;
lock_ReleaseWrite(&cm_scacheLock);
code = cm_IntUnlock(scp, userp, reqp);
if (release_userp) {
cm_ReleaseUser(userp);
release_userp = FALSE;
@ -5321,15 +5383,16 @@ void cm_CheckLocks()
fileLock->userp = NULL;
fileLock->scp = NULL;
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainWrite(&scp->rw);
code = cm_IntUnlock(scp, userp, &req);
lock_ReleaseWrite(&scp->rw);
cm_ReleaseUser(fileLock->userp);
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
if (scp && userp) {
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainWrite(&scp->rw);
code = cm_IntUnlock(scp, userp, &req);
lock_ReleaseWrite(&scp->rw);
cm_ReleaseUser(userp);
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
}
osi_QRemove(&cm_allFileLocks, q);
cm_PutFileLock(fileLock);
@ -5830,7 +5893,7 @@ cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint16
int cm_KeyEquals(cm_key_t *k1, cm_key_t *k2, int flags)
{
return (k1->session_id == k2->session_id) && (k1->file_id == k2->file_id) &&
((flags & CM_UNLOCK_BY_FID) || (k1->process_id == k2->process_id));
((flags & CM_UNLOCK_FLAG_BY_FID) || (k1->process_id == k2->process_id));
}
void cm_ReleaseAllLocks(void)

View File

@ -149,7 +149,7 @@ extern long cm_AssembleLink(cm_scache_t *linkScp, fschar_t *pathSuffixp,
cm_scache_t **newRootScpp, cm_space_t **newSpaceBufferp,
cm_user_t *userp, cm_req_t *reqp);
extern int cm_ExpandSysName(clientchar_t *inp, clientchar_t *outp, long outSizeCch,
extern int cm_ExpandSysName(cm_req_t *reqp, clientchar_t *inp, clientchar_t *outp, long outSizeCch,
unsigned int sysNameIndex);
extern long cm_Open(cm_scache_t *scp, int type, cm_user_t *userp);
@ -197,15 +197,14 @@ extern long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
int allowWait, cm_user_t *userp, cm_req_t *reqp,
cm_file_lock_t **lockpp);
#define CM_UNLOCK_BY_FID 0x0001
extern long cm_UnlockByKey(cm_scache_t * scp,
cm_key_t key,
afs_uint32 flags,
cm_user_t * userp,
cm_req_t * reqp);
#define CM_UNLOCK_FLAG_MATCH_RANGE 0x01
#define CM_UNLOCK_FLAG_BY_FID 0x0001
#define CM_UNLOCK_FLAG_MATCH_RANGE 0x0002
extern long cm_Unlock(cm_scache_t *scp, unsigned char sLockType,
LARGE_INTEGER LOffset, LARGE_INTEGER LLength, cm_key_t key,

View File

@ -46,12 +46,31 @@
#include "smb.h"
#include <WINNT/afsreg.h>
extern DWORD RDR_NetworkAddrChange(void);
extern DWORD RDR_VolumeStatus(ULONG cellID, ULONG volID, BOOLEAN online);
extern DWORD RDR_NetworkStatus(BOOLEAN status);
HMODULE hVolStatus = NULL;
dll_VolStatus_Funcs_t dll_funcs;
cm_VolStatus_Funcs_t cm_funcs;
static char volstat_NetbiosName[64] = "";
static DWORD RDR_Notifications = 0;
rdr_volstat_evt_t *rdr_evtH = NULL;
rdr_volstat_evt_t *rdr_evtT = NULL;
static EVENT_HANDLE rdr_q_event = NULL;
static osi_mutex_t rdr_evt_lock;
void
cm_VolStatus_SetRDRNotifications(DWORD onoff)
{
RDR_Notifications = onoff;
}
afs_uint32
cm_VolStatus_Active(void)
{
@ -77,16 +96,21 @@ cm_VolStatus_Initialization(void)
code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL,
(BYTE *) &wd, &dummyLen);
if (code == 0) {
if (code == ERROR_SUCCESS) {
dummyLen = sizeof(volstat_NetbiosName);
code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
(BYTE *)volstat_NetbiosName, &dummyLen);
}
if (code == ERROR_SUCCESS && wd[0])
hVolStatus = LoadLibrary(wd);
dummyLen = sizeof(wd);
code = RegQueryValueEx(parmKey, "RDRVolStatNotify", NULL, NULL,
(BYTE *) &RDR_Notifications, &dummyLen);
RegCloseKey (parmKey);
}
if (code == ERROR_SUCCESS && wd[0])
hVolStatus = LoadLibrary(wd);
if (hVolStatus) {
(FARPROC) dll_VolStatus_Initialization = GetProcAddress(hVolStatus, "@VolStatus_Initialization@8");
if (dll_VolStatus_Initialization) {
@ -106,6 +130,23 @@ cm_VolStatus_Initialization(void)
}
}
if (RDR_Initialized && RDR_Notifications) {
long pid;
thread_t phandle;
lock_InitializeMutex(&rdr_evt_lock, "rdr_evt_lock", LOCK_HIERARCHY_IGNORE);
phandle = thrd_Create((SecurityAttrib) NULL, 0,
(ThreadFunc) cm_VolStatus_DeliverNotifications,
0, 0, &pid, "cm_VolStatus_DeliverNotifications");
osi_assertx(phandle != NULL, "cm_VolStatus_DeliverNotifications thread creation failure");
thrd_CloseHandle(phandle);
rdr_q_event = thrd_CreateEvent(NULL, TRUE, TRUE, "rdr_q_event");
if ( GetLastError() == ERROR_ALREADY_EXISTS )
afsi_log("Event Object Already Exists: rdr_q_event");
}
osi_Log1(afsd_logp,"cm_VolStatus_Initialization 0x%x", code);
return code;
@ -119,6 +160,10 @@ cm_VolStatus_Finalize(void)
{
osi_Log1(afsd_logp,"cm_VolStatus_Finalize handle 0x%x", hVolStatus);
if ( RDR_Initialized && RDR_Notifications ) {
CloseHandle(rdr_q_event);
}
if (hVolStatus == NULL)
return 0;
@ -180,6 +225,18 @@ cm_VolStatus_Network_Started(const char * netbios32)
{
long code = 0;
if (RDR_Initialized && RDR_Notifications) {
rdr_volstat_evt_t *evp = (rdr_volstat_evt_t *)malloc(sizeof(rdr_volstat_evt_t));
evp->type = netstatus;
evp->netstatus_data.status = TRUE;
lock_ObtainMutex(&rdr_evt_lock);
osi_QAddH((osi_queue_t **) &rdr_evtH, (osi_queue_t **) &rdr_evtT, &evp->q);
lock_ReleaseMutex(&rdr_evt_lock);
thrd_SetEvent(rdr_q_event);
}
if (hVolStatus == NULL)
return 0;
@ -205,6 +262,18 @@ cm_VolStatus_Network_Stopped(const char * netbios32)
{
long code = 0;
if (RDR_Initialized && RDR_Notifications) {
rdr_volstat_evt_t *evp = (rdr_volstat_evt_t *)malloc(sizeof(rdr_volstat_evt_t));
evp->type = netstatus;
evp->netstatus_data.status = FALSE;
lock_ObtainMutex(&rdr_evt_lock);
osi_QAddH((osi_queue_t **) &rdr_evtH, (osi_queue_t **) &rdr_evtT, &evp->q);
lock_ReleaseMutex(&rdr_evt_lock);
thrd_SetEvent(rdr_q_event);
}
if (hVolStatus == NULL)
return 0;
@ -227,6 +296,17 @@ cm_VolStatus_Network_Addr_Change(void)
{
long code = 0;
if (RDR_Initialized && RDR_Notifications) {
rdr_volstat_evt_t *evp = (rdr_volstat_evt_t *)malloc(sizeof(rdr_volstat_evt_t));
evp->type = addrchg;
lock_ObtainMutex(&rdr_evt_lock);
osi_QAddH((osi_queue_t **) &rdr_evtH, (osi_queue_t **) &rdr_evtT, &evp->q);
lock_ReleaseMutex(&rdr_evt_lock);
thrd_SetEvent(rdr_q_event);
}
if (hVolStatus == NULL)
return 0;
@ -243,6 +323,34 @@ cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volst
{
long code = 0;
if (RDR_Initialized && RDR_Notifications) {
rdr_volstat_evt_t *evp = (rdr_volstat_evt_t *)malloc(sizeof(rdr_volstat_evt_t));
switch (status) {
case vl_alldown:
case vl_offline:
evp->type = volstatus;
evp->volstatus_data.cellID = cellID;
evp->volstatus_data.volID = volID;
evp->volstatus_data.online = FALSE;
lock_ObtainMutex(&rdr_evt_lock);
osi_QAddH((osi_queue_t **) &rdr_evtH, (osi_queue_t **) &rdr_evtT, &evp->q);
lock_ReleaseMutex(&rdr_evt_lock);
break;
default:
evp->type = volstatus;
evp->volstatus_data.cellID = cellID;
evp->volstatus_data.volID = volID;
evp->volstatus_data.online = TRUE;
lock_ObtainMutex(&rdr_evt_lock);
osi_QAddH((osi_queue_t **) &rdr_evtH, (osi_queue_t **) &rdr_evtT, &evp->q);
lock_ReleaseMutex(&rdr_evt_lock);
}
thrd_SetEvent(rdr_q_event);
}
if (hVolStatus == NULL)
return 0;
@ -446,3 +554,38 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *
osi_Log1(afsd_logp,"cm_VolStatus_Path_To_DFSlink code 0x%x",code);
return code;
}
void
cm_VolStatus_DeliverNotifications(void * dummy)
{
rdr_volstat_evt_t *evp, *evprev;
afs_uint32 code;
while ( TRUE ) {
code = thrd_WaitForSingleObject_Event( rdr_q_event, INFINITE );
lock_ObtainMutex(&rdr_evt_lock);
for (evp = rdr_evtT; evp; evp = evprev)
{
evprev = (rdr_volstat_evt_t *) osi_QPrev(&evp->q);
osi_QRemoveHT((osi_queue_t **) &rdr_evtH, (osi_queue_t **) &rdr_evtT, &evp->q);
lock_ReleaseMutex(&rdr_evt_lock);
switch ( evp->type ) {
case addrchg:
RDR_NetworkAddrChange();
break;
case volstatus:
RDR_VolumeStatus(evp->volstatus_data.cellID, evp->volstatus_data.volID, evp->volstatus_data.online);
break;
case netstatus:
RDR_NetworkStatus(evp->netstatus_data.status);
break;
}
free(evp);
lock_ObtainMutex(&rdr_evt_lock);
}
lock_ReleaseMutex(&rdr_evt_lock);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007 Secure Endpoints Inc.
* Copyright (c) 2007-2011 Secure Endpoints Inc.
*
* All rights reserved.
*
@ -73,6 +73,11 @@ extern long cm_VolStatus_Notify_DFS_Mapping(cm_scache_t *scp,
extern long cm_VolStatus_Invalidate_DFS_Mapping(cm_scache_t *scp);
extern void cm_VolStatus_DeliverNotifications(void * dummy);
extern void cm_VolStatus_SetRDRNotifications(DWORD onoff);
#define DLL_VOLSTATUS_FUNCS_VERSION 2
typedef struct dll_VolStatus_Funcs {
afs_uint32 version;
@ -112,3 +117,22 @@ struct VolStatTest {
#define VOLSTAT_TEST_NETWORK_UP 4
#define VOLSTAT_TEST_NETWORK_DOWN 8
/* redirector - native file system */
enum rdr_event_type { addrchg, volstatus, netstatus };
typedef struct rdr_volstat_evt {
osi_queue_t q;
enum rdr_event_type type;
union {
struct {
ULONG cellID;
ULONG volID;
BOOLEAN online;
} volstatus_data;
struct {
BOOLEAN status;
} netstatus_data;
};
} rdr_volstat_evt_t;

View File

@ -312,7 +312,7 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
lock_ReleaseWrite(&volp->rw);
if (cellp->flags & CM_CELLFLAG_VLSERVER_INVALID)
cm_UpdateCell(cellp, 0);
cm_UpdateCell(cellp, 0);
/* now we have volume structure locked and held; make RPC to fill it */
code = cm_GetEntryByName(cellp, volp->namep, &vldbEntry, &nvldbEntry,

View File

@ -4839,7 +4839,7 @@ ChGrpCmd(struct cmd_syndesc *as, void *arock)
for(ti=as->parms[1].items; ti; ti=ti->next) {
cm_fid_t fid;
afs_uint32 filetype;
char cell[CELL_MAXNAMELEN];
char cell[CELL_MAXNAMELEN];
/* once per file */
memset(&fid, 0, sizeof(fid));

View File

@ -24,17 +24,21 @@ SOFTWARE.
*/
#include <afsconfig.h>
#include <afs/param.h>
#include <roken.h>
//#pragma keyword("interface",on)
//#define interface struct
#define SECURITY_WIN32
#include "afslogon.h"
#if (_WIN32_WINNT < 0x0500)
#error _WIN32_WINNT < 0x0500
#endif
/**/
#include <security.h>
#include <winioctl.h>
#include <sddl.h>
#include <unknwn.h>
#include <oaidl.h>
@ -42,171 +46,177 @@ SOFTWARE.
#include <adshlp.h>
/**/
#include "afslogon.h"
#include "..\afsrdr\common\AFSUserDefines.h"
#include "..\afsrdr\common\AFSUserIoctl.h"
#include "..\afsrdr\common\AFSUserStructs.h"
#include "..\afsrdr\common\AFSProvider.h"
#define SEC_ERR_VALUE(v) if (status==v) return #v
char * _get_sec_err_text(SECURITY_STATUS status) {
SEC_ERR_VALUE(SEC_E_OK);
SEC_ERR_VALUE(SEC_I_CONTINUE_NEEDED);
SEC_ERR_VALUE(SEC_I_COMPLETE_NEEDED);
SEC_ERR_VALUE(SEC_I_COMPLETE_AND_CONTINUE);
SEC_ERR_VALUE(SEC_E_INCOMPLETE_MESSAGE);
SEC_ERR_VALUE(SEC_I_INCOMPLETE_CREDENTIALS);
SEC_ERR_VALUE(SEC_E_INVALID_HANDLE);
SEC_ERR_VALUE(SEC_E_TARGET_UNKNOWN);
SEC_ERR_VALUE(SEC_E_LOGON_DENIED);
SEC_ERR_VALUE(SEC_E_INTERNAL_ERROR);
SEC_ERR_VALUE(SEC_E_NO_CREDENTIALS);
SEC_ERR_VALUE(SEC_E_NO_AUTHENTICATING_AUTHORITY);
SEC_ERR_VALUE(SEC_E_INSUFFICIENT_MEMORY);
SEC_ERR_VALUE(SEC_E_INVALID_TOKEN);
SEC_ERR_VALUE(SEC_E_UNSUPPORTED_FUNCTION);
SEC_ERR_VALUE(SEC_E_WRONG_PRINCIPAL);
return "Unknown";
SEC_ERR_VALUE(SEC_E_OK);
SEC_ERR_VALUE(SEC_I_CONTINUE_NEEDED);
SEC_ERR_VALUE(SEC_I_COMPLETE_NEEDED);
SEC_ERR_VALUE(SEC_I_COMPLETE_AND_CONTINUE);
SEC_ERR_VALUE(SEC_E_INCOMPLETE_MESSAGE);
SEC_ERR_VALUE(SEC_I_INCOMPLETE_CREDENTIALS);
SEC_ERR_VALUE(SEC_E_INVALID_HANDLE);
SEC_ERR_VALUE(SEC_E_TARGET_UNKNOWN);
SEC_ERR_VALUE(SEC_E_LOGON_DENIED);
SEC_ERR_VALUE(SEC_E_INTERNAL_ERROR);
SEC_ERR_VALUE(SEC_E_NO_CREDENTIALS);
SEC_ERR_VALUE(SEC_E_NO_AUTHENTICATING_AUTHORITY);
SEC_ERR_VALUE(SEC_E_INSUFFICIENT_MEMORY);
SEC_ERR_VALUE(SEC_E_INVALID_TOKEN);
SEC_ERR_VALUE(SEC_E_UNSUPPORTED_FUNCTION);
SEC_ERR_VALUE(SEC_E_WRONG_PRINCIPAL);
return "Unknown";
}
#undef SEC_ERR_VALUE
DWORD LogonSSP(PLUID lpLogonId, PCtxtHandle outCtx) {
DWORD code = 1;
DWORD
LogonSSP(PLUID lpLogonId, PCtxtHandle outCtx) {
DWORD code = 1;
SECURITY_STATUS status;
CredHandle creds;
CtxtHandle ctxclient,ctxserver;
TimeStamp expiry;
BOOL cont = TRUE;
BOOL first = TRUE;
SecBufferDesc sdescc,sdescs;
SecBuffer stokc,stoks;
ULONG cattrs,sattrs;
int iters = 10;
CredHandle creds;
CtxtHandle ctxclient,ctxserver;
TimeStamp expiry;
BOOL cont = TRUE;
BOOL first = TRUE;
SecBufferDesc sdescc,sdescs;
SecBuffer stokc,stoks;
ULONG cattrs,sattrs;
int iters = 10;
outCtx->dwLower = 0;
outCtx->dwUpper = 0;
outCtx->dwLower = 0;
outCtx->dwUpper = 0;
cattrs = 0;
sattrs = 0;
cattrs = 0;
sattrs = 0;
status = AcquireCredentialsHandle(
NULL,
"Negotiate",
SECPKG_CRED_BOTH,
lpLogonId,
NULL,
NULL,
NULL,
&creds,
&expiry);
status = AcquireCredentialsHandle( NULL,
"Negotiate",
SECPKG_CRED_BOTH,
lpLogonId,
NULL,
NULL,
NULL,
&creds,
&expiry);
if (status != SEC_E_OK) {
DebugEvent("AcquireCredentialsHandle failed: %lX", status);
goto ghp_0;
}
if (status != SEC_E_OK) {
DebugEvent("AcquireCredentialsHandle failed: %lX", status);
goto ghp_0;
}
sdescc.cBuffers = 1;
sdescc.pBuffers = &stokc;
sdescc.ulVersion = SECBUFFER_VERSION;
sdescc.cBuffers = 1;
sdescc.pBuffers = &stokc;
sdescc.ulVersion = SECBUFFER_VERSION;
stokc.BufferType = SECBUFFER_TOKEN;
stokc.cbBuffer = 0;
stokc.pvBuffer = NULL;
stokc.BufferType = SECBUFFER_TOKEN;
stokc.cbBuffer = 0;
stokc.pvBuffer = NULL;
sdescs.cBuffers = 1;
sdescs.pBuffers = &stoks;
sdescs.ulVersion = SECBUFFER_VERSION;
sdescs.cBuffers = 1;
sdescs.pBuffers = &stoks;
sdescs.ulVersion = SECBUFFER_VERSION;
stoks.BufferType = SECBUFFER_TOKEN;
stoks.cbBuffer = 0;
stoks.pvBuffer = NULL;
stoks.BufferType = SECBUFFER_TOKEN;
stoks.cbBuffer = 0;
stoks.pvBuffer = NULL;
do {
status = InitializeSecurityContext(
&creds,
((first)? NULL:&ctxclient),
NULL,
ISC_REQ_DELEGATE | ISC_REQ_ALLOCATE_MEMORY,
0,
SECURITY_NATIVE_DREP,
((first)?NULL:&sdescs),
0,
&ctxclient,
&sdescc,
&cattrs,
&expiry
);
do {
status = InitializeSecurityContext( &creds,
((first)? NULL:&ctxclient),
NULL,
ISC_REQ_DELEGATE | ISC_REQ_ALLOCATE_MEMORY,
0,
SECURITY_NATIVE_DREP,
((first)?NULL:&sdescs),
0,
&ctxclient,
&sdescc,
&cattrs,
&expiry
);
DebugEvent("InitializeSecurityContext returns status[%lX](%s)",status,_get_sec_err_text(status));
DebugEvent("InitializeSecurityContext returns status[%lX](%s)",status,_get_sec_err_text(status));
if (!first) FreeContextBuffer(stoks.pvBuffer);
if (!first) FreeContextBuffer(stoks.pvBuffer);
if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
CompleteAuthToken(&ctxclient, &sdescc);
}
if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
CompleteAuthToken(&ctxclient, &sdescc);
}
if (status != SEC_I_CONTINUE_NEEDED && status != SEC_I_COMPLETE_AND_CONTINUE) {
cont = FALSE;
}
if (status != SEC_I_CONTINUE_NEEDED && status != SEC_I_COMPLETE_AND_CONTINUE) {
cont = FALSE;
}
if (!stokc.cbBuffer && !cont) {
DebugEvent("Breaking out after InitializeSecurityContext");
break;
}
if (!stokc.cbBuffer && !cont) {
DebugEvent("Breaking out after InitializeSecurityContext");
break;
}
status = AcceptSecurityContext(
&creds,
((first)?NULL:&ctxserver),
&sdescc,
ASC_REQ_DELEGATE | ASC_REQ_ALLOCATE_MEMORY,
SECURITY_NATIVE_DREP,
&ctxserver,
&sdescs,
&sattrs,
&expiry);
status = AcceptSecurityContext( &creds,
((first)?NULL:&ctxserver),
&sdescc,
ASC_REQ_DELEGATE | ASC_REQ_ALLOCATE_MEMORY,
SECURITY_NATIVE_DREP,
&ctxserver,
&sdescs,
&sattrs,
&expiry);
DebugEvent("AcceptSecurityContext returns status[%lX](%s)", status, _get_sec_err_text(status));
DebugEvent("AcceptSecurityContext returns status[%lX](%s)", status, _get_sec_err_text(status));
FreeContextBuffer(stokc.pvBuffer);
FreeContextBuffer(stokc.pvBuffer);
if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
CompleteAuthToken(&ctxserver,&sdescs);
}
if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
CompleteAuthToken(&ctxserver,&sdescs);
}
if (status == SEC_I_CONTINUE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
cont = TRUE;
}
if (status == SEC_I_CONTINUE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
cont = TRUE;
}
if (!cont)
FreeContextBuffer(stoks.pvBuffer);
if (!cont)
FreeContextBuffer(stoks.pvBuffer);
first = FALSE;
iters--; /* just in case, hard limit on loop */
} while (cont && iters);
first = FALSE;
iters--; /* just in case, hard limit on loop */
} while (cont && iters);
if (sattrs & ASC_RET_DELEGATE) {
DebugEvent("Received delegate context");
*outCtx = ctxserver;
code = 0;
} else {
DebugEvent("Didn't receive delegate context");
outCtx->dwLower = 0;
outCtx->dwUpper = 0;
DeleteSecurityContext(&ctxserver);
}
if (sattrs & ASC_RET_DELEGATE) {
DebugEvent("Received delegate context");
*outCtx = ctxserver;
code = 0;
} else {
DebugEvent("Didn't receive delegate context");
outCtx->dwLower = 0;
outCtx->dwUpper = 0;
DeleteSecurityContext(&ctxserver);
}
DeleteSecurityContext(&ctxclient);
DeleteSecurityContext(&ctxclient);
FreeCredentialsHandle(&creds);
ghp_0:
return code;
ghp_0:
return code;
}
DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWSTR domain) {
DWORD code = 1; /* default is failure */
NTSTATUS rv = 0;
HRESULT hr = S_OK;
LPWSTR p = NULL;
WCHAR adsPath[MAX_PATH] = L"";
BOOL coInitialized = FALSE;
DWORD
QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWSTR domain) {
DWORD code = 1; /* default is failure */
NTSTATUS rv = 0;
HRESULT hr = S_OK;
LPWSTR p = NULL;
WCHAR adsPath[MAX_PATH] = L"";
BOOL coInitialized = FALSE;
CHAR ansidomain[256], *a;
homePath[0] = '\0';
homePath[0] = '\0';
/* I trust this is an ASCII domain name */
for ( p=domain, a=ansidomain; *a = (CHAR)*p; p++, a++);
@ -227,7 +237,9 @@ DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWS
IID_IADsNameTranslate,
(void**)&pNto);
if (FAILED(hr)) { DebugEvent("Can't create nametranslate object"); }
if (FAILED(hr)) {
DebugEvent("Can't create nametranslate object");
}
else {
hr = pNto->Init(ADS_NAME_INITTYPE_GC,L"");
if (FAILED(hr)) {
@ -242,7 +254,9 @@ DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWS
if (!FAILED(hr)) {
hr = pNto->Set(ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, p);
if (FAILED(hr)) { DebugEvent("Can't set sid string"); }
if (FAILED(hr)) {
DebugEvent("Can't set sid string");
}
else {
BSTR bstr;
@ -262,103 +276,104 @@ DWORD QueryAdHomePathFromSid(char * homePath, size_t homePathLen, PSID psid, PWS
}
LocalFree(p);
} else {
DebugEvent("Can't convert sid to string");
}
if (adsPath[0]) {
WCHAR fAdsPath[MAX_PATH];
IADsUser *pAdsUser;
BSTR bstHomeDir = NULL;
if (adsPath[0]) {
WCHAR fAdsPath[MAX_PATH];
IADsUser *pAdsUser;
BSTR bstHomeDir = NULL;
hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
if (hr != S_OK) {
DebugEvent("Can't format full adspath");
goto cleanup;
}
hr = StringCchPrintfW(fAdsPath, MAX_PATH, L"LDAP://%s", adsPath);
if (hr != S_OK) {
DebugEvent("Can't format full adspath");
goto cleanup;
}
DebugEvent("Trying adsPath=[%S]", fAdsPath);
DebugEvent("Trying adsPath=[%S]", fAdsPath);
hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
if (hr != S_OK) {
DebugEvent("Can't open IADs object");
goto cleanup;
}
hr = ADsGetObject( fAdsPath, IID_IADsUser, (LPVOID *) &pAdsUser);
if (hr != S_OK) {
DebugEvent("Can't open IADs object");
goto cleanup;
}
hr = pAdsUser->get_Profile(&bstHomeDir);
if (hr != S_OK) {
DebugEvent("Can't get profile directory");
goto cleanup_homedir_section;
}
if (hr != S_OK) {
DebugEvent("Can't get profile directory");
goto cleanup_homedir_section;
}
wcstombs(homePath, bstHomeDir, homePathLen);
wcstombs(homePath, bstHomeDir, homePathLen);
DebugEvent("Got homepath [%s]", homePath);
DebugEvent("Got homepath [%s]", homePath);
SysFreeString(bstHomeDir);
SysFreeString(bstHomeDir);
code = 0;
code = 0;
cleanup_homedir_section:
pAdsUser->Release();
}
cleanup_homedir_section:
pAdsUser->Release();
}
cleanup:
if (coInitialized)
CoUninitialize();
cleanup:
if (coInitialized)
CoUninitialize();
return code;
return code;
}
/* Try to determine the user's AD home path. *homePath is assumed to be at least MAXPATH bytes.
If successful, opt.flags is updated with LOGON_FLAG_AD_REALM to indicate that we are dealing with
an AD realm. */
DWORD GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
CtxtHandle ctx;
DWORD code = 0;
SECURITY_STATUS status;
DWORD
GetAdHomePath(char * homePath, size_t homePathLen, PLUID lpLogonId, LogonOptions_t * opt) {
CtxtHandle ctx;
DWORD code = 0;
SECURITY_STATUS status;
homePath[0] = '\0';
homePath[0] = '\0';
if (LogonSSP(lpLogonId,&ctx)) {
if (LogonSSP(lpLogonId,&ctx)) {
DebugEvent("Failed LogonSSP");
return 1;
} else {
status = ImpersonateSecurityContext(&ctx);
if (status == SEC_E_OK) {
PSECURITY_LOGON_SESSION_DATA plsd;
NTSTATUS rv;
return 1;
}
rv = LsaGetLogonSessionData(lpLogonId, &plsd);
if (rv == 0) {
PWSTR domain;
status = ImpersonateSecurityContext(&ctx);
if (status == SEC_E_OK) {
PSECURITY_LOGON_SESSION_DATA plsd;
NTSTATUS rv;
domain = (PWSTR)malloc(sizeof(WCHAR) * (plsd->LogonDomain.Length+1));
memcpy(domain, plsd->LogonDomain.Buffer, sizeof(WCHAR) * (plsd->LogonDomain.Length));
domain[plsd->LogonDomain.Length] = 0;
rv = LsaGetLogonSessionData(lpLogonId, &plsd);
if (rv == 0) {
PWSTR domain;
if (!QueryAdHomePathFromSid(homePath,homePathLen,plsd->Sid,domain)) {
DebugEvent("Returned home path [%s]",homePath);
opt->flags |= LOGON_FLAG_AD_REALM;
}
free(domain);
LsaFreeReturnBuffer(plsd);
} else {
DebugEvent("LsaGetLogonSessionData failed [%lX]", rv);
domain = (PWSTR)malloc(sizeof(WCHAR) * (plsd->LogonDomain.Length+1));
memcpy(domain, plsd->LogonDomain.Buffer, sizeof(WCHAR) * (plsd->LogonDomain.Length));
domain[plsd->LogonDomain.Length] = 0;
if (!QueryAdHomePathFromSid(homePath,homePathLen,plsd->Sid,domain)) {
DebugEvent("Returned home path [%s]",homePath);
opt->flags |= LOGON_FLAG_AD_REALM;
}
RevertSecurityContext(&ctx);
} else {
DebugEvent("Can't impersonate context [%lX]",status);
code = 1;
}
free(domain);
LsaFreeReturnBuffer(plsd);
} else {
DebugEvent("LsaGetLogonSessionData failed [%lX]", rv);
}
RevertSecurityContext(&ctx);
} else {
DebugEvent("Can't impersonate context [%lX]",status);
code = 1;
}
DeleteSecurityContext(&ctx);
return code;
}
DeleteSecurityContext(&ctx);
return code;
}
BOOL GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
BOOL
GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
{
HRESULT hr;
IADsADSystemInfo *pADsys;
@ -369,7 +384,7 @@ BOOL GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
if (SUCCEEDED(hr))
coInitialized = TRUE;
hr = CoCreateInstance(CLSID_ADSystemInfo,
hr = CoCreateInstance( CLSID_ADSystemInfo,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsADSystemInfo,
@ -388,8 +403,260 @@ BOOL GetLocalShortDomain(PWSTR Domain, DWORD cbDomain)
pADsys->Release();
}
if (coInitialized)
CoUninitialize();
if (coInitialized)
CoUninitialize();
return retval;
}
static HANDLE
OpenRedirector(void)
{
HANDLE hControlDevice = NULL;
hControlDevice = CreateFileW( AFS_SYMLINK_W,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if( hControlDevice == INVALID_HANDLE_VALUE)
{
hControlDevice = NULL;
DebugEvent("OpenRedirector Failed to open control device error: %d",
GetLastError());
}
return hControlDevice;
}
void
AFSCreatePAG(PLUID lpLogonId)
{
BOOLEAN bRet = FALSE;
HANDLE hControlDevice = NULL;
DWORD dwCopyBytes = 0;
AFSAuthGroupRequestCB *pAuthGroup = NULL;
WCHAR * pwchSIDString = NULL;
CtxtHandle ctx;
SECURITY_STATUS status;
PSECURITY_LOGON_SESSION_DATA plsd = NULL;
NTSTATUS rv;
BOOLEAN bImpersonated = FALSE;
GUID stAuthGroup;
unsigned char *pchGUID = NULL;
DWORD bytesReturned;
if (LogonSSP(lpLogonId, &ctx)) {
DebugEvent("AFSCreatePAG unable to obtain LogonSSP context");
return;
}
status = ImpersonateSecurityContext(&ctx);
if (status == SEC_E_OK)
{
bImpersonated = TRUE;
rv = LsaGetLogonSessionData(lpLogonId, &plsd);
if (rv == 0)
{
if( !ConvertSidToStringSidW( plsd->Sid,
&pwchSIDString))
{
DebugEvent("AFSCreatePAG Failed to convert sid to string Error %08X", GetLastError());
goto cleanup;
}
pAuthGroup = (AFSAuthGroupRequestCB *)LocalAlloc( LPTR, 0x1000);
if( pAuthGroup == NULL)
{
DebugEvent0("AFSCreatePAG Failed auth group allocation");
goto cleanup;
}
memset( pAuthGroup, 0, 0x1000);
pAuthGroup->SIDLength = (USHORT) (wcslen( pwchSIDString) * sizeof( WCHAR));
pAuthGroup->SessionId = plsd->Session;
memcpy( pAuthGroup->SIDString,
pwchSIDString,
pAuthGroup->SIDLength);
RevertSecurityContext(&ctx);
bImpersonated = FALSE;
hControlDevice = OpenRedirector();
if( hControlDevice == NULL)
{
DebugEvent0("AFSCreatePAG Failed to open redirector");
goto cleanup;
}
bRet = DeviceIoControl( hControlDevice,
IOCTL_AFS_AUTHGROUP_SID_QUERY,
NULL,
0,
&stAuthGroup,
sizeof( GUID),
&bytesReturned,
NULL);
if( bRet == FALSE)
{
DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Error 0x%08X", GetLastError());
}
else
{
if( UuidToString( (UUID *)&stAuthGroup,
&pchGUID) == RPC_S_OK)
{
DebugEvent("AFSCreatePAG Initial AuthGroup %s\n", pchGUID);
RpcStringFree( &pchGUID);
}
else
{
DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
}
}
ImpersonateSecurityContext(&ctx); bImpersonated = TRUE;
bRet = DeviceIoControl( hControlDevice,
IOCTL_AFS_AUTHGROUP_SID_QUERY,
NULL,
0,
&stAuthGroup,
sizeof( GUID),
&bytesReturned,
NULL);
if( bRet == FALSE)
{
DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Impersonation Error 0x%08X", GetLastError());
}
else
{
if( UuidToString( (UUID *)&stAuthGroup,
&pchGUID) == RPC_S_OK)
{
DebugEvent("AFSCreatePAG Initial Impersonation AuthGroup %s\n", pchGUID);
RpcStringFree( &pchGUID);
}
else
{
DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
}
}
RevertSecurityContext(&ctx); bImpersonated = FALSE;
bRet = DeviceIoControl( hControlDevice,
IOCTL_AFS_AUTHGROUP_LOGON_CREATE,
pAuthGroup,
sizeof( AFSAuthGroupRequestCB) + pAuthGroup->SIDLength - 1,
NULL,
0,
&dwCopyBytes,
NULL);
if( bRet == FALSE)
{
DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_CREATE Error 0x%08X", GetLastError());
}
else
{
bRet = DeviceIoControl( hControlDevice,
IOCTL_AFS_AUTHGROUP_SID_QUERY,
NULL,
0,
&stAuthGroup,
sizeof( GUID),
&bytesReturned,
NULL);
if( bRet == FALSE)
{
DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Error 0x%08X", GetLastError());
}
else
{
if( UuidToString( (UUID *)&stAuthGroup,
&pchGUID) == RPC_S_OK)
{
DebugEvent("AFSCreatePAG New AuthGroup %s\n", pchGUID);
RpcStringFree( &pchGUID);
}
else
{
DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
}
}
}
ImpersonateSecurityContext(&ctx);
bRet = DeviceIoControl( hControlDevice,
IOCTL_AFS_AUTHGROUP_SID_QUERY,
NULL,
0,
&stAuthGroup,
sizeof( GUID),
&bytesReturned,
NULL);
if( bRet == FALSE)
{
DebugEvent("AFSCreatePAG Failed IOCTL_AFS_AUTHGROUP_SID_QUERY Impersonation Error 0x%08X", GetLastError());
}
else
{
if( UuidToString( (UUID *)&stAuthGroup,
&pchGUID) == RPC_S_OK)
{
DebugEvent("AFSCreatePAG New Impersonation AuthGroup %s\n", pchGUID);
RpcStringFree( &pchGUID);
}
else
{
DebugEvent0("AFSCreatePAG Failed to convert GUID to string\n");
}
}
RevertSecurityContext(&ctx);
}
else
{
DebugEvent("AFSCreatePAG LsaGetLogonSessionData failed [%lX]", rv);
}
}
else
{
DebugEvent("AFSCreatePAG cannot impersonate context [%lX]", status);
}
cleanup:
if (bImpersonated)
RevertSecurityContext(&ctx);
DeleteSecurityContext(&ctx);
if (plsd != NULL)
LsaFreeReturnBuffer(plsd);
if ( hControlDevice != NULL)
CloseHandle( hControlDevice);
if( pwchSIDString != NULL)
LocalFree( pwchSIDString);
}

View File

@ -3117,11 +3117,11 @@ void smb_MapNTError(long code, unsigned long *NTStatusp, afs_uint32 redir)
NTStatus = 0xC000022DL; /* Retry */
else {
#ifdef COMMENT
NTStatus = 0xC000022DL; /* Retry */
NTStatus = 0xC000022DL; /* Retry */
#else
NTStatus = 0xC00000B5L; /* I/O Timeout */
NTStatus = 0xC00000B5L; /* I/O Timeout */
#endif
}
}
}
else if (code == CM_ERROR_NOACCESS) {
NTStatus = 0xC0000022L; /* Access denied */
@ -3281,7 +3281,10 @@ void smb_MapNTError(long code, unsigned long *NTStatusp, afs_uint32 redir)
else if (code == CM_ERROR_RPC_MOREDATA) {
NTStatus = 0x80000005L; /* Buffer overflow */
}
else {
else {
char foo[256];
sprintf(foo, "No mapping for 0x%X using 0xC0982001\r\n", code);
OutputDebugString(foo);
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
@ -6932,8 +6935,10 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
lock_ReleaseMutex(&fidp->mx);
/* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
* in zero. */
/*
* CM_UNLOCK_FLAG_BY_FID doesn't look at the process ID.
* We pass in zero.
*/
key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
lock_ObtainWrite(&scp->rw);
@ -6948,7 +6953,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
goto post_syncopdone;
}
cm_UnlockByKey(scp, key, CM_UNLOCK_BY_FID, userp, &req);
cm_UnlockByKey(scp, key, CM_UNLOCK_FLAG_BY_FID, userp, &req);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);

View File

@ -1087,6 +1087,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
* be freed when the refCount returns to zero.
*/
unp->flags &= ~SMB_USERNAMEFLAG_AFSLOGON;
if (usernIsSID)
unp->flags |= SMB_USERNAMEFLAG_SID;
}
if (usernIsSID)
unp->flags |= SMB_USERNAMEFLAG_SID;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2008 Secure Endpoints, Inc.
* Copyright (c) 2009-2011 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Secure Endpoints Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission from Secure Endpoints, Inc. and
* Your File System, Inc.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
extern void RDR_InitIoctl(void);
extern void RDR_SetupIoctl(ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid, cm_user_t *userp);
extern void RDR_CleanupIoctl(ULONG index);
extern afs_int32 RDR_IoctlRead(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer,
ULONG *pBytesProcessed, cm_req_t *reqp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlWrite(cm_user_t *userp, ULONG RequestId, ULONG BufferLength, void *MappedBuffer,
cm_req_t *reqp);
#ifdef RDR_IOCTL_PRIVATE
typedef struct RDR_ioctl {
struct RDR_ioctl *next, *prev;
ULONG index;
cm_fid_t parentFid;
cm_fid_t rootFid;
cm_scache_t *parentScp;
cm_ioctl_t ioctl;
} RDR_ioctl_t;
/* procedure implementing an ioctl */
typedef long (RDR_ioctlProc_t)(RDR_ioctl_t *, struct cm_user *userp, afs_uint32 pflags);
extern void RDR_IoctlPrepareWrite(RDR_ioctl_t *ioctlp);
extern afs_int32 RDR_IoctlPrepareRead(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern RDR_ioctl_t *RDR_FindIoctl(ULONG index);
extern afs_int32 RDR_ParseIoctlPath(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
cm_scache_t **scpp, afs_uint32 flags);
extern afs_int32 RDR_ParseIoctlParent(RDR_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
cm_scache_t **scpp, wchar_t *leafp);
extern afs_int32
RDR_IoctlSetToken(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetFileCellName(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetACL(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlFlushAllVolumes(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlFlushVolume(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlFlushFile(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetVolumeStatus(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetVolumeStatus(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetFid(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetOwner(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlWhereIs(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlStatMountPoint(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlDeleteMountPoint(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlCheckServers(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGag(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlCheckVolumes(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetCacheSize(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetCacheParms(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlNewCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlNewCell2(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetWsCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSysName(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetCellStatus(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetCellStatus(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetSPrefs(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetSPrefs(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlStoreBehind(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlCreateMountPoint(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp);
extern afs_int32 cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp);
extern afs_int32 cm_FlushVolume(cm_user_t *, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume);
extern afs_int32 cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp);
extern afs_int32 RDR_IoctlTraceControl(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetToken(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetTokenIter(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetToken(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlDelToken(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlDelAllToken(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSymlink(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlIslink(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlListlink(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlDeletelink(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlMakeSubmount(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetRxkcrypt(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetRxkcrypt(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlShutdown(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlFreemountAddCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlFreemountRemoveCell(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlMemoryDump(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlRxStatProcess(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlRxStatPeer(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlUUIDControl(struct RDR_ioctl * ioctlp, struct cm_user *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlPathAvailability(struct RDR_ioctl * ioctlp, struct cm_user *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetFileType(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlVolStatTest(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlUnicodeControl(struct RDR_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetOwner(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetGroup(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlGetUnixMode(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
extern afs_int32 RDR_IoctlSetUnixMode(RDR_ioctl_t *ioctlp, cm_user_t *userp, afs_uint32 pflags);
#endif

View File

@ -0,0 +1,351 @@
/*
* Copyright (c) 2008 Secure Endpoints, Inc.
* Copyright (c) 2009-2011 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Secure Endpoints Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission from Secure Endpoints, Inc. and
* Your File System, Inc.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <afsconfig.h>
#include <afs/param.h>
#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <roken.h>
#include <afs/stds.h>
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <strsafe.h>
#include <osi.h>
#include "afsd.h"
#include "cm_rpc.h"
#include "afs/afsrpc.h"
#include "afs/auth.h"
#include "msrpc.h"
#define RDR_PIPE_PRIVATE
#include "RDRPipe.h"
#include "smb.h"
#include "cm_nls.h"
static RDR_pipe_t * RDR_allPipes = NULL, *RDR_allPipesLast = NULL;
static osi_rwlock_t RDR_globalPipeLock;
static wchar_t RDR_UNCName[64]=L"AFS";
void
RDR_InitPipe(void)
{
lock_InitializeRWLock(&RDR_globalPipeLock, "RDR global pipe lock", LOCK_HIERARCHY_RDR_GLOBAL);
}
RDR_pipe_t *
RDR_FindPipe(ULONG index, int locked)
{
RDR_pipe_t *pipep;
if ( !locked)
lock_ObtainRead(&RDR_globalPipeLock);
for ( pipep=RDR_allPipes; pipep; pipep=pipep->next) {
if (pipep->index == index)
break;
}
if ( !locked)
lock_ReleaseRead(&RDR_globalPipeLock);
return pipep;
}
/* called to make a fid structure into an Pipe fid structure */
DWORD
RDR_SetupPipe( ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid,
WCHAR *Name, DWORD NameLength,
cm_user_t *userp)
{
RDR_pipe_t *pipep;
cm_req_t req;
DWORD status;
char name[MAX_PATH];
cm_InitReq(&req);
lock_ObtainWrite(&RDR_globalPipeLock);
pipep = RDR_FindPipe(index, TRUE);
if (pipep) {
/* we are reusing a previous pipe */
if (cm_FidCmp(&pipep->parentFid, parentFid)) {
pipep->parentFid = *parentFid;
if (pipep->parentScp) {
cm_ReleaseSCache(pipep->parentScp);
pipep->parentScp = NULL;
}
cm_GetSCache(parentFid, &pipep->parentScp, userp, &req);
pipep->rootFid = *rootFid;
}
} else {
/* need to allocate a new one */
pipep = malloc(sizeof(*pipep));
if (pipep == NULL) {
status = STATUS_NO_MEMORY;
goto done;
}
memset(pipep, 0, sizeof(*pipep));
if (RDR_allPipes == NULL)
RDR_allPipes = RDR_allPipesLast = pipep;
else {
pipep->prev = RDR_allPipesLast;
RDR_allPipesLast->next = pipep;
RDR_allPipesLast = pipep;
}
pipep->index = index;
if (parentFid->cell == 0) {
pipep->parentFid = cm_data.rootFid;
pipep->parentScp = cm_RootSCachep(userp, &req);
cm_HoldSCache(pipep->parentScp);
} else {
pipep->parentFid = *parentFid;
cm_GetSCache(parentFid, &pipep->parentScp, userp, &req);
}
if (rootFid->cell == 0) {
pipep->rootFid = cm_data.rootFid;
} else {
pipep->rootFid = *rootFid;
}
}
StringCbCopyNW( pipep->name, sizeof(pipep->name), Name, NameLength);
cm_Utf16ToUtf8( pipep->name, -1, name, sizeof(name));
status = MSRPC_InitConn(&pipep->rpc_conn, name);
if (status == STATUS_SUCCESS) {
pipep->flags |= RDR_PIPEFLAG_MESSAGE_MODE;
pipep->devstate = RDR_DEVICESTATE_READMSGFROMPIPE |
RDR_DEVICESTATE_MESSAGEMODEPIPE |
RDR_DEVICESTATE_PIPECLIENTEND;
}
done:
lock_ReleaseWrite(&RDR_globalPipeLock);
return status;
}
void
RDR_CleanupPipe(ULONG index)
{
RDR_pipe_t *pipep;
lock_ObtainWrite(&RDR_globalPipeLock);
pipep = RDR_FindPipe(index, TRUE);
if (pipep) {
if (pipep->parentScp)
cm_ReleaseSCache(pipep->parentScp);
if (pipep->inAllocp)
free(pipep->inAllocp);
if (pipep->outAllocp)
free(pipep->outAllocp);
MSRPC_FreeConn(&pipep->rpc_conn);
if (RDR_allPipes == RDR_allPipesLast)
RDR_allPipes = RDR_allPipesLast = NULL;
else {
if (pipep->prev == NULL)
RDR_allPipes = pipep->next;
else
pipep->prev->next = pipep->next;
if (pipep->next == NULL) {
RDR_allPipesLast = pipep->prev;
pipep->prev->next = NULL;
} else
pipep->next->prev = pipep->prev;
}
free(pipep);
}
lock_ReleaseWrite(&RDR_globalPipeLock);
}
DWORD
RDR_Pipe_Read(ULONG index, ULONG BufferLength, void *MappedBuffer,
ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp)
{
RDR_pipe_t *pipep;
DWORD code = STATUS_INVALID_PIPE_STATE;
lock_ObtainWrite(&RDR_globalPipeLock);
pipep = RDR_FindPipe(index, TRUE);
if (pipep) {
code = MSRPC_PrepareRead(&pipep->rpc_conn);
if (code == 0) {
*pBytesProcessed = MSRPC_ReadMessageLength(&pipep->rpc_conn, BufferLength);
code = MSRPC_ReadMessage(&pipep->rpc_conn, MappedBuffer, *pBytesProcessed);
}
}
lock_ReleaseWrite(&RDR_globalPipeLock);
return code;
}
DWORD
RDR_Pipe_Write( ULONG index, ULONG BufferLength, void *MappedBuffer,
cm_req_t *reqp, cm_user_t *userp)
{
RDR_pipe_t *pipep;
DWORD code = STATUS_INVALID_PIPE_STATE;
lock_ObtainWrite(&RDR_globalPipeLock);
pipep = RDR_FindPipe(index, TRUE);
if (pipep) {
code = MSRPC_WriteMessage( &pipep->rpc_conn, MappedBuffer,
BufferLength, userp);
}
lock_ReleaseWrite(&RDR_globalPipeLock);
return code;
}
DWORD
RDR_Pipe_QueryInfo( ULONG index, ULONG InfoClass,
ULONG BufferLength, void *MappedBuffer,
ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp)
{
RDR_pipe_t *pipep;
DWORD code = STATUS_INVALID_PIPE_STATE;
size_t length;
lock_ObtainWrite(&RDR_globalPipeLock);
pipep = RDR_FindPipe(index, TRUE);
if (pipep) {
switch ( InfoClass ) {
case FileBasicInformation: {
FILE_BASIC_INFORMATION * fbInfo = (FILE_BASIC_INFORMATION *)MappedBuffer;
memset(fbInfo, 0, sizeof(FILE_BASIC_INFORMATION));
fbInfo->FileAttributes = FILE_ATTRIBUTE_NORMAL;
*pBytesProcessed = (DWORD)(sizeof(FILE_BASIC_INFORMATION));
code = STATUS_SUCCESS;
break;
}
case FileStandardInformation: {
FILE_STANDARD_INFORMATION * fsInfo = (FILE_STANDARD_INFORMATION *)MappedBuffer;
memset(fsInfo, 0, sizeof(FILE_STANDARD_INFORMATION));
*pBytesProcessed = (DWORD)(sizeof(FILE_STANDARD_INFORMATION));
code = STATUS_SUCCESS;
break;
}
case FileNameInformation: {
FILE_NAME_INFORMATION * fnInfo = (FILE_NAME_INFORMATION *)MappedBuffer;
StringCbLengthW(pipep->name, sizeof(pipep->name), &length);
if (BufferLength < sizeof(FILE_NAME_INFORMATION) + length) {
code = STATUS_BUFFER_OVERFLOW;
goto done;
}
fnInfo->FileNameLength = (DWORD)length;
memcpy( fnInfo->FileName, pipep->name, length);
*pBytesProcessed = (DWORD)(sizeof(DWORD) + length);
code = STATUS_SUCCESS;
break;
}
default:
code = STATUS_NOT_SUPPORTED;
}
}
done:
lock_ReleaseWrite(&RDR_globalPipeLock);
if (code)
*pBytesProcessed = 0;
return code;
}
DWORD
RDR_Pipe_SetInfo( ULONG index, ULONG InfoClass,
ULONG BufferLength, void *MappedBuffer,
cm_req_t *reqp, cm_user_t *userp)
{
RDR_pipe_t *pipep;
DWORD code = STATUS_INVALID_PIPE_STATE;
lock_ObtainWrite(&RDR_globalPipeLock);
pipep = RDR_FindPipe(index, TRUE);
if (pipep) {
switch ( InfoClass ) {
case FilePipeInformation: {
FILE_PIPE_INFORMATION * fpInfo = (FILE_PIPE_INFORMATION *)MappedBuffer;
if (BufferLength != sizeof(FILE_PIPE_INFORMATION)) {
code = STATUS_INFO_LENGTH_MISMATCH;
goto done;
}
switch ( fpInfo->ReadMode ) {
case FILE_PIPE_BYTE_STREAM_MODE:
pipep->flags &= ~RDR_PIPEFLAG_MESSAGE_MODE;
break;
case FILE_PIPE_MESSAGE_MODE:
pipep->flags |= RDR_PIPEFLAG_MESSAGE_MODE;
break;
}
switch ( fpInfo->CompletionMode ) {
case FILE_PIPE_QUEUE_OPERATION:
pipep->flags |= RDR_PIPEFLAG_BLOCKING;
break;
case FILE_PIPE_COMPLETE_OPERATION:
pipep->flags &= ~RDR_PIPEFLAG_BLOCKING;
break;
}
code = STATUS_SUCCESS;
break;
}
default:
code = STATUS_NOT_SUPPORTED;
}
}
done:
lock_ReleaseWrite(&RDR_globalPipeLock);
return code;
}

View File

@ -0,0 +1,244 @@
/*
* Copyright (c) 2008 Secure Endpoints, Inc.
* Copyright (c) 2009-2011 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Secure Endpoints Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission from Secure Endpoints, Inc. and
* Your File System, Inc.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
extern void RDR_InitPipe(void);
extern DWORD RDR_SetupPipe( ULONG index, cm_fid_t *parentFid, cm_fid_t *rootFid,
WCHAR *Name, DWORD NameLength,
cm_user_t *userp);
extern void RDR_CleanupPipe(ULONG index);
extern DWORD RDR_Pipe_Read(ULONG index, ULONG BufferLength, void *MappedBuffer,
ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp);
extern DWORD RDR_Pipe_Write(ULONG index, ULONG BufferLength, void *MappedBuffer,
cm_req_t *reqp, cm_user_t *userp);
extern DWORD RDR_Pipe_QueryInfo( ULONG index, ULONG InfoClass,
ULONG BufferLength, void *MappedBuffer,
ULONG *pBytesProcessed, cm_req_t *reqp, cm_user_t *userp);
extern DWORD RDR_Pipe_SetInfo( ULONG index, ULONG InfoClass,
ULONG BufferLength, void *MappedBuffer,
cm_req_t *reqp, cm_user_t *userp);
#ifdef RDR_PIPE_PRIVATE
typedef struct RDR_pipe {
struct RDR_pipe *next, *prev;
ULONG index;
wchar_t name[MAX_PATH];
cm_fid_t parentFid;
cm_fid_t rootFid;
cm_scache_t *parentScp;
afs_uint32 flags;
afs_uint32 devstate;
msrpc_conn rpc_conn;
/* input side */
char *inDatap; /* current position
* in input parameter block */
char *inAllocp; /* allocated input parameter block */
afs_uint32 inCopied; /* # of input bytes copied in so far
* by write calls */
/* output side */
char *outDatap; /* output results assembled so far */
char *outAllocp; /* output results assembled so far */
afs_uint32 outCopied; /* # of output bytes copied back so far */
} RDR_pipe_t;
/* flags for smb_ioctl_t */
#define RDR_PIPEFLAG_DATAIN 1 /* reading data from client to server */
#define RDR_PIPEFLAG_LOGON 2 /* got tokens from integrated logon */
#define RDR_PIPEFLAG_USEUTF8 4 /* this request is using UTF-8 strings */
#define RDR_PIPEFLAG_DATAOUT 8 /* sending data from server to client */
#define RDR_PIPEFLAG_RPC 0x0010
#define RDR_PIPEFLAG_MESSAGE_MODE 0x0020
#define RDR_PIPEFLAG_BLOCKING 0x0040
#define RDR_PIPEFLAG_INCALL 0x0080
/* Device state constants */
#define RDR_DEVICESTATE_READASBYTESTREAM 0x0000
#define RDR_DEVICESTATE_READMSGFROMPIPE 0x0100
#define RDR_DEVICESTATE_BYTESTREAMPIPE 0x0000
#define RDR_DEVICESTATE_MESSAGEMODEPIPE 0x0400
#define RDR_DEVICESTATE_PIPECLIENTEND 0x0000
#define RDR_DEVICESTATE_PIPESERVEREND 0x4000
#define RDR_DEVICESTATE_BLOCKING 0x8000
#define RDR_PIPE_MAXDATA 65536
/* procedure implementing an pipe */
typedef long (RDR_pipeProc_t)(RDR_pipe_t *, struct cm_user *userp);
extern RDR_pipe_t *RDR_FindPipe(ULONG index, int locked);
/*
* DDK Data Structures
*
* This is a userland module and does not include DDK headers.
* Replicate the DDK Data Structures required for pipe handling
* based on [MS-FSC]: File System Control Codes
* http://msdn.microsoft.com/en-us/library/cc231987%28v=PROT.13%29.aspx
*/
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4
FileStandardInformation, // 5
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileIdBothDirectoryInformation, // 37
FileIdFullDirectoryInformation, // 38
FileValidDataLengthInformation, // 39
FileShortNameInformation, // 40
FileIoCompletionNotificationInformation, // 41
FileIoStatusBlockRangeInformation, // 42
FileIoPriorityHintInformation, // 43
FileSfioReserveInformation, // 44
FileSfioVolumeInformation, // 45
FileHardLinkInformation, // 46
FileProcessIdsUsingFileInformation, // 47
FileNormalizedNameInformation, // 48
FileNetworkPhysicalNameInformation, // 49
FileIdGlobalTxDirectoryInformation, // 50
FileIsRemoteDeviceInformation, // 51
FileAttributeCacheInformation, // 52
FileNumaNodeInformation, // 53
FileStandardLinkInformation, // 54
FileRemoteProtocolInformation, // 55
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
ULONG FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
typedef struct _FILE_STANDARD_INFORMATION {
LARGE_INTEGER AllocationSize;
LARGE_INTEGER EndOfFile;
ULONG NumberOfLinks;
BOOLEAN DeletePending;
BOOLEAN IsDirectory;
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
typedef struct _FILE_PIPE_INFORMATION {
ULONG ReadMode;
ULONG CompletionMode;
} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION;
typedef struct _FILE_PIPE_LOCAL_INFORMATION {
ULONG NamedPipeType;
ULONG NamedPipeConfiguration;
ULONG MaximumInstances;
ULONG CurrentInstances;
ULONG InboundQuota;
ULONG ReadDataAvailable;
ULONG OutboundQuota;
ULONG WriteQuotaAvailable;
ULONG NamedPipeState;
ULONG NamedPipeEnd;
} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
typedef struct _FILE_PIPE_REMOTE_INFORMATION {
LARGE_INTEGER CollectDataTime;
ULONG MaximumCollectionCount;
} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION;
#define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000
#define FILE_PIPE_MESSAGE_TYPE 0x00000001
#define FILE_PIPE_ACCEPT_REMOTE_CLIENTS 0x00000000
#define FILE_PIPE_REJECT_REMOTE_CLIENTS 0x00000002
#define FILE_PIPE_TYPE_VALID_MASK 0x00000003
#define FILE_PIPE_QUEUE_OPERATION 0x00000000
#define FILE_PIPE_COMPLETE_OPERATION 0x00000001
#define FILE_PIPE_BYTE_STREAM_MODE 0x00000000
#define FILE_PIPE_MESSAGE_MODE 0x00000001
#define FILE_PIPE_INBOUND 0x00000000
#define FILE_PIPE_OUTBOUND 0x00000001
#define FILE_PIPE_FULL_DUPLEX 0x00000002
#define FILE_PIPE_DISCONNECTED_STATE 0x00000001
#define FILE_PIPE_LISTENING_STATE 0x00000002
#define FILE_PIPE_CONNECTED_STATE 0x00000003
#define FILE_PIPE_CLOSING_STATE 0x00000004
#define FILE_PIPE_CLIENT_END 0x00000000
#define FILE_PIPE_SERVER_END 0x00000001
#define FILE_PIPE_READ_DATA 0x00000000
#define FILE_PIPE_WRITE_SPACE 0x00000001
#endif

View File

@ -0,0 +1,360 @@
/*
* Copyright (c) 2008 Secure Endpoints, Inc.
* Copyright (c) 2009-2011 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Secure Endpoints Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission from Secure Endpoints, Inc. and
* Your File System, Inc.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <ntsecapi.h>
// The following are forward declarations of structures
// which are referenced in the RDR code only by pointer.
typedef struct cm_user cm_user_t;
typedef struct cm_req cm_req_t;
typedef struct cm_fid cm_fid_t;
typedef struct cm_scache cm_scache_t;
// Function Declarations
#include <../common/AFSUserPrototypes.h>
void
RDR_InitReq( IN OUT cm_req_t *reqp );
DWORD
RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo,
OUT DWORD * pRedirInitInfoLen );
DWORD
WINAPI
RDR_RequestWorkerThread( LPVOID lpParameter);
DWORD
RDR_ProcessWorkerThreads( IN DWORD);
void
RDR_ProcessRequest( AFSCommRequest *RequestBuffer);
void
RDR_EnumerateDirectory( IN cm_user_t *userp,
IN AFSFileID ParentID,
IN AFSDirQueryCB *QueryCB,
IN BOOL bWow64,
IN BOOL bQueryStatus,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_EvaluateNodeByName( IN cm_user_t *userp,
IN AFSFileID ParentID,
IN WCHAR *Name,
IN DWORD NameLength,
IN BOOL CaseSensitive,
IN BOOL bWow64,
IN BOOL bQueryStatus,
IN BOOL bHoldFid,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_EvaluateNodeByID( IN cm_user_t *userp,
IN AFSFileID ParentID,
IN AFSFileID SourceID,
IN BOOL bWow64,
IN BOOL bQueryStatus,
IN BOOL bHoldFid,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_CreateFileEntry( IN cm_user_t *userp,
IN WCHAR *FileName,
IN DWORD FileNameLength,
IN AFSFileCreateCB *CreateCB,
IN BOOL bWow64,
IN BOOL bHoldFid,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_UpdateFileEntry( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSFileUpdateCB *UpdateCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_DeleteFileEntry( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN ULONGLONG ProcessId,
IN WCHAR *FileName,
IN DWORD FileNameLength,
IN BOOL bWow64,
IN BOOL bCheckOnly,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_RenameFileEntry( IN cm_user_t *userp,
IN WCHAR *SourceFileName,
IN DWORD SourceFileNameLength,
IN AFSFileID SourceFileId,
IN AFSFileRenameCB *RenameCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_FlushFileEntry( IN cm_user_t *userp,
IN AFSFileID FileId,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_OpenFileEntry( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSFileOpenCB *OpenCB,
IN BOOL bWow64,
IN BOOL bHoldFid,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_CleanupFileEntry( IN cm_user_t *userp,
IN AFSFileID FileId,
IN WCHAR *FileName,
IN DWORD FileNameLength,
IN AFSFileCleanupCB *CleanupCB,
IN BOOL bWow64,
IN BOOL bFlushFile,
IN BOOL bDeleteFile,
IN BOOL bUnlockFile,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
BOOL
RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSRequestExtentsCB *RequestExtentsCB,
IN BOOL bWow64,
IN OUT DWORD * ResultBufferLength,
IN OUT AFSSetFileExtentsCB **ResultCB);
void
RDR_ReleaseFileExtents( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSReleaseExtentsCB *ReleaseExtentsCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
DWORD
RDR_RequestExtentRelease( IN cm_fid_t *fidp,
IN LARGE_INTEGER numOfHeldExtents,
IN DWORD numOfExtents,
IN AFSFileExtentCB *extentList);
DWORD
RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFileExtentsResultCB,
IN DWORD ResultBufferLength);
DWORD
RDR_ReleaseFailedSetFileExtents( IN cm_user_t *userp,
IN AFSSetFileExtentsCB *SetFileExtentsResultCB,
IN DWORD ResultBufferLength);
DWORD
RDR_SetFileExtents( IN AFSSetFileExtentsCB *pSetFileExtentsResultCB,
IN DWORD dwResultBufferLength);
void
RDR_PioctlOpen( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PioctlClose( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PioctlWrite( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPIOCtlIORequestCB *pPioctlCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PioctlRead( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPIOCtlIORequestCB *pPioctlCB,
IN BOOL bWow64,
IN BOOL bIsLocalSystem,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_ByteRangeLockSync( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSByteRangeLockRequestCB *pBRLRequestCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_ByteRangeUnlock( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_ByteRangeUnlockAll( IN cm_user_t *userp,
IN AFSFileID FileId,
IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_GetVolumeInfo( IN cm_user_t *userp,
IN AFSFileID FileId,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_HoldFid( IN cm_user_t *userp,
IN AFSHoldFidRequestCB * pHoldFidCB,
IN BOOL bFast,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_ReleaseFid( IN cm_user_t *userp,
IN AFSReleaseFidRequestCB * pReleaseFidCB,
IN BOOL bFast,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeOpen( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN WCHAR *Name,
IN DWORD NameLength,
IN AFSPipeOpenCloseRequestCB *pPipeCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeClose( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPipeOpenCloseRequestCB *pPipeCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeWrite( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPipeIORequestCB *pPipeCB,
IN BYTE *pPipeData,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeRead( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPipeIORequestCB *pPipeCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeSetInfo( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPipeInfoRequestCB *pPipeCB,
IN BYTE *pPipeData,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeQueryInfo( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPipeInfoRequestCB *pPipeCB,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
void
RDR_PipeTransceive( IN cm_user_t *userp,
IN AFSFileID ParentId,
IN AFSPipeIORequestCB *pPipeCB,
IN BYTE *pPipeData,
IN BOOL bWow64,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB);
cm_user_t *
RDR_UserFromCommRequest( IN AFSCommRequest * pRequest);
cm_user_t *
RDR_UserFromAuthGroup( IN GUID *pGuid);
void
RDR_ReleaseUser( IN cm_user_t *userp);
void
RDR_fid2FID( IN cm_fid_t *fid,
IN AFSFileID *FileId);
void
RDR_FID2fid( IN AFSFileID *FileId,
IN cm_fid_t *fid);
void
RDR_InitIoctl(void);
#ifdef __cplusplus
}
#endif