windows-volstat-and-vista-dfs-support-20071222
authorJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 23 Dec 2007 04:51:59 +0000 (04:51 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sun, 23 Dec 2007 04:51:59 +0000 (04:51 +0000)
LICENSE MIT

This patch completes the implementation of smb_ReceiveTran2GetDFSReferral()
which is called by Vista even if we do not advertise the support of DFS
referrals.  It also adds DFS link mapping notifications to the volstat
interface which can be used by volstat plug-ins to redirect requests to
the dfs target path.

Other miscellaneous items:

(1) return EAS_NOT_SUPPORTED instead of EA length 0 and silently accepting
    but not storing EA data

(2) Call cm_VolStatus_Service_Started() before smb initialization instead
    of afterwards

(3) During directory enumeration and link assembly push the UNC path into
    the lower levels by storing references to the tidPath and the relative
    paths within the cm_req_t object.

(4) During directory enumeration make absolutely sure that we do not
    reference an unallocated cm_dirEntry_t object

(5) publish a prototype for cm_FollowMountPoint()

(6) return ERROR_RETRY instead of BAD_NETWORK_PATH if the server returns
    VBUSY

(7) return PATH_NOT_COVERED instead of BADSHARENAME for DfsLinks when
    a volstat plugin is in use

src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_conn.h
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_vnodeops.h
src/WINNT/afsd/cm_volstat.c
src/WINNT/afsd/cm_volstat.h
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c

index c8ec622..2fdd140 100644 (file)
@@ -114,7 +114,7 @@ extern long rx_mtu;
 
 extern HANDLE WaitToTerminate;
 
-#undef  DFS_SUPPORT
+#define DFS_SUPPORT 1
 #define LOG_PACKET 1
 #undef  NOTSERVICE
 #define LOCK_TESTING 1
index 328e16e..0f7e478 100644 (file)
@@ -1305,6 +1305,9 @@ afsd_Main(DWORD argc, LPTSTR *argv)
         SetServiceStatus(StatusHandle, &ServiceStatus);
 #endif
 
+        /* Notify any volume status handlers that the cache manager has started */
+        cm_VolStatus_Service_Started();
+
 /* the following ifdef chooses the mode of operation for the service.  to enable
  * a runtime flag (instead of compile-time), pioctl() would need to dynamically
  * determine the mode, in order to use the correct ioctl special-file path. */
@@ -1367,9 +1370,6 @@ afsd_Main(DWORD argc, LPTSTR *argv)
        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVICE_RUNNING);
     }
 
-    /* Notify any volume status handlers that we have started */
-    cm_VolStatus_Service_Started();
-
     /* allow an exit to be called when started */
     hHookDll = LoadLibrary(AFSD_HOOK_DLL);
     if (hHookDll)
index 6d8be09..c16f8e9 100644 (file)
@@ -299,6 +299,7 @@ int RXAFS_Lookup (struct rx_connection *,
 #define CM_ERROR_NOT_A_DFSLINK          (CM_ERROR_BASE+53)
 #define CM_ERROR_INEXACT_MATCH          (CM_ERROR_BASE+54)
 #define CM_ERROR_BPLUS_NOMATCH          (CM_ERROR_BASE+55)
+#define CM_ERROR_EAS_NOT_SUPPORTED      (CM_ERROR_BASE+56)
 
 /* Used by cm_FollowMountPoint and cm_GetVolumeByName */
 #define RWVOL  0
index f127254..5cfd346 100644 (file)
@@ -32,13 +32,19 @@ typedef struct cm_conn {
 
 #define CM_CONN_FLAG_FORCE_NEW 1
 
-/* structure used for tracking RPC progress */
+/* 
+ * structure used for tracking RPC progress
+ * and for passing path info from the smb layer 
+ * to the cache manager functions.
+ */
 typedef struct cm_req {
        DWORD startTime;                /* Quit before RDR times us out */
        int rpcError;                   /* RPC error code */
        int volumeError;                /* volume error code */
        int accessError;                /* access error code */
        int flags;
+        char * tidPathp;
+        char * relPathp;
 } cm_req_t;
 
 /* flags in cm_req structure */
index fd35295..3bd1f3f 100644 (file)
@@ -474,7 +474,7 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
     long code;
     osi_hyper_t thyper;
     cm_buf_t *bufferp;
-    cm_dirEntry_t *dep;
+    cm_dirEntry_t *dep = 0;
     unsigned short *hashTable;
     unsigned int i, idx;
     int BeyondPage = 0, HaveDot = 0, HaveDotDot = 0;
@@ -573,7 +573,7 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
 {
     char *tp;
     long code;
-    cm_dirEntry_t *dep;
+    cm_dirEntry_t *dep = 0;
     cm_buf_t *bufferp;
     long temp;
     osi_hyper_t dirLength;
@@ -1717,6 +1717,9 @@ long cm_HandleLink(cm_scache_t *linkScp, cm_user_t *userp, cm_req_t *reqp)
         if (!linkScp->mountPointStringp[0]) {
             strncpy(linkScp->mountPointStringp, bufp->datap, temp);
             linkScp->mountPointStringp[temp] = 0;      /* null terminate */
+
+            if ( !strnicmp(linkScp->mountPointStringp, "msdfs:", strlen("msdfs:")) )
+                 linkScp->fileType = CM_SCACHETYPE_DFSLINK;
         }
         buf_Release(bufp);
     }  /* don't have sym link contents cached */
@@ -1739,9 +1742,12 @@ long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp,
     char *linkp;
     cm_space_t *tsp;
 
+    *newRootScpp = NULL;
+    *newSpaceBufferp = NULL;
+
     lock_ObtainMutex(&linkScp->mx);
     code = cm_HandleLink(linkScp, userp, reqp);
-    if (code) 
+    if (code)
         goto done;
 
     /* if we may overflow the buffer, bail out; buffer is signficantly
@@ -1778,13 +1784,12 @@ long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp,
         } else {
             linkScp->fileType = CM_SCACHETYPE_DFSLINK;
             strcpy(tsp->data, linkp);
-            *newRootScpp = NULL;
             code = CM_ERROR_PATH_NOT_COVERED;
         }
-    } else if ( !strnicmp(linkp, "msdfs:", (len = (long)strlen("msdfs:"))) ) {
+    } else if ( linkScp->fileType == CM_SCACHETYPE_DFSLINK ||
+                !strnicmp(linkp, "msdfs:", (len = (long)strlen("msdfs:"))) ) {
         linkScp->fileType = CM_SCACHETYPE_DFSLINK;
         strcpy(tsp->data, linkp);
-        *newRootScpp = NULL;
         code = CM_ERROR_PATH_NOT_COVERED;
     } else if (*linkp == '\\' || *linkp == '/') {
 #if 0   
@@ -1800,19 +1805,24 @@ long cm_AssembleLink(cm_scache_t *linkScp, char *pathSuffixp,
          */
         linkScp->fileType = CM_SCACHETYPE_INVALID;
         strcpy(tsp->data, linkp);
-        *newRootScpp = NULL;
         code = CM_ERROR_NOSUCHPATH;
 #endif  
     } else {
         /* a relative link */
         strcpy(tsp->data, linkp);
-        *newRootScpp = NULL;
     }
     if (pathSuffixp[0] != 0) { /* if suffix string is non-null */
         strcat(tsp->data, "\\");
         strcat(tsp->data, pathSuffixp);
     }
-    *newSpaceBufferp = tsp;
+    if (code == 0)
+        *newSpaceBufferp = tsp;
+    else {
+        cm_FreeSpace(tsp);
+
+        if (code == CM_ERROR_PATH_NOT_COVERED && reqp->tidPathp && reqp->relPathp)
+            cm_VolStatus_Notify_DFS_Mapping(linkScp, reqp->tidPathp, reqp->relPathp);
+    }
 
   done:
     lock_ReleaseMutex(&linkScp->mx);
index ac9d59f..b376efd 100644 (file)
@@ -189,6 +189,10 @@ extern long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp,
 extern long cm_EvaluateSymLink(cm_scache_t *dscp, cm_scache_t *linkScp,
        cm_scache_t **outScpp, cm_user_t *userp, cm_req_t *reqp);
 
+extern long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
+                                cm_req_t *reqp, cm_scache_t **outScpp);
+
+
 extern long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
         LARGE_INTEGER LOffset, LARGE_INTEGER LLength, cm_key_t key,
        int allowWait, cm_user_t *userp, cm_req_t *reqp,
index 25af0c9..328ca3c 100644 (file)
@@ -46,6 +46,14 @@ HMODULE hVolStatus = NULL;
 dll_VolStatus_Funcs_t dll_funcs;
 cm_VolStatus_Funcs_t cm_funcs;
 
+static char volstat_NetbiosName[64] = "";
+
+afs_uint32
+cm_VolStatus_Active(void)
+{
+    return (hVolStatus != NULL);
+}
+
 /* This function is used to load any Volume Status Handlers 
  * and their associated function pointers.  
  */
@@ -64,6 +72,12 @@ cm_VolStatus_Initialization(void)
         dummyLen = sizeof(wd);
         code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL,
                                 (BYTE *) &wd, &dummyLen);
+
+        if (code == 0) {
+            dummyLen = sizeof(volstat_NetbiosName);
+            code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL, 
+                                   (BYTE *)volstat_NetbiosName, &dummyLen);
+        }
         RegCloseKey (parmKey);
     }
 
@@ -76,6 +90,7 @@ cm_VolStatus_Initialization(void)
             cm_funcs.cm_VolStatus_Path_To_ID = cm_VolStatus_Path_To_ID;
             cm_funcs.cm_VolStatus_Path_To_DFSlink = cm_VolStatus_Path_To_DFSlink;
 
+            dll_funcs.version = DLL_VOLSTATUS_FUNCS_VERSION;
             code = dll_VolStatus_Initialization(&dll_funcs, &cm_funcs);
         } 
 
@@ -87,6 +102,8 @@ cm_VolStatus_Initialization(void)
         }
     }
 
+    osi_Log1(afsd_logp,"cm_VolStatus_Initialization 0x%x", code);
+
     return code;
 }
 
@@ -96,6 +113,8 @@ cm_VolStatus_Initialization(void)
 long 
 cm_VolStatus_Finalize(void)
 {
+    osi_Log1(afsd_logp,"cm_VolStatus_Finalize handle 0x%x", hVolStatus);
+
     if (hVolStatus == NULL)
         return 0;
 
@@ -113,6 +132,8 @@ cm_VolStatus_Service_Started(void)
 {
     long code = 0;
 
+    osi_Log1(afsd_logp,"cm_VolStatus_Service_Started handle 0x%x", hVolStatus);
+
     if (hVolStatus == NULL)
         return 0;
    
@@ -131,6 +152,8 @@ cm_VolStatus_Service_Stopped(void)
 {
     long code = 0;
 
+    osi_Log1(afsd_logp,"cm_VolStatus_Service_Stopped handle 0x%x", hVolStatus);
+
     if (hVolStatus == NULL)
         return 0;
    
@@ -225,22 +248,68 @@ cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volst
 }
 
 
+
+long
+cm_VolStatus_Notify_DFS_Mapping(cm_scache_t *scp, char *tidPathp, char *pathp)
+{
+    long code = 0;
+    char src[1024], *p;
+    size_t len;
+
+    if (hVolStatus == NULL || dll_funcs.version < 2)
+        return 0;
+
+    snprintf(src,sizeof(src), "\\\\%s%s", volstat_NetbiosName, tidPathp);
+    len = strlen(src);
+    if ((src[len-1] == '\\' || src[len-1] == '/') &&
+        (pathp[0] == '\\' || pathp[0] == '/'))
+        strncat(src, &pathp[1], sizeof(src));
+    else
+        strncat(src, pathp, sizeof(src));
+
+    for ( p=src; *p; p++ ) {
+        if (*p == '/')
+            *p = '\\';
+    }
+
+    code = dll_funcs.dll_VolStatus_Notify_DFS_Mapping(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
+                                                      src, scp->mountPointStringp);
+
+    return code;
+}
+
+long
+cm_VolStatus_Invalidate_DFS_Mapping(cm_scache_t *scp)
+{
+    long code = 0;
+
+    if (hVolStatus == NULL || dll_funcs.version < 2)
+        return 0;
+
+    code = dll_funcs.dll_VolStatus_Invalidate_DFS_Mapping(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
+
+    return code;
+}
+
+
 long __fastcall
-cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID)
+cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus)
 {
-    afs_uint32  code;
+    afs_uint32  code = 0;
     cm_req_t    req;
     cm_scache_t *scp;
 
     if (cellID == NULL || volID == NULL)
         return CM_ERROR_INVAL;
 
-    cm_InitReq(&req);
+    osi_Log2(afsd_logp,"cm_VolStatus_Path_To_ID share %s path %s", 
+              osi_LogSaveString(afsd_logp, (char *)share), osi_LogSaveString(afsd_logp, (char *)path));
 
+    cm_InitReq(&req);
 
-    code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
+    code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
     if (code)
-        return code;
+        goto done;
 
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL,cm_rootUserp, &req, 0,
@@ -248,24 +317,27 @@ cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cell
     if (code) {
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
-        return code;
+        goto done;
     }
         
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
     *cellID = scp->fid.cell;
     *volID  = scp->fid.volume;
+    *pstatus = cm_GetVolumeStatus(scp->volp, scp->fid.volume);
 
     lock_ReleaseMutex(&scp->mx);
     cm_ReleaseSCache(scp);
 
-    return 0;
+  done:
+    osi_Log1(afsd_logp,"cm_VolStatus_Path_To_ID code 0x%x",code); 
+    return code;
 }
 
 long __fastcall
 cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer)
 {
-    afs_uint32  code;
+    afs_uint32  code = 0;
     cm_req_t    req;
     cm_scache_t *scp;
     size_t      len;
@@ -273,11 +345,15 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *
     if (pBufSize == NULL || (pBuffer == NULL && *pBufSize != 0))
         return CM_ERROR_INVAL;
 
+    osi_Log2(afsd_logp,"cm_VolStatus_Path_To_DFSlink share %s path %s", 
+              osi_LogSaveString(afsd_logp, (char *)share), osi_LogSaveString(afsd_logp, (char *)path));
+
     cm_InitReq(&req);
 
-    code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
+    code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW, 
+                    cm_rootUserp, (char *)share, &req, &scp);
     if (code)
-        return code;
+        goto done;
 
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, cm_rootUserp, &req, 0,
@@ -285,13 +361,15 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *
     if (code) {
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
-        return code;
+        goto done;
     }
         
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
-    if (scp->fileType != CM_SCACHETYPE_DFSLINK)
-        return CM_ERROR_NOT_A_DFSLINK;
+    if (scp->fileType != CM_SCACHETYPE_DFSLINK) {
+        code = CM_ERROR_NOT_A_DFSLINK;
+        goto done;
+    }
 
     len = strlen(scp->mountPointStringp) + 1;
     if (pBuffer == NULL)
@@ -299,11 +377,15 @@ cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *
     else if (*pBufSize >= len) {
         strcpy(pBuffer, scp->mountPointStringp);
         *pBufSize = len;
-    } else 
+    } else {
         code = CM_ERROR_TOOBIG;
+        goto done;
+    }
 
     lock_ReleaseMutex(&scp->mx);
     cm_ReleaseSCache(scp);
 
-    return 0;
+  done:
+    osi_Log1(afsd_logp,"cm_VolStatus_Path_To_DFSlink code 0x%x",code); 
+    return code;
 }
index 877d37c..8d20cad 100644 (file)
@@ -55,25 +55,36 @@ extern long cm_VolStatus_Network_Addr_Change(void);
 
 extern long cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status);
 
-extern long __fastcall cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID);
+extern long __fastcall cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus);
 
 extern long __fastcall cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer);
 
-#define DLL_VOLSTATUS_FUNCS_VERSION 1
+extern long cm_VolStatus_Notify_DFS_Mapping(cm_scache_t *scp, char *tidPathp, char *pathp);
+
+extern long cm_VolStatus_Invalidate_DFS_Mapping(cm_scache_t *scp);
+
+#define DLL_VOLSTATUS_FUNCS_VERSION 2
 typedef struct dll_VolStatus_Funcs {
     afs_uint32          version;
+    /* version 1 */
     long (__fastcall * dll_VolStatus_Service_Started)(void);
     long (__fastcall * dll_VolStatus_Service_Stopped)(void);
     long (__fastcall * dll_VolStatus_Network_Started)(const char *netbios32, const char *netbios64);
     long (__fastcall * dll_VolStatus_Network_Stopped)(const char *netbios32, const char *netbios64);
     long (__fastcall * dll_VolStatus_Network_Addr_Change)(void);
     long (__fastcall * dll_VolStatus_Change_Notification)(afs_uint32 cellID, afs_uint32 volID, enum volstatus status);
+    /* version 2 */
+    long (__fastcall * dll_VolStatus_Notify_DFS_Mapping)(afs_uint32 cellID, afs_uint32 volID, 
+                                                         afs_uint32 vnodeID, afs_uint32 uniqID,
+                                                         char *src, char *target);
+    long (__fastcall * dll_VolStatus_Invalidate_DFS_Mapping)(afs_uint32 cellID, afs_uint32 volID, 
+                                                             afs_uint32 vnodeID, afs_uint32 uniqID);
 } dll_VolStatus_Funcs_t;
 
 #define CM_VOLSTATUS_FUNCS_VERSION 1
 typedef struct cm_VolStatus_Funcs {
     afs_uint32          version;
-    long (__fastcall * cm_VolStatus_Path_To_ID)(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID);
+    long (__fastcall * cm_VolStatus_Path_To_ID)(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID, enum volstatus *pstatus);
     long (__fastcall * cm_VolStatus_Path_To_DFSlink)(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer);
 } cm_VolStatus_Funcs_t;
 
index fa15b6f..3059ee2 100644 (file)
@@ -2630,23 +2630,12 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     else if (code == CM_ERROR_PATH_NOT_COVERED) {
         NTStatus = 0xC0000257L; /* Path Not Covered */
     } 
-#ifdef COMMENT
     else if (code == CM_ERROR_ALLBUSY) {
-        NTStatus = 0xC00000BFL; /* Network Busy */
+        NTStatus = 0xC000022DL; /* Retry */
     } 
     else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
-        NTStatus = 0xC0000350L; /* Remote Host Down */
-    } 
-#else
-    /* we do not want to be telling the SMB/CIFS client that
-     * the AFS Client Service is busy or down.  
-     */
-    else if (code == CM_ERROR_ALLBUSY || 
-             code == CM_ERROR_ALLOFFLINE ||
-            code == CM_ERROR_ALLDOWN) {
         NTStatus = 0xC00000BEL; /* Bad Network Path */
-    }
-#endif
+    } 
     else if (code == RXKADUNKNOWNKEY) {
        NTStatus = 0xC0000322L; /* Bad Kerberos key */
     } 
@@ -3611,23 +3600,31 @@ int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
 
     /* mask starts out all blanks */
     memset(maskp, ' ', 11);
+    maskp[11] = '\0';
 
     /* find last backslash, or use whole thing if there is none */
     tp = strrchr(pathp, '\\');
-    if (!tp) tp = pathp;
-    else tp++; /* skip slash */
+    if (!tp) 
+        tp = pathp;
+    else 
+        tp++;  /* skip slash */
         
     up = maskp;
 
     /* names starting with a dot are illegal */
-    if (*tp == '.') valid8Dot3 = 0;
+    if (*tp == '.') 
+        valid8Dot3 = 0;
 
     for(i=0;; i++) {
         tc = *tp++;
-        if (tc == 0) return valid8Dot3;
-        if (tc == '.' || tc == '"') break;
-        if (i < 8) *up++ = tc;
-        else valid8Dot3 = 0;
+        if (tc == 0) 
+            return valid8Dot3;
+        if (tc == '.' || tc == '"') 
+            break;
+        if (i < 8) 
+            *up++ = tc;
+        else
+            valid8Dot3 = 0;
     }
         
     /* if we get here, tp point after the dot */
@@ -3706,7 +3703,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 {
     unsigned char *pathp;
     unsigned char *tp;
-    unsigned char mask[11];
+    unsigned char mask[12];
     unsigned char *statBlockp;
     unsigned char initStatBlock[21];
     int statLen;
@@ -3772,8 +3769,10 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
     return 0;
 }       
 
-long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
-                             cm_user_t *userp, cm_req_t *reqp)
+static long 
+smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
+                        char * tidPathp, char * relPathp,
+                        cm_user_t *userp, cm_req_t *reqp)
 {
     long code = 0;
     cm_scache_t *scp;
@@ -3783,13 +3782,20 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     char attr;
     smb_dirListPatch_t *patchp;
     smb_dirListPatch_t *npatchp;
+    char path[AFSPATHMAX];
 
     for (patchp = *dirPatchespp; patchp; patchp =
          (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
 
         dptr = patchp->dptr;
 
+        snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name);
+        reqp->relPathp = path;
+        reqp->tidPathp = tidPathp;
+
         code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
+        reqp->relPathp = reqp->tidPathp = NULL;
+
         if (code) {
             if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
                 *dptr++ = SMB_ATTR_HIDDEN;
@@ -3853,7 +3859,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     char *tp;
     long code = 0;
     char *pathp;
-    cm_dirEntry_t *dep;
+    cm_dirEntry_t *dep = 0;
     int maxCount;
     smb_dirListPatch_t *dirListPatchesp;
     smb_dirListPatch_t *curPatchp;
@@ -3876,7 +3882,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     char shortName[13];
     char *actualName;
     char *shortNameEnd;
-    char mask[11];
+    char mask[12];
     int returnedNames;
     long nextEntryCookie;
     int numDirChunks;          /* # of 32 byte dir chunks in this entry */
@@ -3887,7 +3893,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     int starPattern;
     int rootPath = 0;
     int caseFold;
-    char *tidPathp;
+    char *tidPathp = 0;
     cm_req_t req;
     cm_fid_t fid;
     int fileType;
@@ -3938,7 +3944,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         dsp = smb_NewDirSearch(0);
         dsp->attribute = attribute;
         smb_Get8Dot3MaskFromPath(mask, pathp);
-        memcpy(dsp->mask, mask, 11);
+        memcpy(dsp->mask, mask, 12);
 
         /* track if this is likely to match a lot of entries */
         if (smb_IsStarMask(mask)) 
@@ -3964,7 +3970,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
          */
         memcpy(&clientCookie, &inCookiep[17], 4);
 
-        memcpy(mask, dsp->mask, 11);
+        memcpy(mask, dsp->mask, 12);
 
         /* assume we're doing a star match if it has continued for more
          * than one call.
@@ -3995,17 +4001,21 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             smb_ReleaseDirSearch(dsp);
             return CM_ERROR_NOFILES;
         }
+        strcpy(dsp->tidPath, tidPathp ? tidPathp : "/");
+        strcpy(dsp->relPath, spacep->data);
+
         code = cm_NameI(cm_data.rootSCachep, spacep->data,
                         caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
         if (code == 0) {
 #ifdef DFS_SUPPORT
             if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data);
                 cm_ReleaseSCache(scp);
                 lock_ReleaseMutex(&dsp->mx);
                 cm_ReleaseUser(userp);
                 smb_DeleteDirSearch(dsp);
                 smb_ReleaseDirSearch(dsp);
-                if ( WANTS_DFS_PATHNAMES(inp) )
+                if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
                     return CM_ERROR_BADSHARENAME;
@@ -4129,7 +4139,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
              * the status info for files in the dir.
              */
             if (starPattern) {
-                smb_ApplyDirListPatches(&dirListPatchesp, userp, &req);
+                smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
                 lock_ObtainMutex(&scp->mx);
                 if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                      LargeIntegerGreaterThanOrEqualTo(thyper, 
@@ -4352,7 +4362,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     /* apply and free last set of patches; if not doing a star match, this
      * will be empty, but better safe (and freeing everything) than sorry.
      */
-    smb_ApplyDirListPatches(&dirListPatchesp, userp, &req);
+    smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
 
     /* special return code for unsuccessful search */
     if (code == 0 && dataLength < 21 && returnedNames == 0)
@@ -4439,9 +4449,10 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         
 #ifdef DFS_SUPPORT
     if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp);
         cm_ReleaseSCache(newScp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -4526,9 +4537,10 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
 #ifdef DFS_SUPPORT
     if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp);
         cm_ReleaseSCache(newScp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -4660,7 +4672,8 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         if (code == 0) {
 #ifdef DFS_SUPPORT
             if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-                if ( WANTS_DFS_PATHNAMES(inp) )
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+                if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
                     return CM_ERROR_BADSHARENAME;
@@ -4694,9 +4707,10 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         
 #ifdef DFS_SUPPORT
     if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp);
         cm_ReleaseSCache(newScp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -4849,9 +4863,10 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 #ifdef DFS_SUPPORT
     if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -4963,11 +4978,11 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
 
         cm_DirEntryListAdd(dep->name, &rockp->matches);
 
-            rockp->any = 1;
+        rockp->any = 1;
 
-            /* If we made a case sensitive exact match, we might as well quit now. */
-            if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
-                code = CM_ERROR_STOPNOW;
+        /* If we made a case sensitive exact match, we might as well quit now. */
+        if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
+            code = CM_ERROR_STOPNOW;
         else
             code = 0;
     }
@@ -5025,9 +5040,10 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp,spacep->data);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -5186,9 +5202,10 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         
 #ifdef DFS_SUPPORT
     if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->data);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -5207,10 +5224,11 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
 
 #ifdef DFS_SUPPORT
     if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->data);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseSCache(newDscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -5386,9 +5404,10 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
         
 #ifdef DFS_SUPPORT
     if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->data);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -5406,10 +5425,11 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
 
 #ifdef DFS_SUPPORT
     if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->data);
         cm_ReleaseSCache(newDscp);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -5611,9 +5631,10 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -6944,9 +6965,10 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -7068,9 +7090,10 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
index f305064..5a3eeed 100644 (file)
@@ -447,6 +447,8 @@ typedef struct smb_dirSearch {
                                         * locked by smb_globalLock */
     unsigned short attribute;          /* search attribute
                                         * (used for extended protocol) */
+    char tidPath[256];                  /* tid path */
+    char relPath[1024];                 /* relative path */        
     char mask[256];                    /* search mask for V3 */
 } smb_dirSearch_t;
 
index ca6f2c0..ff3f03b 100644 (file)
@@ -1068,10 +1068,21 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
        if (vcp->flags & SMB_VCFLAG_USENT)
         {
             int policy = smb_FindShareCSCPolicy(shareName);
+            HKEY parmKey;
+            DWORD code;
+            DWORD dwAdvertiseDFS = 0, dwSize = sizeof(DWORD);
+
+            code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+                                 0, KEY_QUERY_VALUE, &parmKey);
+            if (code == ERROR_SUCCESS) {
+                code = RegQueryValueEx(parmKey, "AdvertiseDFS", NULL, NULL,
+                                       (BYTE *)&dwAdvertiseDFS, &dwSize);
+                if (code != ERROR_SUCCESS)
+                    dwAdvertiseDFS = 0;
+                RegCloseKey (parmKey);
+            }
             smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | 
-#ifdef DFS_SUPPORT
-                            SMB_SHARE_IS_IN_DFS |
-#endif
+                           (dwAdvertiseDFS ? SMB_SHARE_IS_IN_DFS : 0) |
                             (policy << 2));
         }
     } else {
@@ -2216,10 +2227,11 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         
 #ifdef DFS_SUPPORT
         if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+            int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
             cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             smb_FreeTran2Packet(outp);
-            if ( WANTS_DFS_PATHNAMES(p) )
+            if ( WANTS_DFS_PATHNAMES(p) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
                 return CM_ERROR_BADSHARENAME;
@@ -2245,10 +2257,11 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     } else {
 #ifdef DFS_SUPPORT
         if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+            int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, lastNamep);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             smb_FreeTran2Packet(outp);
-            if ( WANTS_DFS_PATHNAMES(p) )
+            if ( WANTS_DFS_PATHNAMES(p) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
                 return CM_ERROR_BADSHARENAME;
@@ -2621,6 +2634,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp,
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
+        DebugBreak();
         return CM_ERROR_PATH_NOT_COVERED;
     }
 #endif /* DFS_SUPPORT */
@@ -2764,7 +2778,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 if (code == 0) {
 #ifdef DFS_SUPPORT
                     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-                        if ( WANTS_DFS_PATHNAMES(p) )
+                        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+                        if ( WANTS_DFS_PATHNAMES(p) || pnc )
                             code = CM_ERROR_PATH_NOT_COVERED;
                         else
                             code = CM_ERROR_BADSHARENAME;
@@ -2810,9 +2825,10 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
 #ifdef DFS_SUPPORT
     if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(p) )
+        if ( WANTS_DFS_PATHNAMES(p) || pnc )
             code = CM_ERROR_PATH_NOT_COVERED;
         else
             code = CM_ERROR_BADSHARENAME;
@@ -2976,7 +2992,8 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        infoLevel != SMB_INFO_QUERY_ALL_EAS) {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
-        smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
+        smb_SendTran2Error(vcp, p, opx, 
+                           infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL);
         return 0;
     }
 
@@ -3034,7 +3051,8 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                 if (code == 0) {
 #ifdef DFS_SUPPORT
                     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-                        if ( WANTS_DFS_PATHNAMES(p) )
+                        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+                        if ( WANTS_DFS_PATHNAMES(p) || pnc )
                             code = CM_ERROR_PATH_NOT_COVERED;
                         else
                             code = CM_ERROR_BADSHARENAME;
@@ -3156,7 +3174,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     }               
     else if (infoLevel == SMB_INFO_QUERY_ALL_EAS) {
        /* we don't support EAs */
-       code = CM_ERROR_INVAL;
+       code = CM_ERROR_EAS_NOT_SUPPORTED;
     }       
 
   done:
@@ -3569,11 +3587,14 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     long code = 0;
     int maxReferralLevel = 0;
     char requestFileName[1024] = "";
+    char referralPath[1024] = "";
     smb_tran2Packet_t *outp = 0;
     cm_user_t *userp = 0;
+    cm_scache_t *scp = 0;
+    cm_scache_t *dscp = 0;
     cm_req_t req;
     CPINFO CodePageInfo;
-    int i, nbnLen, reqLen;
+    int i, nbnLen, reqLen, refLen;
     int idx;
 
     cm_InitReq(&req);
@@ -3590,57 +3611,152 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     nbnLen = strlen(cm_NetbiosName);
     reqLen = strlen(requestFileName);
 
-    if (reqLen == nbnLen + 5 &&
-        requestFileName[0] == '\\' &&
+    if (reqLen > nbnLen + 2 && requestFileName[0] == '\\' &&
         !_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) &&
-        requestFileName[nbnLen+1] == '\\' &&
-        (!_strnicmp("all",&requestFileName[nbnLen+2],3) || 
-         !_strnicmp("*.",&requestFileName[nbnLen+2],2)))
+        requestFileName[nbnLen+1] == '\\') 
     {
-        USHORT * sp;
-        struct smb_v2_referral * v2ref;
-        outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (reqLen + 8));
-
-        sp = (USHORT *)outp->datap;
-        idx = 0;
-        sp[idx++] = reqLen;   /* path consumed */
-        sp[idx++] = 1;        /* number of referrals */
-        sp[idx++] = 0x03;     /* flags */
+        int found = 0;
+
+        if (!_strnicmp("all",&requestFileName[nbnLen+2],3) ||
+             !_strnicmp("*.",&requestFileName[nbnLen+2],2)) 
+        {
+            found = 1;
+            strcpy(referralPath, requestFileName);
+            refLen = reqLen;
+        } else {
+            userp = smb_GetTran2User(vcp, p);
+            if (!userp) {
+                osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+                code = CM_ERROR_BADSMB;
+                goto done;
+            }   
+
+            /* 
+             * We have a requested path.  Check to see if it is something 
+             * we know about.
+             */
+            code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2],
+                            CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                            userp, NULL, &req, &scp);
+            if (code == 0) {
+                /* Yes it is. */
+                found = 1;
+                strcpy(referralPath, requestFileName);
+                refLen = reqLen;
+            } else if (code == CM_ERROR_PATH_NOT_COVERED ) {
+                char temp[1024];
+                char pathName[1024];
+                char *lastComponent;
+                /* 
+                 * we have a msdfs link somewhere in the path
+                 * we should figure out where in the path the link is.
+                 * and return it.
+                 */
+                osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral PATH_NOT_COVERED [%s]", requestFileName);
+
+                strcpy(temp, &requestFileName[nbnLen+2]);
+
+                do {
+                    if (dscp) {
+                        cm_ReleaseSCache(dscp);
+                        dscp = 0;
+                    }
+                    if (scp) {
+                        cm_ReleaseSCache(scp);
+                        scp = 0;
+                    }
+                    smb_StripLastComponent(pathName, &lastComponent, temp);
+
+                    code = cm_NameI(cm_data.rootSCachep, pathName,
+                                    CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                                    userp, NULL, &req, &dscp);
+                    if (code == 0) {
+                        code = cm_NameI(dscp, ++lastComponent,
+                                        CM_FLAG_CASEFOLD,
+                                        userp, NULL, &req, &scp);
+                        if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK)
+                            break;
+                    }
+                } while (code == CM_ERROR_PATH_NOT_COVERED);
+
+                /* scp should now be the DfsLink we are looking for */
+                if (scp) {
+                    /* figure out how much of the input path was used */
+                    reqLen = nbnLen+2 + strlen(pathName) + 1 + strlen(lastComponent);
+
+                    strcpy(referralPath, &scp->mountPointStringp[strlen("msdfs:")]);
+                    refLen = strlen(referralPath);
+                    found = 1;
+                }
+            } else {
+                char shareName[MAX_PATH + 1];
+                char *p, *q;
+                /* we may have a sharename that is a volume reference */
+
+                for (p = &requestFileName[nbnLen+2], q = shareName; *p && *p != '\\'; p++, q++)
+                {
+                    *q = *p;
+                }
+                *q = '\0';
+                
+                if (smb_FindShare(vcp, vcp->usersp, shareName, &p)) {
+                    code = cm_NameI(cm_data.rootSCachep, "", 
+                                    CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
+                                    userp, p, &req, &scp);
+                    free(p);
+
+                    if (code == 0) {
+                        found = 1;
+                        strcpy(referralPath, requestFileName);
+                        refLen = reqLen;
+                    }
+                }
+            }
+        }
+        
+        if (found)
+        {
+            USHORT * sp;
+            struct smb_v2_referral * v2ref;
+            outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (refLen + 8));
+
+            sp = (USHORT *)outp->datap;
+            idx = 0;
+            sp[idx++] = reqLen;   /* path consumed */
+            sp[idx++] = 1;        /* number of referrals */
+            sp[idx++] = 0x03;     /* flags */
 #ifdef DFS_VERSION_1
-        sp[idx++] = 1;        /* Version Number */
-        sp[idx++] = reqLen + 4;  /* Referral Size */ 
-        sp[idx++] = 1;        /* Type = SMB Server */
-        sp[idx++] = 0;        /* Do not strip path consumed */
-        for ( i=0;i<=reqLen; i++ )
-            sp[i+idx] = requestFileName[i];
+            sp[idx++] = 1;        /* Version Number */
+            sp[idx++] = refLen + 4;  /* Referral Size */ 
+            sp[idx++] = 1;        /* Type = SMB Server */
+            sp[idx++] = 0;        /* Do not strip path consumed */
+            for ( i=0;i<=refLen; i++ )
+                sp[i+idx] = referralPath[i];
 #else /* DFS_VERSION_2 */
-        sp[idx++] = 2;      /* Version Number */
-        sp[idx++] = sizeof(struct smb_v2_referral);     /* Referral Size */
-        idx += (sizeof(struct smb_v2_referral) / 2);
-        v2ref = (struct smb_v2_referral *) &sp[5];
-        v2ref->ServerType = 1;  /* SMB Server */
-        v2ref->ReferralFlags = 0x03;
-        v2ref->Proximity = 0;   /* closest */
-        v2ref->TimeToLive = 3600; /* seconds */
-        v2ref->DfsPathOffset = idx * 2;
-        v2ref->DfsAlternativePathOffset = idx * 2;
-        v2ref->NetworkAddressOffset = 0;
-        for ( i=0;i<=reqLen; i++ )
-            sp[i+idx] = requestFileName[i];
+            sp[idx++] = 2;      /* Version Number */
+            sp[idx++] = sizeof(struct smb_v2_referral);     /* Referral Size */
+            idx += (sizeof(struct smb_v2_referral) / 2);
+            v2ref = (struct smb_v2_referral *) &sp[5];
+            v2ref->ServerType = 1;  /* SMB Server */
+            v2ref->ReferralFlags = 0x03;
+            v2ref->Proximity = 0;   /* closest */
+            v2ref->TimeToLive = 3600; /* seconds */
+            v2ref->DfsPathOffset = idx * 2;
+            v2ref->DfsAlternativePathOffset = idx * 2;
+            v2ref->NetworkAddressOffset = 0;
+            for ( i=0;i<=refLen; i++ )
+                sp[i+idx] = referralPath[i];
 #endif
+        } 
     } else {
-        userp = smb_GetTran2User(vcp, p);
-        if (!userp) {
-            osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
-            code = CM_ERROR_BADSMB;
-            goto done;
-        }   
-
-               /* not done yet */
         code = CM_ERROR_NOSUCHPATH;
     }
-
+         
   done:
+    if (dscp)
+        cm_ReleaseSCache(dscp);
+    if (scp)
+        cm_ReleaseSCache(scp);
     if (userp)
         cm_ReleaseUser(userp);
     if (code == 0) 
@@ -3673,10 +3789,11 @@ smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_
     return CM_ERROR_BADOP;
 }
 
-long 
-smb_ApplyV3DirListPatches(cm_scache_t *dscp,
-       smb_dirListPatch_t **dirPatchespp, int infoLevel, cm_user_t *userp,
-       cm_req_t *reqp)
+static long 
+smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, 
+                          char * tidPathp, char * relPathp, 
+                          int infoLevel, cm_user_t *userp,
+                          cm_req_t *reqp)
 {
     long code = 0;
     cm_scache_t *scp;
@@ -3691,6 +3808,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
     smb_dirListPatch_t *npatchp;
     afs_uint32 rights;
     afs_int32 mustFake = 0;
+    char path[AFSPATHMAX];
 
     code = cm_FindACLCache(dscp, userp, &rights);
     if (code == 0 && !(rights & PRSFS_READ))
@@ -3710,7 +3828,12 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
     for(patchp = *dirPatchespp; patchp; patchp =
          (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+        snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name);
+        reqp->relPathp = path;
+        reqp->tidPathp = tidPathp;
+
         code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
+        reqp->relPathp = reqp->tidPathp = NULL;
         if (code) 
             continue;
 
@@ -3834,7 +3957,11 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
         code = 0;
         while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
             lock_ReleaseMutex(&scp->mx);
+            snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name);
+            reqp->relPathp = path;
+            reqp->tidPathp = tidPathp;
             code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, reqp);
+            reqp->relPathp = reqp->tidPathp = NULL;
             if (code == 0) {
                 /* we have a more accurate file to use (the
                  * target of the symbolic link).  Otherwise,
@@ -3878,7 +4005,8 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
             /* Copy attributes */
             lattr = smb_ExtAttributes(scp);
-            if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+            if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK ||
+                code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) {
                 if (lattr == SMB_ATTR_NORMAL)
                     lattr = SMB_ATTR_DIRECTORY;
                 else
@@ -4111,7 +4239,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
     int attribute;
     long nextCookie;
     long code = 0, code2 = 0;
-    char *pathp;
+    char *pathp = 0;
     int maxCount;
     smb_dirListPatch_t *dirListPatchesp;
     smb_dirListPatch_t *curPatchp;
@@ -4132,11 +4260,12 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
     int searchFlags;
     int eos;
     smb_tran2Packet_t *outp;           /* response packet */
-    char *tidPathp;
+    char *tidPathp = 0;
     int align;
     char shortName[13];                        /* 8.3 name if needed */
     int NeedShortName;
     char *shortNameEnd;
+    cm_dirEntry_t * dep = NULL;
     cm_req_t req;
     char * s;
 
@@ -4262,9 +4391,10 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
 
 #ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
     if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data);
        cm_ReleaseSCache(scp);
        cm_ReleaseUser(userp);
-       if ( WANTS_DFS_PATHNAMES(p) )
+        if ( WANTS_DFS_PATHNAMES(p) || pnc )
            code = CM_ERROR_PATH_NOT_COVERED;
        else
            code = CM_ERROR_BADSHARENAME;
@@ -4455,7 +4585,11 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
         curPatchp->fid.unique = targetscp->fid.unique;
 
         /* temp */
-        curPatchp->dep = NULL;
+        dep = (cm_dirEntry_t *)malloc(sizeof(cm_dirEntry_t)+strlen(maskp));
+        strcpy(dep->name, maskp);
+        dep->fid.vnode = targetscp->fid.vnode;
+        dep->fid.unique = targetscp->fid.unique;
+        curPatchp->dep = dep;
     }   
 
     if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) {
@@ -4474,7 +4608,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
     }
 
     /* apply the patches */
-    code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp, &req);
+    code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, tidPathp, spacep->data, infoLevel, userp, &req);
 
     outp->parmsp[0] = 0;
     outp->parmsp[1] = 1;        /* number of names returned */
@@ -4498,6 +4632,8 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
 
  skip_file:
     smb_FreeTran2Packet(outp);
+    if (dep)
+        free(dep);
     cm_ReleaseSCache(scp);
     cm_ReleaseSCache(targetscp);
     cm_ReleaseUser(userp);
@@ -4513,10 +4649,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     char *tp;
     long code = 0, code2 = 0;
     char *pathp;
-    cm_dirEntry_t *dep;
+    cm_dirEntry_t *dep = 0;
     int maxCount;
-    smb_dirListPatch_t *dirListPatchesp;
-    smb_dirListPatch_t *curPatchp;
+    smb_dirListPatch_t *dirListPatchesp = 0;
+    smb_dirListPatch_t *curPatchp = 0;
     cm_buf_t *bufferp;
     long temp;
     long orbytes;                      /* # of bytes in this output record */
@@ -4725,6 +4861,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             smb_ReleaseDirSearch(dsp);
             return 0;
         }
+
+        strcpy(dsp->tidPath, tidPathp ? tidPathp : "/");
+        strcpy(dsp->relPath, spacep->data);
+
         code = cm_NameI(cm_data.rootSCachep, spacep->data,
                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
@@ -4733,9 +4873,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         if (code == 0) {
 #ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
             if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data);
                 cm_ReleaseSCache(scp);
                 cm_ReleaseUser(userp);
-                if ( WANTS_DFS_PATHNAMES(p) )
+                if ( WANTS_DFS_PATHNAMES(p) || pnc )
                     code = CM_ERROR_PATH_NOT_COVERED;
                 else
                     code = CM_ERROR_BADSHARENAME;
@@ -4871,9 +5012,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
              * of all of the status info for files in the dir.
              */
             if (starPattern) {
-                smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
-                                           infoLevel, userp,
-                                           &req);
+                code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, infoLevel, userp, &req);
+                
                 lock_ObtainMutex(&scp->mx);
                 if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                     LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
@@ -5183,8 +5323,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     /* apply and free last set of patches; if not doing a star match, this
      * will be empty, but better safe (and freeing everything) than sorry.
      */
-    code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp, &req);
-        
+    code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, 
+                                      dsp->relPath, infoLevel, userp, &req);
+
     /* now put out the final parameters */
     if (returnedNames == 0) 
         eos = 1;
@@ -5387,9 +5528,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 #ifdef DFS_SUPPORT
     if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
-        if ( WANTS_DFS_PATHNAMES(inp) )
+        if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
             return CM_ERROR_BADSHARENAME;
@@ -5407,9 +5549,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 #ifdef DFS_SUPPORT
         if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+            int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
             cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
-            if ( WANTS_DFS_PATHNAMES(inp) )
+            if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
                 return CM_ERROR_BADSHARENAME;
@@ -6565,12 +6708,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if (code == 0) {
 #ifdef DFS_SUPPORT
             if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
                 cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
                if (baseFidp) 
                    smb_ReleaseFID(baseFidp);
-                if ( WANTS_DFS_PATHNAMES(inp) )
+                if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
                     return CM_ERROR_BADSHARENAME;
@@ -6598,12 +6742,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                         userp, tidPathp, &req, &scp);
 #ifdef DFS_SUPPORT
         if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+            int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, realPathp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
            if (baseFidp) 
                smb_ReleaseFID(baseFidp);
-            if ( WANTS_DFS_PATHNAMES(inp) )
+            if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
                 return CM_ERROR_BADSHARENAME;
@@ -6634,6 +6779,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 #ifdef DFS_SUPPORT
                 if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                    int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
                     if (scp)
                         cm_ReleaseSCache(scp);
                     cm_ReleaseSCache(dscp);
@@ -6641,7 +6787,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     free(realPathp);
                    if (baseFidp) 
                        smb_ReleaseFID(baseFidp);
-                    if ( WANTS_DFS_PATHNAMES(inp) )
+                    if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                         return CM_ERROR_PATH_NOT_COVERED;
                     else
                         return CM_ERROR_BADSHARENAME;
@@ -7364,12 +7510,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         if (code == 0) {
 #ifdef DFS_SUPPORT
             if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
                 cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
                if (baseFidp)
                    smb_ReleaseFID(baseFidp);
-                if ( WANTS_DFS_PATHNAMES(inp) )
+                if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
                     return CM_ERROR_BADSHARENAME;
@@ -7397,12 +7544,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                         userp, tidPathp, &req, &scp);
 #ifdef DFS_SUPPORT
         if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+            int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, realPathp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
            if (baseFidp)
                smb_ReleaseFID(baseFidp);
-            if ( WANTS_DFS_PATHNAMES(inp) )
+            if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
                 return CM_ERROR_BADSHARENAME;
@@ -7421,12 +7569,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                              userp, tidPathp, &req, &dscp);
 #ifdef DFS_SUPPORT
             if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
                 cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
                if (baseFidp)
                    smb_ReleaseFID(baseFidp);
-                if ( WANTS_DFS_PATHNAMES(inp) )
+                if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
                     return CM_ERROR_BADSHARENAME;