windows-query-afsid-20060420
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index b63c379..70b93cb 100644 (file)
@@ -9,6 +9,9 @@
 
 #include <afs/param.h>
 #include <afs/stds.h>
+#include <afs/cellconfig.h>
+#include <afs/ptserver.h>
+#include <ubik.h>
 
 #ifndef DJGPP
 #include <windows.h>
@@ -26,6 +29,7 @@
 
 #include "afsd.h"
 #include "afsd_init.h"
+#include <WINNT\afsreg.h>
 
 #include "smb.h"
 #include "cm_server.h"
@@ -40,6 +44,9 @@
 
 #include "cm_rpc.h"
 #include <strsafe.h>
+#include <winioctl.h>
+#include <..\afsrdr\kif.h>
+#include <rx\rx.h>
 
 #ifdef _DEBUG
 #include <crtdbg.h>
@@ -61,6 +68,22 @@ void cm_InitIoctl(void)
     lock_InitializeMutex(&cm_Afsdsbmt_Lock, "AFSDSBMT.INI Access Lock");
 }
 
+long cm_CleanFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
+{
+    long code;
+
+    lock_ObtainWrite(&scp->bufCreateLock);
+    code = buf_CleanVnode(scp, userp, reqp);
+        
+    lock_ObtainMutex(&scp->mx);
+    cm_DiscardSCache(scp);
+    lock_ReleaseMutex(&scp->mx);
+
+    lock_ReleaseWrite(&scp->bufCreateLock);
+    osi_Log2(afsd_logp,"cm_CleanFile scp 0x%x returns error: [%x]",scp, code);
+    return code;
+}
+
 long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 {
     long code;
@@ -69,12 +92,51 @@ long cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
     code = buf_FlushCleanPages(scp, userp, reqp);
         
     lock_ObtainMutex(&scp->mx);
-    scp->cbServerp = NULL;
-    scp->cbExpires = 0;
+    cm_DiscardSCache(scp);
+
     lock_ReleaseMutex(&scp->mx);
 
     lock_ReleaseWrite(&scp->bufCreateLock);
-    cm_dnlcPurgedp(scp);
+    osi_Log2(afsd_logp,"cm_FlushFile scp 0x%x returns error: [%x]",scp, code);
+    return code;
+}
+
+long cm_FlushParent(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
+{
+    long code = 0;
+    cm_scache_t * pscp;
+  
+    pscp = cm_FindSCacheParent(scp);
+  
+    /* now flush the file */
+    code = cm_FlushFile(pscp, userp, reqp);
+    cm_ReleaseSCache(scp);
+
+    return code;
+}
+
+
+long cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 volume)
+{
+    long code = 0;
+    cm_scache_t *scp;
+    int i;
+
+    lock_ObtainWrite(&cm_scacheLock);
+    for (i=0; i<cm_data.hashTableSize; i++) {
+        for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
+            if (scp->fid.volume == volume && scp->fid.cell == cell) {
+                cm_HoldSCacheNoLock(scp);
+                lock_ReleaseWrite(&cm_scacheLock);
+
+                /* now flush the file */
+                code = cm_FlushFile(scp, userp, reqp);
+                lock_ObtainWrite(&cm_scacheLock);
+                cm_ReleaseSCacheNoLock(scp);
+            }
+        }
+    }
+    lock_ReleaseWrite(&cm_scacheLock);
 
     return code;
 }
@@ -89,15 +151,15 @@ void cm_ResetACLCache(cm_user_t *userp)
     int hash;
 
     lock_ObtainWrite(&cm_scacheLock);
-    for (hash=0; hash < cm_hashTableSize; hash++) {
-        for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
-            scp->refCount++;
+    for (hash=0; hash < cm_data.hashTableSize; hash++) {
+        for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
+            cm_HoldSCacheNoLock(scp);
             lock_ReleaseWrite(&cm_scacheLock);
             lock_ObtainMutex(&scp->mx);
             cm_InvalidateACLUser(scp, userp);
             lock_ReleaseMutex(&scp->mx);
             lock_ObtainWrite(&cm_scacheLock);
-            scp->refCount--;
+            cm_ReleaseSCacheNoLock(scp);
         }
     }
     lock_ReleaseWrite(&cm_scacheLock);
@@ -142,6 +204,13 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
     long code;
     cm_scache_t *substRootp;
     char * relativePath = ioctlp->inDatap;
+#ifdef AFSIFS
+    char * absRoot[MAX_PATH];
+    long length;
+    wchar_t absRoot_w[MAX_PATH];
+    HANDLE rootDir;
+#endif
+    osi_Log1(afsd_logp, "cm_ParseIoctlPath %s", osi_LogSaveString(afsd_logp,relativePath));
 
     /* This is usually the file name, but for StatMountPoint it is the path. */
     /* ioctlp->inDatap can be either of the form:
@@ -152,6 +221,28 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
      */
     TranslateExtendedChars(relativePath);
 
+#ifdef AFSIFS
+    /* we have passed the whole path, including the afs prefix.
+          when the pioctl call is made, we perform an ioctl to afsrdr
+          and it returns the correct (full) path.  therefore, there is
+          no drive letter, and the path is absolute. */
+    code = cm_NameI(cm_data.rootSCachep, relativePath,
+                     CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
+                     userp, "", reqp, scpp);
+
+    if (code)
+        return code;
+
+    /* # of bytes of path */
+    code = strlen(ioctlp->inDatap) + 1;
+    ioctlp->inDatap += code;
+
+    /* This is usually nothing, but for StatMountPoint it is the file name. */
+    TranslateExtendedChars(ioctlp->inDatap);
+
+    return 0;
+#endif /* AFSIFS */
+
     if (relativePath[0] == relativePath[1] &&
          relativePath[1] == '\\' && 
          !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName))) 
@@ -166,7 +257,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
          * since it had better expand into the value of ioctl->tidPathp
          */
         char * p;
-        p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
+        p = relativePath + 2 + strlen(cm_NetbiosName) + 1;                     /* buffer overflow vuln.? */
         if ( !_strnicmp("all", p, 3) )
             p += 4;
 
@@ -179,7 +270,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
         if ( shareFound ) {
             /* we found a sharename, therefore use the resulting path */
-            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, sharePath, reqp, &substRootp);
             free(sharePath);
@@ -208,7 +299,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
             shareName[i] = 0;       /* terminate string */
 
 
-            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, shareName, reqp, &substRootp);
             if (code) 
@@ -220,7 +311,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
                 return code;
         }
     } else {
-        code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+        code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
                          CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                          userp, ioctlp->tidPathp, reqp, &substRootp);
         if (code) 
@@ -233,7 +324,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
     }
 
     /* # of bytes of path */
-    code = strlen(ioctlp->inDatap) + 1;
+    code = (long)strlen(ioctlp->inDatap) + 1;
     ioctlp->inDatap += code;
 
     /* This is usually nothing, but for StatMountPoint it is the file name. */
@@ -247,7 +338,7 @@ void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
 {
     long temp;
         
-    temp = strlen(ioctlp->inDatap) + 1;
+    temp = (long) strlen(ioctlp->inDatap) + 1;
     ioctlp->inDatap += temp;
 }       
 
@@ -259,7 +350,7 @@ void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
  * easier (because we can always jump past the initial "/afs" to find
  * the AFS path that should be written into afsdsbmt.ini).
  */
-void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
+void cm_NormalizeAfsPath(char *outpathp, long outlen, char *inpathp)
 {
     char *cp;
     char bslash_mountRoot[256];
@@ -268,13 +359,13 @@ void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
     bslash_mountRoot[0] = '\\';
        
     if (!strnicmp (inpathp, cm_mountRoot, strlen(cm_mountRoot)))
-        lstrcpy (outpathp, inpathp);
+        StringCbCopy(outpathp, outlen, inpathp);
     else if (!strnicmp (inpathp, bslash_mountRoot, strlen(bslash_mountRoot)))
-        lstrcpy (outpathp, inpathp);
+        StringCbCopy(outpathp, outlen, inpathp);
     else if ((inpathp[0] == '/') || (inpathp[0] == '\\'))
-        sprintf (outpathp, "%s%s", cm_mountRoot, inpathp);
+        StringCbPrintfA(outpathp, outlen, "%s%s", cm_mountRoot, inpathp);
     else // inpathp looks like "<cell>/usr"
-        sprintf (outpathp, "%s/%s", cm_mountRoot, inpathp);
+        StringCbPrintfA(outpathp, outlen, "%s/%s", cm_mountRoot, inpathp);
 
     for (cp = outpathp; *cp != 0; ++cp) {
         if (*cp == '\\')
@@ -286,10 +377,11 @@ void cm_NormalizeAfsPath (char *outpathp, char *inpathp)
     }
 
     if (!strcmpi (outpathp, cm_mountRoot)) {
-        strcpy (outpathp, cm_mountRoot);
+        StringCbCopy(outpathp, outlen, cm_mountRoot);
     }
 }
 
+#define LEAF_SIZE 256
 /* parse the passed-in file name and do a namei on its parent.  If we fail,
  * return an error code, otherwise return the vnode located in *scpp.
  */
@@ -301,7 +393,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
     char *tp, *jp;
     cm_scache_t *substRootp;
 
-    strcpy(tbuffer, ioctlp->inDatap);
+    StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap);
     tp = strrchr(tbuffer, '\\');
     jp = strrchr(tbuffer, '/');
     if (!tp)
@@ -309,14 +401,14 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
     else if (jp && (tp - tbuffer) < (jp - tbuffer))
         tp = jp;
     if (!tp) {
-        strcpy(tbuffer, "\\");
+        StringCbCopyA(tbuffer, sizeof(tbuffer), "\\");
         if (leafp) 
-            strcpy(leafp, ioctlp->inDatap);
+            StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap);
     }
     else {
         *tp = 0;
         if (leafp) 
-            strcpy(leafp, tp+1);
+            StringCbCopyA(leafp, LEAF_SIZE, tp+1);
     }   
 
     if (tbuffer[0] == tbuffer[1] &&
@@ -346,7 +438,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
         shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
         if ( shareFound ) {
             /* we found a sharename, therefore use the resulting path */
-            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, sharePath, reqp, &substRootp);
             free(sharePath);
@@ -372,7 +464,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
             shareName[i++] = '/';      /* add trailing slash */
             shareName[i] = 0;       /* terminate string */
 
-            code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+            code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
                              CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                              userp, shareName, reqp, &substRootp);
             if (code) return code;
@@ -382,18 +474,18 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
             if (code) return code;
         }
     } else {
-        code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+        code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                         userp, ioctlp->tidPathp, reqp, &substRootp);
         if (code) return code;
 
-        code = cm_NameI(substRootp, tbuffer, CM_FLAG_FOLLOW,
+        code = cm_NameI(substRootp, tbuffer, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                         userp, NULL, reqp, scpp);
         if (code) return code;
     }
 
     /* # of bytes of path */
-    code = strlen(ioctlp->inDatap) + 1;
+    code = (long)strlen(ioctlp->inDatap) + 1;
     ioctlp->inDatap += code;
 
     /* and return success */
@@ -439,7 +531,7 @@ long cm_IoctlGetACL(smb_ioctl_t *ioctlp, cm_user_t *userp)
     if (code) return code;
 
     /* skip over return data */
-    tlen = strlen(ioctlp->outDatap) + 1;
+    tlen = (int)strlen(ioctlp->outDatap) + 1;
     ioctlp->outDatap += tlen;
 
     /* and return success */
@@ -458,13 +550,26 @@ long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
     code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
     if (code) return code;
 
-    cellp = cm_FindCellByID(scp->fid.cell);
-    if (cellp) {
-        strcpy(ioctlp->outDatap, cellp->namep);
+#ifdef AFS_FREELANCE_CLIENT
+    if ( cm_freelanceEnabled && 
+         scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+         scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
+         scp->fid.vnode==0x1 && scp->fid.unique==0x1 ) {
+        StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
         ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
         code = 0;
+    } else 
+#endif /* AFS_FREELANCE_CLIENT */
+    {
+        cellp = cm_FindCellByID(scp->fid.cell);
+        if (cellp) {
+            StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cellp->name);
+            ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
+            code = 0;
+        }
+        else 
+            code = CM_ERROR_NOSUCHCELL;
     }
-    else code = CM_ERROR_NOSUCHCELL;
 
     cm_ReleaseSCache(scp);
     return code;
@@ -493,7 +598,7 @@ long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
     fid.Unique = scp->fid.unique;
     do {
         acl.AFSOpaque_val = ioctlp->inDatap;
-        acl.AFSOpaque_len = strlen(ioctlp->inDatap)+1;
+        acl.AFSOpaque_len = (u_int)strlen(ioctlp->inDatap)+1;
         code = cm_Conn(&scp->fid, userp, &req, &connp);
         if (code) continue;
 
@@ -514,12 +619,40 @@ long cm_IoctlSetACL(struct smb_ioctl *ioctlp, struct cm_user *userp)
     return code;
 }
 
+
+
+long cm_IoctlFlushAllVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    long code;
+    cm_scache_t *scp;
+    int i;
+    cm_req_t req;
+
+    cm_InitReq(&req);
+
+    lock_ObtainWrite(&cm_scacheLock);
+    for (i=0; i<cm_data.hashTableSize; i++) {
+        for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
+           cm_HoldSCacheNoLock(scp);
+           lock_ReleaseWrite(&cm_scacheLock);
+
+           /* now flush the file */
+           code = cm_FlushFile(scp, userp, &req);
+           lock_ObtainWrite(&cm_scacheLock);
+           cm_ReleaseSCacheNoLock(scp);
+        }
+    }
+    lock_ReleaseWrite(&cm_scacheLock);
+
+    return code;
+}
+
 long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
     long code;
     cm_scache_t *scp;
     unsigned long volume;
-    int i;
+    unsigned long cell;
     cm_req_t req;
 
     cm_InitReq(&req);
@@ -528,25 +661,10 @@ long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code) return code;
         
     volume = scp->fid.volume;
+    cell = scp->fid.cell;
     cm_ReleaseSCache(scp);
 
-    lock_ObtainWrite(&cm_scacheLock);
-    for (i=0; i<cm_hashTableSize; i++) {
-        for (scp = cm_hashTablep[i]; scp; scp = scp->nextp) {
-            if (scp->fid.volume == volume) {
-                scp->refCount++;
-                lock_ReleaseWrite(&cm_scacheLock);
-
-                /* now flush the file */
-                code = cm_FlushFile(scp, userp, &req);
-                if ( code )
-                    afsi_log("cm_FlushFile returns error: [%x]",code);
-                lock_ObtainWrite(&cm_scacheLock);
-                scp->refCount--;
-            }
-        }
-    }
-    lock_ReleaseWrite(&cm_scacheLock);
+    code = cm_FlushVolume(userp, &req, cell, volume);
 
     return code;
 }
@@ -607,11 +725,11 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp = ioctlp->inDatap;
     memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus));
     cp += sizeof(AFSFetchVolumeStatus);
-    strcpy(volName, cp);
+    StringCbCopyA(volName, sizeof(volName), cp);
     cp += strlen(volName)+1;
-    strcpy(offLineMsg, cp);
+    StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp);
     cp +=  strlen(offLineMsg)+1;
-    strcpy(motd, cp);
+    StringCbCopyA(motd, sizeof(motd), cp);
     storeStat.Mask = 0;
     if (volStat.MinQuota != -1) {
         storeStat.MinQuota = volStat.MinQuota;
@@ -647,11 +765,11 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp = ioctlp->outDatap;
     memcpy(cp, (char *)&volStat, sizeof(VolumeStatus));
     cp += sizeof(VolumeStatus);
-    strcpy(cp, volName);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
     cp += strlen(volName)+1;
-    strcpy(cp, offLineMsg);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
     cp += strlen(offLineMsg)+1;
-    strcpy(cp, motd);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
     cp += strlen(motd)+1;
 
     /* now return updated return data pointer */
@@ -703,11 +821,11 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp = ioctlp->outDatap;
     memcpy(cp, (char *)&volStat, sizeof(AFSFetchVolumeStatus));
     cp += sizeof(AFSFetchVolumeStatus);
-    strcpy(cp, volName);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), volName);
     cp += strlen(volName)+1;
-    strcpy(cp, offLineMsg);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), offLineMsg);
     cp += strlen(offLineMsg)+1;
-    strcpy(cp, motd);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), motd);
     cp += strlen(motd)+1;
 
     /* return new size */
@@ -716,6 +834,64 @@ long cm_IoctlGetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp)
     return 0;
 }
 
+long cm_IoctlGetFid(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    cm_scache_t *scp;
+    register long code;
+    register char *cp;
+    cm_fid_t fid;
+    cm_req_t req;
+
+    cm_InitReq(&req);
+
+    code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
+    if (code) return code;
+
+    memset(&fid, 0, sizeof(cm_fid_t));
+    fid.volume = scp->fid.volume;
+    fid.vnode  = scp->fid.vnode;
+    fid.unique = scp->fid.unique;
+
+    cm_ReleaseSCache(scp);
+
+    /* Copy all this junk into msg->im_data, keeping track of the lengths. */
+    cp = ioctlp->outDatap;
+    memcpy(cp, (char *)&fid, sizeof(cm_fid_t));
+    cp += sizeof(cm_fid_t);
+
+    /* return new size */
+    ioctlp->outDatap = cp;
+
+    return 0;
+}
+
+long cm_IoctlGetOwner(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    cm_scache_t *scp;
+    register long code;
+    register char *cp;
+    cm_req_t req;
+
+    cm_InitReq(&req);
+
+    code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
+    if (code) return code;
+
+    /* Copy all this junk into msg->im_data, keeping track of the lengths. */
+    cp = ioctlp->outDatap;
+    memcpy(cp, (char *)&scp->owner, sizeof(afs_uint32));
+    cp += sizeof(afs_uint32);
+    memcpy(cp, (char *)&scp->group, sizeof(afs_uint32));
+    cp += sizeof(afs_uint32);
+
+    /* return new size */
+    ioctlp->outDatap = cp;
+
+    cm_ReleaseSCache(scp);
+
+    return 0;
+}
+
 long cm_IoctlWhereIs(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
     long code;
@@ -798,7 +974,7 @@ long cm_IoctlStatMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
     code = cm_ReadMountPoint(scp, userp, &req);
     if (code == 0) {
         cp = ioctlp->outDatap;
-        strcpy(cp, scp->mountPointStringp);
+        StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), scp->mountPointStringp);
         cp += strlen(cp) + 1;
         ioctlp->outDatap = cp;
     }
@@ -882,12 +1058,12 @@ long cm_IoctlCheckServers(struct smb_ioctl *ioctlp, struct cm_user *userp)
         memcpy(&csi, tp, sizeof(csi));
         if (csi.tinterval >= 0) {
             cp = ioctlp->outDatap;
-            memcpy(cp, (char *)&cm_daemonCheckInterval, sizeof(long));
+            memcpy(cp, (char *)&cm_daemonCheckDownInterval, sizeof(long));
             ioctlp->outDatap += sizeof(long);
             if (csi.tinterval > 0) {
                 if (!smb_SUser(userp))
                     return CM_ERROR_NOACCESS;
-                cm_daemonCheckInterval = csi.tinterval;
+                cm_daemonCheckDownInterval = csi.tinterval;
             }
             return 0;
         }
@@ -953,17 +1129,17 @@ long cm_IoctlCheckVolumes(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
 long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
-    long temp;
+    afs_uint64 temp;
     long code;
 
     cm_SkipIoctlPath(ioctlp);
 
     memcpy(&temp, ioctlp->inDatap, sizeof(temp));
     if (temp == 0) 
-        temp = buf_nOrigBuffers;
+        temp = cm_data.buf_nOrigBuffers;
     else {
         /* temp is in 1K units, convert to # of buffers */
-        temp = temp / (buf_bufferSize / 1024);
+        temp = temp / (cm_data.buf_blockSize / 1024);
     }       
 
     /* now adjust the cache size */
@@ -983,6 +1159,7 @@ long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
     /* print trace */
     if (inValue & 8) {
         afsd_ForceTrace(FALSE);
+        buf_ForceTrace(FALSE);
     }
         
     if (inValue & 2) {
@@ -990,10 +1167,12 @@ long cm_IoctlTraceControl(struct smb_ioctl *ioctlp, struct cm_user *userp)
         if ((inValue & 1) == 0) {
             /* disable tracing */
             osi_LogDisable(afsd_logp);
+           rx_DebugOnOff(FALSE);
         }
         else {
             /* enable tracing */
             osi_LogEnable(afsd_logp);
+           rx_DebugOnOff(TRUE);
         }
     }
 
@@ -1016,12 +1195,12 @@ long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
     memset(&parms, 0, sizeof(parms));
 
     /* first we get, in 1K units, the cache size */
-    parms.parms[0] = buf_nbuffers * (buf_bufferSize / 1024);
+    parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
 
     /* and then the actual # of buffers in use (not in the free list, I guess,
      * will be what we do).
      */
-    parms.parms[1] = (buf_nbuffers - buf_CountFreeList()) * (buf_bufferSize / 1024);
+    parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
 
     memcpy(ioctlp->outDatap, &parms, sizeof(parms));
     ioctlp->outDatap += sizeof(parms);
@@ -1054,7 +1233,7 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
     }
 
     lock_ObtainRead(&cm_cellLock);
-    for (tcellp = cm_allCellsp; tcellp; tcellp = tcellp->nextp) {
+    for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
         if (whichCell == 0) break;
         whichCell--;
     }
@@ -1082,8 +1261,8 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
         }
         lock_ReleaseRead(&cm_serverLock);
         cp = basep + max * sizeof(afs_int32);
-        strcpy(cp, tcellp->namep);
-        cp += strlen(tcellp->namep)+1;
+        StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), tcellp->name);
+        cp += strlen(tcellp->name)+1;
         ioctlp->outDatap = cp;
     }
 
@@ -1097,7 +1276,7 @@ extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
 
 long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
-    /* NT cache manager will read cell information from afsdcell.ini each time
+    /* NT cache manager will read cell information from CellServDB each time
      * cell is accessed. So, this call is necessary only if list of server for a cell 
      * changes (or IP addresses of cell servers changes).
      * All that needs to be done is to refresh server information for all cells that 
@@ -1111,18 +1290,19 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_SkipIoctlPath(ioctlp);
     lock_ObtainWrite(&cm_cellLock);
   
-    for (cp = cm_allCellsp; cp; cp=cp->nextp) 
+    for (cp = cm_data.allCellsp; cp; cp=cp->nextp) 
     {
         long code;
+       lock_ObtainMutex(&cp->mx);
         /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
         cm_FreeServerList(&cp->vlServersp);
         cp->vlServersp = NULL;
-        code = cm_SearchCellFile(cp->namep, cp->namep, cm_AddCellProc, cp);
+        code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
 #ifdef AFS_AFSDB_ENV
         if (code) {
             if (cm_dnsEnabled) {
                 int ttl;
-                code = cm_SearchCellByDNS(cp->namep, cp->namep, &ttl, cm_AddCellProc, cp);
+                code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
                 if ( code == 0 ) { /* got cell from DNS */
                     cp->flags |= CM_CELLFLAG_DNS;
                     cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
@@ -1141,6 +1321,7 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
             cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
             cm_RandomizeServer(&cp->vlServersp);
         }
+       lock_ReleaseMutex(&cp->mx);
     }
     
     lock_ReleaseWrite(&cm_cellLock);
@@ -1149,17 +1330,22 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
 long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
 {
-    /* if we don't know our default cell, return failure */
-    if (cm_rootCellp == NULL) {
-        return CM_ERROR_NOSUCHCELL;
-    }
+       long code = 0;
 
-    /* return the default cellname to the caller */
-    strcpy(ioctlp->outDatap, cm_rootCellp->namep);
-    ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
+       if (cm_freelanceEnabled) {
+            if (cm_GetRootCellName(ioctlp->outDatap))
+                StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "Freelance.Local.Root");
+            ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
+       } else if (cm_data.rootCellp) {
+           /* return the default cellname to the caller */
+           StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), cm_data.rootCellp->name);
+           ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
+       } else {
+           /* if we don't know our default cell, return failure */
+            code = CM_ERROR_NOSUCHCELL;
+    }
 
-    /* done: success */
-    return 0;
+    return code;
 }
 
 long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
@@ -1181,7 +1367,7 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
         cp2 = ioctlp->inDatap;
         for ( cp=ioctlp->inDatap, count = 0; count < setSysName; count++ ) {
             /* won't go past end of ioctlp->inDatap since maxsysname*num < ioctlp->inDatap length */
-            t = strlen(cp);
+            t = (int)strlen(cp);
             if (t >= MAXSYSNAME || t <= 0)
                 return EINVAL;
             /* check for names that can shoot us in the foot */
@@ -1193,7 +1379,7 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
         /* inname gets first entry in case we're being a translator */
         /* (we are never a translator) */
-        t = strlen(ioctlp->inDatap);
+        t = (int)strlen(ioctlp->inDatap);
         memcpy(inname, ioctlp->inDatap, t + 1);
         ioctlp->inDatap += t + 1;
         num = count;
@@ -1204,7 +1390,7 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
         osi_panic("cm_IoctlSysName: !cm_sysName\n", __FILE__, __LINE__);
 
     if (!setSysName) {      /* user just wants the info */
-        strcpy(outname, cm_sysName);
+        StringCbCopyA(outname, sizeof(outname), cm_sysName);
         foundname = cm_sysNameCount;
         *sysnamelist = cm_sysNameList;
     } else {        
@@ -1212,16 +1398,16 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
         /* 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, ... */
-        strcpy(cm_sysName, inname);
-               strcpy(cm_sysNameList[0], inname);
+        StringCbCopyA(cm_sysName, sizeof(cm_sysName), inname);
+        StringCbCopyA(cm_sysNameList[0], MAXSYSNAME, inname);
         if (setSysName > 1) {       /* ... or list */
             cp = ioctlp->inDatap;
             for (count = 1; count < setSysName; ++count) {
                 if (!cm_sysNameList[count])
                     osi_panic("cm_IoctlSysName: no cm_sysNameList entry to write\n",
                                __FILE__, __LINE__);
-                t = strlen(cp);
-                strcpy(cm_sysNameList[count], cp);
+                t = (int)strlen(cp);
+                StringCbCopyA(cm_sysNameList[count], MAXSYSNAME, cp);
                 cp += t + 1;
             }
         }
@@ -1234,17 +1420,17 @@ long cm_IoctlSysName(struct smb_ioctl *ioctlp, struct cm_user *userp)
         memcpy(cp, (char *)&foundname, sizeof(afs_int32));
         cp += sizeof(afs_int32);       /* skip found flag */
         if (foundname) {
-            strcpy(cp, outname);
+            StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), outname);
             cp += strlen(outname) + 1; /* skip name and terminating null char */
             for ( count=1; count < foundname ; ++count) {   /* ... or list */
                 if ( !(*sysnamelist)[count] )
                     osi_panic("cm_IoctlSysName: no cm_sysNameList entry to read\n", 
                                __FILE__, __LINE__);
-                t = strlen((*sysnamelist)[count]);
+                t = (int)strlen((*sysnamelist)[count]);
                 if (t >= MAXSYSNAME)
                     osi_panic("cm_IoctlSysName: sysname entry garbled\n", 
                                __FILE__, __LINE__);
-                strcpy(cp, (*sysnamelist)[count]);
+                StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), (*sysnamelist)[count]);
                 cp += t + 1;
             }
         }
@@ -1333,25 +1519,29 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
         {
             tsp->ipRank = rank; /* no need to protect by mutex*/
 
-            if ( type == CM_SERVER_FILE) /* fileserver */
-            {
+            if (type == CM_SERVER_FILE)
+            {   /* fileserver */
                 /* find volumes which might have RO copy 
                 /* on server and change the ordering of 
-                ** their RO list */
-                    cm_ChangeRankVolume(tsp);
+                 * their RO list 
+                 */
+                cm_ChangeRankVolume(tsp);
             }
             else       
             {
                 /* set preferences for an existing vlserver */
                 cm_ChangeRankCellVLServer(tsp);
             }
-            cm_PutServer(tsp);  /* decrease refcount */
         }
         else   /* add a new server without a cell */
         {
             tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
             tsp->ipRank = rank;
         }
+       lock_ObtainMutex(&tsp->mx);
+       tsp->flags |= CM_SERVERFLAG_PREF_SET;
+       lock_ReleaseMutex(&tsp->mx);
+       cm_PutServer(tsp);  /* decrease refcount */
     }
     return 0;
 }
@@ -1412,7 +1602,7 @@ long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
-    char leaf[256];
+    char leaf[LEAF_SIZE];
     long code;
     cm_scache_t *dscp;
     cm_attr_t tattr;
@@ -1439,12 +1629,12 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
      */
 
     /* Extract the possibly partial cell name */
-    strcpy(cell, ioctlp->inDatap + 1);      /* Skip the mp type character */
+    StringCbCopyA(cell, sizeof(cell), ioctlp->inDatap + 1);      /* Skip the mp type character */
         
     if (cp = strchr(cell, ':')) {
         /* Extract the volume name */
         *cp = 0;
-        strcpy(volume,  cp + 1);
+        StringCbCopyA(volume,  sizeof(volume), cp + 1);
        
         /* Get the full name for this cell */
         code = cm_SearchCellFile(cell, fullCell, 0, 0);
@@ -1455,14 +1645,14 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
         if (code)
             return CM_ERROR_NOSUCHCELL;
        
-        sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
+        StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
     } else {
         /* No cell name specified */
-        strcpy(mpInfo, ioctlp->inDatap);
+        StringCbCopyA(mpInfo, sizeof(mpInfo), ioctlp->inDatap);
     }
 
 #ifdef AFS_FREELANCE_CLIENT
-    if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
+    if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
         /* we are adding the mount point to the root dir., so call
          * the freelance code to do the add. */
         osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
@@ -1490,7 +1680,7 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
-    char leaf[256];
+    char leaf[LEAF_SIZE];
     long code;
     cm_scache_t *dscp;
     cm_attr_t tattr;
@@ -1510,6 +1700,26 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     cp = ioctlp->inDatap;              /* contents of link */
 
+#ifdef AFS_FREELANCE_CLIENT
+    if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
+        /* we are adding the symlink to the root dir., so call
+         * the freelance code to do the add. */
+        if (cp[0] == cp[1] && cp[1] == '\\' && 
+            !_strnicmp(cm_NetbiosName,cp+2,strlen(cm_NetbiosName))) 
+        {
+            /* skip \\AFS\ or \\AFS\all\ */
+            char * p;
+            p = cp + 2 + strlen(cm_NetbiosName) + 1;
+            if ( !_strnicmp("all", p, 3) )
+                p += 4;
+            cp = p;
+        }
+        osi_Log0(afsd_logp,"IoctlCreateSymlink within Freelance root dir");
+        code = cm_FreelanceAddSymlink(leaf, cp, NULL);
+        return code;
+    }
+#endif
+
     /* Create symlink with mode 0755. */
     tattr.mask = CM_ATTRMASK_UNIXMODEBITS;
     tattr.unixModeBits = 0755;
@@ -1526,9 +1736,6 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     return code;
 }
 
-extern long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp,
-                            cm_scache_t **newRootScpp, cm_space_t **newSpaceBufferp,
-                            cm_user_t *userp, cm_req_t *reqp);
 
 long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
@@ -1552,7 +1759,9 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code) return code;
 
     /* Check that it's a real symlink */
-    if (scp->fileType != CM_SCACHETYPE_SYMLINK){
+    if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
+        scp->fileType != CM_SCACHETYPE_DFSLINK &&
+        scp->fileType != CM_SCACHETYPE_INVALID) {
         cm_ReleaseSCache(scp);
         return CM_ERROR_INVAL;
     }
@@ -1562,17 +1771,30 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code == 0) {
         cp = ioctlp->outDatap;
         if (newRootScp != NULL) {
-            strcpy(cp, cm_mountRoot);
-            strcat(cp, "/");
+            StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), cm_mountRoot);
+            StringCbCatA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), "/");
             cp += strlen(cp);
         }
-        strcpy(cp, spacep->data);
+        StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
         cp += strlen(cp) + 1;
         ioctlp->outDatap = cp;
         cm_FreeSpace(spacep);
         if (newRootScp != NULL)
             cm_ReleaseSCache(newRootScp);
-    }       
+        code = 0;
+    } else if (code == CM_ERROR_PATH_NOT_COVERED && 
+                scp->fileType == CM_SCACHETYPE_DFSLINK ||
+               code == CM_ERROR_NOSUCHPATH &&
+                scp->fileType == CM_SCACHETYPE_INVALID) {
+        cp = ioctlp->outDatap;
+        StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), spacep->data);
+        cp += strlen(cp) + 1;
+        ioctlp->outDatap = cp;
+        cm_FreeSpace(spacep);
+        if (newRootScp != NULL)
+            cm_ReleaseSCache(newRootScp);
+        code = 0;
+    }
 
     return code;
 }
@@ -1598,7 +1820,9 @@ long cm_IoctlIslink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code) return code;
 
     /* Check that it's a real symlink */
-    if (scp->fileType != CM_SCACHETYPE_SYMLINK)
+    if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
+        scp->fileType != CM_SCACHETYPE_DFSLINK &&
+        scp->fileType != CM_SCACHETYPE_INVALID)
         code = CM_ERROR_INVAL;
     cm_ReleaseSCache(scp);
     return code;
@@ -1619,6 +1843,16 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     cp = ioctlp->inDatap;
 
+#ifdef AFS_FREELANCE_CLIENT
+    if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
+        /* we are adding the mount point to the root dir., so call
+         * the freelance code to do the add. */
+        osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
+        code = cm_FreelanceRemoveSymlink(cp);
+        return code;
+    }
+#endif
+
     code = cm_Lookup(dscp, cp, CM_FLAG_NOMOUNTCHASE, userp, &req, &scp);
         
     /* if something went wrong, bail out now */
@@ -1636,7 +1870,9 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     }
        
     /* now check that this is a real symlink */
-    if (scp->fileType != CM_SCACHETYPE_SYMLINK) {
+    if (scp->fileType != CM_SCACHETYPE_SYMLINK &&
+        scp->fileType != CM_SCACHETYPE_DFSLINK &&
+        scp->fileType != CM_SCACHETYPE_INVALID) {
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
         code = CM_ERROR_INVAL;
@@ -1660,6 +1896,82 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     return code;
 }
 
+long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
+{
+    afs_int32 code;
+    namelist lnames;
+    idlist lids;
+    static struct afsconf_cell info;
+    struct rx_connection *serverconns[MAXSERVERS];
+    struct rx_securityClass *sc[3];
+    afs_int32 scIndex = 2;     /* authenticated - we have a token */
+    struct ubik_client *pruclient = NULL;
+    struct afsconf_dir *tdir;
+    int i;
+    char * p, * r;
+
+    tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
+    code = afsconf_GetCellInfo(tdir, ucellp->cellp->name, "afsprot", &info);
+    afsconf_Close(tdir);
+
+    sc[0] = 0;
+    sc[1] = 0;
+    sc[2] = 0;
+
+    /* we have the token that was given to us in the settoken 
+     * call.   we just have to use it. 
+     */
+    scIndex = 2;       /* kerberos ticket */
+    sc[2] = rxkad_NewClientSecurityObject(rxkad_clear, &ucellp->sessionKey,
+                                         ucellp->kvno, ucellp->ticketLen,
+                                         ucellp->ticketp);
+
+    memset(serverconns, 0, sizeof(serverconns));       /* terminate list!!! */
+    for (i = 0; i < info.numServers; i++)
+       serverconns[i] =
+           rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
+                            info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
+                            scIndex);
+
+    code = ubik_ClientInit(serverconns, &pruclient);
+    if (code) {
+       return code;
+    }
+
+    code = rxs_Release(sc[scIndex]);
+
+    lids.idlist_len = 0;
+    lids.idlist_val = 0;
+    lnames.namelist_len = 1;
+    lnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
+    strncpy(lnames.namelist_val[0], uname, PR_MAXNAMELEN);
+    lnames.namelist_val[0][PR_MAXNAMELEN-1] = '\0';
+    for ( p=lnames.namelist_val[0], r=NULL; *p; p++ ) {
+       if (isupper(*p))
+           *p = tolower(*p);
+       if (*p == '@')
+           r = p;
+    }
+    if (r && !stricmp(r+1,ucellp->cellp->name))
+       *r = '\0';
+
+    code = ubik_Call(PR_NameToID, pruclient, 0, &lnames, &lids);
+    if (lids.idlist_val) {
+       *uid = *lids.idlist_val;
+       free(lids.idlist_val);
+    }
+    if (lnames.namelist_val)
+       free(lnames.namelist_val);
+
+    if ( pruclient ) {
+       ubik_ClientDestroy(pruclient);
+       pruclient = NULL;
+    }
+
+    return 0;
+}
+
+
 long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
     char *saveDataPtr;
@@ -1675,6 +1987,8 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
     int flags;
     char sessionKey[8];
     char *smbname;
+    int release_userp = 0;
+    char * wdir = NULL;
 
     saveDataPtr = ioctlp->inDatap;
 
@@ -1719,6 +2033,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
         uname = tp;
         tp += strlen(tp) + 1;
 
+#ifndef AFSIFS                 /* no SMB username, so we cannot log based on this */
         if (flags & PIOCTL_LOGON) {
             /* SMB user name with which to associate tokens */
             smbname = tp;
@@ -1730,6 +2045,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
             osi_Log1(smb_logp,"cm_IoctlSetToken for user [%s]",
                      osi_LogSaveString(smb_logp,uname));
         }
+#endif
 
 #ifndef DJGPP   /* for win95, session key is back in pioctl */
                /* uuid */
@@ -1738,12 +2054,14 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
             return CM_ERROR_INVAL;
 #endif /* !DJGPP */
     } else {
-        cellp = cm_rootCellp;
+        cellp = cm_data.rootCellp;
         osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
     }
 
     if (flags & PIOCTL_LOGON) {
-        userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname);
+        userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
+                                    SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
+       release_userp = 1;
     }
 
     /* store the token */
@@ -1770,7 +2088,12 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
     ucellp->kvno = ct.AuthHandle;
     ucellp->expirationTime = ct.EndTimestamp;
     ucellp->gen++;
-    if (uname) strcpy(ucellp->userName, uname);
+    ucellp->uid = ANONYMOUSID;
+    if (uname) {
+        StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
+
+       cm_UsernameToId(uname, ucellp, &ucellp->uid);
+    }
     ucellp->flags |= CM_UCELLFLAG_RXKAD;
     lock_ReleaseMutex(&userp->mx);
 
@@ -1780,6 +2103,9 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     cm_ResetACLCache(userp);
 
+    if (release_userp)
+       cm_ReleaseUser(userp);
+
     return 0;
 }
 
@@ -1856,11 +2182,11 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp += sizeof(temp);
 
     /* cell name */
-    strcpy(cp, ucellp->cellp->namep);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
     cp += strlen(cp) + 1;
 
     /* user name */
-    strcpy(cp, ucellp->userName);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
     cp += strlen(cp) + 1;
 
     ioctlp->outDatap = cp;
@@ -1890,7 +2216,8 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     /* cell name is right here */
     cellp = cm_GetCell(tp, 0);
-    if (!cellp) return CM_ERROR_NOSUCHCELL;
+    if (!cellp) 
+        return CM_ERROR_NOSUCHCELL;
     tp += strlen(tp) + 1;
 
 #ifndef DJGPP
@@ -1944,11 +2271,11 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cp += sizeof(temp);
 
     /* cell name */
-    strcpy(cp, ucellp->cellp->namep);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->cellp->name);
     cp += strlen(cp) + 1;
 
     /* user name */
-    strcpy(cp, ucellp->userName);
+    StringCbCopyA(cp, SMB_IOCTL_MAXDATA - (cp - ioctlp->outAllocp), ucellp->userName);
     cp += strlen(cp) + 1;
 
     ioctlp->outDatap = cp;
@@ -1990,6 +2317,11 @@ long cm_IoctlDelToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
         free(ucellp->ticketp);
         ucellp->ticketp = NULL;
     }
+    ucellp->ticketLen = 0;
+    memset(ucellp->sessionKey.data, 0, 8);
+    ucellp->kvno = 0;
+    ucellp->expirationTime = 0;
+    ucellp->userName[0] = '\0';
     ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
     ucellp->gen++;
 
@@ -2008,6 +2340,16 @@ long cm_IoctlDelAllToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
     for (ucellp = userp->cellInfop; ucellp; ucellp = ucellp->nextp) {
         osi_Log1(smb_logp,"cm_IoctlDelAllToken ucellp %lx", ucellp);
+
+       if (ucellp->ticketp) {
+           free(ucellp->ticketp);
+           ucellp->ticketp = NULL;
+       }
+       ucellp->ticketLen = 0;
+       memset(ucellp->sessionKey.data, 0, 8);
+       ucellp->kvno = 0;
+       ucellp->expirationTime = 0;
+       ucellp->userName[0] = '\0';
         ucellp->flags &= ~CM_UCELLFLAG_RXKAD;
         ucellp->gen++;
     }
@@ -2040,7 +2382,7 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
     /* Parse the input parameters--first the required afs path,
      * then the requested submount name (which may be "").
      */
-    cm_NormalizeAfsPath (afspath, ioctlp->inDatap);
+    cm_NormalizeAfsPath (afspath, sizeof(afspath), ioctlp->inDatap);
     submountreqp = ioctlp->inDatap + (strlen(ioctlp->inDatap)+1);
 
     /* If the caller supplied a suggested submount name, see if
@@ -2049,7 +2391,7 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
      */
 
     RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
-                    "SOFTWARE\\OpenAFS\\Client\\Submounts",
+                    AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
                     0, 
                     "AFS", 
                     REG_OPTION_NON_VOLATILE,
@@ -2078,12 +2420,12 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
                            (strlen(&afspath[strlen(cm_mountRoot)])) ?
                            &afspath[strlen(cm_mountRoot)]:"/",
                            (strlen(&afspath[strlen(cm_mountRoot)])) ?
-                           strlen(&afspath[strlen(cm_mountRoot)])+1:2);
+                           (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
 
             RegCloseKey( hkSubmounts );
-                       strcpy(ioctlp->outDatap, submountreqp);
-                       ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
-                       lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
+            StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
+            ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
+            lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
             return 0;
         }
 
@@ -2091,9 +2433,9 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
          * supplied path matches the submount's path, we can still
          * use the suggested submount name.
          */
-        cm_NormalizeAfsPath (submountPathNormalized, submountPath);
+        cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
         if (!strcmp (submountPathNormalized, afspath)) {
-            strcpy(ioctlp->outDatap, submountreqp);
+            StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountreqp);
             ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
             RegCloseKey( hkSubmounts );
             lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
@@ -2160,9 +2502,9 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
          * that our caller specified. If so, we can return
          * this submount.
          */
-        cm_NormalizeAfsPath (submountPathNormalized, submountPath);
+        cm_NormalizeAfsPath (submountPathNormalized, sizeof(submountPathNormalized), submountPath);
         if (!strcmp (submountPathNormalized, afspath)) {
-            strcpy(ioctlp->outDatap, submountName);
+            StringCbCopyA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), submountName);
             ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
             RegCloseKey(hkSubmounts);
             lock_ReleaseMutex(&cm_Afsdsbmt_Lock);
@@ -2177,7 +2519,7 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
      * when writing out the submount.
      */
 
-    sprintf(ioctlp->outDatap, "auto%ld", nextAutoSubmount);
+    StringCbPrintfA(ioctlp->outDatap, SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp), "auto%ld", nextAutoSubmount);
 
     RegSetValueEx( hkSubmounts, 
                    ioctlp->outDatap,
@@ -2186,7 +2528,7 @@ long cm_IoctlMakeSubmount(smb_ioctl_t *ioctlp, cm_user_t *userp)
                    (strlen(&afspath[strlen(cm_mountRoot)])) ?
                    &afspath[strlen(cm_mountRoot)]:"/",
                    (strlen(&afspath[strlen(cm_mountRoot)])) ?
-                   strlen(&afspath[strlen(cm_mountRoot)])+1:2);
+                   (DWORD)strlen(&afspath[strlen(cm_mountRoot)])+1:2);
 
     ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
     RegCloseKey(hkSubmounts);
@@ -2204,10 +2546,64 @@ long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
 
 long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
 {
+    afs_int32 c = cryptall;
+
     cm_SkipIoctlPath(ioctlp);
 
     memcpy(&cryptall, ioctlp->inDatap, sizeof(cryptall));
 
+    if (c != cryptall) {
+       if (cryptall)
+            LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_ON);
+       else
+            LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_CRYPT_OFF);
+    }
+    return 0;
+}
+
+long cm_IoctlRxStatProcess(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    afs_int32 flags;
+    int code = 0;
+
+    cm_SkipIoctlPath(ioctlp);
+
+    memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
+    if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
+        return -1;
+    }
+    if (flags & AFSCALL_RXSTATS_ENABLE) {
+        rx_enableProcessRPCStats();
+    }
+    if (flags & AFSCALL_RXSTATS_DISABLE) {
+        rx_disableProcessRPCStats();
+    }
+    if (flags & AFSCALL_RXSTATS_CLEAR) {
+        rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
+    }
+    return 0;
+}
+
+long cm_IoctlRxStatPeer(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    afs_int32 flags;
+    int code = 0;
+
+    cm_SkipIoctlPath(ioctlp);
+
+    memcpy((char *)&flags, ioctlp->inDatap, sizeof(afs_int32));
+    if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
+       return -1;
+    }
+    if (flags & AFSCALL_RXSTATS_ENABLE) {
+        rx_enablePeerRPCStats();
+    }
+    if (flags & AFSCALL_RXSTATS_DISABLE) {
+        rx_disablePeerRPCStats();
+    }
+    if (flags & AFSCALL_RXSTATS_CLEAR) {
+        rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
+    }
     return 0;
 }
 
@@ -2237,9 +2633,9 @@ long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp)
  * functions to dump contents of various structures. 
  * In debug build (linked with crt debug library) will dump allocated but not freed memory
  */
-extern int cm_DumpSCache(FILE *outputFile, char *cookie);
-extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie);
-extern int smb_DumpVCP(FILE *outputFile, char *cookie);
+extern int cm_DumpSCache(FILE *outputFile, char *cookie, int lock);
+extern int cm_DumpBufHashTable(FILE *outputFile, char *cookie, int lock);
+extern int smb_DumpVCP(FILE *outputFile, char *cookie, int lock);
 
 long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
@@ -2247,6 +2643,7 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
     HANDLE hLogFile;
     char logfileName[MAX_PATH+1];
     char *cookie;
+    DWORD dwSize;
   
 #ifdef _DEBUG  
     static _CrtMemState memstate;
@@ -2255,12 +2652,8 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_SkipIoctlPath(ioctlp);
     memcpy(&inValue, ioctlp->inDatap, sizeof(long));
   
-    if (getenv("TEMP"))
-    {
-        strncpy(logfileName, getenv("TEMP"), MAX_PATH);
-        logfileName[MAX_PATH] = '\0';
-    }
-    else
+    dwSize = GetEnvironmentVariable("TEMP", logfileName, sizeof(logfileName));
+    if ( dwSize == 0 || dwSize > sizeof(logfileName) )
     {
         GetWindowsDirectory(logfileName, sizeof(logfileName));
     }
@@ -2297,9 +2690,9 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
 #endif
   
     /* dump all interesting data */
-    cm_DumpSCache(hLogFile, cookie);
-    cm_DumpBufHashTable(hLogFile, cookie);
-    smb_DumpVCP(hLogFile, cookie);
+    cm_DumpSCache(hLogFile, cookie, 1);
+    cm_DumpBufHashTable(hLogFile, cookie, 1);
+    smb_DumpVCP(hLogFile, cookie, 1);
 
     CloseHandle(hLogFile);