windows-byte-range-locks-20050816
[openafs.git] / src / WINNT / afsd / smb3.c
index 4e56d16..149c740 100644 (file)
@@ -12,6 +12,7 @@
 
 #ifndef DJGPP
 #include <windows.h>
+#include <ntstatus.h>
 #define SECURITY_WIN32
 #include <security.h>
 #include <lmaccess.h>
 #include <string.h>
 #include <stdio.h>
 #include <time.h>
-
 #include <osi.h>
 
 #include "afsd.h"
+#include <WINNT\afsreg.h>
 
 #include "smb.h"
 
@@ -44,18 +45,18 @@ smb_tran2Packet_t *smb_tran2AssemblyQueuep;
  * request */
 cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
 {
-       smb_user_t *uidp;
+    smb_user_t *uidp;
     cm_user_t *up = NULL;
         
     uidp = smb_FindUID(vcp, inp->uid, 0);
     if (!uidp) return NULL;
         
-       lock_ObtainMutex(&uidp->mx);
+    lock_ObtainMutex(&uidp->mx);
     if (uidp->unp) {
         up = uidp->unp->userp;
         cm_HoldUser(up);
     }
-       lock_ReleaseMutex(&uidp->mx);
+    lock_ReleaseMutex(&uidp->mx);
 
     smb_ReleaseUID(uidp);
 
@@ -69,49 +70,57 @@ cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
  */
 unsigned long smb_ExtAttributes(cm_scache_t *scp)
 {
-       unsigned long attrs;
-
-       if (scp->fileType == CM_SCACHETYPE_DIRECTORY
-           || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-               attrs = SMB_ATTR_DIRECTORY;
-       else
-               attrs = 0;
-       /*
-        * We used to mark a file RO if it was in an RO volume, but that
-        * turns out to be impolitic in NT.  See defect 10007.
-        */
+    unsigned long attrs;
+
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+        scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+        scp->fileType == CM_SCACHETYPE_INVALID)
+    {
+        attrs = SMB_ATTR_DIRECTORY;
+#ifdef SPECIAL_FOLDERS
+        attrs |= SMB_ATTR_SYSTEM;              /* FILE_ATTRIBUTE_SYSTEM */
+#endif /* SPECIAL_FOLDERS */
+    } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
+    } else
+        attrs = 0;
+    /*
+     * We used to mark a file RO if it was in an RO volume, but that
+     * turns out to be impolitic in NT.  See defect 10007.
+     */
 #ifdef notdef
-       if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+    if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+        attrs |= SMB_ATTR_READONLY;            /* Read-only */
+#else
+    if ((scp->unixModeBits & 0222) == 0)
+        attrs |= SMB_ATTR_READONLY;            /* Read-only */
 #endif
-       if ((scp->unixModeBits & 0222) == 0)
-               attrs |= SMB_ATTR_READONLY;             /* Read-only */
 
-       if (attrs == 0)
-               attrs = SMB_ATTR_NORMAL;                /* FILE_ATTRIBUTE_NORMAL */
+    if (attrs == 0)
+        attrs = SMB_ATTR_NORMAL;               /* FILE_ATTRIBUTE_NORMAL */
 
-       return attrs;
+    return attrs;
 }
 
 int smb_V3IsStarMask(char *maskp)
 {
     char tc;
 
-       while (tc = *maskp++)
-        if (tc == '?' || tc == '*') 
+    while (tc = *maskp++)
+        if (tc == '?' || tc == '*' || tc == '<' || tc == '>') 
             return 1;
-       return 0;
+    return 0;
 }
 
 unsigned char *smb_ParseString(unsigned char *inp, char **chainpp)
 {
     if (chainpp) {
-               /* skip over null-terminated string */
-               *chainpp = inp + strlen(inp) + 1;
+        /* skip over null-terminated string */
+        *chainpp = inp + strlen(inp) + 1;
     }
     return inp;
 }   
 
-/*DEBUG do not checkin*/
 void OutputDebugF(char * format, ...) {
     va_list args;
     int len;
@@ -135,7 +144,7 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
 
     OutputDebugF("Hexdump length [%d]",len);
 
-    for(i=0;i<len;i++) {
+    for (i=0;i<len;i++) {
         if(!(i%16)) {
             if(i) {
                 osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
@@ -162,78 +171,76 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
         osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
         strcat(buf,"\n");
         OutputDebugString(buf);
-}   
+    }   
 }
-/**/
 
 #define SMB_EXT_SEC_PACKAGE_NAME "Negotiate"
-void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength){
+
+void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength) {
     SECURITY_STATUS status, istatus;
-       CredHandle creds = {0,0};
-       TimeStamp expiry;
-       SecBufferDesc secOut;
-       SecBuffer secTok;
-       CtxtHandle ctx;
-       ULONG flags;
+    CredHandle creds = {0,0};
+    TimeStamp expiry;
+    SecBufferDesc secOut;
+    SecBuffer secTok;
+    CtxtHandle ctx;
+    ULONG flags;
 
-       *secBlob = NULL;
-       *secBlobLength = 0;
+    *secBlob = NULL;
+    *secBlobLength = 0;
 
     OutputDebugF("Negotiating Extended Security");
 
-       status = AcquireCredentialsHandle(
-               NULL,
-               SMB_EXT_SEC_PACKAGE_NAME,
-               SECPKG_CRED_INBOUND,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               &creds,
-               &expiry);
-
-       if (status != SEC_E_OK) {
-               /* Really bad. We return an empty security blob */
-               OutputDebugF("AcquireCredentialsHandle failed with %lX", status);
-               goto nes_0;
-       }
+    status = AcquireCredentialsHandle( NULL,
+                                       SMB_EXT_SEC_PACKAGE_NAME,
+                                       SECPKG_CRED_INBOUND,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &creds,
+                                       &expiry);
+
+    if (status != SEC_E_OK) {
+        /* Really bad. We return an empty security blob */
+        OutputDebugF("AcquireCredentialsHandle failed with %lX", status);
+        goto nes_0;
+    }
 
-       secOut.cBuffers = 1;
-       secOut.pBuffers = &secTok;
-       secOut.ulVersion = SECBUFFER_VERSION;
-
-       secTok.BufferType = SECBUFFER_TOKEN;
-       secTok.cbBuffer = 0;
-       secTok.pvBuffer = NULL;
-
-        ctx.dwLower = ctx.dwUpper = 0;
-
-       status = AcceptSecurityContext(
-               &creds,
-               NULL,
-               NULL,
-        ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY,
-               SECURITY_NETWORK_DREP,
-               &ctx,
-               &secOut,
-               &flags,
-               &expiry
-               );
-
-       if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
-               OutputDebugF("Completing token...");
-               istatus = CompleteAuthToken(&ctx, &secOut);
+    secOut.cBuffers = 1;
+    secOut.pBuffers = &secTok;
+    secOut.ulVersion = SECBUFFER_VERSION;
+
+    secTok.BufferType = SECBUFFER_TOKEN;
+    secTok.cbBuffer = 0;
+    secTok.pvBuffer = NULL;
+
+    ctx.dwLower = ctx.dwUpper = 0;
+
+    status = AcceptSecurityContext( &creds,
+                                    NULL,
+                                    NULL,
+                                    ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY,
+                                    SECURITY_NETWORK_DREP,
+                                    &ctx,
+                                    &secOut,
+                                    &flags,
+                                    &expiry
+                                    );
+
+    if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
+        OutputDebugF("Completing token...");
+        istatus = CompleteAuthToken(&ctx, &secOut);
         if ( istatus != SEC_E_OK )
             OutputDebugF("Token completion failed: %x", istatus);
-       }
+    }
 
-       if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
-               if (secTok.pvBuffer) {
-                       *secBlobLength = secTok.cbBuffer;
-                       *secBlob = malloc( secTok.cbBuffer );
-                       memcpy(*secBlob, secTok.pvBuffer, secTok.cbBuffer );
-               }
-       } else {
+    if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
+        if (secTok.pvBuffer) {
+            *secBlobLength = secTok.cbBuffer;
+            *secBlob = malloc( secTok.cbBuffer );
+            memcpy(*secBlob, secTok.pvBuffer, secTok.cbBuffer );
+        }
+    } else {
         if ( status != SEC_E_OK )
             OutputDebugF("AcceptSecurityContext status != CONTINUE  %lX", status);
     }
@@ -241,50 +248,50 @@ void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength){
     /* Discard partial security context */
     DeleteSecurityContext(&ctx);
 
-       if (secTok.pvBuffer) FreeContextBuffer( secTok.pvBuffer );
+    if (secTok.pvBuffer) FreeContextBuffer( secTok.pvBuffer );
 
-       /* Discard credentials handle.  We'll reacquire one when we get the session setup X */
-       FreeCredentialsHandle(&creds);
+    /* Discard credentials handle.  We'll reacquire one when we get the session setup X */
+    FreeCredentialsHandle(&creds);
 
   nes_0:
-       return;
+    return;
 }
 
 struct smb_ext_context {
-       CredHandle creds;
-       CtxtHandle ctx;
-       int partialTokenLen;
-       void * partialToken;
-};
+    CredHandle creds;
+    CtxtHandle ctx;
+    int partialTokenLen;
+    void * partialToken;
+};      
 
 long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int secBlobInLength, char ** secBlobOut, int * secBlobOutLength) {
     SECURITY_STATUS status, istatus;
-       CredHandle creds;
-       TimeStamp expiry;
-       long code = 0;
-       SecBufferDesc secBufIn;
-       SecBuffer secTokIn;
-       SecBufferDesc secBufOut;
-       SecBuffer secTokOut;
-       CtxtHandle ctx;
-       struct smb_ext_context * secCtx = NULL;
-       struct smb_ext_context * newSecCtx = NULL;
-       void * assembledBlob = NULL;
-       int assembledBlobLength = 0;
-       ULONG flags;
-
-       OutputDebugF("In smb_AuthenticateUserExt");
-
-       *secBlobOut = NULL;
-       *secBlobOutLength = 0;
-
-       if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) {
-               secCtx = vcp->secCtx;
-               lock_ObtainMutex(&vcp->mx);
-               vcp->flags &= ~SMB_VCFLAG_AUTH_IN_PROGRESS;
-               vcp->secCtx = NULL;
-               lock_ReleaseMutex(&vcp->mx);
-       }
+    CredHandle creds;
+    TimeStamp expiry;
+    long code = 0;
+    SecBufferDesc secBufIn;
+    SecBuffer secTokIn;
+    SecBufferDesc secBufOut;
+    SecBuffer secTokOut;
+    CtxtHandle ctx;
+    struct smb_ext_context * secCtx = NULL;
+    struct smb_ext_context * newSecCtx = NULL;
+    void * assembledBlob = NULL;
+    int assembledBlobLength = 0;
+    ULONG flags;
+
+    OutputDebugF("In smb_AuthenticateUserExt");
+
+    *secBlobOut = NULL;
+    *secBlobOutLength = 0;
+
+    if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) {
+        secCtx = vcp->secCtx;
+        lock_ObtainMutex(&vcp->mx);
+        vcp->flags &= ~SMB_VCFLAG_AUTH_IN_PROGRESS;
+        vcp->secCtx = NULL;
+        lock_ReleaseMutex(&vcp->mx);
+    }
 
     if (secBlobIn) {
         OutputDebugF("Received incoming token:");
@@ -296,130 +303,128 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int
         creds = secCtx->creds;
         ctx = secCtx->ctx;
 
-               if (secCtx->partialToken) {
-                       assembledBlobLength = secCtx->partialTokenLen + secBlobInLength;
-                       assembledBlob = malloc(assembledBlobLength);
+        if (secCtx->partialToken) {
+            assembledBlobLength = secCtx->partialTokenLen + secBlobInLength;
+            assembledBlob = malloc(assembledBlobLength);
             memcpy(assembledBlob,secCtx->partialToken, secCtx->partialTokenLen);
-                       memcpy(((BYTE *)assembledBlob) + secCtx->partialTokenLen, secBlobIn, secBlobInLength);
-               }
-       } else {
-               status = AcquireCredentialsHandle(
-                       NULL,
-                       SMB_EXT_SEC_PACKAGE_NAME,
-                       SECPKG_CRED_INBOUND,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       &creds,
-                       &expiry);
-
-               if (status != SEC_E_OK) {
-                       OutputDebugF("Can't acquire Credentials handle [%lX]", status);
-                       code = CM_ERROR_BADPASSWORD; /* means "try again when I'm sober" */
-                       goto aue_0;
-               }
-
-               ctx.dwLower = 0;
-               ctx.dwUpper = 0;
-       }
+            memcpy(((BYTE *)assembledBlob) + secCtx->partialTokenLen, secBlobIn, secBlobInLength);
+        }
+    } else {
+        status = AcquireCredentialsHandle( NULL,
+                                           SMB_EXT_SEC_PACKAGE_NAME,
+                                           SECPKG_CRED_INBOUND,
+                                           NULL,
+                                           NULL,
+                                           NULL,
+                                           NULL,
+                                           &creds,
+                                           &expiry);
+
+        if (status != SEC_E_OK) {
+            OutputDebugF("Can't acquire Credentials handle [%lX]", status);
+            code = CM_ERROR_BADPASSWORD; /* means "try again when I'm sober" */
+            goto aue_0;
+        }
+
+        ctx.dwLower = 0;
+        ctx.dwUpper = 0;
+    }
 
     secBufIn.cBuffers = 1;
-       secBufIn.pBuffers = &secTokIn;
-       secBufIn.ulVersion = SECBUFFER_VERSION;
-
-       secTokIn.BufferType = SECBUFFER_TOKEN;
-       if (assembledBlob) {
-               secTokIn.cbBuffer = assembledBlobLength;
-               secTokIn.pvBuffer = assembledBlob;
-       } else {
-               secTokIn.cbBuffer = secBlobInLength;
-               secTokIn.pvBuffer = secBlobIn;
-       }
+    secBufIn.pBuffers = &secTokIn;
+    secBufIn.ulVersion = SECBUFFER_VERSION;
+
+    secTokIn.BufferType = SECBUFFER_TOKEN;
+    if (assembledBlob) {
+        secTokIn.cbBuffer = assembledBlobLength;
+        secTokIn.pvBuffer = assembledBlob;
+    } else {
+        secTokIn.cbBuffer = secBlobInLength;
+        secTokIn.pvBuffer = secBlobIn;
+    }
 
-       secBufOut.cBuffers = 1;
-       secBufOut.pBuffers = &secTokOut;
-       secBufOut.ulVersion = SECBUFFER_VERSION;
-
-       secTokOut.BufferType = SECBUFFER_TOKEN;
-       secTokOut.cbBuffer = 0;
-       secTokOut.pvBuffer = NULL;
-
-       status = AcceptSecurityContext(
-               &creds,
-               ((secCtx)?&ctx:NULL),
-               &secBufIn,
-               ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR     | ASC_REQ_ALLOCATE_MEMORY,
-               SECURITY_NETWORK_DREP,
-               &ctx,
-               &secBufOut,
-               &flags,
-               &expiry
-               );
-
-       if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
-               OutputDebugF("Completing token...");
-               istatus = CompleteAuthToken(&ctx, &secBufOut);
+    secBufOut.cBuffers = 1;
+    secBufOut.pBuffers = &secTokOut;
+    secBufOut.ulVersion = SECBUFFER_VERSION;
+
+    secTokOut.BufferType = SECBUFFER_TOKEN;
+    secTokOut.cbBuffer = 0;
+    secTokOut.pvBuffer = NULL;
+
+    status = AcceptSecurityContext( &creds,
+                                    ((secCtx)?&ctx:NULL),
+                                    &secBufIn,
+                                    ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR        | ASC_REQ_ALLOCATE_MEMORY,
+                                    SECURITY_NETWORK_DREP,
+                                    &ctx,
+                                    &secBufOut,
+                                    &flags,
+                                    &expiry
+                                    );
+
+    if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
+        OutputDebugF("Completing token...");
+        istatus = CompleteAuthToken(&ctx, &secBufOut);
         if ( istatus != SEC_E_OK )
             OutputDebugF("Token completion failed: %lX", istatus);
-       }
+    }
 
-       if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
-               OutputDebugF("Continue needed");
+    if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
+        OutputDebugF("Continue needed");
 
-               newSecCtx = malloc(sizeof(*newSecCtx));
+        newSecCtx = malloc(sizeof(*newSecCtx));
 
-               newSecCtx->creds = creds;
-               newSecCtx->ctx = ctx;
-               newSecCtx->partialToken = NULL;
-               newSecCtx->partialTokenLen = 0;
+        newSecCtx->creds = creds;
+        newSecCtx->ctx = ctx;
+        newSecCtx->partialToken = NULL;
+        newSecCtx->partialTokenLen = 0;
 
-               lock_ObtainMutex( &vcp->mx );
-               vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
-               vcp->secCtx = newSecCtx;
-               lock_ReleaseMutex( &vcp->mx );
+        lock_ObtainMutex( &vcp->mx );
+        vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
+        vcp->secCtx = newSecCtx;
+        lock_ReleaseMutex( &vcp->mx );
 
-               code = CM_ERROR_GSSCONTINUE;
-       }
+        code = CM_ERROR_GSSCONTINUE;
+    }
 
-       if ((status == SEC_I_COMPLETE_NEEDED || status == SEC_E_OK || 
-         status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) && 
-        secTokOut.pvBuffer) {
-               OutputDebugF("Need to send token back to client");
+    if ((status == SEC_I_COMPLETE_NEEDED || status == SEC_E_OK || 
+          status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) && 
+         secTokOut.pvBuffer) {
+        OutputDebugF("Need to send token back to client");
 
-               *secBlobOutLength = secTokOut.cbBuffer;
-               *secBlobOut = malloc(secTokOut.cbBuffer);
-               memcpy(*secBlobOut, secTokOut.pvBuffer, secTokOut.cbBuffer);
+        *secBlobOutLength = secTokOut.cbBuffer;
+        *secBlobOut = malloc(secTokOut.cbBuffer);
+        memcpy(*secBlobOut, secTokOut.pvBuffer, secTokOut.cbBuffer);
 
         OutputDebugF("Outgoing token:");
         OutputDebugHexDump(*secBlobOut,*secBlobOutLength);
-       } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
-               OutputDebugF("Incomplete message");
+    } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
+        OutputDebugF("Incomplete message");
 
-               newSecCtx = malloc(sizeof(*newSecCtx));
+        newSecCtx = malloc(sizeof(*newSecCtx));
 
-               newSecCtx->creds = creds;
-               newSecCtx->ctx = ctx;
-               newSecCtx->partialToken = malloc(secTokOut.cbBuffer);
-               memcpy(newSecCtx->partialToken, secTokOut.pvBuffer, secTokOut.cbBuffer);
-               newSecCtx->partialTokenLen = secTokOut.cbBuffer;
+        newSecCtx->creds = creds;
+        newSecCtx->ctx = ctx;
+        newSecCtx->partialToken = malloc(secTokOut.cbBuffer);
+        memcpy(newSecCtx->partialToken, secTokOut.pvBuffer, secTokOut.cbBuffer);
+        newSecCtx->partialTokenLen = secTokOut.cbBuffer;
 
-               lock_ObtainMutex( &vcp->mx );
-               vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
-               vcp->secCtx = newSecCtx;
-               lock_ReleaseMutex( &vcp->mx );
+        lock_ObtainMutex( &vcp->mx );
+        vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
+        vcp->secCtx = newSecCtx;
+        lock_ReleaseMutex( &vcp->mx );
 
-               code = CM_ERROR_GSSCONTINUE;
-       }
+        code = CM_ERROR_GSSCONTINUE;
+    }
 
-       if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
-               /* woo hoo! */
-               SecPkgContext_Names names;
+    if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
+        /* woo hoo! */
+        SecPkgContext_Names names;
 
-               OutputDebugF("Authentication completed");
+        OutputDebugF("Authentication completed");
         OutputDebugF("Returned flags : [%lX]", flags);
 
-               if (!QueryContextAttributes(&ctx, SECPKG_ATTR_NAMES, &names)) {
+        if (!QueryContextAttributes(&ctx, SECPKG_ATTR_NAMES, &names)) {
             OutputDebugF("Received name [%s]", names.sUserName);
             strcpy(usern, names.sUserName);
             strlwr(usern); /* in tandem with smb_GetNormalizedUsername */
@@ -429,7 +434,7 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int
             OutputDebugF("QueryContextAttributes Names failed [%x]", GetLastError());
             code = CM_ERROR_BADPASSWORD; 
         }
-       } else if (!code) {
+    } else if (!code) {
         switch ( status ) {
         case SEC_E_INVALID_TOKEN:
             OutputDebugF("Returning bad password :: INVALID_TOKEN");
@@ -461,28 +466,28 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int
         default:
             OutputDebugF("Returning bad password :: Status == %lX", status);
         }
-               code = CM_ERROR_BADPASSWORD;
-       }
+        code = CM_ERROR_BADPASSWORD;
+    }
 
-       if (secCtx) {
-               if (secCtx->partialToken) free(secCtx->partialToken);
-               free(secCtx);
-       }
+    if (secCtx) {
+        if (secCtx->partialToken) free(secCtx->partialToken);
+        free(secCtx);
+    }
 
-       if (assembledBlob) {
-               free(assembledBlob);
-       }
+    if (assembledBlob) {
+        free(assembledBlob);
+    }
 
-       if (secTokOut.pvBuffer)
-               FreeContextBuffer(secTokOut.pvBuffer);
+    if (secTokOut.pvBuffer)
+        FreeContextBuffer(secTokOut.pvBuffer);
 
-       if (code != CM_ERROR_GSSCONTINUE) {
-               DeleteSecurityContext(&ctx);
-               FreeCredentialsHandle(&creds);
-       }
+    if (code != CM_ERROR_GSSCONTINUE) {
+        DeleteSecurityContext(&ctx);
+        FreeCredentialsHandle(&creds);
+    }
 
   aue_0:
-       return code;
+    return code;
 }
 
 #define P_LEN 256
@@ -491,160 +496,164 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int
 /* LsaLogonUser expects input parameters to be in a contiguous block of memory. 
    So put stuff in a struct. */
 struct Lm20AuthBlob {
-       MSV1_0_LM20_LOGON lmlogon;
-       BYTE ciResponse[P_RESP_LEN];    /* Unicode representation */
-       BYTE csResponse[P_RESP_LEN];    /* ANSI representation */
-       WCHAR accountNameW[P_LEN];
-       WCHAR primaryDomainW[P_LEN];
-       WCHAR workstationW[MAX_COMPUTERNAME_LENGTH + 1];
-       TOKEN_GROUPS tgroups;
-       TOKEN_SOURCE tsource;
+    MSV1_0_LM20_LOGON lmlogon;
+    BYTE ciResponse[P_RESP_LEN];    /* Unicode representation */
+    BYTE csResponse[P_RESP_LEN];    /* ANSI representation */
+    WCHAR accountNameW[P_LEN];
+    WCHAR primaryDomainW[P_LEN];
+    WCHAR workstationW[MAX_COMPUTERNAME_LENGTH + 1];
+    TOKEN_GROUPS tgroups;
+    TOKEN_SOURCE tsource;
 };
 
-long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength) {
-
-       NTSTATUS nts, ntsEx;
-       struct Lm20AuthBlob lmAuth;
-       PMSV1_0_LM20_LOGON_PROFILE lmprofilep;
-       QUOTA_LIMITS quotaLimits;
-       DWORD size;
-       ULONG lmprofilepSize;
-       LUID lmSession;
-       HANDLE lmToken;
-
-       OutputDebugF("In smb_AuthenticateUser for user [%s] domain [%s]", accountName, primaryDomain);
-       OutputDebugF("ciPwdLength is %d and csPwdLength is %d", ciPwdLength, csPwdLength);
-
-       if (ciPwdLength > P_RESP_LEN || csPwdLength > P_RESP_LEN) {
-               OutputDebugF("ciPwdLength or csPwdLength is too long");
-               return CM_ERROR_BADPASSWORD;
-       }
+long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength) 
+{
+    NTSTATUS nts, ntsEx;
+    struct Lm20AuthBlob lmAuth;
+    PMSV1_0_LM20_LOGON_PROFILE lmprofilep;
+    QUOTA_LIMITS quotaLimits;
+    DWORD size;
+    ULONG lmprofilepSize;
+    LUID lmSession;
+    HANDLE lmToken;
+
+    OutputDebugF("In smb_AuthenticateUser for user [%s] domain [%s]", accountName, primaryDomain);
+    OutputDebugF("ciPwdLength is %d and csPwdLength is %d", ciPwdLength, csPwdLength);
+
+    if (ciPwdLength > P_RESP_LEN || csPwdLength > P_RESP_LEN) {
+        OutputDebugF("ciPwdLength or csPwdLength is too long");
+        return CM_ERROR_BADPASSWORD;
+    }
 
-       memset(&lmAuth,0,sizeof(lmAuth));
+    memset(&lmAuth,0,sizeof(lmAuth));
 
-       lmAuth.lmlogon.MessageType = MsV1_0NetworkLogon;
+    lmAuth.lmlogon.MessageType = MsV1_0NetworkLogon;
        
-       lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW;
-       mbstowcs(lmAuth.primaryDomainW, primaryDomain, P_LEN);
-       lmAuth.lmlogon.LogonDomainName.Length = wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR);
-       lmAuth.lmlogon.LogonDomainName.MaximumLength = P_LEN * sizeof(WCHAR);
-
-       lmAuth.lmlogon.UserName.Buffer = lmAuth.accountNameW;
-       mbstowcs(lmAuth.accountNameW, accountName, P_LEN);
-       lmAuth.lmlogon.UserName.Length = wcslen(lmAuth.accountNameW) * sizeof(WCHAR);
-       lmAuth.lmlogon.UserName.MaximumLength = P_LEN * sizeof(WCHAR);
-
-       lmAuth.lmlogon.Workstation.Buffer = lmAuth.workstationW;
-       lmAuth.lmlogon.Workstation.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
-       size = MAX_COMPUTERNAME_LENGTH + 1;
-       GetComputerNameW(lmAuth.workstationW, &size);
+    lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW;
+    mbstowcs(lmAuth.primaryDomainW, primaryDomain, P_LEN);
+    lmAuth.lmlogon.LogonDomainName.Length = wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR);
+    lmAuth.lmlogon.LogonDomainName.MaximumLength = P_LEN * sizeof(WCHAR);
+
+    lmAuth.lmlogon.UserName.Buffer = lmAuth.accountNameW;
+    mbstowcs(lmAuth.accountNameW, accountName, P_LEN);
+    lmAuth.lmlogon.UserName.Length = wcslen(lmAuth.accountNameW) * sizeof(WCHAR);
+    lmAuth.lmlogon.UserName.MaximumLength = P_LEN * sizeof(WCHAR);
+
+    lmAuth.lmlogon.Workstation.Buffer = lmAuth.workstationW;
+    lmAuth.lmlogon.Workstation.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
+    size = MAX_COMPUTERNAME_LENGTH + 1;
+    GetComputerNameW(lmAuth.workstationW, &size);
     lmAuth.lmlogon.Workstation.Length = wcslen(lmAuth.workstationW) * sizeof(WCHAR);
 
-       memcpy(lmAuth.lmlogon.ChallengeToClient, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
-
-       lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Buffer = lmAuth.ciResponse;
-       lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Length = ciPwdLength;
-       lmAuth.lmlogon.CaseInsensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
-       memcpy(lmAuth.ciResponse, ciPwd, ciPwdLength);
-
-       lmAuth.lmlogon.CaseSensitiveChallengeResponse.Buffer = lmAuth.csResponse;
-       lmAuth.lmlogon.CaseSensitiveChallengeResponse.Length = csPwdLength;
-       lmAuth.lmlogon.CaseSensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
-       memcpy(lmAuth.csResponse, csPwd, csPwdLength);
-
-       lmAuth.lmlogon.ParameterControl = 0;
-
-       lmAuth.tgroups.GroupCount = 0;
-       lmAuth.tgroups.Groups[0].Sid = NULL;
-       lmAuth.tgroups.Groups[0].Attributes = 0;
-
-       lmAuth.tsource.SourceIdentifier.HighPart = 0;
-       lmAuth.tsource.SourceIdentifier.LowPart = (DWORD) vcp;
-       strcpy(lmAuth.tsource.SourceName,"OpenAFS"); /* 8 char limit */
-
-       nts = LsaLogonUser(
-               smb_lsaHandle,
-               &smb_lsaLogonOrigin,
-               Network, /*3*/
-        smb_lsaSecPackage,
-               &lmAuth,
-               sizeof(lmAuth),
-        &lmAuth.tgroups,
-               &lmAuth.tsource,
-               &lmprofilep,
-               &lmprofilepSize,
-               &lmSession,
-               &lmToken,
-               &quotaLimits,
-               &ntsEx);
-
-       OutputDebugF("Return from LsaLogonUser is 0x%lX", nts);
-       OutputDebugF("Extended status is 0x%lX", ntsEx);
-
-       if (nts == ERROR_SUCCESS) {
-               /* free the token */
-               LsaFreeReturnBuffer(lmprofilep);
+    memcpy(lmAuth.lmlogon.ChallengeToClient, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
+
+    lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Buffer = lmAuth.ciResponse;
+    lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Length = ciPwdLength;
+    lmAuth.lmlogon.CaseInsensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
+    memcpy(lmAuth.ciResponse, ciPwd, ciPwdLength);
+
+    lmAuth.lmlogon.CaseSensitiveChallengeResponse.Buffer = lmAuth.csResponse;
+    lmAuth.lmlogon.CaseSensitiveChallengeResponse.Length = csPwdLength;
+    lmAuth.lmlogon.CaseSensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
+    memcpy(lmAuth.csResponse, csPwd, csPwdLength);
+
+    lmAuth.lmlogon.ParameterControl = 0;
+
+    lmAuth.tgroups.GroupCount = 0;
+    lmAuth.tgroups.Groups[0].Sid = NULL;
+    lmAuth.tgroups.Groups[0].Attributes = 0;
+
+    lmAuth.tsource.SourceIdentifier.HighPart = 0;
+    lmAuth.tsource.SourceIdentifier.LowPart = (DWORD) vcp;
+    strcpy(lmAuth.tsource.SourceName,"OpenAFS"); /* 8 char limit */
+
+    nts = LsaLogonUser( smb_lsaHandle,
+                        &smb_lsaLogonOrigin,
+                        Network, /*3*/
+                        smb_lsaSecPackage,
+                        &lmAuth,
+                        sizeof(lmAuth),
+                        &lmAuth.tgroups,
+                        &lmAuth.tsource,
+                        &lmprofilep,
+                        &lmprofilepSize,
+                        &lmSession,
+                        &lmToken,
+                        &quotaLimits,
+                        &ntsEx);
+
+    if (nts != STATUS_SUCCESS || ntsEx != STATUS_SUCCESS)
+        osi_Log2(smb_logp,"LsaLogonUser failure: nts %u ntsEx %u",
+                  nts, ntsEx);
+
+    OutputDebugF("Return from LsaLogonUser is 0x%lX", nts);
+    OutputDebugF("Extended status is 0x%lX", ntsEx);
+
+    if (nts == ERROR_SUCCESS) {
+        /* free the token */
+        LsaFreeReturnBuffer(lmprofilep);
         CloseHandle(lmToken);
-               return 0;
-       } else {
-               /* No AFS for you */
-               if (nts == 0xC000015BL)
-                       return CM_ERROR_BADLOGONTYPE;
-               else /* our catchall is a bad password though we could be more specific */
-                       return CM_ERROR_BADPASSWORD;
-       }
+        return 0;
+    } else {
+        /* No AFS for you */
+        if (nts == 0xC000015BL)
+            return CM_ERROR_BADLOGONTYPE;
+        else /* our catchall is a bad password though we could be more specific */
+            return CM_ERROR_BADPASSWORD;
+    }       
 }
 
 /* The buffer pointed to by usern is assumed to be at least SMB_MAX_USERNAME_LENGTH bytes */
-long smb_GetNormalizedUsername(char * usern, const char * accountName, const char * domainName) {
-
-       char * atsign;
-       const char * domain;
-
-       /* check if we have sane input */
-       if ((strlen(accountName) + strlen(domainName) + 1) > SMB_MAX_USERNAME_LENGTH)
-               return 1;
-
-       /* we could get : [accountName][domainName]
-          [user][domain]
-          [user@domain][]
-          [user][]/[user][?]
-          [][]/[][?] */
-
-       atsign = strchr(accountName, '@');
-
-       if (atsign) /* [user@domain][] -> [user@domain][domain] */
-               domain = atsign + 1;
-       else
-               domain = domainName;
-
-       /* if for some reason the client doesn't know what domain to use,
-                  it will either return an empty string or a '?' */
-       if (!domain[0] || domain[0] == '?')
-               /* Empty domains and empty usernames are usually sent from tokenless contexts.
-                  This way such logins will get an empty username (easy to check).  I don't know 
-                  when a non-empty username would be supplied with an anonymous domain, but *shrug* */
-               strcpy(usern,accountName);
-       else {
-               /* TODO: what about WIN.MIT.EDU\user vs. WIN\user? */
-               strcpy(usern,domain);
-               strcat(usern,"\\");
-               if (atsign)
-                       strncat(usern,accountName,atsign - accountName);
-               else
-                       strcat(usern,accountName);
-       }
+long smb_GetNormalizedUsername(char * usern, const char * accountName, const char * domainName) 
+{
+    char * atsign;
+    const char * domain;
+
+    /* check if we have sane input */
+    if ((strlen(accountName) + strlen(domainName) + 1) > SMB_MAX_USERNAME_LENGTH)
+        return 1;
+
+    /* we could get : [accountName][domainName]
+       [user][domain]
+       [user@domain][]
+       [user][]/[user][?]
+       [][]/[][?] */
 
-       strlwr(usern);
+    atsign = strchr(accountName, '@');
 
-       return 0;
+    if (atsign) /* [user@domain][] -> [user@domain][domain] */
+        domain = atsign + 1;
+    else
+        domain = domainName;
+
+    /* if for some reason the client doesn't know what domain to use,
+       it will either return an empty string or a '?' */
+    if (!domain[0] || domain[0] == '?')
+        /* Empty domains and empty usernames are usually sent from tokenless contexts.
+           This way such logins will get an empty username (easy to check).  I don't know 
+           when a non-empty username would be supplied with an anonymous domain, but *shrug* */
+        strcpy(usern,accountName);
+    else {
+        /* TODO: what about WIN.MIT.EDU\user vs. WIN\user? */
+        strcpy(usern,domain);
+        strcat(usern,"\\");
+        if (atsign)
+            strncat(usern,accountName,atsign - accountName);
+        else
+            strcat(usern,accountName);
+    }       
+
+    strlwr(usern);
+
+    return 0;
 }
 
-/* When using SMB auth, all SMB sessions have to pass through here first to
- * authenticate the user. 
- * Caveat: If not use the SMB auth the protocol does not require sending a
- * session setup packet, which means that we can't rely on a UID in subsequent
- * packets.  Though in practice we get one anyway.
+/* When using SMB auth, all SMB sessions have to pass through here
+ * first to authenticate the user.  
+ *
+ * Caveat: If not using SMB auth, the protocol does not require
+ * sending a session setup packet, which means that we can't rely on a
+ * UID in subsequent packets.  Though in practice we get one anyway.
  */
 long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
@@ -669,6 +678,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
             /* extended authentication */
             char *secBlobIn;
             int secBlobInLength;
+
+            OutputDebugF("NT Session Setup: Extended");
         
             if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
                 caps = smb_GetSMBParm(inp,10) | (((unsigned long) smb_GetSMBParm(inp,11)) << 16);
@@ -705,6 +716,11 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
             char *primaryDomain;
             int  datalen;
 
+            if (smb_authType == SMB_AUTH_NTLM)
+                OutputDebugF("NT Session Setup: NTLM");
+            else
+                OutputDebugF("NT Session Setup: None");
+
             /* TODO: parse for extended auth as well */
             ciPwdLength = smb_GetSMBParm(inp, 7); /* case insensitive password length */
             csPwdLength = smb_GetSMBParm(inp, 8); /* case sensitive password length */
@@ -721,6 +737,11 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
             accountName = smb_ParseString(tp, &tp);
             primaryDomain = smb_ParseString(tp, NULL);
 
+            OutputDebugF("Account Name: %s",accountName);
+            OutputDebugF("Primary Domain: %s", primaryDomain);
+            OutputDebugF("Case Sensitive Password: %s", csPwd && csPwd[0] ? "yes" : "no");
+            OutputDebugF("Case Insensitive Password: %s", ciPwd && ciPwd[0] ? "yes" : "no");
+
             if (smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
                 /* shouldn't happen */
                 code = CM_ERROR_BADSMB;
@@ -734,57 +755,79 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 
             if (smb_authType == SMB_AUTH_NTLM) {
                 code = smb_AuthenticateUserLM(vcp, accountName, primaryDomain, ciPwd, ciPwdLength, csPwd, csPwdLength);
+                if ( code )
+                    OutputDebugF("LM authentication failed [%d]", code);
+                else
+                    OutputDebugF("LM authentication succeeded");
             }
         }
     }  else { /* V3 */
         unsigned ciPwdLength;
         char *ciPwd;
-               char *accountName;
-               char *primaryDomain;
+        char *accountName;
+        char *primaryDomain;
 
-               ciPwdLength = smb_GetSMBParm(inp, 7);
+        switch ( smb_authType ) {
+        case SMB_AUTH_EXTENDED:
+            OutputDebugF("V3 Session Setup: Extended");
+            break;
+        case SMB_AUTH_NTLM:
+            OutputDebugF("V3 Session Setup: NTLM");
+            break;
+        default:
+            OutputDebugF("V3 Session Setup: None");
+        }
+        ciPwdLength = smb_GetSMBParm(inp, 7);
         tp = smb_GetSMBData(inp, NULL);
-               ciPwd = tp;
-               tp += ciPwdLength;
+        ciPwd = tp;
+        tp += ciPwdLength;
+
+        accountName = smb_ParseString(tp, &tp);
+        primaryDomain = smb_ParseString(tp, NULL);
 
-               accountName = smb_ParseString(tp, &tp);
-               primaryDomain = smb_ParseString(tp, NULL);
+        OutputDebugF("Account Name: %s",accountName);
+        OutputDebugF("Primary Domain: %s", primaryDomain);
+        OutputDebugF("Case Insensitive Password: %s", ciPwd && ciPwd[0] ? "yes" : "no");
 
-               if ( smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
-                       /* shouldn't happen */
-                       code = CM_ERROR_BADSMB;
+        if ( smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
+            /* shouldn't happen */
+            code = CM_ERROR_BADSMB;
             goto after_read_packet;
-               }
+        }
 
         /* even if we wanted extended auth, if we only negotiated V3, we have to fallback
          * to NTLM.
          */
-               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
-                       code = smb_AuthenticateUserLM(vcp,accountName,primaryDomain,ciPwd,ciPwdLength,"",0);
-               }
-       }
+        if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+            code = smb_AuthenticateUserLM(vcp,accountName,primaryDomain,ciPwd,ciPwdLength,"",0);
+            if ( code )
+                OutputDebugF("LM authentication failed [%d]", code);
+            else
+                OutputDebugF("LM authentication succeeded");
+        }
+    }
 
   after_read_packet:
-       /* note down that we received a session setup X and set the capabilities flag */
-       if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
-               lock_ObtainMutex(&vcp->mx);
-               vcp->flags |= SMB_VCFLAG_SESSX_RCVD;
+    /* note down that we received a session setup X and set the capabilities flag */
+    if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
+        lock_ObtainMutex(&vcp->mx);
+        vcp->flags |= SMB_VCFLAG_SESSX_RCVD;
         /* for the moment we can only deal with NTSTATUS */
         if (caps & NTNEGOTIATE_CAPABILITY_NTSTATUS) {
             vcp->flags |= SMB_VCFLAG_STATUS32;
-        }
-               lock_ReleaseMutex(&vcp->mx);
-       }
+        }       
+        lock_ReleaseMutex(&vcp->mx);
+    }
 
-       /* code would be non-zero if there was an authentication failure.
-          Ideally we would like to invalidate the uid for this session or break
-          early to avoid accidently stealing someone else's tokens. */
+    /* code would be non-zero if there was an authentication failure.
+       Ideally we would like to invalidate the uid for this session or break
+       early to avoid accidently stealing someone else's tokens. */
 
-       if (code) {
-               return code;
-       }
+    if (code) {
+        return code;
+    }
 
-       OutputDebugF("Received username=[%s]", usern);
+    OutputDebugF("Received username=[%s]", usern);
 
     /* On Windows 2000, this function appears to be called more often than
        it is expected to be called. This resulted in multiple smb_user_t
@@ -898,7 +941,8 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         if (s1 == NULL) {s1 = s2; s2 = " ";}
 
         osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID,
-                  osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), s1, s2);
+                  osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), 
+                  osi_LogSaveString(smb_logp,s1), osi_LogSaveString(smb_logp,s2));
 
         lock_ObtainMutex(&uidp->mx);
         uidp->flags |= SMB_USERFLAG_DELETE;
@@ -916,6 +960,7 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 }
 
 #define SMB_SUPPORT_SEARCH_BITS        0x0001
+#define SMB_SHARE_IS_IN_DFS            0x0002
 
 long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
@@ -938,6 +983,8 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
     tp = smb_GetSMBData(inp, NULL);
     passwordp = smb_ParseString(tp, &tp);
     pathp = smb_ParseString(tp, &tp);
+    if (smb_StoreAnsiFilenames)
+        OemToChar(pathp,pathp);
     servicep = smb_ParseString(tp, &tp);
 
     tp = strrchr(pathp, '\\');
@@ -967,7 +1014,7 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
         
     tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
 
-    if(!ipc) {
+    if (!ipc) {
         uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
        shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
         if (uidp)
@@ -980,7 +1027,11 @@ 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);
-            smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | (policy << 2));
+            smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | 
+#ifdef DFS_SUPPORT
+                            SMB_SHARE_IS_IN_DFS |
+#endif
+                            (policy << 2));
         }
     } else {
         smb_SetSMBParm(outp, 2, 0);
@@ -990,7 +1041,8 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
     lock_ObtainMutex(&tidp->mx);
     tidp->userp = userp;
     tidp->pathname = sharePath;
-    if(ipc) tidp->flags |= SMB_TIDFLAG_IPC;
+    if (ipc) 
+        tidp->flags |= SMB_TIDFLAG_IPC;
     lock_ReleaseMutex(&tidp->mx);
     smb_ReleaseTID(tidp);
 
@@ -998,10 +1050,16 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
     ((smb_t *)inp)->tid = newTid;
     tp = smb_GetSMBData(outp, NULL);
     if (!ipc) {
+        /* XXX - why is this a drive letter? */
         *tp++ = 'A';
         *tp++ = ':';
         *tp++ = 0;
-        smb_SetSMBDataLength(outp, 3);
+        *tp++ = 'N';
+        *tp++ = 'T';
+        *tp++ = 'F';
+        *tp++ = 'S';
+        *tp++ = 0;
+        smb_SetSMBDataLength(outp, 8);
     } else {
         strcpy(tp, "IPC");
         smb_SetSMBDataLength(outp, 4);
@@ -1104,13 +1162,14 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
 /* free a tran2 packet; must be called with smb_globalLock held */
 void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
 {
-    if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
-       if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
-               if (t2p->parmsp)
-                       free(t2p->parmsp);
-               if (t2p->datap)
-                       free(t2p->datap);
-       }
+    if (t2p->vcp) 
+        smb_ReleaseVC(t2p->vcp);
+    if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
+        if (t2p->parmsp)
+            free(t2p->parmsp);
+        if (t2p->datap)
+            free(t2p->datap);
+    }       
     free(t2p);
 }
 
@@ -1123,19 +1182,19 @@ void smb_SendTran2Error(smb_vc_t *vcp, smb_tran2Packet_t *t2p,
     smb_t *smbp;
     unsigned short errCode;
     unsigned char errClass;
-       unsigned long NTStatus;
+    unsigned long NTStatus;
 
     if (vcp->flags & SMB_VCFLAG_STATUS32)
-               smb_MapNTError(code, &NTStatus);
-       else
-               smb_MapCoreError(code, vcp, &errCode, &errClass);
+        smb_MapNTError(code, &NTStatus);
+    else
+        smb_MapCoreError(code, vcp, &errCode, &errClass);
 
     smb_FormatResponsePacket(vcp, NULL, tp);
     smbp = (smb_t *) tp;
 
-       /* We can handle long names */
-       if (vcp->flags & SMB_VCFLAG_USENT)
-               smbp->flg2 |= 0x40;     /* IS_LONG_NAME */
+    /* We can handle long names */
+    if (vcp->flags & SMB_VCFLAG_USENT)
+        smbp->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
         
     /* now copy important fields from the tran 2 packet */
     smbp->com = t2p->com;
@@ -1143,19 +1202,19 @@ void smb_SendTran2Error(smb_vc_t *vcp, smb_tran2Packet_t *t2p,
     smbp->mid = t2p->mid;
     smbp->pid = t2p->pid;
     smbp->uid = t2p->uid;
-       smbp->res[0] = t2p->res[0];
-       if (vcp->flags & SMB_VCFLAG_STATUS32) {
-               smbp->rcls = (unsigned char) (NTStatus & 0xff);
-               smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
-               smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
-               smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
-               smbp->flg2 |= 0x4000;
-       }
-       else {
+    smbp->res[0] = t2p->res[0];
+    if (vcp->flags & SMB_VCFLAG_STATUS32) {
+        smbp->rcls = (unsigned char) (NTStatus & 0xff);
+        smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
+        smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
+        smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
+        smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
+    }
+    else {
         smbp->rcls = errClass;
-               smbp->errLow = (unsigned char) (errCode & 0xff);
-               smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
-       }
+        smbp->errLow = (unsigned char) (errCode & 0xff);
+        smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+    }
         
     /* send packet */
     smb_SendPacket(vcp, tp);
@@ -1165,17 +1224,17 @@ void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp
 {
     smb_t *smbp;
     unsigned short parmOffset;
-       unsigned short dataOffset;
-       unsigned short totalLength;
-       unsigned short dataAlign;
+    unsigned short dataOffset;
+    unsigned short totalLength;
+    unsigned short dataAlign;
     char *datap;
-        
+
     smb_FormatResponsePacket(vcp, NULL, tp);
     smbp = (smb_t *) tp;
 
-       /* We can handle long names */
-       if (vcp->flags & SMB_VCFLAG_USENT)
-               smbp->flg2 |= 0x40;     /* IS_LONG_NAME */
+    /* We can handle long names */
+    if (vcp->flags & SMB_VCFLAG_USENT)
+        smbp->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
 
     /* now copy important fields from the tran 2 packet */
     smbp->com = t2p->com;
@@ -1183,7 +1242,7 @@ void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp
     smbp->mid = t2p->mid;
     smbp->pid = t2p->pid;
     smbp->uid = t2p->uid;
-       smbp->res[0] = t2p->res[0];
+    smbp->res[0] = t2p->res[0];
 
     totalLength = 1 + t2p->totalData + t2p->totalParms;
 
@@ -1192,24 +1251,24 @@ void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp
     smb_SetSMBParm(tp, 1, t2p->totalData);     /* data bytes */
     smb_SetSMBParm(tp, 2, 0);          /* reserved */
     smb_SetSMBParm(tp, 3, t2p->totalParms);    /* parm bytes in this packet */
-       parmOffset = 10*2 + 35;                 /* parm offset in packet */
-       parmOffset++;                           /* round to even */
+    parmOffset = 10*2 + 35;                    /* parm offset in packet */
+    parmOffset++;                              /* round to even */
     smb_SetSMBParm(tp, 4, parmOffset); /* 11 parm words plus *
     * hdr, bcc and wct */
     smb_SetSMBParm(tp, 5, 0);          /* parm displacement */
     smb_SetSMBParm(tp, 6, t2p->totalData);     /* data in this packet */
-       dataOffset = parmOffset + t2p->oldTotalParms;
-       dataAlign = dataOffset & 2;             /* quad-align */
-       dataOffset += dataAlign;
+    dataOffset = parmOffset + t2p->oldTotalParms;
+    dataAlign = dataOffset & 2;                /* quad-align */
+    dataOffset += dataAlign;
     smb_SetSMBParm(tp, 7, dataOffset); /* offset of data */
     smb_SetSMBParm(tp, 8, 0);          /* data displacement */
     smb_SetSMBParm(tp, 9, 0);          /* low: setup word count *
-    * high: resvd */
+                                         * high: resvd */
 
     datap = smb_GetSMBData(tp, NULL);
-       *datap++ = 0;                           /* we rounded to even */
+    *datap++ = 0;                              /* we rounded to even */
 
-       totalLength += dataAlign;
+    totalLength += dataAlign;
     smb_SetSMBDataLength(tp, totalLength);
         
     /* next, send the datagram */
@@ -1228,56 +1287,56 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int parmCount;
     int dataCount;
     int firstPacket;
-       int rapOp;
+    int rapOp;
     long code = 0;
 
-       /* We sometimes see 0 word count.  What to do? */
-       if (*inp->wctp == 0) {
+    /* We sometimes see 0 word count.  What to do? */
+    if (*inp->wctp == 0) {
 #ifndef DJGPP
-               HANDLE h;
-               char *ptbuf[1];
+        HANDLE h;
+        char *ptbuf[1];
 
-               osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
+        osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
 
-               h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-               ptbuf[0] = "Transaction2 word count = 0";
-               ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
-                           1, inp->ncb_length, ptbuf, inp);
-               DeregisterEventSource(h);
+        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+        ptbuf[0] = "Transaction2 word count = 0";
+        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
+                    1, inp->ncb_length, ptbuf, inp);
+        DeregisterEventSource(h);
 #else /* DJGPP */
-               osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
+        osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
 #endif /* !DJGPP */
 
         smb_SetSMBDataLength(outp, 0);
         smb_SendPacket(vcp, outp);
-               return 0;
-       }
+        return 0;
+    }
 
     totalParms = smb_GetSMBParm(inp, 0);
     totalData = smb_GetSMBParm(inp, 1);
         
     firstPacket = (inp->inCom == 0x25);
         
-       /* find the packet we're reassembling */
-       lock_ObtainWrite(&smb_globalLock);
+    /* find the packet we're reassembling */
+    lock_ObtainWrite(&smb_globalLock);
     asp = smb_FindTran2Packet(vcp, inp);
     if (!asp) {
         asp = smb_NewTran2Packet(vcp, inp, totalParms, totalData);
-       }
+    }
     lock_ReleaseWrite(&smb_globalLock);
         
     /* now merge in this latest packet; start by looking up offsets */
-       if (firstPacket) {
-               parmDisp = dataDisp = 0;
+    if (firstPacket) {
+        parmDisp = dataDisp = 0;
         parmOffset = smb_GetSMBParm(inp, 10);
         dataOffset = smb_GetSMBParm(inp, 12);
         parmCount = smb_GetSMBParm(inp, 9);
         dataCount = smb_GetSMBParm(inp, 11);
-               asp->maxReturnParms = smb_GetSMBParm(inp, 2);
+        asp->maxReturnParms = smb_GetSMBParm(inp, 2);
         asp->maxReturnData = smb_GetSMBParm(inp, 3);
 
-               osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
-                 totalData, dataCount, asp->maxReturnData);
+        osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
+                  totalData, dataCount, asp->maxReturnData);
     }
     else {
         parmDisp = smb_GetSMBParm(inp, 4);
@@ -1309,13 +1368,13 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         asp->curParms > 0 &&
         asp->totalData <= asp->curData &&
         asp->totalParms <= asp->curParms) {
-               /* we've received it all */
+        /* we've received it all */
         lock_ObtainWrite(&smb_globalLock);
-               osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
+        osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
         lock_ReleaseWrite(&smb_globalLock);
 
         /* now dispatch it */
-               rapOp = asp->parmsp[0];
+        rapOp = asp->parmsp[0];
 
         if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
             osi_LogEvent("AFS-Dispatch-RAP[%s]",myCrt_RapDispatch(rapOp),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
@@ -1357,416 +1416,416 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
    share names, but we don't support unicode yet. */
 
 typedef struct smb_rap_share_info_0 {
-       char                    shi0_netname[13];
+    char        shi0_netname[13];
 } smb_rap_share_info_0_t;
 
 typedef struct smb_rap_share_info_1 {
-       char                    shi1_netname[13];
-       char                    shi1_pad;
-       WORD                    shi1_type;
-       DWORD                   shi1_remark; /* char *shi1_remark; data offset */
+    char                       shi1_netname[13];
+    char                       shi1_pad;
+    WORD                       shi1_type;
+    DWORD                      shi1_remark; /* char *shi1_remark; data offset */
 } smb_rap_share_info_1_t;
 
 typedef struct smb_rap_share_info_2 {
-       char                            shi2_netname[13];
-       char                            shi2_pad;
-       unsigned short          shi2_type;
-       DWORD                           shi2_remark; /* char *shi2_remark; data offset */
-       unsigned short          shi2_permissions;
-       unsigned short          shi2_max_uses;
-       unsigned short          shi2_current_uses;
-       DWORD                           shi2_path;  /* char *shi2_path; data offset */
-       unsigned short          shi2_passwd[9];
-       unsigned short          shi2_pad2;
+    char                               shi2_netname[13];
+    char                               shi2_pad;
+    unsigned short             shi2_type;
+    DWORD                              shi2_remark; /* char *shi2_remark; data offset */
+    unsigned short             shi2_permissions;
+    unsigned short             shi2_max_uses;
+    unsigned short             shi2_current_uses;
+    DWORD                              shi2_path;  /* char *shi2_path; data offset */
+    unsigned short             shi2_passwd[9];
+    unsigned short             shi2_pad2;
 } smb_rap_share_info_2_t;
 
 #define SMB_RAP_MAX_SHARES 512
 
 typedef struct smb_rap_share_list {
-       int cShare;
-       int maxShares;
-       smb_rap_share_info_0_t * shares;
+    int cShare;
+    int maxShares;
+    smb_rap_share_info_0_t * shares;
 } smb_rap_share_list_t;
 
 int smb_rapCollectSharesProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp) {
-       smb_rap_share_list_t * sp;
-       char * name;
+    smb_rap_share_list_t * sp;
+    char * name;
 
-       name = dep->name;
+    name = dep->name;
 
-       if(name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
-               return 0; /* skip over '.' and '..' */
+    if (name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
+        return 0; /* skip over '.' and '..' */
 
-       sp = (smb_rap_share_list_t *) vrockp;
+    sp = (smb_rap_share_list_t *) vrockp;
 
-       strncpy(sp->shares[sp->cShare].shi0_netname, name, 12);
-       sp->shares[sp->cShare].shi0_netname[12] = 0;
+    strncpy(sp->shares[sp->cShare].shi0_netname, name, 12);
+    sp->shares[sp->cShare].shi0_netname[12] = 0;
 
-       sp->cShare++;
+    sp->cShare++;
 
-       if(sp->cShare >= sp->maxShares)
-               return CM_ERROR_STOPNOW;
-       else
-               return 0;
-}
+    if (sp->cShare >= sp->maxShares)
+        return CM_ERROR_STOPNOW;
+    else
+        return 0;
+}       
 
 long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
-       smb_tran2Packet_t *outp;
-       unsigned short * tp;
-       int len;
-       int infoLevel;
-       int bufsize;
-       int outParmsTotal;      /* total parameter bytes */
-       int outDataTotal;       /* total data bytes */
-       int code = 0;
-       DWORD rv;
-       DWORD allSubmount;
-       USHORT nShares;
-       DWORD nRegShares;
-       DWORD nSharesRet;
-       HKEY hkParam;
-       HKEY hkSubmount = NULL;
-       smb_rap_share_info_1_t * shares;
-       USHORT cshare = 0;
-       char * cstrp;
-       char thisShare[256];
-       int i,j;
-       int nonrootShares;
-       smb_rap_share_list_t rootShares;
-       cm_req_t req;
-       cm_user_t * userp;
-       osi_hyper_t thyper;
-
-       tp = p->parmsp + 1; /* skip over function number (always 0) */
-       (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over parm descriptor */
-       (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over data descriptor */
-       infoLevel = tp[0];
+    smb_tran2Packet_t *outp;
+    unsigned short * tp;
+    int len;
+    int infoLevel;
+    int bufsize;
+    int outParmsTotal; /* total parameter bytes */
+    int outDataTotal;  /* total data bytes */
+    int code = 0;
+    DWORD rv;
+    DWORD allSubmount;
+    USHORT nShares;
+    DWORD nRegShares;
+    DWORD nSharesRet;
+    HKEY hkParam;
+    HKEY hkSubmount = NULL;
+    smb_rap_share_info_1_t * shares;
+    USHORT cshare = 0;
+    char * cstrp;
+    char thisShare[256];
+    int i,j;
+    int nonrootShares;
+    smb_rap_share_list_t rootShares;
+    cm_req_t req;
+    cm_user_t * userp;
+    osi_hyper_t thyper;
+
+    tp = p->parmsp + 1; /* skip over function number (always 0) */
+    (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over parm descriptor */
+    (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over data descriptor */
+    infoLevel = tp[0];
     bufsize = tp[1];
 
-       if(infoLevel != 1) {
-               return CM_ERROR_INVAL;
-       }
+    if (infoLevel != 1) {
+        return CM_ERROR_INVAL;
+    }
 
-       /* first figure out how many shares there are */
-    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
-               KEY_QUERY_VALUE, &hkParam);
-       if (rv == ERROR_SUCCESS) {
+    /* first figure out how many shares there are */
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
+                      KEY_QUERY_VALUE, &hkParam);
+    if (rv == ERROR_SUCCESS) {
         len = sizeof(allSubmount);
         rv = RegQueryValueEx(hkParam, "AllSubmount", NULL, NULL,
-                                (BYTE *) &allSubmount, &len);
-               if (rv != ERROR_SUCCESS || allSubmount != 0) {
-                       allSubmount = 1;
-               }
+                             (BYTE *) &allSubmount, &len);
+        if (rv != ERROR_SUCCESS || allSubmount != 0) {
+            allSubmount = 1;
+        }
         RegCloseKey (hkParam);
-       }
+    }
 
-       rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
-               0, KEY_QUERY_VALUE, &hkSubmount);
-       if (rv == ERROR_SUCCESS) {
+    rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
+                      0, KEY_QUERY_VALUE, &hkSubmount);
+    if (rv == ERROR_SUCCESS) {
         rv = RegQueryInfoKey(hkSubmount, NULL, NULL, NULL, NULL,
-                       NULL, NULL, &nRegShares, NULL, NULL, NULL, NULL);
-               if (rv != ERROR_SUCCESS)
-                       nRegShares = 0;
-       } else {
-               hkSubmount = NULL;
-       }
+                             NULL, NULL, &nRegShares, NULL, NULL, NULL, NULL);
+        if (rv != ERROR_SUCCESS)
+            nRegShares = 0;
+    } else {
+        hkSubmount = NULL;
+    }
 
-       /* fetch the root shares */
-       rootShares.maxShares = SMB_RAP_MAX_SHARES;
-       rootShares.cShare = 0;
-       rootShares.shares = malloc( sizeof(smb_rap_share_info_0_t) * SMB_RAP_MAX_SHARES );
+    /* fetch the root shares */
+    rootShares.maxShares = SMB_RAP_MAX_SHARES;
+    rootShares.cShare = 0;
+    rootShares.shares = malloc( sizeof(smb_rap_share_info_0_t) * SMB_RAP_MAX_SHARES );
 
-       cm_InitReq(&req);
+    cm_InitReq(&req);
 
-       userp = smb_GetTran2User(vcp,p);
+    userp = smb_GetTran2User(vcp,p);
 
-       thyper.HighPart = 0;
-       thyper.LowPart = 0;
+    thyper.HighPart = 0;
+    thyper.LowPart = 0;
 
-       cm_HoldSCache(cm_rootSCachep);
-       cm_ApplyDir(cm_rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
-       cm_ReleaseSCache(cm_rootSCachep);
+    cm_HoldSCache(cm_data.rootSCachep);
+    cm_ApplyDir(cm_data.rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
+    cm_ReleaseSCache(cm_data.rootSCachep);
 
-       cm_ReleaseUser(userp);
+    cm_ReleaseUser(userp);
 
-       nShares = rootShares.cShare + nRegShares + allSubmount;
+    nShares = rootShares.cShare + nRegShares + allSubmount;
 
 #define REMARK_LEN 1
-       outParmsTotal = 8; /* 4 dwords */
-       outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nShares ;
-       if(outDataTotal > bufsize) {
-               nSharesRet = bufsize / (sizeof(smb_rap_share_info_1_t) + REMARK_LEN);
-               outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet;
-       }
-       else {
-               nSharesRet = nShares;
-       }
+    outParmsTotal = 8; /* 4 dwords */
+    outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nShares ;
+    if(outDataTotal > bufsize) {
+        nSharesRet = bufsize / (sizeof(smb_rap_share_info_1_t) + REMARK_LEN);
+        outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet;
+    }
+    else {
+        nSharesRet = nShares;
+    }
     
-       outp = smb_GetTran2ResponsePacket(vcp, p, op, outParmsTotal, outDataTotal);
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, outParmsTotal, outDataTotal);
 
-       /* now for the submounts */
+    /* now for the submounts */
     shares = (smb_rap_share_info_1_t *) outp->datap;
-       cstrp = outp->datap + sizeof(smb_rap_share_info_1_t) * nSharesRet;
+    cstrp = outp->datap + sizeof(smb_rap_share_info_1_t) * nSharesRet;
 
-       memset(outp->datap, 0, (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet);
+    memset(outp->datap, 0, (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet);
 
-       if(allSubmount) {
-               strcpy( shares[cshare].shi1_netname, "all" );
-               shares[cshare].shi1_remark = cstrp - outp->datap;
-               /* type and pad are zero already */
-               cshare++;
-               cstrp+=REMARK_LEN;
-       }
+    if (allSubmount) {
+        strcpy( shares[cshare].shi1_netname, "all" );
+        shares[cshare].shi1_remark = cstrp - outp->datap;
+        /* type and pad are zero already */
+        cshare++;
+        cstrp+=REMARK_LEN;
+    }
 
-       if(hkSubmount) {
-               for(i=0; i < nRegShares && cshare < nSharesRet; i++) {
-                       len = sizeof(thisShare);
+    if (hkSubmount) {
+        for (i=0; i < nRegShares && cshare < nSharesRet; i++) {
+            len = sizeof(thisShare);
             rv = RegEnumValue(hkSubmount, i, thisShare, &len, NULL, NULL, NULL, NULL);
-                       if(rv == ERROR_SUCCESS && strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) {
-                               strncpy(shares[cshare].shi1_netname, thisShare, sizeof(shares->shi1_netname)-1);
-                               shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */
-                               shares[cshare].shi1_remark = cstrp - outp->datap;
-                               cshare++;
-                               cstrp+=REMARK_LEN;
-                       }
-                       else
-                               nShares--; /* uncount key */
-               }
-
-               RegCloseKey(hkSubmount);
-       }
+            if (rv == ERROR_SUCCESS && strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) {
+                strncpy(shares[cshare].shi1_netname, thisShare, sizeof(shares->shi1_netname)-1);
+                shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */
+                shares[cshare].shi1_remark = cstrp - outp->datap;
+                cshare++;
+                cstrp+=REMARK_LEN;
+            }
+            else
+                nShares--; /* uncount key */
+        }
 
-       nonrootShares = cshare;
+        RegCloseKey(hkSubmount);
+    }
+
+    nonrootShares = cshare;
 
-       for(i=0; i < rootShares.cShare && cshare < nSharesRet; i++) {
+    for (i=0; i < rootShares.cShare && cshare < nSharesRet; i++) {
         /* in case there are collisions with submounts, submounts have higher priority */              
-               for(j=0; j < nonrootShares; j++)
-                       if(!stricmp(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
-                               break;
+        for (j=0; j < nonrootShares; j++)
+            if (!stricmp(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
+                break;
                
-               if(j < nonrootShares) {
-                       nShares--; /* uncount */
-                       continue;
-               }
-
-               strcpy(shares[cshare].shi1_netname, rootShares.shares[i].shi0_netname);
-               shares[cshare].shi1_remark = cstrp - outp->datap;
-               cshare++;
-               cstrp+=REMARK_LEN;
-       }
+        if (j < nonrootShares) {
+            nShares--; /* uncount */
+            continue;
+        }
+
+        strcpy(shares[cshare].shi1_netname, rootShares.shares[i].shi0_netname);
+        shares[cshare].shi1_remark = cstrp - outp->datap;
+        cshare++;
+        cstrp+=REMARK_LEN;
+    }
 
-       outp->parmsp[0] = ((cshare == nShares)? ERROR_SUCCESS : ERROR_MORE_DATA);
-       outp->parmsp[1] = 0;
-       outp->parmsp[2] = cshare;
-       outp->parmsp[3] = nShares;
+    outp->parmsp[0] = ((cshare == nShares)? ERROR_SUCCESS : ERROR_MORE_DATA);
+    outp->parmsp[1] = 0;
+    outp->parmsp[2] = cshare;
+    outp->parmsp[3] = nShares;
 
-       outp->totalData = cstrp - outp->datap;
-       outp->totalParms = outParmsTotal;
+    outp->totalData = cstrp - outp->datap;
+    outp->totalParms = outParmsTotal;
 
-       smb_SendTran2Packet(vcp, outp, op);
-       smb_FreeTran2Packet(outp);
+    smb_SendTran2Packet(vcp, outp, op);
+    smb_FreeTran2Packet(outp);
 
-       free(rootShares.shares);
+    free(rootShares.shares);
 
-       return code;
+    return code;
 }
 
 long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
-       smb_tran2Packet_t *outp;
-       unsigned short * tp;
-       char * shareName;
-       BOOL shareFound = FALSE;
-       unsigned short infoLevel;
-       unsigned short bufsize;
-       int totalData;
-       int totalParam;
-       DWORD len;
-       HKEY hkParam;
-       HKEY hkSubmount;
-       DWORD allSubmount;
-       LONG rv;
-       long code = 0;
-
-       tp = p->parmsp + 1; /* skip over function number (always 1) */
-       (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over param descriptor */
-       (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over data descriptor */
-       shareName = smb_ParseString( (char *) tp, (char **) &tp);
+    smb_tran2Packet_t *outp;
+    unsigned short * tp;
+    char * shareName;
+    BOOL shareFound = FALSE;
+    unsigned short infoLevel;
+    unsigned short bufsize;
+    int totalData;
+    int totalParam;
+    DWORD len;
+    HKEY hkParam;
+    HKEY hkSubmount;
+    DWORD allSubmount;
+    LONG rv;
+    long code = 0;
+
+    tp = p->parmsp + 1; /* skip over function number (always 1) */
+    (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over param descriptor */
+    (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over data descriptor */
+    shareName = smb_ParseString( (char *) tp, (char **) &tp);
     infoLevel = *tp++;
     bufsize = *tp++;
     
-       totalParam = 6;
-
-       if(infoLevel == 0)
-               totalData = sizeof(smb_rap_share_info_0_t);
-       else if(infoLevel == 1)
-               totalData = sizeof(smb_rap_share_info_1_t) + 1; /* + empty string */
-       else if(infoLevel == 2)
-               totalData = sizeof(smb_rap_share_info_2_t) + 2; /* + two empty strings */
-       else
-               return CM_ERROR_INVAL;
-
-       outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
-
-       if(!stricmp(shareName,"all")) {
-               rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
-                       KEY_QUERY_VALUE, &hkParam);
-               if (rv == ERROR_SUCCESS) {
-                       len = sizeof(allSubmount);
-                       rv = RegQueryValueEx(hkParam, "AllSubmount", NULL, NULL,
-                                                                       (BYTE *) &allSubmount, &len);
-                       if (rv != ERROR_SUCCESS || allSubmount != 0) {
-                               allSubmount = 1;
-                       }
-                       RegCloseKey (hkParam);
-               }
-
-               if(allSubmount)
-                       shareFound = TRUE;
-
-       } else {
-               rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts", 0,
-                       KEY_QUERY_VALUE, &hkSubmount);
-               if(rv == ERROR_SUCCESS) {
+    totalParam = 6;
+
+    if (infoLevel == 0)
+        totalData = sizeof(smb_rap_share_info_0_t);
+    else if(infoLevel == SMB_INFO_STANDARD)
+        totalData = sizeof(smb_rap_share_info_1_t) + 1; /* + empty string */
+    else if(infoLevel == SMB_INFO_QUERY_EA_SIZE)
+        totalData = sizeof(smb_rap_share_info_2_t) + 2; /* + two empty strings */
+    else
+        return CM_ERROR_INVAL;
+
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
+
+    if(!stricmp(shareName,"all")) {
+        rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
+                          KEY_QUERY_VALUE, &hkParam);
+        if (rv == ERROR_SUCCESS) {
+            len = sizeof(allSubmount);
+            rv = RegQueryValueEx(hkParam, "AllSubmount", NULL, NULL,
+                                  (BYTE *) &allSubmount, &len);
+            if (rv != ERROR_SUCCESS || allSubmount != 0) {
+                allSubmount = 1;
+            }
+            RegCloseKey (hkParam);
+        }
+
+        if (allSubmount)
+            shareFound = TRUE;
+
+    } else {
+        rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY "\\Submounts", 0,
+                          KEY_QUERY_VALUE, &hkSubmount);
+        if (rv == ERROR_SUCCESS) {
             rv = RegQueryValueEx(hkSubmount, shareName, NULL, NULL, NULL, NULL);
-                       if(rv == ERROR_SUCCESS) {
-                               shareFound = TRUE;
-                       }
-                       RegCloseKey(hkSubmount);
-               }
-       }
+            if (rv == ERROR_SUCCESS) {
+                shareFound = TRUE;
+            }
+            RegCloseKey(hkSubmount);
+        }
+    }
 
-       if(!shareFound) {
-               smb_FreeTran2Packet(outp);
-               return CM_ERROR_BADSHARENAME;
-       }
+    if (!shareFound) {
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSHARENAME;
+    }
 
-       memset(outp->datap, 0, totalData);
+    memset(outp->datap, 0, totalData);
 
-       outp->parmsp[0] = 0;
-       outp->parmsp[1] = 0;
-       outp->parmsp[2] = totalData;
+    outp->parmsp[0] = 0;
+    outp->parmsp[1] = 0;
+    outp->parmsp[2] = totalData;
 
-       if(infoLevel == 0) {
-               smb_rap_share_info_0_t * info = (smb_rap_share_info_0_t *) outp->datap;
-               strncpy(info->shi0_netname, shareName, sizeof(info->shi0_netname)-1);
-               info->shi0_netname[sizeof(info->shi0_netname)-1] = 0;
-       } else if(infoLevel == 1) {
-               smb_rap_share_info_1_t * info = (smb_rap_share_info_1_t *) outp->datap;
+    if (infoLevel == 0) {
+        smb_rap_share_info_0_t * info = (smb_rap_share_info_0_t *) outp->datap;
+        strncpy(info->shi0_netname, shareName, sizeof(info->shi0_netname)-1);
+        info->shi0_netname[sizeof(info->shi0_netname)-1] = 0;
+    } else if(infoLevel == SMB_INFO_STANDARD) {
+        smb_rap_share_info_1_t * info = (smb_rap_share_info_1_t *) outp->datap;
         strncpy(info->shi1_netname, shareName, sizeof(info->shi1_netname)-1);
-               info->shi1_netname[sizeof(info->shi1_netname)-1] = 0;
-               info->shi1_remark = ((unsigned char *) (info + 1)) - outp->datap;
-               /* type and pad are already zero */
-       } else { /* infoLevel==2 */
-               smb_rap_share_info_2_t * info = (smb_rap_share_info_2_t *) outp->datap;
-               strncpy(info->shi2_netname, shareName, sizeof(info->shi2_netname)-1);
-               info->shi2_netname[sizeof(info->shi2_netname)-1] = 0;
-               info->shi2_remark = ((unsigned char *) (info + 1)) - outp->datap;
+        info->shi1_netname[sizeof(info->shi1_netname)-1] = 0;
+        info->shi1_remark = ((unsigned char *) (info + 1)) - outp->datap;
+        /* type and pad are already zero */
+    } else { /* infoLevel==2 */
+        smb_rap_share_info_2_t * info = (smb_rap_share_info_2_t *) outp->datap;
+        strncpy(info->shi2_netname, shareName, sizeof(info->shi2_netname)-1);
+        info->shi2_netname[sizeof(info->shi2_netname)-1] = 0;
+        info->shi2_remark = ((unsigned char *) (info + 1)) - outp->datap;
         info->shi2_permissions = ACCESS_ALL;
-               info->shi2_max_uses = (unsigned short) -1;
+        info->shi2_max_uses = (unsigned short) -1;
         info->shi2_path = 1 + (((unsigned char *) (info + 1)) - outp->datap);
-       }
+    }
 
-       outp->totalData = totalData;
-       outp->totalParms = totalParam;
+    outp->totalData = totalData;
+    outp->totalParms = totalParam;
 
-       smb_SendTran2Packet(vcp, outp, op);
-       smb_FreeTran2Packet(outp);
+    smb_SendTran2Packet(vcp, outp, op);
+    smb_FreeTran2Packet(outp);
 
-       return code;
+    return code;
 }
 
 typedef struct smb_rap_wksta_info_10 {
-       DWORD   wki10_computername;     /*char *wki10_computername;*/
-       DWORD   wki10_username; /* char *wki10_username; */
-       DWORD   wki10_langroup; /* char *wki10_langroup;*/
-       unsigned char   wki10_ver_major;
-       unsigned char   wki10_ver_minor;
-       DWORD   wki10_logon_domain;     /*char *wki10_logon_domain;*/
-       DWORD   wki10_oth_domains; /* char *wki10_oth_domains;*/
+    DWORD      wki10_computername;     /*char *wki10_computername;*/
+    DWORD      wki10_username; /* char *wki10_username; */
+    DWORD      wki10_langroup; /* char *wki10_langroup;*/
+    unsigned char      wki10_ver_major;
+    unsigned char      wki10_ver_minor;
+    DWORD      wki10_logon_domain;     /*char *wki10_logon_domain;*/
+    DWORD      wki10_oth_domains; /* char *wki10_oth_domains;*/
 } smb_rap_wksta_info_10_t;
 
 
 long smb_ReceiveRAPNetWkstaGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
-       smb_tran2Packet_t *outp;
+    smb_tran2Packet_t *outp;
     long code = 0;
-       int infoLevel;
-       int bufsize;
-       unsigned short * tp;
-       int totalData;
-       int totalParams;
-       smb_rap_wksta_info_10_t * info;
-       char * cstrp;
-       smb_user_t *uidp;
-
-       tp = p->parmsp + 1; /* Skip over function number */
-       (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
-       (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
-       infoLevel = *tp++;
-       bufsize = *tp++;
-
-       if(infoLevel != 10) {
-               return CM_ERROR_INVAL;
-       }
+    int infoLevel;
+    int bufsize;
+    unsigned short * tp;
+    int totalData;
+    int totalParams;
+    smb_rap_wksta_info_10_t * info;
+    char * cstrp;
+    smb_user_t *uidp;
+
+    tp = p->parmsp + 1; /* Skip over function number */
+    (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
+    (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
+    infoLevel = *tp++;
+    bufsize = *tp++;
+
+    if (infoLevel != 10) {
+        return CM_ERROR_INVAL;
+    }
 
-       totalParams = 6;
+    totalParams = 6;
        
-       /* infolevel 10 */
-       totalData = sizeof(*info) +             /* info */
-               MAX_COMPUTERNAME_LENGTH +       /* wki10_computername */
-               SMB_MAX_USERNAME_LENGTH +       /* wki10_username */
-               MAX_COMPUTERNAME_LENGTH +       /* wki10_langroup */
-               MAX_COMPUTERNAME_LENGTH +       /* wki10_logon_domain */
-               1;                                                      /* wki10_oth_domains (null)*/
+    /* infolevel 10 */
+    totalData = sizeof(*info) +                /* info */
+        MAX_COMPUTERNAME_LENGTH +      /* wki10_computername */
+        SMB_MAX_USERNAME_LENGTH +      /* wki10_username */
+        MAX_COMPUTERNAME_LENGTH +      /* wki10_langroup */
+        MAX_COMPUTERNAME_LENGTH +      /* wki10_logon_domain */
+        1;                             /* wki10_oth_domains (null)*/
 
-       outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
 
-       memset(outp->parmsp,0,totalParams);
-       memset(outp->datap,0,totalData);
+    memset(outp->parmsp,0,totalParams);
+    memset(outp->datap,0,totalData);
 
     info = (smb_rap_wksta_info_10_t *) outp->datap;
-       cstrp = (char *) (info + 1);
-
-       info->wki10_computername = (DWORD) (cstrp - outp->datap);
-       strcpy(cstrp, smb_localNamep);
-       cstrp += strlen(cstrp) + 1;
-
-       info->wki10_username = (DWORD) (cstrp - outp->datap);
-       uidp = smb_FindUID(vcp, p->uid, 0);
-       if(uidp) {
-               lock_ObtainMutex(&uidp->mx);
-               if(uidp->unp && uidp->unp->name)
-                       strcpy(cstrp, uidp->unp->name);
-               lock_ReleaseMutex(&uidp->mx);
-               smb_ReleaseUID(uidp);
-       }
-       cstrp += strlen(cstrp) + 1;
+    cstrp = (char *) (info + 1);
+
+    info->wki10_computername = (DWORD) (cstrp - outp->datap);
+    strcpy(cstrp, smb_localNamep);
+    cstrp += strlen(cstrp) + 1;
+
+    info->wki10_username = (DWORD) (cstrp - outp->datap);
+    uidp = smb_FindUID(vcp, p->uid, 0);
+    if (uidp) {
+        lock_ObtainMutex(&uidp->mx);
+        if(uidp->unp && uidp->unp->name)
+            strcpy(cstrp, uidp->unp->name);
+        lock_ReleaseMutex(&uidp->mx);
+        smb_ReleaseUID(uidp);
+    }
+    cstrp += strlen(cstrp) + 1;
 
-       info->wki10_langroup = (DWORD) (cstrp - outp->datap);
-       strcpy(cstrp, "WORKGROUP");
-       cstrp += strlen(cstrp) + 1;
+    info->wki10_langroup = (DWORD) (cstrp - outp->datap);
+    strcpy(cstrp, "WORKGROUP");
+    cstrp += strlen(cstrp) + 1;
 
-       /* TODO: Not sure what values these should take, but these work */
-       info->wki10_ver_major = 5;
-       info->wki10_ver_minor = 1;
+    /* TODO: Not sure what values these should take, but these work */
+    info->wki10_ver_major = 5;
+    info->wki10_ver_minor = 1;
 
-       info->wki10_logon_domain = (DWORD) (cstrp - outp->datap);
-       strcpy(cstrp, smb_ServerDomainName);
-       cstrp += strlen(cstrp) + 1;
+    info->wki10_logon_domain = (DWORD) (cstrp - outp->datap);
+    strcpy(cstrp, smb_ServerDomainName);
+    cstrp += strlen(cstrp) + 1;
 
-       info->wki10_oth_domains = (DWORD) (cstrp - outp->datap);
-       cstrp ++; /* no other domains */
+    info->wki10_oth_domains = (DWORD) (cstrp - outp->datap);
+    cstrp ++; /* no other domains */
 
-       outp->totalData = (unsigned short) (cstrp - outp->datap); /* actual data size */
-       outp->parmsp[2] = outp->totalData;
-       outp->totalParms = totalParams;
+    outp->totalData = (unsigned short) (cstrp - outp->datap); /* actual data size */
+    outp->parmsp[2] = outp->totalData;
+    outp->totalParms = totalParams;
 
-       smb_SendTran2Packet(vcp,outp,op);
-       smb_FreeTran2Packet(outp);
+    smb_SendTran2Packet(vcp,outp,op);
+    smb_FreeTran2Packet(outp);
 
-       return code;
+    return code;
 }
 
 typedef struct smb_rap_server_info_0 {
@@ -1790,43 +1849,43 @@ int smb_ServerCommentLen = sizeof(smb_ServerComment);
 
 long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
-       smb_tran2Packet_t *outp;
+    smb_tran2Packet_t *outp;
     long code = 0;
-       int infoLevel;
-       int bufsize;
-       unsigned short * tp;
-       int totalData;
-       int totalParams;
+    int infoLevel;
+    int bufsize;
+    unsigned short * tp;
+    int totalData;
+    int totalParams;
     smb_rap_server_info_0_t * info0;
     smb_rap_server_info_1_t * info1;
     char * cstrp;
 
-       tp = p->parmsp + 1; /* Skip over function number */
-       (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
-       (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
-       infoLevel = *tp++;
-       bufsize = *tp++;
+    tp = p->parmsp + 1; /* Skip over function number */
+    (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
+    (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
+    infoLevel = *tp++;
+    bufsize = *tp++;
 
-    if(infoLevel != 0 && infoLevel != 1) {
+    if (infoLevel != 0 && infoLevel != 1) {
         return CM_ERROR_INVAL;
     }
 
-       totalParams = 6;
-       
-       totalData = 
+    totalParams = 6;
+
+    totalData = 
         (infoLevel == 0) ? sizeof(smb_rap_server_info_0_t)
         : (sizeof(smb_rap_server_info_1_t) + smb_ServerCommentLen);
 
-       outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
 
-       memset(outp->parmsp,0,totalParams);
-       memset(outp->datap,0,totalData);
+    memset(outp->parmsp,0,totalParams);
+    memset(outp->datap,0,totalData);
 
-    if(infoLevel == 0) {
+    if (infoLevel == 0) {
         info0 = (smb_rap_server_info_0_t *) outp->datap;
         cstrp = (char *) (info0 + 1);
         strcpy(info0->sv0_name, "AFS");
-    } else { /* infoLevel == 1 */
+    } else { /* infoLevel == SMB_INFO_STANDARD */
         info1 = (smb_rap_server_info_1_t *) outp->datap;
         cstrp = (char *) (info1 + 1);
         strcpy(info1->sv1_name, "AFS");
@@ -1846,13 +1905,13 @@ long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pac
     }
 
     totalData = cstrp - outp->datap;
-       outp->totalData = min(bufsize,totalData); /* actual data size */
+    outp->totalData = min(bufsize,totalData); /* actual data size */
     outp->parmsp[0] = (outp->totalData == totalData)? 0 : ERROR_MORE_DATA;
-       outp->parmsp[2] = totalData;
-       outp->totalParms = totalParams;
+    outp->parmsp[2] = totalData;
+    outp->totalParms = totalParams;
 
-       smb_SendTran2Packet(vcp,outp,op);
-       smb_FreeTran2Packet(outp);
+    smb_SendTran2Packet(vcp,outp,op);
+    smb_FreeTran2Packet(outp);
 
     return code;
 }
@@ -1871,52 +1930,52 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int firstPacket;
     long code = 0;
 
-       /* We sometimes see 0 word count.  What to do? */
-       if (*inp->wctp == 0) {
+    /* We sometimes see 0 word count.  What to do? */
+    if (*inp->wctp == 0) {
 #ifndef DJGPP
-               HANDLE h;
-               char *ptbuf[1];
+        HANDLE h;
+        char *ptbuf[1];
 
-               osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
+        osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
 
-               h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-               ptbuf[0] = "Transaction2 word count = 0";
-               ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
-                           1, inp->ncb_length, ptbuf, inp);
-               DeregisterEventSource(h);
+        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+        ptbuf[0] = "Transaction2 word count = 0";
+        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
+                    1, inp->ncb_length, ptbuf, inp);
+        DeregisterEventSource(h);
 #else /* DJGPP */
-               osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
+        osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
 #endif /* !DJGPP */
 
         smb_SetSMBDataLength(outp, 0);
         smb_SendPacket(vcp, outp);
-               return 0;
-       }
+        return 0;
+    }
 
     totalParms = smb_GetSMBParm(inp, 0);
     totalData = smb_GetSMBParm(inp, 1);
         
     firstPacket = (inp->inCom == 0x32);
         
-       /* find the packet we're reassembling */
-       lock_ObtainWrite(&smb_globalLock);
+    /* find the packet we're reassembling */
+    lock_ObtainWrite(&smb_globalLock);
     asp = smb_FindTran2Packet(vcp, inp);
     if (!asp) {
         asp = smb_NewTran2Packet(vcp, inp, totalParms, totalData);
-       }
+    }
     lock_ReleaseWrite(&smb_globalLock);
         
     /* now merge in this latest packet; start by looking up offsets */
-       if (firstPacket) {
-               parmDisp = dataDisp = 0;
+    if (firstPacket) {
+        parmDisp = dataDisp = 0;
         parmOffset = smb_GetSMBParm(inp, 10);
         dataOffset = smb_GetSMBParm(inp, 12);
         parmCount = smb_GetSMBParm(inp, 9);
         dataCount = smb_GetSMBParm(inp, 11);
-               asp->maxReturnParms = smb_GetSMBParm(inp, 2);
+        asp->maxReturnParms = smb_GetSMBParm(inp, 2);
         asp->maxReturnData = smb_GetSMBParm(inp, 3);
 
-               osi_Log3(smb_logp, "SMB3 received T2 init packet total data %d, cur data %d, max return data %d",
+        osi_Log3(smb_logp, "SMB3 received T2 init packet total data %d, cur data %d, max return data %d",
                  totalData, dataCount, asp->maxReturnData);
     }
     else {
@@ -1949,9 +2008,9 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         asp->curParms > 0 &&
         asp->totalData <= asp->curData &&
         asp->totalParms <= asp->curParms) {
-               /* we've received it all */
+        /* we've received it all */
         lock_ObtainWrite(&smb_globalLock);
-               osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
+        osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
         lock_ReleaseWrite(&smb_globalLock);
 
         /* now dispatch it */
@@ -1966,7 +2025,7 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             code = CM_ERROR_BADOP;
         }
 
-               /* if an error is returned, we're supposed to send an error packet,
+        /* if an error is returned, we're supposed to send an error packet,
          * otherwise the dispatched function already did the data sending.
          * We give dispatched proc the responsibility since it knows how much
          * space to allocate.
@@ -1975,20 +2034,20 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             smb_SendTran2Error(vcp, asp, outp, code);
         }
 
-               /* free the input tran 2 packet */
-               lock_ObtainWrite(&smb_globalLock);
+        /* free the input tran 2 packet */
+        lock_ObtainWrite(&smb_globalLock);
         smb_FreeTran2Packet(asp);
-               lock_ReleaseWrite(&smb_globalLock);
+        lock_ReleaseWrite(&smb_globalLock);
     }
     else if (firstPacket) {
-               /* the first packet in a multi-packet request, we need to send an
+        /* the first packet in a multi-packet request, we need to send an
          * ack to get more data.
          */
         smb_SetSMBDataLength(outp, 0);
         smb_SendPacket(vcp, outp);
     }
 
-       return 0;
+    return 0;
 }
 
 long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
@@ -2006,7 +2065,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     smb_fid_t *fidp;
     int attributes;
     char *lastNamep;
-    time_t dosTime;
+    afs_uint32 dosTime;
     int openFun;
     int trunc;
     int openMode;
@@ -2035,10 +2094,13 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         
     /* compute initial mode bits based on read-only flag in attributes */
     initialModeBits = 0666;
-    if (attributes & 1) initialModeBits &= ~0222;
+    if (attributes & 1) 
+        initialModeBits &= ~0222;
         
     pathp = (char *) (&p->parmsp[14]);
-        
+    if (smb_StoreAnsiFilenames)
+        OemToChar(pathp,pathp);
+    
     outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
 
     spacep = cm_GetSpace();
@@ -2053,26 +2115,26 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 
         /* copy out remainder of the parms */
         parmSlot = 0;
-        outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+        outp->parmsp[parmSlot++] = fidp->fid;
         if (extraInfo) {
-            outp->parmsp[parmSlot] = /* attrs */ 0; parmSlot++;
-            outp->parmsp[parmSlot] = 0; parmSlot++;    /* mod time */
-            outp->parmsp[parmSlot] = 0; parmSlot++;
-            outp->parmsp[parmSlot] = 0; parmSlot++;    /* len */
-            outp->parmsp[parmSlot] = 0x7fff; parmSlot++;
-            outp->parmsp[parmSlot] = openMode; parmSlot++;
-            outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
-            outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+            outp->parmsp[parmSlot++] = 0;       /* attrs */
+            outp->parmsp[parmSlot++] = 0;       /* mod time */
+            outp->parmsp[parmSlot++] = 0; 
+            outp->parmsp[parmSlot++] = 0;       /* len */
+            outp->parmsp[parmSlot++] = 0x7fff;
+            outp->parmsp[parmSlot++] = openMode;
+            outp->parmsp[parmSlot++] = 0;       /* file type 0 ==> normal file or dir */
+            outp->parmsp[parmSlot++] = 0;       /* IPC junk */
         }   
         /* and the final "always present" stuff */
-        outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
+        outp->parmsp[parmSlot++] = 1;           /* openAction found existing file */
         /* next write out the "unique" ID */
-        outp->parmsp[parmSlot] = 0x1234; parmSlot++;
-        outp->parmsp[parmSlot] = 0x5678; parmSlot++;
-        outp->parmsp[parmSlot] = 0; parmSlot++;
+        outp->parmsp[parmSlot++] = 0x1234;
+        outp->parmsp[parmSlot++] = 0x5678;
+        outp->parmsp[parmSlot++] = 0;
         if (returnEALength) {
-            outp->parmsp[parmSlot] = 0; parmSlot++;
-            outp->parmsp[parmSlot] = 0; parmSlot++;
+            outp->parmsp[parmSlot++] = 0;
+            outp->parmsp[parmSlot++] = 0;
         }       
                 
         outp->totalData = 0;
@@ -2107,21 +2169,25 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 
     code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
     if (code == CM_ERROR_TIDIPC) {
-        /* Attempt to use TID allocated for IPC.  The client is
-           probably trying to locate DCE RPC end points, which
-           we don't support. */
+        /* Attempt to use a TID allocated for IPC.  The client
+         * is probably looking for DCE RPC end points which we
+         * don't support OR it could be looking to make a DFS
+         * referral request. 
+         */
         osi_Log0(smb_logp, "Tran2Open received IPC TID");
+#ifndef DFS_SUPPORT
         cm_ReleaseUser(userp);
         smb_FreeTran2Packet(outp);
         return CM_ERROR_NOSUCHPATH;
+#endif
     }
 
     dscp = NULL;
-    code = cm_NameI(cm_rootSCachep, pathp,
+    code = cm_NameI(cm_data.rootSCachep, pathp,
                      CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                      userp, tidPathp, &req, &scp);
     if (code != 0) {
-        code = cm_NameI(cm_rootSCachep, spacep->data,
+        code = cm_NameI(cm_data.rootSCachep, spacep->data,
                          CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                          userp, tidPathp, &req, &dscp);
         cm_FreeSpace(spacep);
@@ -2132,6 +2198,18 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             return code;
         }
         
+#ifdef DFS_SUPPORT
+        if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            smb_FreeTran2Packet(outp);
+            if ( WANTS_DFS_PATHNAMES(p) )
+                return CM_ERROR_PATH_NOT_COVERED;
+            else
+                return CM_ERROR_BADSHARENAME;
+        }
+#endif /* DFS_SUPPORT */
+
         /* otherwise, scp points to the parent directory.  Do a lookup,
          * and truncate the file if we find it, otherwise we create the
          * file.
@@ -2148,18 +2226,31 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             smb_FreeTran2Packet(outp);
             return code;
         }
-    }
-    else {
-        cm_FreeSpace(spacep);
-    }
-        
-    /* if we get here, if code is 0, the file exists and is represented by
-     * scp.  Otherwise, we have to create it.
+    } else {
+#ifdef DFS_SUPPORT
+        if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            smb_FreeTran2Packet(outp);
+            if ( WANTS_DFS_PATHNAMES(p) )
+                return CM_ERROR_PATH_NOT_COVERED;
+            else
+                return CM_ERROR_BADSHARENAME;
+        }
+#endif /* DFS_SUPPORT */
+
+        /* macintosh is expensive to program for it */
+        cm_FreeSpace(spacep);
+    }
+        
+    /* if we get here, if code is 0, the file exists and is represented by
+     * scp.  Otherwise, we have to create it.
      */
     if (code == 0) {
         code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
         if (code) {
-            if (dscp) cm_ReleaseSCache(dscp);
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             smb_FreeTran2Packet(outp);
@@ -2168,7 +2259,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 
         if (excl) {
             /* oops, file shouldn't be there */
-            if (dscp) cm_ReleaseSCache(dscp);
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             smb_FreeTran2Packet(outp);
@@ -2185,9 +2277,10 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         else 
             openAction = 1;    /* found existing file */
     }
-    else if (!(openFun & SMB_ATTR_DIRECTORY)) {
+    else if (!(openFun & 0x10)) {
         /* don't create if not found */
-        if (dscp) cm_ReleaseSCache(dscp);
+        if (dscp) 
+            cm_ReleaseSCache(dscp);
         osi_assert(scp == NULL);
         cm_ReleaseUser(userp);
         smb_FreeTran2Packet(outp);
@@ -2226,11 +2319,13 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     }
         
     /* we don't need this any longer */
-    if (dscp) cm_ReleaseSCache(dscp);
+    if (dscp) 
+        cm_ReleaseSCache(dscp);
 
     if (code) {
         /* something went wrong creating or truncating the file */
-        if (scp) cm_ReleaseSCache(scp);
+        if (scp) 
+            cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
         smb_FreeTran2Packet(outp);
         return code;
@@ -2244,9 +2339,9 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
             if (code == 0) {
                 /* we have a more accurate file to use (the
-                * target of the symbolic link).  Otherwise,
-                * we'll just use the symlink anyway.
-                */
+                 * target of the symbolic link).  Otherwise,
+                 * we'll just use the symlink anyway.
+                 */
                 osi_Log2(smb_logp, "symlink vp %x to vp %x",
                           scp, targetScp);
                 cm_ReleaseSCache(scp);
@@ -2279,30 +2374,28 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 
     /* copy out remainder of the parms */
     parmSlot = 0;
-    outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+    outp->parmsp[parmSlot++] = fidp->fid;
     lock_ObtainMutex(&scp->mx);
     if (extraInfo) {
-        outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
+        outp->parmsp[parmSlot++] = smb_Attributes(scp);
         smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-        outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++;
-        outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++;
-        outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
-        parmSlot++;
-        outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
-        parmSlot++;
-        outp->parmsp[parmSlot] = openMode; parmSlot++;
-        outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
-        outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+        outp->parmsp[parmSlot++] = (unsigned short)(dosTime & 0xffff);
+        outp->parmsp[parmSlot++] = (unsigned short)((dosTime>>16) & 0xffff);
+        outp->parmsp[parmSlot++] = (unsigned short) (scp->length.LowPart & 0xffff);
+        outp->parmsp[parmSlot++] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
+        outp->parmsp[parmSlot++] = openMode;
+        outp->parmsp[parmSlot++] = 0;   /* file type 0 ==> normal file or dir */
+        outp->parmsp[parmSlot++] = 0;   /* IPC junk */
     }   
     /* and the final "always present" stuff */
-    outp->parmsp[parmSlot] = openAction; parmSlot++;
+    outp->parmsp[parmSlot++] = openAction;
     /* next write out the "unique" ID */
-    outp->parmsp[parmSlot] = (unsigned short) (scp->fid.vnode & 0xffff); parmSlot++;
-    outp->parmsp[parmSlot] = (unsigned short) (scp->fid.volume & 0xffff); parmSlot++;
-    outp->parmsp[parmSlot] = 0; parmSlot++;
+    outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.vnode & 0xffff); 
+    outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.volume & 0xffff); 
+    outp->parmsp[parmSlot++] = 0; 
     if (returnEALength) {
-        outp->parmsp[parmSlot] = 0; parmSlot++;
-        outp->parmsp[parmSlot] = 0; parmSlot++;
+        outp->parmsp[parmSlot++] = 0; 
+        outp->parmsp[parmSlot++] = 0; 
     }   
     lock_ReleaseMutex(&scp->mx);
     outp->totalData = 0;               /* total # of data bytes */
@@ -2346,6 +2439,8 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
     case 0x103: responseSize = sizeof(qi.u.FSsizeInfo); break;
     case 0x104: responseSize = sizeof(qi.u.FSdeviceInfo); break;
     case 0x105: responseSize = sizeof(qi.u.FSattributeInfo); break;
+    case 0x200: /* CIFS Unix Info */
+    case 0x301: /* Mac FS Info */
     default: return CM_ERROR_INVAL;
     }
 
@@ -2470,10 +2565,19 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp,
     spacep = cm_GetSpace();
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
                      reqp, &dscp);
     cm_FreeSpace(spacep);
-    if (code) return code;
+    if (code) 
+        return code;
+
+#ifdef DFS_SUPPORT
+    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        return CM_ERROR_PATH_NOT_COVERED;
+    }
+#endif /* DFS_SUPPORT */
 
     if (!lastNamep) lastNamep = pathp;
     else lastNamep++;
@@ -2482,8 +2586,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp,
     rock.shortName = shortName;
     rock.vnode = vnode;
     rock.maskp = lastNamep;
-    code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp,
-                        reqp, NULL);
+    code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp, reqp, NULL);
 
     cm_ReleaseSCache(dscp);
 
@@ -2499,7 +2602,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp,
 long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
 {
     smb_tran2Packet_t *outp;
-    time_t dosTime;
+    afs_uint32 dosTime;
     FILETIME ft;
     unsigned short infoLevel;
     int nbytesRequired;
@@ -2519,13 +2622,20 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     cm_InitReq(&req);
 
     infoLevel = p->parmsp[0];
-    if (infoLevel == 6) nbytesRequired = 0;
-    else if (infoLevel == 1) nbytesRequired = 22;
-    else if (infoLevel == 2) nbytesRequired = 26;
-    else if (infoLevel == 0x101) nbytesRequired = 40;
-    else if (infoLevel == 0x102) nbytesRequired = 24;
-    else if (infoLevel == 0x103) nbytesRequired = 4;
-    else if (infoLevel == 0x108) nbytesRequired = 30;
+    if (infoLevel == SMB_INFO_IS_NAME_VALID) 
+        nbytesRequired = 0;
+    else if (infoLevel == SMB_INFO_STANDARD) 
+        nbytesRequired = 22;
+    else if (infoLevel == SMB_INFO_QUERY_EA_SIZE) 
+        nbytesRequired = 26;
+    else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) 
+        nbytesRequired = 40;
+    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) 
+        nbytesRequired = 24;
+    else if (infoLevel == SMB_QUERY_FILE_EA_INFO) 
+        nbytesRequired = 4;
+    else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO) 
+        nbytesRequired = 30;
     else {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
@@ -2547,7 +2657,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
      * the syntax, so we just OK things now.  In particular, we're *not*
      * being asked to verify anything about the state of any parent dirs.
      */
-    if (infoLevel == 6) {
+    if (infoLevel == SMB_INFO_IS_NAME_VALID) {
         smb_SendTran2Packet(vcp, outp, opx);
         smb_FreeTran2Packet(outp);
         return 0;
@@ -2582,21 +2692,29 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
      * yet been evaluated and for directories that haven't yet been
      * fetched.
      */
-    if (infoLevel == 0x101) {
+    if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         spacep = cm_GetSpace();
         smb_StripLastComponent(spacep->data, &lastComp,
                                 (char *)(&p->parmsp[3]));
+#ifndef SPECIAL_FOLDERS
         /* Make sure that lastComp is not NULL */
         if (lastComp) {
-            if (strcmp(lastComp, "\\desktop.ini") == 0) {
-                code = cm_NameI(cm_rootSCachep, spacep->data,
+            if (stricmp(lastComp, "\\desktop.ini") == 0) {
+                code = cm_NameI(cm_data.rootSCachep, spacep->data,
                                  CM_FLAG_CASEFOLD
                                  | CM_FLAG_DIRSEARCH
                                  | CM_FLAG_FOLLOW,
                                  userp, tidPathp, &req, &dscp);
                 if (code == 0) {
-                    if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
-                         && !dscp->mountRootFidp)
+#ifdef DFS_SUPPORT
+                    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                        if ( WANTS_DFS_PATHNAMES(p) )
+                            code = CM_ERROR_PATH_NOT_COVERED;
+                        else
+                            code = CM_ERROR_BADSHARENAME;
+                    } else
+#endif /* DFS_SUPPORT */
+                    if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
                         code = CM_ERROR_NOSUCHFILE;
                     else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
                         cm_buf_t *bp = buf_Find(dscp, &hzero);
@@ -2616,11 +2734,13 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 }
             }
         }
+#endif /* SPECIAL_FOLDERS */
+
         cm_FreeSpace(spacep);
     }
 
     /* now do namei and stat, and copy out the info */
-    code = cm_NameI(cm_rootSCachep, (char *)(&p->parmsp[3]),
+    code = cm_NameI(cm_data.rootSCachep, (char *)(&p->parmsp[3]),
                      CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
 
     if (code) {
@@ -2630,6 +2750,20 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         return 0;
     }
 
+#ifdef DFS_SUPPORT
+    if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(p) )
+            code = CM_ERROR_PATH_NOT_COVERED;
+        else
+            code = CM_ERROR_BADSHARENAME;
+        smb_SendTran2Error(vcp, p, opx, code);
+        smb_FreeTran2Packet(outp);
+        return 0;
+    }
+#endif /* DFS_SUPPORT */
+
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -2655,7 +2789,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
         goto done;
     }
-    if (infoLevel == 1 || infoLevel == 2) {
+    if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
         smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
         *((u_long *)op) = dosTime; op += 4;    /* creation time */
         *((u_long *)op) = dosTime; op += 4;    /* access time */
@@ -2665,7 +2799,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         attributes = smb_Attributes(scp);
         *((u_short *)op) = attributes; op += 2;        /* attributes */
     }
-    else if (infoLevel == 0x101) {
+    else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         *((FILETIME *)op) = ft; op += 8;       /* creation time */
         *((FILETIME *)op) = ft; op += 8;       /* last access time */
@@ -2675,7 +2809,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         *((u_long *)op) = extAttributes; op += 4; /* extended attribs */
         *((u_long *)op) = 0; op += 4;  /* don't know what this is */
     }
-    else if (infoLevel == 0x102) {
+    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
         *((u_long *)op) = scp->linkCount; op += 4;
@@ -2684,12 +2818,12 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         *op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
         *op++ = 0;
     }
-    else if (infoLevel == 0x103) {
+    else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
         memset(op, 0, 4); op += 4;     /* EA size */
     }
 
     /* now, if we are being asked about extended attrs, return a 0 size */
-    if (infoLevel == 2) {
+    if (infoLevel == SMB_INFO_QUERY_EA_SIZE) {
         *((u_long *)op) = 0; op += 4;
     }
 
@@ -2740,10 +2874,14 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     }
 
     infoLevel = p->parmsp[1];
-    if (infoLevel == 0x101) nbytesRequired = 40;
-    else if (infoLevel == 0x102) nbytesRequired = 24;
-    else if (infoLevel == 0x103) nbytesRequired = 4;
-    else if (infoLevel == 0x104) nbytesRequired = 6;
+    if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) 
+        nbytesRequired = 40;
+    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) 
+        nbytesRequired = 24;
+    else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+        nbytesRequired = 4;
+    else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) 
+        nbytesRequired = 6;
     else {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
@@ -2779,7 +2917,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
      * Marshall the output data.
      */
     op = outp->datap;
-    if (infoLevel == 0x101) {
+    if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         *((FILETIME *)op) = ft; op += 8;       /* creation time */
         *((FILETIME *)op) = ft; op += 8;       /* last access time */
@@ -2789,7 +2927,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         *((u_long *)op) = attributes; op += 4;
         *((u_long *)op) = 0; op += 4;
     }
-    else if (infoLevel == 0x102) {
+    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
         *((u_long *)op) = scp->linkCount; op += 4;
@@ -2798,10 +2936,10 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         *op++ = 0;
         *op++ = 0;
     }
-    else if (infoLevel == 0x103) {
+    else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
         *((u_long *)op) = 0; op += 4;
     }
-    else if (infoLevel == 0x104) {
+    else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
         unsigned long len;
         char *name;
 
@@ -2860,12 +2998,12 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         return 0;
     }
 
-    if (infoLevel == 0x102 && !(fidp->flags & SMB_FID_OPENDELETE)) {
+    if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO && !(fidp->flags & SMB_FID_OPENDELETE)) {
         smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
         smb_ReleaseFID(fidp);
         return 0;
     }
-    if ((infoLevel == 0x103 || infoLevel == 0x104)
+    if ((infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO)
          && !(fidp->flags & SMB_FID_OPENWRITE)) {
         smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
         smb_ReleaseFID(fidp);
@@ -2888,7 +3026,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
     scp = fidp->scp;
 
-    if (infoLevel == 0x101) {
+    if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         FILETIME lastMod;
         unsigned int attribute;
         cm_attr_t attr;
@@ -2916,8 +3054,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && 
              lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
             attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
-            smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
-                                             &lastMod);
+            smb_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
             fidp->flags |= SMB_FID_MTIMESETDONE;
         }
                
@@ -2944,7 +3081,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         else
             code = 0;
     }               
-    else if (infoLevel == 0x103 || infoLevel == 0x104) {
+    else if (infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO) {
         LARGE_INTEGER size = *((LARGE_INTEGER *)(p->datap));
         cm_attr_t attr;
 
@@ -2953,7 +3090,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         attr.length.HighPart = size.HighPart;
         code = cm_SetAttr(scp, &attr, userp, &req);
     }       
-    else if (infoLevel == 0x102) {
+    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
         if (*((char *)(p->datap))) {
             code = cm_CheckNTDelete(fidp->NTopen_dscp, scp, userp,
                                      &req);
@@ -3020,16 +3157,131 @@ smb_ReceiveTran2SessionSetup(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
     return CM_ERROR_BADOP;
 }
 
+struct smb_v2_referral {
+    USHORT ServerType;
+    USHORT ReferralFlags;
+    ULONG  Proximity;
+    ULONG  TimeToLive;
+    USHORT DfsPathOffset;
+    USHORT DfsAlternativePathOffset;
+    USHORT NetworkAddressOffset;
+};
+
 long 
-smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
+smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
-    osi_Log0(smb_logp,"ReceiveTran2GetDFSReferral - NOT_SUPPORTED");
+    /* This is a UNICODE only request (bit15 of Flags2) */
+    /* The TID must be IPC$ */
+
+    /* The documentation for the Flags response field is contradictory */
+
+    /* Use Version 1 Referral Element Format */
+    /* ServerType = 0; indicates the next server should be queried for the file */
+    /* ReferralFlags = 0x01; PathConsumed characters should be stripped */
+    /* Node = UnicodeString of UNC path of the next share name */
+#ifdef DFS_SUPPORT
+    long code = 0;
+    int maxReferralLevel = 0;
+    char requestFileName[1024] = "";
+    smb_tran2Packet_t *outp = 0;
+    cm_user_t *userp = 0;
+    cm_req_t req;
+    CPINFO CodePageInfo;
+    int i, nbnLen, reqLen;
+    int idx;
+
+    cm_InitReq(&req);
+
+    maxReferralLevel = p->parmsp[0];
+
+    GetCPInfo(CP_ACP, &CodePageInfo);
+    WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) &p->parmsp[1], -1, 
+                        requestFileName, 1024, NULL, NULL);
+
+    osi_Log2(smb_logp,"ReceiveTran2GetDfsReferral [%d][%s]", 
+             maxReferralLevel, osi_LogSaveString(smb_logp, requestFileName));
+
+    nbnLen = strlen(cm_NetbiosName);
+    reqLen = strlen(requestFileName);
+
+    if (reqLen == nbnLen + 5 &&
+        requestFileName[0] == '\\' &&
+        !_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) &&
+        requestFileName[nbnLen+1] == '\\' &&
+        !_strnicmp("all",&requestFileName[nbnLen+2],3)) 
+    {
+        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 */
+#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];
+#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];
+#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 (userp)
+        cm_ReleaseUser(userp);
+    if (code == 0) 
+        smb_SendTran2Packet(vcp, outp, op);
+    else 
+        smb_SendTran2Error(vcp, p, op, code);
+    if (outp)
+        smb_FreeTran2Packet(outp);
+    return 0;
+#else /* DFS_SUPPORT */
+    osi_Log0(smb_logp,"ReceiveTran2GetDfsReferral - NOT_SUPPORTED"); 
     return CM_ERROR_BADOP;
+#endif /* DFS_SUPPORT */
 }
 
 long 
 smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
+    /* This is a UNICODE only request (bit15 of Flags2) */
+
+    /* There is nothing we can do about this operation.  The client is going to
+     * tell us that there is a Version 1 Referral Element for which there is a DFS Error.
+     * Unfortunately, there is really nothing we can do about it other then log it 
+     * somewhere.  Even then I don't think there is anything for us to do.
+     * So let's return an error value.
+     */
+
     osi_Log0(smb_logp,"ReceiveTran2ReportDFSInconsistency - NOT_SUPPORTED");
     return CM_ERROR_BADOP;
 }
@@ -3043,7 +3295,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
     cm_scache_t *scp;
     cm_scache_t *targetScp;                    /* target if scp is a symlink */
     char *dptr;
-    time_t dosTime;
+    afs_uint32 dosTime;
     FILETIME ft;
     int shortTemp;
     unsigned short attr;
@@ -3058,9 +3310,9 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
         lock_ObtainMutex(&scp->mx);
         code = cm_SyncOp(scp, NULL, userp, reqp, 0,
                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-               if (code) { 
-                       lock_ReleaseMutex(&scp->mx);
-                       cm_ReleaseSCache(scp);
+        if (code) { 
+            lock_ReleaseMutex(&scp->mx);
+            cm_ReleaseSCache(scp);
 
             dptr = patchp->dptr;
 
@@ -3071,69 +3323,69 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
                 ft.dwHighDateTime = 0x19DB200;
                 ft.dwLowDateTime = 0x5BB78980;
 
-                           /* copy to Creation Time */
-                           *((FILETIME *)dptr) = ft;
-                           dptr += 8;
+                /* copy to Creation Time */
+                *((FILETIME *)dptr) = ft;
+                dptr += 8;
 
-                           /* copy to Last Access Time */
-                           *((FILETIME *)dptr) = ft;
-                           dptr += 8;
+                /* copy to Last Access Time */
+                *((FILETIME *)dptr) = ft;
+                dptr += 8;
 
-                           /* copy to Last Write Time */
-                           *((FILETIME *)dptr) = ft;
-                           dptr += 8;
+                /* copy to Last Write Time */
+                *((FILETIME *)dptr) = ft;
+                dptr += 8;
 
-                           /* copy to Change Time */
-                           *((FILETIME *)dptr) = ft;
+                /* copy to Change Time */
+                *((FILETIME *)dptr) = ft;
                 dptr += 24;
 
                 /* merge in hidden attribute */
                 if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
-                               *((u_long *)dptr) = SMB_ATTR_HIDDEN;
+                    *((u_long *)dptr) = SMB_ATTR_HIDDEN;
                 }
-                           dptr += 4;
+                dptr += 4;
             } else {
                 /* 1969-12-31 23:59:58 +00*/
                 dosTime = 0xEBBFBF7D;
 
-                           /* and copy out date */
-                           shortTemp = (dosTime>>16) & 0xffff;
-                           *((u_short *)dptr) = shortTemp;
-                           dptr += 2;
+                /* and copy out date */
+                shortTemp = (dosTime>>16) & 0xffff;
+                *((u_short *)dptr) = shortTemp;
+                dptr += 2;
 
-                           /* copy out creation time */
-                           shortTemp = dosTime & 0xffff;
-                           *((u_short *)dptr) = shortTemp;
-                           dptr += 2;
+                /* copy out creation time */
+                shortTemp = dosTime & 0xffff;
+                *((u_short *)dptr) = shortTemp;
+                dptr += 2;
 
-                           /* and copy out date */
-                           shortTemp = (dosTime>>16) & 0xffff;
-                           *((u_short *)dptr) = shortTemp;
-                           dptr += 2;
+                /* and copy out date */
+                shortTemp = (dosTime>>16) & 0xffff;
+                *((u_short *)dptr) = shortTemp;
+                dptr += 2;
                        
-                           /* copy out access time */
-                           shortTemp = dosTime & 0xffff;
-                           *((u_short *)dptr) = shortTemp;
-                           dptr += 2;
-
-                           /* and copy out date */
-                           shortTemp = (dosTime>>16) & 0xffff;
-                           *((u_short *)dptr) = shortTemp;
-                           dptr += 2;
+                /* copy out access time */
+                shortTemp = dosTime & 0xffff;
+                *((u_short *)dptr) = shortTemp;
+                dptr += 2;
+
+                /* and copy out date */
+                shortTemp = (dosTime>>16) & 0xffff;
+                *((u_short *)dptr) = shortTemp;
+                dptr += 2;
                        
-                           /* copy out mod time */
-                           shortTemp = dosTime & 0xffff;
-                           *((u_short *)dptr) = shortTemp;
-                           dptr += 10;
+                /* copy out mod time */
+                shortTemp = dosTime & 0xffff;
+                *((u_short *)dptr) = shortTemp;
+                dptr += 10;
 
                 /* merge in hidden (dot file) attribute */
                 if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
                     attr = SMB_ATTR_HIDDEN;
-                               *dptr++ = attr & 0xff;
-                               *dptr++ = (attr >> 8) & 0xff;
-                }
+                    *dptr++ = attr & 0xff;
+                    *dptr++ = (attr >> 8) & 0xff;
+                }       
             }
-                       continue;
+            continue;
         }
                 
         /* now watch for a symlink */
@@ -3154,102 +3406,115 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
             lock_ObtainMutex(&scp->mx);
         }
 
-               dptr = patchp->dptr;
+        dptr = patchp->dptr;
 
-               if (infoLevel >= 0x101) {
-                       /* get filetime */
-                       smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        if (infoLevel >= 0x101) {
+            /* get filetime */
+            smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
 
-                       /* copy to Creation Time */
-                       *((FILETIME *)dptr) = ft;
-                       dptr += 8;
+            /* copy to Creation Time */
+            *((FILETIME *)dptr) = ft;
+            dptr += 8;
 
-                       /* copy to Last Access Time */
-                       *((FILETIME *)dptr) = ft;
-                       dptr += 8;
+            /* copy to Last Access Time */
+            *((FILETIME *)dptr) = ft;
+            dptr += 8;
 
-                       /* copy to Last Write Time */
-                       *((FILETIME *)dptr) = ft;
-                       dptr += 8;
+            /* copy to Last Write Time */
+            *((FILETIME *)dptr) = ft;
+            dptr += 8;
 
-                       /* copy to Change Time */
-                       *((FILETIME *)dptr) = ft;
-                       dptr += 8;
+            /* copy to Change Time */
+            *((FILETIME *)dptr) = ft;
+            dptr += 8;
 
-                       /* Use length for both file length and alloc length */
-                       *((LARGE_INTEGER *)dptr) = scp->length;
-                       dptr += 8;
-                       *((LARGE_INTEGER *)dptr) = scp->length;
-                       dptr += 8;
+            /* Use length for both file length and alloc length */
+            *((LARGE_INTEGER *)dptr) = scp->length;
+            dptr += 8;
+            *((LARGE_INTEGER *)dptr) = scp->length;
+            dptr += 8;
 
-                       /* Copy attributes */
-                       lattr = smb_ExtAttributes(scp);
+            /* Copy attributes */
+            lattr = smb_ExtAttributes(scp);
+            if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+                if (lattr == SMB_ATTR_NORMAL)
+                    lattr = SMB_ATTR_DIRECTORY;
+                else
+                    lattr |= SMB_ATTR_DIRECTORY;
+            }
             /* merge in hidden (dot file) attribute */
-                       if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
-                               lattr |= SMB_ATTR_HIDDEN;
-                       *((u_long *)dptr) = lattr;
-                       dptr += 4;
-               }
-               else {
-                       /* get dos time */
-                       smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-
-                       /* and copy out date */
-                       shortTemp = (dosTime>>16) & 0xffff;
-                       *((u_short *)dptr) = shortTemp;
-                       dptr += 2;
-
-                       /* copy out creation time */
-                       shortTemp = dosTime & 0xffff;
-                       *((u_short *)dptr) = shortTemp;
-                       dptr += 2;
-
-                       /* and copy out date */
-                       shortTemp = (dosTime>>16) & 0xffff;
-                       *((u_short *)dptr) = shortTemp;
-                       dptr += 2;
-                       
-                       /* copy out access time */
-                       shortTemp = dosTime & 0xffff;
-                       *((u_short *)dptr) = shortTemp;
-                       dptr += 2;
-
-                       /* and copy out date */
-                       shortTemp = (dosTime>>16) & 0xffff;
-                       *((u_short *)dptr) = shortTemp;
-                       dptr += 2;
-                       
-                       /* copy out mod time */
-                       shortTemp = dosTime & 0xffff;
-                       *((u_short *)dptr) = shortTemp;
-                       dptr += 2;
-
-                       /* copy out file length and alloc length,
-                        * using the same for both
-                        */
-                       *((u_long *)dptr) = scp->length.LowPart;
-                       dptr += 4;
-                       *((u_long *)dptr) = scp->length.LowPart;
-                       dptr += 4;
-
-                       /* finally copy out attributes as short */
-                       attr = smb_Attributes(scp);
+            if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
+                if (lattr == SMB_ATTR_NORMAL)
+                    lattr = SMB_ATTR_HIDDEN;
+                else
+                    lattr |= SMB_ATTR_HIDDEN;
+            }
+            *((u_long *)dptr) = lattr;
+            dptr += 4;
+        } else {
+            /* get dos time */
+            smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+
+            /* and copy out date */
+            shortTemp = (dosTime>>16) & 0xffff;
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* copy out creation time */
+            shortTemp = dosTime & 0xffff;
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* and copy out date */
+            shortTemp = (dosTime>>16) & 0xffff;
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* copy out access time */
+            shortTemp = dosTime & 0xffff;
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* and copy out date */
+            shortTemp = (dosTime>>16) & 0xffff;
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* copy out mod time */
+            shortTemp = dosTime & 0xffff;
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* copy out file length and alloc length,
+             * using the same for both
+             */
+            *((u_long *)dptr) = scp->length.LowPart;
+            dptr += 4;
+            *((u_long *)dptr) = scp->length.LowPart;
+            dptr += 4;
+
+            /* finally copy out attributes as short */
+            attr = smb_Attributes(scp);
             /* merge in hidden (dot file) attribute */
-            if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
-                attr |= SMB_ATTR_HIDDEN;
-                       *dptr++ = attr & 0xff;
-                       *dptr++ = (attr >> 8) & 0xff;
-               }
+            if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
+                if (lattr == SMB_ATTR_NORMAL)
+                    lattr = SMB_ATTR_HIDDEN;
+                else
+                    lattr |= SMB_ATTR_HIDDEN;
+            }
+            *dptr++ = attr & 0xff;
+            *dptr++ = (attr >> 8) & 0xff;
+        }
 
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
-       }
+    }
         
     /* now free the patches */
-    for(patchp = *dirPatchespp; patchp; patchp = npatchp) {
-               npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
+    for (patchp = *dirPatchespp; patchp; patchp = npatchp) {
+        npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
         free(patchp);
-       }
+    }
         
     /* and mark the list as empty */
     *dirPatchespp = NULL;
@@ -3284,7 +3549,7 @@ VOID initUpperCaseTable(VOID)
 // BOOL : TRUE/FALSE (match/mistmatch)
 
 BOOL 
-szWildCardMatchFileName(PSZ pattern, PSZ name) 
+szWildCardMatchFileName(PSZ pattern, PSZ name, int casefold) 
 {
     PSZ pename;         // points to the last 'name' character
     PSZ p;
@@ -3301,18 +3566,20 @@ szWildCardMatchFileName(PSZ pattern, PSZ name)
             if (*pattern == '\0')
                 return TRUE;
             for (p = pename; p >= name; --p) {
-                if ((mapCaseTable[*p] == mapCaseTable[*pattern]) &&
-                     szWildCardMatchFileName(pattern + 1, p + 1))
+                if ((casefold && (mapCaseTable[*p] == mapCaseTable[*pattern]) ||
+                     !casefold && (*p == *pattern)) &&
+                     szWildCardMatchFileName(pattern + 1, p + 1, casefold))
                     return TRUE;
             } /* endfor */
             return FALSE;
         default:
-            if (mapCaseTable[*name] != mapCaseTable[*pattern]) 
+            if ((casefold && mapCaseTable[*name] != mapCaseTable[*pattern]) ||
+                (!casefold && *name != *pattern))
                 return FALSE;
             ++pattern, ++name;
             break;
-      } /* endswitch */
-   } /* endwhile */ 
+        } /* endswitch */
+    } /* endwhile */ 
 
     if (*pattern == '\0' || *pattern == '*' && *(pattern+1) == '\0')
         return TRUE;
@@ -3326,12 +3593,14 @@ szWildCardMatchFileName(PSZ pattern, PSZ name)
 int smb_V3MatchMask(char *namep, char *maskp, int flags) 
 {
     char * newmask;
-    int    i, j, star, qmark, retval;
+    int    i, j, star, qmark, casefold, retval;
 
     /* make sure we only match 8.3 names, if requested */
     if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep)) 
         return 0;
     
+    casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
+
     /* optimize the pattern:
      * if there is a mixture of '?' and '*',
      * for example  the sequence "*?*?*?*"
@@ -3368,7 +3637,7 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
     }
     newmask[j++] = '\0';
 
-    retval = szWildCardMatchFileName(newmask, namep) ? 1:0;
+    retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
 
     free(newmask);
     return retval;
@@ -3380,146 +3649,146 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
  */
 int smb_V3MatchMask(char *namep, char *maskp, int flags)
 {
-       unsigned char tcp1, tcp2;       /* Pattern characters */
+    unsigned char tcp1, tcp2;  /* Pattern characters */
     unsigned char tcn1;                /* Name characters */
-       int sawDot = 0, sawStar = 0, req8dot3 = 0;
-       char *starNamep, *starMaskp;
-       static char nullCharp[] = {0};
+    int sawDot = 0, sawStar = 0, req8dot3 = 0;
+    char *starNamep, *starMaskp;
+    static char nullCharp[] = {0};
     int casefold = flags & CM_FLAG_CASEFOLD;
 
-       /* make sure we only match 8.3 names, if requested */
+    /* make sure we only match 8.3 names, if requested */
     req8dot3 = (flags & CM_FLAG_8DOT3);
-       if (req8dot3 && !cm_Is8Dot3(namep)) 
+    if (req8dot3 && !cm_Is8Dot3(namep)) 
         return 0;
 
-       /* loop */
-       while (1) {
-               /* Next pattern character */
-               tcp1 = *maskp++;
-
-               /* Next name character */
-               tcn1 = *namep;
-
-               if (tcp1 == 0) {
-                       /* 0 - end of pattern */
-                       if (tcn1 == 0)
-                               return 1;
-                       else
-                               return 0;
-               }
-               else if (tcp1 == '.' || tcp1 == '"') {
-                       if (sawDot) {
-                               if (tcn1 == '.') {
-                                       namep++;
-                                       continue;
-                               } else
-                                       return 0;
-                       }
-                       else {
-                               /*
-                                * first dot in pattern;
-                                * must match dot or end of name
-                                */
-                               sawDot = 1;
-                               if (tcn1 == 0)
-                                       continue;
-                               else if (tcn1 == '.') {
-                                       sawStar = 0;
-                                       namep++;
-                                       continue;
-                               }
-                               else
-                                       return 0;
-                       }
-               }
-               else if (tcp1 == '?') {
-                       if (tcn1 == 0 || tcn1 == '.')
-                               return 0;
-                       namep++;
-                       continue;
-               }
-               else if (tcp1 == '>') {
-                       if (tcn1 != 0 && tcn1 != '.')
-                               namep++;
-                       continue;
-               }
-               else if (tcp1 == '*' || tcp1 == '<') {
-                       tcp2 = *maskp++;
-                       if (tcp2 == 0)
-                               return 1;
-                       else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
-                               while (req8dot3 && tcn1 != '.' && tcn1 != 0)
-                                       tcn1 = *++namep;
-                               if (tcn1 == 0) {
-                                       if (sawDot)
-                                               return 0;
-                                       else
-                                               continue;
-                               }
-                               else {
-                                       namep++;
-                                       continue;
-                               }
-                       }
-                       else {
-                               /*
-                                * pattern character after '*' is not null or
-                                * period.  If it is '?' or '>', we are not
-                                * going to understand it.  If it is '*' or
-                                * '<', we are going to skip over it.  None of
-                                * these are likely, I hope.
-                                */
-                               /* skip over '*' and '<' */
-                               while (tcp2 == '*' || tcp2 == '<')
-                                       tcp2 = *maskp++;
-
-                               /* skip over characters that don't match tcp2 */
-                               while (req8dot3 && tcn1 != '.' && tcn1 != 0 && 
-                       ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) || 
-                         (!casefold && tcn1 != tcp2)))
-                                       tcn1 = *++namep;
-
-                               /* No match */
-                               if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
-                                       return 0;
-
-                               /* Remember where we are */
-                               sawStar = 1;
-                               starMaskp = maskp;
-                               starNamep = namep;
-
-                               namep++;
-                               continue;
-                       }
-               }
-               else {
-                       /* tcp1 is not a wildcard */
+    /* loop */
+    while (1) {
+        /* Next pattern character */
+        tcp1 = *maskp++;
+
+        /* Next name character */
+        tcn1 = *namep;
+
+        if (tcp1 == 0) {
+            /* 0 - end of pattern */
+            if (tcn1 == 0)
+                return 1;
+            else
+                return 0;
+        }
+        else if (tcp1 == '.' || tcp1 == '"') {
+            if (sawDot) {
+                if (tcn1 == '.') {
+                    namep++;
+                    continue;
+                } else
+                    return 0;
+            }
+            else {
+                /*
+                 * first dot in pattern;
+                 * must match dot or end of name
+                 */
+                sawDot = 1;
+                if (tcn1 == 0)
+                    continue;
+                else if (tcn1 == '.') {
+                    sawStar = 0;
+                    namep++;
+                    continue;
+                }
+                else
+                    return 0;
+            }
+        }
+        else if (tcp1 == '?') {
+            if (tcn1 == 0 || tcn1 == '.')
+                return 0;
+            namep++;
+            continue;
+        }
+        else if (tcp1 == '>') {
+            if (tcn1 != 0 && tcn1 != '.')
+                namep++;
+            continue;
+        }
+        else if (tcp1 == '*' || tcp1 == '<') {
+            tcp2 = *maskp++;
+            if (tcp2 == 0)
+                return 1;
+            else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
+                while (req8dot3 && tcn1 != '.' && tcn1 != 0)
+                    tcn1 = *++namep;
+                if (tcn1 == 0) {
+                    if (sawDot)
+                        return 0;
+                    else
+                        continue;
+                }
+                else {
+                    namep++;
+                    continue;
+                }
+            }
+            else {
+                /*
+                 * pattern character after '*' is not null or
+                 * period.  If it is '?' or '>', we are not
+                 * going to understand it.  If it is '*' or
+                 * '<', we are going to skip over it.  None of
+                 * these are likely, I hope.
+                 */
+                /* skip over '*' and '<' */
+                while (tcp2 == '*' || tcp2 == '<')
+                    tcp2 = *maskp++;
+
+                /* skip over characters that don't match tcp2 */
+                while (req8dot3 && tcn1 != '.' && tcn1 != 0 && 
+                        ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) || 
+                          (!casefold && tcn1 != tcp2)))
+                    tcn1 = *++namep;
+
+                /* No match */
+                if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
+                    return 0;
+
+                /* Remember where we are */
+                sawStar = 1;
+                starMaskp = maskp;
+                starNamep = namep;
+
+                namep++;
+                continue;
+            }
+        }
+        else {
+            /* tcp1 is not a wildcard */
             if ((casefold && cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) || 
-                (!casefold && tcn1 == tcp1)) {
-                               /* they match */
-                               namep++;
-                               continue;
-                       }
-                       /* if trying to match a star pattern, go back */
-                       if (sawStar) {
-                               maskp = starMaskp - 2;
-                               namep = starNamep + 1;
-                               sawStar = 0;
-                               continue;
-                       }
-                       /* that's all */
-                       return 0;
-               }
-       }
+                 (!casefold && tcn1 == tcp1)) {
+                /* they match */
+                namep++;
+                continue;
+            }
+            /* if trying to match a star pattern, go back */
+            if (sawStar) {
+                maskp = starMaskp - 2;
+                namep = starNamep + 1;
+                sawStar = 0;
+                continue;
+            }
+            /* that's all */
+            return 0;
+        }
+    }
 }
 #endif /* USE_OLD_MATCHING */
 
 long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
 {
-       int attribute;
+    int attribute;
     long nextCookie;
     char *tp;
-    long code = 0;
+    long code = 0, code2 = 0;
     char *pathp;
     cm_dirEntry_t *dep;
     int maxCount;
@@ -3538,14 +3807,14 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     cm_scache_t *scp;
     long entryInDir;
     long entryInBuffer;
-       cm_pageHeader_t *pageHeaderp;
+    cm_pageHeader_t *pageHeaderp;
     cm_user_t *userp = NULL;
     int slotInPage;
     int returnedNames;
     long nextEntryCookie;
     int numDirChunks;          /* # of 32 byte dir chunks in this entry */
     char *op;                  /* output data ptr */
-       char *origOp;                   /* original value of op */
+    char *origOp;                      /* original value of op */
     cm_space_t *spacep;                /* for pathname buffer */
     long maxReturnData;                /* max # of return data */
     long maxReturnParms;               /* max # of return parms */
@@ -3556,22 +3825,21 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     int searchFlags;
     int eos;
     smb_tran2Packet_t *outp;   /* response packet */
-       char *tidPathp;
-       int align;
-       char shortName[13];             /* 8.3 name if needed */
-       int NeedShortName;
+    char *tidPathp;
+    int align;
+    char shortName[13];                /* 8.3 name if needed */
+    int NeedShortName;
     int foundInexact;
-       char *shortNameEnd;
+    char *shortNameEnd;
     int fileType;
     cm_fid_t fid;
-
     cm_req_t req;
 
-       cm_InitReq(&req);
+    cm_InitReq(&req);
 
-       eos = 0;
-       if (p->opcode == 1) {
-               /* find first; obtain basic parameters from request */
+    eos = 0;
+    if (p->opcode == 1) {
+        /* find first; obtain basic parameters from request */
         attribute = p->parmsp[0];
         maxCount = p->parmsp[1];
         infoLevel = p->parmsp[3];
@@ -3579,45 +3847,53 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         dsp = smb_NewDirSearch(1);
         dsp->attribute = attribute;
         pathp = ((char *) p->parmsp) + 12;     /* points to path */
+        if (smb_StoreAnsiFilenames)
+            OemToChar(pathp,pathp);
         nextCookie = 0;
         maskp = strrchr(pathp, '\\');
-        if (maskp == NULL) maskp = pathp;
-               else maskp++;   /* skip over backslash */
+        if (maskp == NULL) 
+            maskp = pathp;
+        else 
+            maskp++;   /* skip over backslash */
         strcpy(dsp->mask, maskp);      /* and save mask */
-               /* track if this is likely to match a lot of entries */
+        /* track if this is likely to match a lot of entries */
         starPattern = smb_V3IsStarMask(maskp);
-        }
+    }
     else {
-               osi_assert(p->opcode == 2);
+        osi_assert(p->opcode == 2);
         /* find next; obtain basic parameters from request or open dir file */
         dsp = smb_FindDirSearch(p->parmsp[0]);
-        if (!dsp) return CM_ERROR_BADFD;
-        attribute = dsp->attribute;
         maxCount = p->parmsp[1];
         infoLevel = p->parmsp[2];
+        nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
         searchFlags = p->parmsp[5];
+        if (!dsp) {
+            osi_Log2(smb_logp, "T2 search dir bad search ID: id %d nextCookie 0x%x",
+                     p->parmsp[0], nextCookie);
+            return CM_ERROR_BADFD;
+        }
+        attribute = dsp->attribute;
         pathp = NULL;
-        nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
         maskp = dsp->mask;
-               starPattern = 1;        /* assume, since required a Find Next */
+        starPattern = 1;       /* assume, since required a Find Next */
     }
 
-       osi_Log4(smb_logp,
+    osi_Log4(smb_logp,
               "T2 search dir attr 0x%x, info level %d, max count %d, flags 0x%x",
               attribute, infoLevel, maxCount, searchFlags);
 
-       osi_Log2(smb_logp, "...T2 search op %d, nextCookie 0x%x",
-              p->opcode, nextCookie);
+    osi_Log3(smb_logp, "...T2 search op %d, id %d, nextCookie 0x%x",
+              p->opcode, dsp->cookie, nextCookie);
 
-       if (infoLevel >= 0x101)
-               searchFlags &= ~4;      /* no resume keys */
+    if (infoLevel >= 0x101)
+        searchFlags &= ~4;     /* no resume keys */
 
     dirListPatchesp = NULL;
 
-       maxReturnData = p->maxReturnData;
+    maxReturnData = p->maxReturnData;
     if (p->opcode == 1)        /* find first */
         maxReturnParms = 10;   /* bytes */
-       else    
+    else    
         maxReturnParms = 8;    /* bytes */
 
 #ifndef CM_CONFIG_MULTITRAN2RESPONSES
@@ -3625,11 +3901,11 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         maxReturnData = 6000;
 #endif /* CM_CONFIG_MULTITRAN2RESPONSES */
 
-       outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
+    outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
                                       maxReturnData);
 
-    osi_Log1(smb_logp, "T2 receive search dir %s",
-             osi_LogSaveString(smb_logp, pathp));
+    osi_Log2(smb_logp, "T2 receive search dir count %d [%s]",
+             maxCount, osi_LogSaveString(smb_logp, pathp));
         
     /* bail out if request looks bad */
     if (p->opcode == 1 && !pathp) {
@@ -3638,83 +3914,95 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         return CM_ERROR_BADSMB;
     }
         
-       osi_Log2(smb_logp, "T2 dir search cookie 0x%x, connection %d",
-             nextCookie, dsp->cookie);
+    osi_Log3(smb_logp, "T2 search dir id %d, nextCookie 0x%x, attr 0x%x",
+             dsp->cookie, nextCookie, attribute);
 
-       userp = smb_GetTran2User(vcp, p);
+    userp = smb_GetTran2User(vcp, p);
     if (!userp) {
-       osi_Log1(smb_logp, "T2 dir search unable to resolve user [%d]", p->uid);
+       osi_Log1(smb_logp, "T2 search dir unable to resolve user [%d]", p->uid);
        smb_ReleaseDirSearch(dsp);
        smb_FreeTran2Packet(outp);
        return CM_ERROR_BADSMB;
     }
 
-       /* try to get the vnode for the path name next */
-       lock_ObtainMutex(&dsp->mx);
-       if (dsp->scp) {
-               scp = dsp->scp;
+    /* try to get the vnode for the path name next */
+    lock_ObtainMutex(&dsp->mx);
+    if (dsp->scp) {
+        scp = dsp->scp;
         cm_HoldSCache(scp);
         code = 0;
-    }
-    else {
-               spacep = cm_GetSpace();
+    } else {
+        spacep = cm_GetSpace();
         smb_StripLastComponent(spacep->data, NULL, pathp);
-        lock_ReleaseMutex(&dsp->mx);
-
-               code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
-        if(code) {
-                   cm_ReleaseUser(userp);
+        code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
+        if (code) {
+            cm_ReleaseUser(userp);
             smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES);
             smb_FreeTran2Packet(outp);
-                   smb_DeleteDirSearch(dsp);
-                   smb_ReleaseDirSearch(dsp);
+            lock_ReleaseMutex(&dsp->mx);
+            smb_DeleteDirSearch(dsp);
+            smb_ReleaseDirSearch(dsp);
             return 0;
         }
-        code = cm_NameI(cm_rootSCachep, spacep->data,
+        code = cm_NameI(cm_data.rootSCachep, spacep->data,
                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
         cm_FreeSpace(spacep);
 
-        lock_ObtainMutex(&dsp->mx);
-               if (code == 0) {
-            if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
-                       dsp->scp = scp;
-                       /* we need one hold for the entry we just stored into,
+        if (code == 0) {
+#ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
+            if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+                cm_ReleaseSCache(scp);
+                cm_ReleaseUser(userp);
+                if ( WANTS_DFS_PATHNAMES(p) )
+                    code = CM_ERROR_PATH_NOT_COVERED;
+                else
+                    code = CM_ERROR_BADSHARENAME;
+                smb_SendTran2Error(vcp, p, opx, code);
+                smb_FreeTran2Packet(outp);
+                lock_ReleaseMutex(&dsp->mx);
+                smb_DeleteDirSearch(dsp);
+                smb_ReleaseDirSearch(dsp);
+                return 0;
+            }
+#endif /* DFS_SUPPORT */
+            dsp->scp = scp;
+            /* we need one hold for the entry we just stored into,
              * and one for our own processing.  When we're done
-                        * with this function, we'll drop the one for our own
-                        * processing.  We held it once from the namei call,
-                        * and so we do another hold now.
+             * with this function, we'll drop the one for our own
+             * processing.  We held it once from the namei call,
+             * and so we do another hold now.
              */
             cm_HoldSCache(scp);
-                       lock_ObtainMutex(&scp->mx);
-                       if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0
-                           && LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
+            lock_ObtainMutex(&scp->mx);
+            if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0 &&
+                 LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
                 scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
-                               dsp->flags |= SMB_DIRSEARCH_BULKST;
-                       }
-                       lock_ReleaseMutex(&scp->mx);
-        }
+                dsp->flags |= SMB_DIRSEARCH_BULKST;
+            }
+            lock_ReleaseMutex(&scp->mx);
+        } 
     }
-       lock_ReleaseMutex(&dsp->mx);
+    lock_ReleaseMutex(&dsp->mx);
     if (code) {
-               cm_ReleaseUser(userp);
+        cm_ReleaseUser(userp);
         smb_FreeTran2Packet(outp);
-               smb_DeleteDirSearch(dsp);
-               smb_ReleaseDirSearch(dsp);
+        smb_DeleteDirSearch(dsp);
+        smb_ReleaseDirSearch(dsp);
         return code;
-        }
+    }
 
     /* get the directory size */
-       lock_ObtainMutex(&scp->mx);
+    lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-       if (code) {
-               lock_ReleaseMutex(&scp->mx);
+    if (code) {
+        lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
         smb_FreeTran2Packet(outp);
-               smb_DeleteDirSearch(dsp);
-               smb_ReleaseDirSearch(dsp);
+        smb_DeleteDirSearch(dsp);
+        smb_ReleaseDirSearch(dsp);
         return code;
     }
 
@@ -3724,31 +4012,31 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     bufferOffset.LowPart = bufferOffset.HighPart = 0;
     curOffset.HighPart = 0;
     curOffset.LowPart = nextCookie;
-       origOp = outp->datap;
+    origOp = outp->datap;
 
     foundInexact = 0;
     code = 0;
     returnedNames = 0;
     bytesInBuffer = 0;
     while (1) {
-               op = origOp;
-               if (searchFlags & 4)
-                       /* skip over resume key */
-                       op += 4;
+        op = origOp;
+        if (searchFlags & 4)
+            /* skip over resume key */
+            op += 4;
 
-               /* make sure that curOffset.LowPart doesn't point to the first
+        /* make sure that curOffset.LowPart doesn't point to the first
          * 32 bytes in the 2nd through last dir page, and that it doesn't
          * point at the first 13 32-byte chunks in the first dir page,
          * since those are dir and page headers, and don't contain useful
          * information.
          */
-               temp = curOffset.LowPart & (2048-1);
+        temp = curOffset.LowPart & (2048-1);
         if (curOffset.HighPart == 0 && curOffset.LowPart < 2048) {
-                       /* we're in the first page */
+            /* we're in the first page */
             if (temp < 13*32) temp = 13*32;
-               }
-               else {
-                       /* we're in a later dir page */
+        }
+        else {
+            /* we're in a later dir page */
             if (temp < 32) temp = 32;
         }
                
@@ -3761,6 +4049,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
         /* check if we've passed the dir's EOF */
         if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+            osi_Log0(smb_logp, "T2 search dir passed eof");
             eos = 1;
             break;
         }
@@ -3771,6 +4060,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
          * the dir entry, since we'll need to check its size.
          */
         if (returnedNames >= maxCount) {
+            osi_Log2(smb_logp, "T2 search dir returnedNames %d >= maxCount %d",
+                      returnedNames, maxCount);
             break;
         }
 
@@ -3779,128 +4070,150 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
          * the offset of the buffer we have.  If not, get the buffer.
          */
         thyper.HighPart = curOffset.HighPart;
-        thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+        thyper.LowPart = curOffset.LowPart & ~(cm_data.buf_blockSize-1);
         if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
-                       /* wrong buffer */
+            /* wrong buffer */
             if (bufferp) {
                 buf_Release(bufferp);
                 bufferp = NULL;
-                       }       
-                       lock_ReleaseMutex(&scp->mx);
-                       lock_ObtainRead(&scp->bufCreateLock);
+            }       
+            lock_ReleaseMutex(&scp->mx);
+            lock_ObtainRead(&scp->bufCreateLock);
             code = buf_Get(scp, &thyper, &bufferp);
-                       lock_ReleaseRead(&scp->bufCreateLock);
+            lock_ReleaseRead(&scp->bufCreateLock);
+            lock_ObtainMutex(&dsp->mx);
 
-                       /* now, if we're doing a star match, do bulk fetching
-                        * of all of the status info for files in the dir.
+            /* now, if we're doing a star match, do bulk fetching
+             * of all of the status info for files in the dir.
              */
             if (starPattern) {
-                               smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
-                                          infoLevel, userp,
-                                          &req);
-                               if ((dsp->flags & SMB_DIRSEARCH_BULKST)
-                    && LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
-                                       /* Don't bulk stat if risking timeout */
-                                       int now = GetCurrentTime();
-                                       if (now - req.startTime > 5000) {
-                                               scp->bulkStatProgress = thyper;
-                                               scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
-                                               dsp->flags &= ~SMB_DIRSEARCH_BULKST;
-                                       } else
+                smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
+                                           infoLevel, userp,
+                                           &req);
+                lock_ObtainMutex(&scp->mx);
+                if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
+                    LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
+                    /* Don't bulk stat if risking timeout */
+                    int now = GetCurrentTime();
+                    if (now - req.startTime > 5000) {
+                        scp->bulkStatProgress = thyper;
+                        scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
+                        dsp->flags &= ~SMB_DIRSEARCH_BULKST;
+                    } else
                         cm_TryBulkStat(scp, &thyper, userp, &req);
-                               }
-                       }
+                }
+            } else {
+                lock_ObtainMutex(&scp->mx);
+            }
+            lock_ReleaseMutex(&dsp->mx);
+            if (code) {
+                osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
+                break;
+            }
 
-            lock_ObtainMutex(&scp->mx);
-            if (code) break;
             bufferOffset = thyper;
 
             /* now get the data in the cache */
             while (1) {
-                               code = cm_SyncOp(scp, bufferp, userp, &req,
+                code = cm_SyncOp(scp, bufferp, userp, &req,
                                  PRSFS_LOOKUP,
                                  CM_SCACHESYNC_NEEDCALLBACK
                                  | CM_SCACHESYNC_READ);
-                               if (code) break;
+                if (code) {
+                    osi_Log2(smb_logp, "T2 search dir cm_SyncOp scp %x failed %d", scp, code);
+                    break;
+                }
                                 
-                if (cm_HaveBuffer(scp, bufferp, 0)) break;
+                if (cm_HaveBuffer(scp, bufferp, 0)) {
+                    osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+                    break;
+                }
 
                 /* otherwise, load the buffer and try again */
                 code = cm_GetBuffer(scp, bufferp, NULL, userp,
                                     &req);
-                if (code) break;
+                if (code) {
+                    osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d", 
+                              scp, bufferp, code);
+                    break;
+                }
             }
             if (code) {
-                               buf_Release(bufferp);
+                buf_Release(bufferp);
                 bufferp = NULL;
                 break;
-                       }
+            }
         }      /* if (wrong buffer) ... */
                 
         /* now we have the buffer containing the entry we're interested
          * in; copy it out if it represents a non-deleted entry.
          */
-               entryInDir = curOffset.LowPart & (2048-1);
-        entryInBuffer = curOffset.LowPart & (buf_bufferSize - 1);
+        entryInDir = curOffset.LowPart & (2048-1);
+        entryInBuffer = curOffset.LowPart & (cm_data.buf_blockSize - 1);
 
-               /* page header will help tell us which entries are free.  Page
-                * header can change more often than once per buffer, since
-                * AFS 3 dir page size may be less than (but not more than)
-                * a buffer package buffer.
+        /* page header will help tell us which entries are free.  Page
+         * header can change more often than once per buffer, since
+         * AFS 3 dir page size may be less than (but not more than)
+         * a buffer package buffer.
          */
-               /* only look intra-buffer */
-               temp = curOffset.LowPart & (buf_bufferSize - 1);
+        /* only look intra-buffer */
+        temp = curOffset.LowPart & (cm_data.buf_blockSize - 1);
         temp &= ~(2048 - 1);   /* turn off intra-page bits */
-               pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
+        pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
 
-               /* now determine which entry we're looking at in the page.
-                * If it is free (there's a free bitmap at the start of the
-                * dir), we should skip these 32 bytes.
+        /* now determine which entry we're looking at in the page.
+         * If it is free (there's a free bitmap at the start of the
+         * dir), we should skip these 32 bytes.
          */
         slotInPage = (entryInDir & 0x7e0) >> 5;
-        if (!(pageHeaderp->freeBitmap[slotInPage>>3]
-               & (1 << (slotInPage & 0x7)))) {
-                       /* this entry is free */
+        if (!(pageHeaderp->freeBitmap[slotInPage>>3] &
+            (1 << (slotInPage & 0x7)))) {
+            /* this entry is free */
             numDirChunks = 1;  /* only skip this guy */
             goto nextEntry;
         }
 
-               tp = bufferp->datap + entryInBuffer;
+        tp = bufferp->datap + entryInBuffer;
         dep = (cm_dirEntry_t *) tp;    /* now points to AFS3 dir entry */
 
         /* while we're here, compute the next entry's location, too,
-                * since we'll need it when writing out the cookie into the dir
-                * listing stream.
+         * since we'll need it when writing out the cookie into the dir
+         * listing stream.
          *
          * XXXX Probably should do more sanity checking.
          */
-               numDirChunks = cm_NameEntries(dep->name, &onbytes);
+        numDirChunks = cm_NameEntries(dep->name, &onbytes);
                
         /* compute offset of cookie representing next entry */
         nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
 
-               /* Need 8.3 name? */
-               NeedShortName = 0;
-               if (infoLevel == 0x104
-                   && dep->fid.vnode != 0
-                   && !cm_Is8Dot3(dep->name)) {
-                       cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
-                       NeedShortName = 1;
-               }
+        /* Need 8.3 name? */
+        NeedShortName = 0;
+        if (infoLevel == SMB_QUERY_FILE_NAME_INFO
+             && dep->fid.vnode != 0
+             && !cm_Is8Dot3(dep->name)) {
+            cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
+            NeedShortName = 1;
+        }
+
+        osi_Log3(smb_logp, "T2 search dir vn %u name %s (%s)",
+                  dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+                  NeedShortName ? osi_LogSaveString(smb_logp, shortName) : "");
 
         /* When matching, we are using doing a case fold if we have a wildcard mask.
          * If we get a non-wildcard match, it's a lookup for a specific file. 
          */
         if (dep->fid.vnode != 0 && 
-            (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0))
-              || (NeedShortName
-                   && smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))) {
+            (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
+             (NeedShortName &&
+              smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))) {
 
             /* Eliminate entries that don't match requested attributes */
             if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && 
-                 smb_IsDotFile(dep->name))
+                 smb_IsDotFile(dep->name)) {
+                osi_Log0(smb_logp, "T2 search dir skipping hidden");
                 goto nextEntry; /* no hidden files */
-                    
+            }
             if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
             {
                 /* We have already done the cm_TryBulkStat above */
@@ -3912,136 +4225,144 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 /*osi_Log2(smb_logp, "smb_ReceiveTran2SearchDir: file %s "
                  "has filetype %d", dep->name,
                  fileType);*/
-                if (fileType == CM_SCACHETYPE_DIRECTORY)
+                if (fileType == CM_SCACHETYPE_DIRECTORY ||
+                    fileType == CM_SCACHETYPE_DFSLINK ||
+                    fileType == CM_SCACHETYPE_INVALID)
+                    osi_Log0(smb_logp, "T2 search dir skipping directory or bad link");
                     goto nextEntry;
             }
 
-                       /* finally check if this name will fit */
+            /* finally check if this name will fit */
 
-                       /* standard dir entry stuff */
-                       if (infoLevel < 0x101)
-                               ohbytes = 23;   /* pre-NT */
-                       else if (infoLevel == 0x103)
-                               ohbytes = 12;   /* NT names only */
-                       else
-                               ohbytes = 64;   /* NT */
+            /* standard dir entry stuff */
+            if (infoLevel < 0x101)
+                ohbytes = 23;  /* pre-NT */
+            else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+                ohbytes = 12;  /* NT names only */
+            else
+                ohbytes = 64;  /* NT */
 
-                       if (infoLevel == 0x104)
-                               ohbytes += 26;  /* Short name & length */
+            if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+                ohbytes += 26; /* Short name & length */
 
             if (searchFlags & 4) {
                 ohbytes += 4;  /* if resume key required */
-                       }   
+            }   
 
             if (infoLevel != 1
                  && infoLevel != 0x101
                  && infoLevel != 0x103)
-                               ohbytes += 4;   /* EASIZE */
+                ohbytes += 4;  /* EASIZE */
 
-                       /* add header to name & term. null */
-                       orbytes = onbytes + ohbytes + 1;
+            /* add header to name & term. null */
+            orbytes = onbytes + ohbytes + 1;
 
-                       /* now, we round up the record to a 4 byte alignment,
-                        * and we make sure that we have enough room here for
-                        * even the aligned version (so we don't have to worry
-                        * about an * overflow when we pad things out below).
-                        * That's the reason for the alignment arithmetic below.
+            /* now, we round up the record to a 4 byte alignment,
+             * and we make sure that we have enough room here for
+             * even the aligned version (so we don't have to worry
+             * about an * overflow when we pad things out below).
+             * That's the reason for the alignment arithmetic below.
              */
-                       if (infoLevel >= 0x101)
-                               align = (4 - (orbytes & 3)) & 3;
-                       else
-                               align = 0;
-                       if (orbytes + bytesInBuffer + align > maxReturnData)
+            if (infoLevel >= 0x101)
+                align = (4 - (orbytes & 3)) & 3;
+            else
+                align = 0;
+            if (orbytes + bytesInBuffer + align > maxReturnData) {
+                osi_Log1(smb_logp, "T2 dir search exceed max return data %d",
+                          maxReturnData);
                 break;
+            }
 
-                       /* this is one of the entries to use: it is not deleted
-                        * and it matches the star pattern we're looking for.
-                        * Put out the name, preceded by its length.
+            /* this is one of the entries to use: it is not deleted
+             * and it matches the star pattern we're looking for.
+             * Put out the name, preceded by its length.
              */
-                       /* First zero everything else */
-                       memset(origOp, 0, ohbytes);
+            /* First zero everything else */
+            memset(origOp, 0, ohbytes);
 
-                       if (infoLevel <= 0x101)
+            if (infoLevel <= 0x101)
                 *(origOp + ohbytes - 1) = (unsigned char) onbytes;
-                       else if (infoLevel == 0x103)
-                               *((u_long *)(op + 8)) = onbytes;
-                       else
-                               *((u_long *)(op + 60)) = onbytes;
+            else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+                *((u_long *)(op + 8)) = onbytes;
+            else
+                *((u_long *)(op + 60)) = onbytes;
             strcpy(origOp+ohbytes, dep->name);
-
-                       /* Short name if requested and needed */
-            if (infoLevel == 0x104) {
-                               if (NeedShortName) {
-                                       strcpy(op + 70, shortName);
-                                       *(op + 68) = shortNameEnd - shortName;
-                               }
-                       }
+            if (smb_StoreAnsiFilenames)
+                CharToOem(origOp+ohbytes, origOp+ohbytes);
+
+            /* Short name if requested and needed */
+            if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
+                if (NeedShortName) {
+                    strcpy(op + 70, shortName);
+                    if (smb_StoreAnsiFilenames)
+                        CharToOem(op + 70, op + 70);
+                    *(op + 68) = shortNameEnd - shortName;
+                }
+            }
 
             /* now, adjust the # of entries copied */
             returnedNames++;
 
-                       /* NextEntryOffset and FileIndex */
-                       if (infoLevel >= 101) {
-                               int entryOffset = orbytes + align;
-                               *((u_long *)op) = entryOffset;
-                               *((u_long *)(op+4)) = nextEntryCookie;
-                       }
+            /* NextEntryOffset and FileIndex */
+            if (infoLevel >= 101) {
+                int entryOffset = orbytes + align;
+                *((u_long *)op) = entryOffset;
+                *((u_long *)(op+4)) = nextEntryCookie;
+            }
 
             /* now we emit the attribute.  This is tricky, since
              * we need to really stat the file to find out what
-                        * type of entry we've got.  Right now, we're copying
-                        * out data from * a buffer, while holding the scp
-                        * locked, so it isn't really convenient to stat
-                        * something now.  We'll put in a place holder
+             * type of entry we've got.  Right now, we're copying
+             * out data from a buffer, while holding the scp
+             * locked, so it isn't really convenient to stat
+             * something now.  We'll put in a place holder
              * now, and make a second pass before returning this
-                        * to get the real attributes.  So, we just skip the
-                        * data for now, and adjust it later.  We allocate a
-                        * patch record to make it easy to find this point
-                        * later.  The replay will happen at a time when it is
-                        * safe to unlock the directory.
+             * to get the real attributes.  So, we just skip the
+             * data for now, and adjust it later.  We allocate a
+             * patch record to make it easy to find this point
+             * later.  The replay will happen at a time when it is
+             * safe to unlock the directory.
              */
-                       if (infoLevel != 0x103) {
-                               curPatchp = malloc(sizeof(*curPatchp));
+            if (infoLevel != 0x103) {
+                curPatchp = malloc(sizeof(*curPatchp));
                 osi_QAdd((osi_queue_t **) &dirListPatchesp,
                           &curPatchp->q);
-                               curPatchp->dptr = op;
-                               if (infoLevel >= 0x101)
-                                       curPatchp->dptr += 8;
+                curPatchp->dptr = op;
+                if (infoLevel >= 0x101)
+                    curPatchp->dptr += 8;
 
                 if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
                     curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
-                }
-                else
+                }       
+                else    
                     curPatchp->flags = 0;
 
-                               curPatchp->fid.cell = scp->fid.cell;
-                               curPatchp->fid.volume = scp->fid.volume;
-                               curPatchp->fid.vnode = ntohl(dep->fid.vnode);
-                               curPatchp->fid.unique = ntohl(dep->fid.unique);
+                curPatchp->fid.cell = scp->fid.cell;
+                curPatchp->fid.volume = scp->fid.volume;
+                curPatchp->fid.vnode = ntohl(dep->fid.vnode);
+                curPatchp->fid.unique = ntohl(dep->fid.unique);
 
                 /* temp */
                 curPatchp->dep = dep;
-                       }   
+            }   
 
-                       if (searchFlags & 4)
-                               /* put out resume key */
-                               *((u_long *)origOp) = nextEntryCookie;
+            if (searchFlags & 4)
+                /* put out resume key */
+                *((u_long *)origOp) = nextEntryCookie;
 
-                       /* Adjust byte ptr and count */
-                       origOp += orbytes;      /* skip entire record */
+            /* Adjust byte ptr and count */
+            origOp += orbytes; /* skip entire record */
             bytesInBuffer += orbytes;
 
-                       /* and pad the record out */
+            /* and pad the record out */
             while (--align >= 0) {
-                               *origOp++ = 0;
+                *origOp++ = 0;
                 bytesInBuffer++;
             }
-
-               }       /* if we're including this name */
-        else if (!NeedShortName &&
-                 !starPattern &&
+        }      /* if we're including this name */
+        else if (!starPattern &&
                  !foundInexact &&
-                                                       dep->fid.vnode != 0 &&
+                 dep->fid.vnode != 0 &&
                  smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
             /* We were looking for exact matches, but here's an inexact one*/
             foundInexact = 1;
@@ -4049,10 +4370,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 
       nextEntry:
         /* and adjust curOffset to be where the new cookie is */
-               thyper.HighPart = 0;
+        thyper.HighPart = 0;
         thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
         curOffset = LargeIntegerAdd(thyper, curOffset);
-    }          /* while copying data for dir listing */
+    } /* while copying data for dir listing */
 
     /* If we didn't get a star pattern, we did an exact match during the first pass. 
      * If there were no exact matches found, we fail over to inexact matches by
@@ -4065,20 +4386,22 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         goto startsearch;
     }
 
-       /* release the mutex */
-       lock_ReleaseMutex(&scp->mx);
-    if (bufferp) buf_Release(bufferp);
+    /* release the mutex */
+    lock_ReleaseMutex(&scp->mx);
+    if (bufferp) 
+        buf_Release(bufferp);
 
-       /* 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.
+    /* 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_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
+    code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
                               &req);
         
     /* now put out the final parameters */
-       if (returnedNames == 0) eos = 1;
+    if (returnedNames == 0) 
+        eos = 1;
     if (p->opcode == 1) {
-               /* find first */
+        /* find first */
         outp->parmsp[0] = (unsigned short) dsp->cookie;
         outp->parmsp[1] = returnedNames;
         outp->parmsp[2] = eos;
@@ -4100,30 +4423,30 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         outp->totalParms = 8;  /* in bytes */
     }   
 
-       /* return # of bytes in the buffer */
+    /* return # of bytes in the buffer */
     outp->totalData = bytesInBuffer;
 
-       osi_Log2(smb_logp, "T2 search dir done, %d names, code %d",
-              returnedNames, code);
+    /* Return error code if unsuccessful on first request */
+    if (code == 0 && p->opcode == 1 && returnedNames == 0)
+        code = CM_ERROR_NOSUCHFILE;
 
-       /* Return error code if unsuccessful on first request */
-       if (code == 0 && p->opcode == 1 && returnedNames == 0)
-               code = CM_ERROR_NOSUCHFILE;
+    osi_Log4(smb_logp, "T2 search dir done, opcode %d, id %d, %d names, code %d",
+             p->opcode, dsp->cookie, returnedNames, code);
 
-       /* if we're supposed to close the search after this request, or if
+    /* if we're supposed to close the search after this request, or if
      * we're supposed to close the search if we're done, and we're done,
      * or if something went wrong, close the search.
      */
     /* ((searchFlags & 1) || ((searchFlags & 2) && eos) */
-       if ((searchFlags & 1) || (returnedNames == 0) || 
+    if ((searchFlags & 1) || (returnedNames == 0) || 
          ((searchFlags & 2) && eos) || code != 0)
-           smb_DeleteDirSearch(dsp);
-       if (code)
+        smb_DeleteDirSearch(dsp);
+    if (code)
         smb_SendTran2Error(vcp, p, opx, code);
-       else {
+    else
         smb_SendTran2Packet(vcp, outp, opx);
-       }
-       smb_FreeTran2Packet(outp);
+
+    smb_FreeTran2Packet(outp);
     smb_ReleaseDirSearch(dsp);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
@@ -4142,29 +4465,29 @@ long smb_ReceiveV3FindClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     dsp = smb_FindDirSearch(dirHandle);
         
     if (!dsp)
-               return CM_ERROR_BADFD;
+        return CM_ERROR_BADFD;
        
     /* otherwise, we have an FD to destroy */
     smb_DeleteDirSearch(dsp);
     smb_ReleaseDirSearch(dsp);
         
-       /* and return results */
-       smb_SetSMBDataLength(outp, 0);
+    /* and return results */
+    smb_SetSMBDataLength(outp, 0);
 
     return 0;
 }
 
 long smb_ReceiveV3FindNotifyClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBDataLength(outp, 0);
     return 0;
 }
 
 long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       char *pathp;
+    char *pathp;
     long code = 0;
-       cm_space_t *spacep;
+    cm_space_t *spacep;
     int excl;
     cm_user_t *userp;
     cm_scache_t *dscp;         /* dir we're dealing with */
@@ -4174,41 +4497,43 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_fid_t *fidp;
     int attributes;
     char *lastNamep;
-    time_t dosTime;
+    afs_uint32 dosTime;
     int openFun;
     int trunc;
     int openMode;
     int extraInfo;
     int openAction;
     int parmSlot;                      /* which parm we're dealing with */
-       char *tidPathp;
-       cm_req_t req;
+    char *tidPathp;
+    cm_req_t req;
 
-       cm_InitReq(&req);
+    cm_InitReq(&req);
 
     scp = NULL;
         
-       extraInfo = (smb_GetSMBParm(inp, 2) & 1);       /* return extra info */
-       openFun = smb_GetSMBParm(inp, 8);       /* open function */
+    extraInfo = (smb_GetSMBParm(inp, 2) & 1); /* return extra info */
+    openFun = smb_GetSMBParm(inp, 8); /* open function */
     excl = ((openFun & 3) == 0);
-    trunc = ((openFun & 3) == 2);              /* truncate it */
-       openMode = (smb_GetSMBParm(inp, 3) & 0x7);
-    openAction = 0;                    /* tracks what we did */
+    trunc = ((openFun & 3) == 2); /* truncate it */
+    openMode = (smb_GetSMBParm(inp, 3) & 0x7);
+    openAction = 0;             /* tracks what we did */
 
     attributes = smb_GetSMBParm(inp, 5);
     dosTime = smb_GetSMBParm(inp, 6) | (smb_GetSMBParm(inp, 7) << 16);
 
-       /* compute initial mode bits based on read-only flag in attributes */
+                                /* compute initial mode bits based on read-only flag in attributes */
     initialModeBits = 0666;
     if (attributes & 1) initialModeBits &= ~0222;
         
     pathp = smb_GetSMBData(inp, NULL);
+    if (smb_StoreAnsiFilenames)
+        OemToChar(pathp,pathp);
 
-       spacep = inp->spacep;
+    spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
-       if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
-               /* special case magic file name for receiving IOCTL requests
+    if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+        /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
          */
 #ifdef NOTSERVICE
@@ -4218,13 +4543,13 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
         smb_SetupIoctlFid(fidp, spacep);
 
-               /* set inp->fid so that later read calls in same msg can find fid */
+        /* set inp->fid so that later read calls in same msg can find fid */
         inp->fid = fidp->fid;
         
         /* copy out remainder of the parms */
-               parmSlot = 2;
-               smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
-               if (extraInfo) {
+        parmSlot = 2;
+        smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+        if (extraInfo) {
             smb_SetSMBParm(outp, parmSlot, /* attrs */ 0); parmSlot++;
             smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* mod time */
             smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
@@ -4233,16 +4558,16 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             smb_SetSMBParm(outp, parmSlot, openMode); parmSlot++;
             smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* file type 0 ==> normal file or dir */
             smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* IPC junk */
-               }   
-               /* and the final "always present" stuff */
+        }   
+        /* and the final "always present" stuff */
         smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
-               /* next write out the "unique" ID */
-               smb_SetSMBParm(outp, parmSlot, 0x1234); parmSlot++;
-               smb_SetSMBParm(outp, parmSlot, 0x5678); parmSlot++;
+        /* next write out the "unique" ID */
+        smb_SetSMBParm(outp, parmSlot, 0x1234); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, 0x5678); parmSlot++;
         smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
         smb_SetSMBDataLength(outp, 0);
 
-               /* and clean up fid reference */
+        /* and clean up fid reference */
         smb_ReleaseFID(fidp);
         return 0;
     }
@@ -4258,46 +4583,70 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #endif
     userp = smb_GetUser(vcp, inp);
 
-       dscp = NULL;
-       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
-    if(code) {
+    dscp = NULL;
+    code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if (code) {
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-       code = cm_NameI(cm_rootSCachep, pathp,
+    code = cm_NameI(cm_data.rootSCachep, pathp,
                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                     userp, tidPathp, &req, &scp);
-       if (code != 0) {
-               code = cm_NameI(cm_rootSCachep, spacep->data,
+
+#ifdef DFS_SUPPORT
+    if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
+    if (code != 0) {
+        code = cm_NameI(cm_data.rootSCachep, spacep->data,
                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &dscp);
-
         if (code) {
             cm_ReleaseUser(userp);
             return code;
         }
-        
+
+#ifdef DFS_SUPPORT
+        if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            if ( WANTS_DFS_PATHNAMES(inp) )
+                return CM_ERROR_PATH_NOT_COVERED;
+            else
+                return CM_ERROR_BADSHARENAME;
+        }
+#endif /* DFS_SUPPORT */
+
         /* otherwise, scp points to the parent directory.  Do a lookup,
          * and truncate the file if we find it, otherwise we create the
          * file.
          */
-        if (!lastNamep) lastNamep = pathp;
-        else lastNamep++;
+        if (!lastNamep) 
+            lastNamep = pathp;
+        else 
+            lastNamep++;
         code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
                           &req, &scp);
         if (code && code != CM_ERROR_NOSUCHFILE) {
-                       cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             return code;
         }
-       }
+    }
         
     /* if we get here, if code is 0, the file exists and is represented by
      * scp.  Otherwise, we have to create it.  The dir may be represented
      * by dscp, or we may have found the file directly.  If code is non-zero,
      * scp is NULL.
      */
-       if (code == 0) {
+    if (code == 0) {
         code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
         if (code) {
             if (dscp) cm_ReleaseSCache(dscp);
@@ -4306,105 +4655,109 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             return code;
         }
 
-               if (excl) {
-                       /* oops, file shouldn't be there */
-            if (dscp) cm_ReleaseSCache(dscp);
-            cm_ReleaseSCache(scp);
-            cm_ReleaseUser(userp);
+        if (excl) {
+            /* oops, file shouldn't be there */
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
             return CM_ERROR_EXISTS;
         }
 
-               if (trunc) {
-                       setAttr.mask = CM_ATTRMASK_LENGTH;
+        if (trunc) {
+            setAttr.mask = CM_ATTRMASK_LENGTH;
             setAttr.length.LowPart = 0;
             setAttr.length.HighPart = 0;
-                       code = cm_SetAttr(scp, &setAttr, userp, &req);
+            code = cm_SetAttr(scp, &setAttr, userp, &req);
             openAction = 3;    /* truncated existing file */
-               }
+        }
         else openAction = 1;   /* found existing file */
     }
-       else if (!(openFun & 0x10)) {
-               /* don't create if not found */
+    else if (!(openFun & SMB_ATTR_DIRECTORY)) {
+        /* don't create if not found */
         if (dscp) cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHFILE;
     }
     else {
-               osi_assert(dscp != NULL);
-               osi_Log1(smb_logp, "smb_ReceiveV3OpenX creating file %s",
+        osi_assert(dscp != NULL);
+        osi_Log1(smb_logp, "smb_ReceiveV3OpenX creating file %s",
                  osi_LogSaveString(smb_logp, lastNamep));
-               openAction = 2; /* created file */
-               setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
-               smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
+        openAction = 2;        /* created file */
+        setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+        smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                          &req);
-               if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                       smb_NotifyChange(FILE_ACTION_ADDED,
+        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+            smb_NotifyChange(FILE_ACTION_ADDED,
                              FILE_NOTIFY_CHANGE_FILE_NAME,
                              dscp, lastNamep, NULL, TRUE);
         if (!excl && code == CM_ERROR_EXISTS) {
-                       /* not an exclusive create, and someone else tried
-                        * creating it already, then we open it anyway.  We
-                        * don't bother retrying after this, since if this next
-                        * fails, that means that the file was deleted after we
-                        * started this call.
+            /* not an exclusive create, and someone else tried
+             * creating it already, then we open it anyway.  We
+             * don't bother retrying after this, since if this next
+             * fails, that means that the file was deleted after we
+             * started this call.
              */
             code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
                              userp, &req, &scp);
             if (code == 0) {
                 if (trunc) {
-                                       setAttr.mask = CM_ATTRMASK_LENGTH;
+                    setAttr.mask = CM_ATTRMASK_LENGTH;
                     setAttr.length.LowPart = 0;
                     setAttr.length.HighPart = 0;
                     code = cm_SetAttr(scp, &setAttr, userp, &req);
                 }   
-                       }       /* lookup succeeded */
+            }  /* lookup succeeded */
         }
     }
         
-       /* we don't need this any longer */
-       if (dscp) cm_ReleaseSCache(dscp);
+    /* we don't need this any longer */
+    if (dscp) 
+        cm_ReleaseSCache(dscp);
 
     if (code) {
-               /* something went wrong creating or truncating the file */
-        if (scp) cm_ReleaseSCache(scp);
+        /* something went wrong creating or truncating the file */
+        if (scp) 
+            cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
         return code;
     }
         
-       /* make sure we're about to open a file */
-       if (scp->fileType != CM_SCACHETYPE_FILE) {
-            cm_ReleaseSCache(scp);
-            cm_ReleaseUser(userp);
-            return CM_ERROR_ISDIR;
-       }
+    /* make sure we're about to open a file */
+    if (scp->fileType != CM_SCACHETYPE_FILE) {
+        cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        return CM_ERROR_ISDIR;
+    }
 
     /* now all we have to do is open the file itself */
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
        
-       /* save a pointer to the vnode */
+    /* save a pointer to the vnode */
     fidp->scp = scp;
         
-       /* compute open mode */
-    if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+    /* compute open mode */
+    if (openMode != 1) 
+        fidp->flags |= SMB_FID_OPENREAD;
     if (openMode == 1 || openMode == 2)
         fidp->flags |= SMB_FID_OPENWRITE;
 
-       smb_ReleaseFID(fidp);
+    smb_ReleaseFID(fidp);
         
-       cm_Open(scp, 0, userp);
+    cm_Open(scp, 0, userp);
 
-       /* set inp->fid so that later read calls in same msg can find fid */
+    /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fidp->fid;
         
     /* copy out remainder of the parms */
-       parmSlot = 2;
-       smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
-       lock_ObtainMutex(&scp->mx);
-       if (extraInfo) {
+    parmSlot = 2;
+    smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+    lock_ObtainMutex(&scp->mx);
+    if (extraInfo) {
         smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
-               smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
+        smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
         smb_SetSMBParm(outp, parmSlot, dosTime & 0xffff); parmSlot++;
         smb_SetSMBParm(outp, parmSlot, (dosTime>>16) & 0xffff); parmSlot++;
         smb_SetSMBParm(outp, parmSlot, scp->length.LowPart & 0xffff); parmSlot++;
@@ -4412,171 +4765,307 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         smb_SetSMBParm(outp, parmSlot, openMode); parmSlot++;
         smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* file type 0 ==> normal file or dir */
         smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* IPC junk */
-       }
-       /* and the final "always present" stuff */
+    }
+    /* and the final "always present" stuff */
     smb_SetSMBParm(outp, parmSlot, openAction); parmSlot++;
-       /* next write out the "unique" ID */
-       smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
-       smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
+    /* next write out the "unique" ID */
+    smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
+    smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
     smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
-       lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseMutex(&scp->mx);
     smb_SetSMBDataLength(outp, 0);
 
-       osi_Log1(smb_logp, "SMB OpenX opening fid %d", fidp->fid);
+    osi_Log1(smb_logp, "SMB OpenX opening fid %d", fidp->fid);
 
     cm_ReleaseUser(userp);
     /* leave scp held since we put it in fidp->scp */
     return 0;
-}   
+}       
+
+static void smb_GetLockParams(unsigned char LockType, 
+                              char ** buf, 
+                              unsigned int * ppid, 
+                              LARGE_INTEGER * pOffset, 
+                              LARGE_INTEGER * pLength)
+{
+    if (LockType & LOCKING_ANDX_LARGE_FILES) {
+        /* Large Files */
+        *ppid = *((USHORT *) *buf);
+        pOffset->HighPart = *((LONG *)(*buf + 4));
+        pOffset->LowPart = *((DWORD *)(*buf + 8));
+        pLength->HighPart = *((LONG *)(*buf + 12));
+        pLength->LowPart = *((DWORD *)(*buf + 16));
+        *buf += 20;
+    }
+    else {
+        /* Not Large Files */
+        *ppid = *((USHORT *) *buf);
+        pOffset->HighPart = 0;
+        pOffset->LowPart = *((DWORD *)(*buf + 2));
+        pLength->HighPart = 0;
+        pLength->LowPart = *((DWORD *)(*buf + 6));
+        *buf += 10;
+    }
+}
 
 long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       cm_req_t req;
-       cm_user_t *userp;
-       unsigned short fid;
-       smb_fid_t *fidp;
-       cm_scache_t *scp;
-       unsigned char LockType;
-       unsigned short NumberOfUnlocks, NumberOfLocks;
-       unsigned long Timeout;
-       char *op;
-       LARGE_INTEGER LOffset, LLength;
-       smb_waitingLock_t *waitingLock;
-       void *lockp;
-       long code = 0;
-       int i;
-
-       cm_InitReq(&req);
-
-       fid = smb_GetSMBParm(inp, 2);
-       fid = smb_ChainFID(fid, inp);
-
-       fidp = smb_FindFID(vcp, fid, 0);
-       if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
-               return CM_ERROR_BADFD;
-       }
-       /* set inp->fid so that later read calls in same msg can find fid */
+    cm_req_t req;
+    cm_user_t *userp;
+    unsigned short fid;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
+    unsigned char LockType;
+    unsigned short NumberOfUnlocks, NumberOfLocks;
+    long Timeout;
+    char *op;
+    char *op_locks;
+    LARGE_INTEGER LOffset, LLength;
+    smb_waitingLockRequest_t *wlRequest = NULL;
+    cm_file_lock_t *lockp;
+    long code = 0;
+    int i;
+    cm_key_t key;
+    unsigned int pid;
+
+    cm_InitReq(&req);
+
+    fid = smb_GetSMBParm(inp, 2);
+    fid = smb_ChainFID(fid, inp);
+
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+        osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
+        return CM_ERROR_BADFD;
+    }
+    /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fid;
 
-       userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
 
-       scp = fidp->scp;
+    scp = fidp->scp;
 
-       lock_ObtainMutex(&scp->mx);
-       code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                        CM_SCACHESYNC_NEEDCALLBACK
+    lock_ObtainMutex(&scp->mx);
+    code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                      CM_SCACHESYNC_NEEDCALLBACK
                         | CM_SCACHESYNC_GETSTATUS
                         | CM_SCACHESYNC_LOCK);
-       if (code) goto doneSync;
-
-       LockType = smb_GetSMBParm(inp, 3) & 0xff;
-       Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
-       NumberOfUnlocks = smb_GetSMBParm(inp, 6);
-       NumberOfLocks = smb_GetSMBParm(inp, 7);
-
-       op = smb_GetSMBData(inp, NULL);
-
-       for (i=0; i<NumberOfUnlocks; i++) {
-               if (LockType & 0x10) {
-                       /* Large Files */
-                       LOffset.HighPart = *((LONG *)(op + 4));
-                       LOffset.LowPart = *((DWORD *)(op + 8));
-                       LLength.HighPart = *((LONG *)(op + 12));
-                       LLength.LowPart = *((DWORD *)(op + 16));
-                       op += 20;
-               }
-               else {
-                       /* Not Large Files */
-                       LOffset.HighPart = 0;
-                       LOffset.LowPart = *((DWORD *)(op + 2));
-                       LLength.HighPart = 0;
-                       LLength.LowPart = *((DWORD *)(op + 6));
-                       op += 10;
-               }
-               if (LargeIntegerNotEqualToZero(LOffset))
-                       continue;
-               /* Do not check length -- length check done in cm_Unlock */
-
-               code = cm_Unlock(scp, LockType, LOffset, LLength, userp, &req);
-               if (code) goto done;
-       }
+    if (code) {
+        osi_Log1(smb_logp, "smb_ReceiveV3Locking SyncOp failure code 0x%x", code);
+        goto doneSync;
+    }
 
-       for (i=0; i<NumberOfLocks; i++) {
-               if (LockType & 0x10) {
-                       /* Large Files */
-                       LOffset.HighPart = *((LONG *)(op + 4));
-                       LOffset.LowPart = *((DWORD *)(op + 8));
-                       LLength.HighPart = *((LONG *)(op + 12));
-                       LLength.LowPart = *((DWORD *)(op + 16));
-                       op += 20;
-               }
-               else {
-                       /* Not Large Files */
-                       LOffset.HighPart = 0;
-                       LOffset.LowPart = *((DWORD *)(op + 2));
-                       LLength.HighPart = 0;
-                       LLength.LowPart = *((DWORD *)(op + 6));
-                       op += 10;
-               }
-               if (LargeIntegerNotEqualToZero(LOffset))
-                       continue;
-               if (LargeIntegerLessThan(LOffset, scp->length))
-                       continue;
-
-               code = cm_Lock(scp, LockType, LOffset, LLength, Timeout,
-                               userp, &req, &lockp);
-               if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
-                       /* Put on waiting list */
-                       waitingLock = malloc(sizeof(smb_waitingLock_t));
-                       waitingLock->vcp = vcp;
-                       waitingLock->inp = smb_CopyPacket(inp);
-                       waitingLock->outp = smb_CopyPacket(outp);
-                       waitingLock->timeRemaining = Timeout;
-                       waitingLock->lockp = lockp;
-                       lock_ObtainWrite(&smb_globalLock);
-                       osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
-                                &waitingLock->q);
-                       osi_Wakeup((long) &smb_allWaitingLocks);
-                       lock_ReleaseWrite(&smb_globalLock);
-                       /* don't send reply immediately */
-                       outp->flags |= SMB_PACKETFLAG_NOSEND;
-               }
-               if (code) break;
-       }
+    LockType = smb_GetSMBParm(inp, 3) & 0xff;
+    Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
+    NumberOfUnlocks = smb_GetSMBParm(inp, 6);
+    NumberOfLocks = smb_GetSMBParm(inp, 7);
 
-       if (code) {
-               /* release any locks acquired before the failure */
-       }
-       else
-               smb_SetSMBDataLength(outp, 0);
-done:
-       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
-doneSync:
-       lock_ReleaseMutex(&scp->mx);
-       cm_ReleaseUser(userp);
-       smb_ReleaseFID(fidp);
-
-       return code;
+    if ((LockType & LOCKING_ANDX_CANCEL_LOCK) ||
+        (LockType & LOCKING_ANDX_CHANGE_LOCKTYPE)) {
+
+        /* We don't support these requests.  Apparently, we can safely
+           not deal with them too. */
+        osi_Log1(smb_logp, "smb_ReceiveV3Locking received unsupported request [%s]",
+                 ((LockType & LOCKING_ANDX_CANCEL_LOCK)?
+                  "LOCKING_ANDX_CANCEL_LOCK":
+                  "LOCKING_ANDX_CHANGE_LOCKTYPE")); 
+        /* No need to call osi_LogSaveString since these are string
+           constants.*/
+
+        code = CM_ERROR_BADOP;
+        goto done;
+
+    }
+
+    op = smb_GetSMBData(inp, NULL);
+
+    for (i=0; i<NumberOfUnlocks; i++) {
+        smb_GetLockParams(LockType, &op, &pid, &LOffset, &LLength);
+
+        key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+        code = cm_Unlock(scp, LockType, LOffset, LLength, key, userp, &req);
+
+        if (code) 
+            goto done;
+    }
+
+    op_locks = op;
+
+    for (i=0; i<NumberOfLocks; i++) {
+        smb_GetLockParams(LockType, &op, &pid, &LOffset, &LLength);
+
+        key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+        code = cm_Lock(scp, LockType, LOffset, LLength, key, (Timeout != 0),
+                        userp, &req, &lockp);
+
+        if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+            smb_waitingLock_t * wLock;
+
+            /* Put on waiting list */
+            if(wlRequest == NULL) {
+                int j;
+                char * opt;
+                cm_key_t tkey;
+                LARGE_INTEGER tOffset, tLength;
+
+                wlRequest = malloc(sizeof(smb_waitingLockRequest_t));
+
+                osi_assert(wlRequest != NULL);
+
+                wlRequest->vcp = vcp;
+                smb_HoldVC(vcp);
+                wlRequest->scp = scp;
+                cm_HoldSCache(scp);
+                wlRequest->inp = smb_CopyPacket(inp);
+                wlRequest->outp = smb_CopyPacket(outp);
+                wlRequest->lockType = LockType;
+                wlRequest->timeRemaining = Timeout;
+                wlRequest->locks = NULL;
+
+                /* The waiting lock request needs to have enough
+                   information to undo all the locks in the request.
+                   We do the following to store info about locks that
+                   have already been granted.  Sure, we can get most
+                   of the info from the packet, but the packet doesn't
+                   hold the result of cm_Lock call.  In practice we
+                   only receive packets with one or two locks, so we
+                   are only wasting a few bytes here and there and
+                   only for a limited period of time until the waiting
+                   lock times out or is freed. */
+
+                for(opt = op_locks, j=i; j > 0; j--) {
+                    smb_GetLockParams(LockType, &opt, &pid, &tOffset, &tLength);
+
+                    tkey = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+                    wLock = malloc(sizeof(smb_waitingLock_t));
+
+                    osi_assert(wLock != NULL);
+
+                    wLock->key = tkey;
+                    wLock->LOffset = tOffset;
+                    wLock->LLength = tLength;
+                    wLock->lockp = NULL;
+                    wLock->state = SMB_WAITINGLOCKSTATE_DONE;
+                    osi_QAdd((osi_queue_t **) &wlRequest->locks,
+                             &wLock->q);
+                }
+            }
+
+            wLock = malloc(sizeof(smb_waitingLock_t));
+
+            osi_assert(wLock != NULL);
+
+            wLock->key = key;
+            wLock->LOffset = LOffset;
+            wLock->LLength = LLength;
+            wLock->lockp = lockp;
+            wLock->state = SMB_WAITINGLOCKSTATE_WAITING;
+            osi_QAdd((osi_queue_t **) &wlRequest->locks,
+                     &wLock->q);
+
+            osi_Log1(smb_logp, "smb_ReceiveV3Locking WaitingLock created 0x%x",
+                     (long) wLock);
+
+            code = 0;
+            continue;
+        }
+
+        if (code) {
+            osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Lock failure code 0x%x", code);
+            break;
+        }
+    }
+
+    if (code) {
+
+        /* Since something went wrong with the lock number i, we now
+           have to go ahead and release any locks acquired before the
+           failure.  All locks before lock number i (of which there
+           are i of them) have either been successful or are waiting.
+           Either case requires calling cm_Unlock(). */
+
+        /* And purge the waiting lock */
+        if(wlRequest != NULL) {
+            smb_waitingLock_t * wl;
+            smb_waitingLock_t * wlNext;
+            long ul_code;
+
+            for(wl = wlRequest->locks; wl; wl = wlNext) {
+
+                wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
+
+                ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, userp, &req);
+                
+                if(ul_code != 0) {
+                    osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Unlock returns code %d", ul_code);
+                } else {
+                    osi_Log0(smb_logp, "smb_ReceiveV3Locking cm_Unlock successful");
+                }
+
+                osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
+                free(wl);
+
+            }
+
+            smb_ReleaseVC(wlRequest->vcp);
+            cm_ReleaseSCache(wlRequest->scp);
+            smb_FreePacket(wlRequest->inp);
+            smb_FreePacket(wlRequest->outp);
+
+            free(wlRequest);
+
+            wlRequest = NULL;
+        }
+
+    } else {
+
+        if (wlRequest != NULL) {
+
+            lock_ObtainWrite(&smb_globalLock);
+            osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
+                     &wlRequest->q);
+            osi_Wakeup((long) &smb_allWaitingLocks);
+            lock_ReleaseWrite(&smb_globalLock);
+
+            /* don't send reply immediately */
+            outp->flags |= SMB_PACKETFLAG_NOSEND;
+        }
+
+        smb_SetSMBDataLength(outp, 0);
+    }
+
+  done:   
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
+
+  doneSync:
+    lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseUser(userp);
+    smb_ReleaseFID(fidp);
+
+    return code;
 }
 
 long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       unsigned short fid;
+    unsigned short fid;
     smb_fid_t *fidp;
     cm_scache_t *scp;
     long code = 0;
-    time_t searchTime;
+    afs_uint32 searchTime;
     cm_user_t *userp;
-       cm_req_t req;
+    cm_req_t req;
 
-       cm_InitReq(&req);
+    cm_InitReq(&req);
 
     fid = smb_GetSMBParm(inp, 0);
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
     if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
-               return CM_ERROR_BADFD;
+        return CM_ERROR_BADFD;
     }
         
     userp = smb_GetUser(vcp, inp);
@@ -4584,16 +5073,16 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     scp = fidp->scp;
         
     /* otherwise, stat the file */
-       lock_ObtainMutex(&scp->mx);
+    lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-       if (code) goto done;
+    if (code) goto done;
 
-       /* decode times.  We need a search time, but the response to this
+    /* decode times.  We need a search time, but the response to this
      * call provides the date first, not the time, as returned in the
      * searchTime variable.  So we take the high-order bits first.
      */
-       smb_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
+    smb_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
     smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff);      /* ctime */
     smb_SetSMBParm(outp, 1, searchTime & 0xffff);
     smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff);      /* atime */
@@ -4607,7 +5096,7 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     smb_SetSMBParm(outp, 8, scp->length.LowPart & 0xffff);             /* alloc size */
     smb_SetSMBParm(outp, 9, (scp->length.LowPart >> 16) & 0xffff);
 
-       /* file attribute */
+    /* file attribute */
     smb_SetSMBParm(outp, 10, smb_Attributes(scp));
         
     /* and finalize stuff */
@@ -4615,46 +5104,46 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     code = 0;
 
   done:
-       lock_ReleaseMutex(&scp->mx);
-       cm_ReleaseUser(userp);
-       smb_ReleaseFID(fidp);
-       return code;
-}
+    lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseUser(userp);
+    smb_ReleaseFID(fidp);
+    return code;
+}       
 
 long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       unsigned short fid;
+    unsigned short fid;
     smb_fid_t *fidp;
     cm_scache_t *scp;
     long code = 0;
-    time_t searchTime;
+    afs_uint32 searchTime;
     time_t unixTime;
     cm_user_t *userp;
     cm_attr_t attrs;
-       cm_req_t req;
+    cm_req_t req;
 
-       cm_InitReq(&req);
+    cm_InitReq(&req);
 
     fid = smb_GetSMBParm(inp, 0);
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
     if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
-               return CM_ERROR_BADFD;
+        return CM_ERROR_BADFD;
     }
         
     userp = smb_GetUser(vcp, inp);
         
     scp = fidp->scp;
         
-       /* now prepare to call cm_setattr.  This message only sets various times,
+    /* now prepare to call cm_setattr.  This message only sets various times,
      * and AFS only implements mtime, and we'll set the mtime if that's
      * requested.  The others we'll ignore.
      */
-       searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
+    searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
         
     if (searchTime != 0) {
-               smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+        smb_UnixTimeFromSearchTime(&unixTime, searchTime);
 
         if ( unixTime != -1 ) {
             attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
@@ -4668,20 +5157,23 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     }
     else code = 0;
 
-       cm_ReleaseUser(userp);
-       smb_ReleaseFID(fidp);
-       return code;
+    cm_ReleaseUser(userp);
+    smb_ReleaseFID(fidp);
+    return code;
 }
 
 
 long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       osi_hyper_t offset;
-    long count, finalCount;
+    osi_hyper_t offset;
+    long count;
+    long finalCount = 0;
     unsigned short fd;
+    unsigned pid;
     smb_fid_t *fidp;
     long code = 0;
     cm_user_t *userp;
+    cm_key_t key;
     char *op;
         
     fd = smb_GetSMBParm(inp, 2);
@@ -4692,35 +5184,56 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     osi_Log3(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
         
-       fd = smb_ChainFID(fd, inp);
+    fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
-               return CM_ERROR_BADFD;
+        return CM_ERROR_BADFD;
+    }
+
+    pid = ((smb_t *) inp)->pid;
+    key = cm_GenerateKey(vcp->vcID, pid, fd);
+    {
+        LARGE_INTEGER LOffset, LLength;
+
+        LOffset.HighPart = offset.HighPart;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
+
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+    }
+
+    if (code) {
+        smb_ReleaseFID(fidp);
+        return code;
     }
-       /* set inp->fid so that later read calls in same msg can find fid */
+
+    /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fd;
 
     if (fidp->flags & SMB_FID_IOCTL) {
-               return smb_IoctlV3Read(fidp, vcp, inp, outp);
+        return smb_IoctlV3Read(fidp, vcp, inp, outp);
     }
-        
-       userp = smb_GetUser(vcp, inp);
 
-       /* 0 and 1 are reserved for request chaining, were setup by our caller,
+    userp = smb_GetUser(vcp, inp);
+
+    /* 0 and 1 are reserved for request chaining, were setup by our caller,
      * and will be further filled in after we return.
      */
     smb_SetSMBParm(outp, 2, 0);        /* remaining bytes, for pipes */
     smb_SetSMBParm(outp, 3, 0);        /* resvd */
     smb_SetSMBParm(outp, 4, 0);        /* resvd */
-       smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
+    smb_SetSMBParm(outp, 5, count);    /* # of bytes we're going to read */
     /* fill in #6 when we have all the parameters' space reserved */
     smb_SetSMBParm(outp, 7, 0);        /* resv'd */
     smb_SetSMBParm(outp, 8, 0);        /* resv'd */
     smb_SetSMBParm(outp, 9, 0);        /* resv'd */
     smb_SetSMBParm(outp, 10, 0);       /* resv'd */
-       smb_SetSMBParm(outp, 11, 0);    /* reserved */
+    smb_SetSMBParm(outp, 11, 0);       /* reserved */
 
-       /* get op ptr after putting in the parms, since otherwise we don't
+    /* get op ptr after putting in the parms, since otherwise we don't
      * know where the data really is.
      */
     op = smb_GetSMBData(outp, NULL);
@@ -4728,18 +5241,18 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* now fill in offset from start of SMB header to first data byte (to op) */
     smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
 
-       /* set the packet data length the count of the # of bytes */
+    /* set the packet data length the count of the # of bytes */
     smb_SetSMBDataLength(outp, count);
 
 #ifndef DJGPP
-       code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
+    code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
 #else /* DJGPP */
-       code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
+    code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
 #endif /* !DJGPP */
 
-       /* fix some things up */
-       smb_SetSMBParm(outp, 5, finalCount);
-       smb_SetSMBDataLength(outp, finalCount);
+    /* fix some things up */
+    smb_SetSMBParm(outp, 5, finalCount);
+    smb_SetSMBDataLength(outp, finalCount);
 
     smb_ReleaseFID(fidp);
 
@@ -4757,6 +5270,23 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #define  FILE_OVERWRITE        4       // (open & truncate, but do not create)
 #define  FILE_OVERWRITE_IF 5   // (open & truncate, or create)
 
+/* Flags field */
+#define REQUEST_OPLOCK 2
+#define REQUEST_BATCH_OPLOCK 4
+#define OPEN_DIRECTORY 8
+#define EXTENDED_RESPONSE_REQUIRED 0x10
+
+/* CreateOptions field. */
+#define FILE_DIRECTORY_FILE       0x0001
+#define FILE_WRITE_THROUGH        0x0002
+#define FILE_SEQUENTIAL_ONLY      0x0004
+#define FILE_NON_DIRECTORY_FILE   0x0040
+#define FILE_NO_EA_KNOWLEDGE      0x0200
+#define FILE_EIGHT_DOT_THREE_ONLY 0x0400
+#define FILE_RANDOM_ACCESS        0x0800
+#define FILE_DELETE_ON_CLOSE      0x1000
+#define FILE_OPEN_BY_FILE_ID      0x2000
+
 long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     char *pathp, *realPathp;
@@ -4774,12 +5304,14 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     unsigned int requestOpLock;
     unsigned int requestBatchOpLock;
     unsigned int mustBeDir;
+    unsigned int extendedRespRequired;
     unsigned int treeCreate;
     int realDirFlag;
     unsigned int desiredAccess;
     unsigned int extAttributes;
     unsigned int createDisp;
     unsigned int createOptions;
+    unsigned int shareAccess;
     int initialModeBits;
     unsigned short baseFid;
     smb_fid_t *baseFidp;
@@ -4796,16 +5328,22 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     cm_InitReq(&req);
 
+    /* This code is very long and has a lot of if-then-else clauses
+     * scp and dscp get reused frequently and we need to ensure that 
+     * we don't lose a reference.  Start by ensuring that they are NULL.
+     */
+    scp = NULL;
+    dscp = NULL;
     treeCreate = FALSE;
     foundscp = FALSE;
-    scp = NULL;
 
     nameLength = smb_GetSMBOffsetParm(inp, 2, 1);
     flags = smb_GetSMBOffsetParm(inp, 3, 1)
         | (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
-    requestOpLock = flags & 0x02;
-    requestBatchOpLock = flags & 0x04;
-    mustBeDir = flags & 0x08;
+    requestOpLock = flags & REQUEST_OPLOCK;
+    requestBatchOpLock = flags & REQUEST_BATCH_OPLOCK;
+    mustBeDir = flags & OPEN_DIRECTORY;
+    extendedRespRequired = flags & EXTENDED_RESPONSE_REQUIRED;
 
     /*
      * Why all of a sudden 32-bit FID?
@@ -4818,6 +5356,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
     extAttributes = smb_GetSMBOffsetParm(inp, 13, 1)
         | (smb_GetSMBOffsetParm(inp, 14, 1) << 16);
+    shareAccess = smb_GetSMBOffsetParm(inp, 15, 1)
+        | (smb_GetSMBOffsetParm(inp, 16, 1) << 16);
     createDisp = smb_GetSMBOffsetParm(inp, 17, 1)
         | (smb_GetSMBOffsetParm(inp, 18, 1) << 16);
     createOptions = smb_GetSMBOffsetParm(inp, 19, 1)
@@ -4826,9 +5366,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* mustBeDir is never set; createOptions directory bit seems to be
      * more important
      */
-    if (createOptions & 1)
+    if (createOptions & FILE_DIRECTORY_FILE)
         realDirFlag = 1;
-    else if (createOptions & 0x40)
+    else if (createOptions & FILE_NON_DIRECTORY_FILE)
         realDirFlag = 0;
     else
         realDirFlag = -1;
@@ -4838,7 +5378,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
      * extended attributes
      */
     initialModeBits = 0666;
-    if (extAttributes & 1) 
+    if (extAttributes & SMB_ATTR_READONLY) 
         initialModeBits &= ~0222;
 
     pathp = smb_GetSMBData(inp, NULL);
@@ -4846,13 +5386,15 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     realPathp = malloc(nameLength+1);
     memcpy(realPathp, pathp, nameLength);
     realPathp[nameLength] = 0;
+    if (smb_StoreAnsiFilenames)
+        OemToChar(realPathp,realPathp);
 
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
 
     osi_Log1(smb_logp,"NTCreateX for [%s]",osi_LogSaveString(smb_logp,realPathp));
     osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
-    osi_Log2(smb_logp,"... flags=[%x] lastNamep=[%s]", flags, osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
+    osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%s]", shareAccess, flags, osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
 
     if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
         /* special case magic file name for receiving IOCTL requests
@@ -4900,6 +5442,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        free(hexp);
     }
 #endif
+
     userp = smb_GetUser(vcp, inp);
     if (!userp) {
        osi_Log1(smb_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
@@ -4908,19 +5451,22 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 
     if (baseFid == 0) {
-        baseDirp = cm_rootSCachep;
+        baseDirp = cm_data.rootSCachep;
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
         if (code == CM_ERROR_TIDIPC) {
             /* Attempt to use a TID allocated for IPC.  The client
              * is probably looking for DCE RPC end points which we
-             * don't support. */
+             * don't support OR it could be looking to make a DFS
+             * referral request. 
+             */
             osi_Log0(smb_logp, "NTCreateX received IPC TID");
+#ifndef DFS_SUPPORT
             free(realPathp);
             cm_ReleaseUser(userp);
             return CM_ERROR_NOSUCHFILE;
+#endif /* DFS_SUPPORT */
         }
-    }
-    else {
+    } else {
         baseFidp = smb_FindFID(vcp, baseFid, 0);
         if (!baseFidp) {
             osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
@@ -4942,9 +5488,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidflags |= SMB_FID_OPENREAD;
     if (desiredAccess & AFS_ACCESS_WRITE)
         fidflags |= SMB_FID_OPENWRITE;
+    if (createOptions & FILE_DELETE_ON_CLOSE)
+        fidflags |= SMB_FID_DELONCLOSE;
+
+    /* and the share mode */
+    if (shareAccess & FILE_SHARE_READ)
+        fidflags |= SMB_FID_SHARE_READ;
+    if (shareAccess & FILE_SHARE_WRITE)
+        fidflags |= SMB_FID_SHARE_WRITE;
 
-    dscp = NULL;
     code = 0;
+
     /* For an exclusive create, we want to do a case sensitive match for the last component. */
     if ( createDisp == FILE_CREATE || 
          createDisp == FILE_OVERWRITE ||
@@ -4952,6 +5506,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &dscp);
         if (code == 0) {
+#ifdef DFS_SUPPORT
+            if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                cm_ReleaseSCache(dscp);
+                cm_ReleaseUser(userp);
+                free(realPathp);
+                if ( WANTS_DFS_PATHNAMES(inp) )
+                    return CM_ERROR_PATH_NOT_COVERED;
+                else
+                    return CM_ERROR_BADSHARENAME;
+            }
+#endif /* DFS_SUPPORT */
             code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
                              userp, &req, &scp);
             if (code == CM_ERROR_NOSUCHFILE) {
@@ -4965,15 +5530,28 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     return CM_ERROR_EXISTS;
                 }
             }
-        } else
-            dscp = NULL;
+        }
+        /* we have both scp and dscp */
     } else {
         code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
+#ifdef DFS_SUPPORT
+        if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            if ( WANTS_DFS_PATHNAMES(inp) )
+                return CM_ERROR_PATH_NOT_COVERED;
+            else
+                return CM_ERROR_BADSHARENAME;
+        }
+#endif /* DFS_SUPPORT */
+        /* we might have scp but not dscp */
     }
-    if (code == 0) 
-        foundscp = TRUE;
 
+    if (scp)
+        foundscp = TRUE;
+    
     if (!foundscp || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
         /* look up parent directory */
         /* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
@@ -4981,14 +5559,30 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
          * recognize.
          */
 
-        if ( !dscp ) {
-            while (1) {
+        /* we might or might not have scp */
+
+        if (dscp == NULL) {
+            do {
                 char *tp;
 
                 code = cm_NameI(baseDirp, spacep->data,
                              CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                              userp, tidPathp, &req, &dscp);
 
+#ifdef DFS_SUPPORT
+                if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                    if (scp)
+                        cm_ReleaseSCache(scp);
+                    cm_ReleaseSCache(dscp);
+                    cm_ReleaseUser(userp);
+                    free(realPathp);
+                    if ( WANTS_DFS_PATHNAMES(inp) )
+                        return CM_ERROR_PATH_NOT_COVERED;
+                    else
+                        return CM_ERROR_BADSHARENAME;
+                }
+#endif /* DFS_SUPPORT */
+
                 if (code && 
                      (tp = strrchr(spacep->data,'\\')) &&
                      (createDisp == FILE_CREATE) &&
@@ -5002,20 +5596,27 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                             smb_ReleaseFID(baseFidp);
                         cm_ReleaseUser(userp);
                         free(realPathp);
+                        if (scp)
+                            cm_ReleaseSCache(scp);
                         return CM_ERROR_BADNTFILENAME;
                     }
+                    code = 0;
                 }
-                else
-                    break;
-            }
+            } while (dscp == NULL && code == 0);
         } else
             code = 0;
 
+        /* we might have scp and we might have dscp */
+
         if (baseFid != 0) 
-                       smb_ReleaseFID(baseFidp);
+            smb_ReleaseFID(baseFidp);
 
         if (code) {
             osi_Log0(smb_logp,"NTCreateX parent not found");
+            if (scp)
+                cm_ReleaseSCache(scp);
+            if (dscp)
+                cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
             return code;
@@ -5023,6 +5624,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         if (treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
             /* A file exists where we want a directory. */
+            if (scp)
+                cm_ReleaseSCache(scp);
             cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5035,7 +5638,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             lastNamep++;
 
         if (!smb_IsLegalFilename(lastNamep)) {
-            cm_ReleaseSCache(dscp);
+            if (scp)
+                cm_ReleaseSCache(scp);
+            if (dscp)
+                cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
             return CM_ERROR_BADNTFILENAME;
@@ -5044,211 +5650,228 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if (!foundscp && !treeCreate) {
             if ( createDisp == FILE_CREATE || 
                  createDisp == FILE_OVERWRITE ||
-                 createDisp == FILE_OVERWRITE_IF) {
+                 createDisp == FILE_OVERWRITE_IF) 
+            {
                 code = cm_Lookup(dscp, lastNamep,
                                   CM_FLAG_FOLLOW, userp, &req, &scp);
-                 } else {
-                     code = cm_Lookup(dscp, lastNamep,
-                                       CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                                       userp, &req, &scp);
-                 }
+            } else {
+                code = cm_Lookup(dscp, lastNamep,
+                                 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                                 userp, &req, &scp);
+            }
             if (code && code != CM_ERROR_NOSUCHFILE) {
-                cm_ReleaseSCache(dscp);
+                if (dscp)
+                    cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
                 return code;
             }
         }
-    }
-    else {
+        /* we have scp and dscp */
+    } else {
+        /* we have scp but not dscp */
         if (baseFid != 0) 
             smb_ReleaseFID(baseFidp);
-       }       
-
-       /* if we get here, if code is 0, the file exists and is represented by
-        * scp.  Otherwise, we have to create it.  The dir may be represented
-        * by dscp, or we may have found the file directly.  If code is non-zero,
-        * scp is NULL.
-        */
-       if (code == 0 && !treeCreate) {
-            if (createDisp == FILE_CREATE) {
-                /* oops, file shouldn't be there */
-                if (dscp) cm_ReleaseSCache(dscp);
+    }
+
+    /* if we get here, if code is 0, the file exists and is represented by
+     * scp.  Otherwise, we have to create it.  The dir may be represented
+     * by dscp, or we may have found the file directly.  If code is non-zero,
+     * scp is NULL.
+     */
+    if (code == 0 && !treeCreate) {
+        if (createDisp == FILE_CREATE) {
+            /* oops, file shouldn't be there */
+            if (dscp)
+                cm_ReleaseSCache(dscp);
+            if (scp)
                 cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                free(realPathp);
-                return CM_ERROR_EXISTS;
-            }
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_EXISTS;
+        }
 
-            if ( createDisp == FILE_OVERWRITE || 
-                 createDisp == FILE_OVERWRITE_IF) {
-                setAttr.mask = CM_ATTRMASK_LENGTH;
-                setAttr.length.LowPart = 0;
-                setAttr.length.HighPart = 0;
-                /* now watch for a symlink */
-                code = 0;
-                while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
-                    targetScp = 0;
-                    code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
-                    if (code == 0) {
-                        /* we have a more accurate file to use (the
-                        * target of the symbolic link).  Otherwise,
-                        * we'll just use the symlink anyway.
-                        */
-                        osi_Log2(smb_logp, "symlink vp %x to vp %x",
-                                  scp, targetScp);
-                        cm_ReleaseSCache(scp);
-                        scp = targetScp;
-                    }
+        if ( createDisp == FILE_OVERWRITE || 
+             createDisp == FILE_OVERWRITE_IF) {
+
+            setAttr.mask = CM_ATTRMASK_LENGTH;
+            setAttr.length.LowPart = 0;
+            setAttr.length.HighPart = 0;
+            /* now watch for a symlink */
+            code = 0;
+            while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+                targetScp = 0;
+                osi_assert(dscp != NULL);
+                code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
+                if (code == 0) {
+                    /* we have a more accurate file to use (the
+                     * target of the symbolic link).  Otherwise,
+                     * we'll just use the symlink anyway.
+                     */
+                    osi_Log2(smb_logp, "symlink vp %x to vp %x",
+                              scp, targetScp);
+                    cm_ReleaseSCache(scp);
+                    scp = targetScp;
                 }
-                code = cm_SetAttr(scp, &setAttr, userp, &req);
-                openAction = 3;        /* truncated existing file */
             }
-            else 
-                               openAction = 1; /* found existing file */
+            code = cm_SetAttr(scp, &setAttr, userp, &req);
+            openAction = 3;    /* truncated existing file */
+        }
+        else 
+            openAction = 1;    /* found existing file */
 
-                       code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
-                                  &req);
-            if (code) {
-                if (dscp) cm_ReleaseSCache(dscp);
+        code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
+        if (code) {
+            if (dscp)
+                cm_ReleaseSCache(dscp);
+            if (scp)
                 cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                free(realPathp);
-                return code;
-            }
-       }       
-       else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
-            /* don't create if not found */
-            if (dscp) cm_ReleaseSCache(dscp);
             cm_ReleaseUser(userp);
             free(realPathp);
-            return CM_ERROR_NOSUCHFILE;
-       }       
-       else if (realDirFlag == 0 || realDirFlag == -1) {
-            osi_assert(dscp != NULL);
-            osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
-                      osi_LogSaveString(smb_logp, lastNamep));
-            openAction = 2;            /* created file */
-            setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
-            setAttr.clientModTime = time(NULL);
-            code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
-                              &req);
-            if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+            return code;
+        }
+    } else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
+        /* don't create if not found */
+        if (dscp)
+            cm_ReleaseSCache(dscp);
+        if (scp)
+            cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        free(realPathp);
+        return CM_ERROR_NOSUCHFILE;
+    } else if (realDirFlag == 0 || realDirFlag == -1) {
+        osi_assert(dscp != NULL);
+        osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
+                  osi_LogSaveString(smb_logp, lastNamep));
+        openAction = 2;                /* created file */
+        setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+        setAttr.clientModTime = time(NULL);
+        code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
+        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+            smb_NotifyChange(FILE_ACTION_ADDED,
+                              FILE_NOTIFY_CHANGE_FILE_NAME,
+                              dscp, lastNamep, NULL, TRUE);
+        if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+            /* Not an exclusive create, and someone else tried
+             * creating it already, then we open it anyway.  We
+             * don't bother retrying after this, since if this next
+             * fails, that means that the file was deleted after we
+             * started this call.
+             */
+            code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
+                              userp, &req, &scp);
+            if (code == 0) {
+                if (createDisp == FILE_OVERWRITE_IF) {
+                    setAttr.mask = CM_ATTRMASK_LENGTH;
+                    setAttr.length.LowPart = 0;
+                    setAttr.length.HighPart = 0;
+
+                    /* now watch for a symlink */
+                    code = 0;
+                    while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+                        targetScp = 0;
+                        code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
+                        if (code == 0) {
+                            /* we have a more accurate file to use (the
+                             * target of the symbolic link).  Otherwise,
+                             * we'll just use the symlink anyway.
+                             */
+                            osi_Log2(smb_logp, "symlink vp %x to vp %x",
+                                      scp, targetScp);
+                            cm_ReleaseSCache(scp);
+                            scp = targetScp;
+                        }
+                    }
+                    code = cm_SetAttr(scp, &setAttr, userp, &req);
+                }
+            }  /* lookup succeeded */
+        }
+    } else {
+        char *tp, *pp;
+        char *cp; /* This component */
+        int clen = 0; /* length of component */
+        cm_scache_t *tscp1, *tscp2;
+        int isLast = 0;
+
+        /* create directory */
+        if ( !treeCreate ) 
+            treeStartp = lastNamep;
+        osi_assert(dscp != NULL);
+        osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
+                  osi_LogSaveString(smb_logp, treeStartp));
+        openAction = 2;                /* created directory */
+
+        setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+        setAttr.clientModTime = time(NULL);
+
+        pp = treeStartp;
+        cp = spacep->data;
+        tscp1 = dscp;
+        cm_HoldSCache(tscp1);
+        tscp2 = NULL;
+
+        while (pp && *pp) {
+            tp = strchr(pp, '\\');
+            if (!tp) {
+                strcpy(cp,pp);
+                clen = strlen(cp);
+                isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
+            } else {
+                clen = tp - pp;
+                strncpy(cp,pp,clen);
+                *(cp + clen) = 0;
+                tp++;
+            }
+            pp = tp;
+
+            if (clen == 0) 
+                continue; /* the supplied path can't have consecutive slashes either , but */
+
+            /* cp is the next component to be created. */
+            code = cm_MakeDir(tscp1, cp, 0, &setAttr, userp, &req);
+            if (code == 0 && (tscp1->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_ADDED,
-                                  FILE_NOTIFY_CHANGE_FILE_NAME,
-                                  dscp, lastNamep, NULL, TRUE);
-            if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+                                  FILE_NOTIFY_CHANGE_DIR_NAME,
+                                  tscp1, cp, NULL, TRUE);
+            if (code == 0 || 
+                 (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
                 /* Not an exclusive create, and someone else tried
                  * creating it already, then we open it anyway.  We
                  * don't bother retrying after this, since if this next
                  * fails, that means that the file was deleted after we
                  * started this call.
                  */
-                code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                  userp, &req, &scp);
-                if (code == 0) {
-                    if (createDisp == FILE_OVERWRITE_IF) {
-                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                        setAttr.length.LowPart = 0;
-                        setAttr.length.HighPart = 0;
-
-                        /* now watch for a symlink */
-                        code = 0;
-                        while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
-                            targetScp = 0;
-                            code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
-                            if (code == 0) {
-                                /* we have a more accurate file to use (the
-                                * target of the symbolic link).  Otherwise,
-                                * we'll just use the symlink anyway.
-                                */
-                                osi_Log2(smb_logp, "symlink vp %x to vp %x",
-                                          scp, targetScp);
-                                cm_ReleaseSCache(scp);
-                                scp = targetScp;
-                            }
-                        }
-                        code = cm_SetAttr(scp, &setAttr, userp, &req);
-                    }
-                }      /* lookup succeeded */
-            }
-       }       
-       else {
-            char *tp, *pp;
-            char *cp; /* This component */
-            int clen = 0; /* length of component */
-            cm_scache_t *tscp;
-            int isLast = 0;
-               
-            /* create directory */
-            if ( !treeCreate ) 
-                treeStartp = lastNamep;
-            osi_assert(dscp != NULL);
-            osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
-                      osi_LogSaveString(smb_logp, treeStartp));
-            openAction = 2;            /* created directory */
-
-            setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
-            setAttr.clientModTime = time(NULL);
-               
-            pp = treeStartp;
-            cp = spacep->data;
-            tscp = dscp;
-
-            while (pp && *pp) {
-                tp = strchr(pp, '\\');
-                if (!tp) {
-                    strcpy(cp,pp);
-                    clen = strlen(cp);
-                    isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
-                }
-                else {
-                    clen = tp - pp;
-                    strncpy(cp,pp,clen);
-                    *(cp + clen) = 0;
-                    tp++;
-                }
-                pp = tp;
-
-                if (clen == 0) 
-                    continue; /* the supplied path can't have consecutive slashes either , but */
-
-                /* cp is the next component to be created. */
-                code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
-                if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                    smb_NotifyChange(FILE_ACTION_ADDED,
-                                      FILE_NOTIFY_CHANGE_DIR_NAME,
-                                      tscp, cp, NULL, TRUE);
-                if (code == 0 || 
-                     (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
-                    /* Not an exclusive create, and someone else tried
-                     * creating it already, then we open it anyway.  We
-                     * don't bother retrying after this, since if this next
-                     * fails, that means that the file was deleted after we
-                     * started this call.
-                     */
-                    code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
-                                      userp, &req, &scp);
-                }
-                if (code) break;
+                code = cm_Lookup(tscp1, cp, CM_FLAG_CASEFOLD,
+                                  userp, &req, &tscp2);
+            }       
+            if (code) 
+                break;
 
-                if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
-                    cm_ReleaseSCache(tscp);
-                    tscp = scp; /* Newly created directory will be next parent */
-                }
+            if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
+                cm_ReleaseSCache(tscp1);
+                tscp1 = tscp2; /* Newly created directory will be next parent */
+                /* the hold is transfered to tscp1 from tscp2 */
             }
+        }
 
-            /* 
-             * if we get here and code == 0, then scp is the last directory created, and tscp is the
-             * parent of scp.  dscp got released if dscp != tscp. both tscp and scp are held.
-             */
-            dscp = tscp;
-       }
+        if (dscp)
+            cm_ReleaseSCache(dscp);
+        dscp = tscp1;
+        if (scp)
+            cm_ReleaseSCache(scp);
+        scp = tscp2;
+        /* 
+         * if we get here and code == 0, then scp is the last directory created, and dscp is the
+         * parent of scp.
+         */
+    }
 
     if (code) {
         /* something went wrong creating or truncating the file */
-        if (scp) cm_ReleaseSCache(scp);
-        if (dscp) cm_ReleaseSCache(dscp);
+        if (scp) 
+            cm_ReleaseSCache(scp);
+        if (dscp) 
+            cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         free(realPathp);
         return code;
@@ -5266,14 +5889,15 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 * target of the symbolic link).  Otherwise,
                 * we'll just use the symlink anyway.
                 */
-                osi_Log2(smb_logp, "symlink vp %x to vp %x",
-                          scp, targetScp);
+                osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
                 cm_ReleaseSCache(scp);
                 scp = targetScp;
             }
         }
 
         if (scp->fileType != CM_SCACHETYPE_FILE) {
+            if (dscp)
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5284,7 +5908,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* (only applies to single component case) */
     if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
         cm_ReleaseSCache(scp);
-        if (dscp) cm_ReleaseSCache(dscp);
+        if (dscp)
+            cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         free(realPathp);
         return CM_ERROR_NOTDIR;
@@ -5293,8 +5918,48 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* open the file itself */
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
+
+    /* If we are restricting sharing, we should do so with a suitable
+       share lock. */
+    if (scp->fileType == CM_SCACHETYPE_FILE &&
+        !(fidflags & SMB_FID_SHARE_WRITE)) {
+        cm_key_t key;
+        LARGE_INTEGER LOffset, LLength;
+        int sLockType;
+
+        LOffset.HighPart = SMB_FID_QLOCK_HIGH;
+        LOffset.LowPart = SMB_FID_QLOCK_LOW;
+        LLength.HighPart = 0;
+        LLength.LowPart = SMB_FID_QLOCK_LENGTH;
+
+        if (fidflags & SMB_FID_SHARE_READ) {
+            sLockType = LOCKING_ANDX_SHARED_LOCK;
+        } else {
+            sLockType = 0;
+        }
+
+        key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
+        
+        lock_ObtainMutex(&scp->mx);
+        code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
+        lock_ReleaseMutex(&scp->mx);
+
+        if (code) {
+            fidp->flags = SMB_FID_DELETE;
+            smb_ReleaseFID(fidp);
+
+            cm_ReleaseSCache(scp);
+            if (dscp)
+                cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            
+            return CM_ERROR_SHARING_VIOLATION;
+        }
+    }
+
     /* save a pointer to the vnode */
-    fidp->scp = scp;
+    fidp->scp = scp;    /* Hold transfered to fidp->scp and no longer needed */
 
     fidp->flags = fidflags;
 
@@ -5308,7 +5973,11 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp->NTopen_wholepathp = realPathp;
 
     /* we don't need this any longer */
-    if (dscp) cm_ReleaseSCache(dscp);
+    if (dscp) {
+        cm_ReleaseSCache(dscp);
+        dscp = NULL;
+    }
+
     cm_Open(scp, 0, userp);
 
     /* set inp->fid so that later read calls in same msg can find fid */
@@ -5343,7 +6012,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     cm_ReleaseUser(userp);
 
-    /* Can't free realPathp if we get here since fidp->NTopen_wholepathp is pointing there */
+    /* Can't free realPathp if we get here since
+       fidp->NTopen_wholepathp is pointing there */
 
     /* leave scp held since we put it in fidp->scp */
     return 0;
@@ -5374,8 +6044,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     unsigned int desiredAccess;
 #ifdef DEBUG_VERBOSE    
     unsigned int allocSize;
-    unsigned int shareAccess;
 #endif
+    unsigned int shareAccess;
     unsigned int extAttributes;
     unsigned int createDisp;
 #ifdef DEBUG_VERBOSE
@@ -5410,10 +6080,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     lparmp = (ULONG *) parmp;
 
     flags = lparmp[0];
-    requestOpLock = flags & 0x02;
-    requestBatchOpLock = flags & 0x04;
-    mustBeDir = flags & 0x08;
-    extendedRespRequired = flags & 0x10;
+    requestOpLock = flags & REQUEST_OPLOCK;
+    requestBatchOpLock = flags & REQUEST_BATCH_OPLOCK;
+    mustBeDir = flags & OPEN_DIRECTORY;
+    extendedRespRequired = flags & EXTENDED_RESPONSE_REQUIRED;
 
     /*
      * Why all of a sudden 32-bit FID?
@@ -5427,9 +6097,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     allocSize = lparmp[3];
 #endif /* DEBUG_VERSOSE */
     extAttributes = lparmp[5];
-#ifdef DEBUG_VEROSE
     shareAccess = lparmp[6];
-#endif
     createDisp = lparmp[7];
     createOptions = lparmp[8];
 #ifdef DEBUG_VERBOSE
@@ -5446,9 +6114,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     /* mustBeDir is never set; createOptions directory bit seems to be
      * more important
      */
-    if (createOptions & 1)
+    if (createOptions & FILE_DIRECTORY_FILE)
         realDirFlag = 1;
-    else if (createOptions & 0x40)
+    else if (createOptions & FILE_NON_DIRECTORY_FILE)
         realDirFlag = 0;
     else
         realDirFlag = -1;
@@ -5466,6 +6134,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     realPathp = malloc(nameLength+1);
     memcpy(realPathp, pathp, nameLength);
     realPathp[nameLength] = 0;
+    if (smb_StoreAnsiFilenames)
+        OemToChar(realPathp,realPathp);
 
     spacep = cm_GetSpace();
     smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
@@ -5493,19 +6163,22 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     }
 
     if (baseFid == 0) {
-        baseDirp = cm_rootSCachep;
+        baseDirp = cm_data.rootSCachep;
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
-        if(code == CM_ERROR_TIDIPC) {
-            /* Attempt to use TID allocated for IPC.  The client is
-             * probably trying to locate DCE RPC endpoints, which we
-             * don't support. */
+        if (code == CM_ERROR_TIDIPC) {
+            /* Attempt to use a TID allocated for IPC.  The client
+             * is probably looking for DCE RPC end points which we
+             * don't support OR it could be looking to make a DFS
+             * referral request. 
+             */
             osi_Log0(smb_logp, "NTTranCreate received IPC TID");
+#ifndef DFS_SUPPORT
             free(realPathp);
             cm_ReleaseUser(userp);
             return CM_ERROR_NOSUCHPATH;
+#endif 
         }
-    }
-    else {
+    } else {
         baseFidp = smb_FindFID(vcp, baseFid, 0);
         if (!baseFidp) {
                osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
@@ -5525,6 +6198,14 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         fidflags |= SMB_FID_OPENREAD;
     if (desiredAccess & AFS_ACCESS_WRITE)
         fidflags |= SMB_FID_OPENWRITE;
+    if (createOptions & FILE_DELETE_ON_CLOSE)
+        fidflags |= SMB_FID_DELONCLOSE;
+
+    /* And the share mode */
+    if (shareAccess & FILE_SHARE_READ)
+        fidflags |= SMB_FID_SHARE_READ;
+    if (shareAccess & FILE_SHARE_WRITE)
+        fidflags |= SMB_FID_SHARE_WRITE;
 
     dscp = NULL;
     code = 0;
@@ -5534,6 +6215,17 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &dscp);
         if (code == 0) {
+#ifdef DFS_SUPPORT
+            if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                cm_ReleaseSCache(dscp);
+                cm_ReleaseUser(userp);
+                free(realPathp);
+                if ( WANTS_DFS_PATHNAMES(inp) )
+                    return CM_ERROR_PATH_NOT_COVERED;
+                else
+                    return CM_ERROR_BADSHARENAME;
+            }
+#endif /* DFS_SUPPORT */
             code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
                              userp, &req, &scp);
             if (code == CM_ERROR_NOSUCHFILE) {
@@ -5552,17 +6244,39 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     } else {
         code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
+#ifdef DFS_SUPPORT
+        if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            if ( WANTS_DFS_PATHNAMES(inp) )
+                return CM_ERROR_PATH_NOT_COVERED;
+            else
+                return CM_ERROR_BADSHARENAME;
+        }
+#endif /* DFS_SUPPORT */
     }
 
     if (code == 0) 
         foundscp = TRUE;
-    if (code != 0
-         || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
+
+    if (code != 0 || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
         /* look up parent directory */
         if ( !dscp ) {
             code = cm_NameI(baseDirp, spacep->data,
                              CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                              userp, tidPathp, &req, &dscp);
+#ifdef DFS_SUPPORT
+            if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                cm_ReleaseSCache(dscp);
+                cm_ReleaseUser(userp);
+                free(realPathp);
+                if ( WANTS_DFS_PATHNAMES(inp) )
+                    return CM_ERROR_PATH_NOT_COVERED;
+                else
+                    return CM_ERROR_BADSHARENAME;
+            }
+#endif /* DFS_SUPPORT */
         } else
             code = 0;
         
@@ -5601,8 +6315,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 return code;
             }
         }
-    }
-    else {
+    } else {
         if (baseFid != 0) {
             smb_ReleaseFID(baseFidp);
             baseFidp = 0;
@@ -5619,7 +6332,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
                                &req);
         if (code) {     
-            if (dscp) cm_ReleaseSCache(dscp);
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5628,7 +6342,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
         if (createDisp == FILE_CREATE) {
             /* oops, file shouldn't be there */
-            if (dscp) cm_ReleaseSCache(dscp);
+            if (dscp) 
+                cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
@@ -5664,7 +6379,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     }
     else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
         /* don't create if not found */
-        if (dscp) cm_ReleaseSCache(dscp);
+        if (dscp) 
+            cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         free(realPathp);
         return CM_ERROR_NOSUCHFILE;
@@ -5717,8 +6433,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 }       
             }  /* lookup succeeded */
         }
-    }
-    else {
+    } else {
         /* create directory */
         osi_assert(dscp != NULL);
         osi_Log1(smb_logp,
@@ -5747,7 +6462,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
     if (code) {
         /* something went wrong creating or truncating the file */
-        if (scp) cm_ReleaseSCache(scp);
+        if (scp) 
+            cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
         free(realPathp);
         return code;
@@ -5791,6 +6507,43 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
 
+    /* If we are restricting sharing, we should do so with a suitable
+       share lock. */
+    if (scp->fileType == CM_SCACHETYPE_FILE &&
+        !(fidflags & SMB_FID_SHARE_WRITE)) {
+        cm_key_t key;
+        LARGE_INTEGER LOffset, LLength;
+        int sLockType;
+
+        LOffset.HighPart = SMB_FID_QLOCK_HIGH;
+        LOffset.LowPart = SMB_FID_QLOCK_LOW;
+        LLength.HighPart = 0;
+        LLength.LowPart = SMB_FID_QLOCK_LENGTH;
+
+        if (fidflags & SMB_FID_SHARE_READ) {
+            sLockType = LOCKING_ANDX_SHARED_LOCK;
+        } else {
+            sLockType = 0;
+        }
+
+        key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
+        
+        lock_ObtainMutex(&scp->mx);
+        code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
+        lock_ReleaseMutex(&scp->mx);
+
+        if (code) {
+            fidp->flags = SMB_FID_DELETE;
+            smb_ReleaseFID(fidp);
+
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            
+            return CM_ERROR_SHARING_VIOLATION;
+        }
+    }
+
     /* save a pointer to the vnode */
     fidp->scp = scp;
 
@@ -5806,7 +6559,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     fidp->NTopen_wholepathp = realPathp;
 
     /* we don't need this any longer */
-    if (dscp) cm_ReleaseSCache(dscp);
+    if (dscp) 
+        cm_ReleaseSCache(dscp);
 
     cm_Open(scp, 0, userp);
 
@@ -5929,15 +6683,15 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
        smb_packet_t *outp)
 {
-       smb_packet_t *savedPacketp;
-       ULONG filter; USHORT fid, watchtree;
-       smb_fid_t *fidp;
-       cm_scache_t *scp;
+    smb_packet_t *savedPacketp;
+    ULONG filter; USHORT fid, watchtree;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
         
-       filter = smb_GetSMBParm(inp, 19)
-                       | (smb_GetSMBParm(inp, 20) << 16);
-       fid = smb_GetSMBParm(inp, 21);
-       watchtree = smb_GetSMBParm(inp, 22) && 0xffff;  /* TODO: should this be 0xff ? */
+    filter = smb_GetSMBParm(inp, 19) |
+             (smb_GetSMBParm(inp, 20) << 16);
+    fid = smb_GetSMBParm(inp, 21);
+    watchtree = smb_GetSMBParm(inp, 22) && 0xffff;  /* TODO: should this be 0xff ? */
 
     fidp = smb_FindFID(vcp, fid, 0);
     if (!fidp) {
@@ -5945,13 +6699,13 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
         return CM_ERROR_BADFD;
     }
 
-       savedPacketp = smb_CopyPacket(inp);
+    savedPacketp = smb_CopyPacket(inp);
     smb_HoldVC(vcp);
-       savedPacketp->vcp = vcp;
-       lock_ObtainMutex(&smb_Dir_Watch_Lock);
-       savedPacketp->nextp = smb_Directory_Watches;
-       smb_Directory_Watches = savedPacketp;
-       lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+    savedPacketp->vcp = vcp;
+    lock_ObtainMutex(&smb_Dir_Watch_Lock);
+    savedPacketp->nextp = smb_Directory_Watches;
+    smb_Directory_Watches = savedPacketp;
+    lock_ReleaseMutex(&smb_Dir_Watch_Lock);
 
     osi_Log4(smb_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
              filter, fid, watchtree, osi_LogSaveString(smb_logp, fidp->NTopen_wholepathp));
@@ -5965,91 +6719,91 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
     lock_ReleaseMutex(&scp->mx);
     smb_ReleaseFID(fidp);
 
-       outp->flags |= SMB_PACKETFLAG_NOSEND;
-       return 0;
+    outp->flags |= SMB_PACKETFLAG_NOSEND;
+    return 0;
 }
 
 unsigned char nullSecurityDesc[36] = {
-       0x01,                           /* security descriptor revision */
-       0x00,                           /* reserved, should be zero */
-       0x00, 0x80,                     /* security descriptor control;
-                                        * 0x8000 : self-relative format */
-       0x14, 0x00, 0x00, 0x00,         /* offset of owner SID */
-       0x1c, 0x00, 0x00, 0x00,         /* offset of group SID */
-       0x00, 0x00, 0x00, 0x00,         /* offset of DACL would go here */
-       0x00, 0x00, 0x00, 0x00,         /* offset of SACL would go here */
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       /* "null SID" owner SID */
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-                                       /* "null SID" group SID */
-};
+    0x01,                              /* security descriptor revision */
+    0x00,                              /* reserved, should be zero */
+    0x00, 0x80,                                /* security descriptor control;
+                                         * 0x8000 : self-relative format */
+    0x14, 0x00, 0x00, 0x00,            /* offset of owner SID */
+    0x1c, 0x00, 0x00, 0x00,            /* offset of group SID */
+    0x00, 0x00, 0x00, 0x00,            /* offset of DACL would go here */
+    0x00, 0x00, 0x00, 0x00,            /* offset of SACL would go here */
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                        /* "null SID" owner SID */
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+                                        /* "null SID" group SID */
+};      
 
 long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       int parmOffset, parmCount, dataOffset, dataCount;
-       int parmSlot;
-       int maxData;
-       char *outData;
-       char *parmp;
-       USHORT *sparmp;
-       ULONG *lparmp;
-       USHORT fid;
-       ULONG securityInformation;
-
-       parmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
-                       | (smb_GetSMBOffsetParm(inp, 12, 1) << 16);
-       parmp = inp->data + parmOffset;
-       sparmp = (USHORT *) parmp;
-       lparmp = (ULONG *) parmp;
-
-       fid = sparmp[0];
-       securityInformation = lparmp[1];
-
-       maxData = smb_GetSMBOffsetParm(inp, 7, 1)
-                       | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
-
-       if (maxData < 36)
-               dataCount = 0;
-       else
-               dataCount = 36;
-
-       /* out parms */
-       parmOffset = 8*4 + 39;
-       parmOffset += 1;        /* pad to 4 */
-       parmCount = 4;
-       dataOffset = parmOffset + parmCount;
-
-       parmSlot = 1;
-       outp->oddByte = 1;
-       /* Total Parameter Count */
-       smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
-       /* Total Data Count */
-       smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
-       /* Parameter Count */
-       smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
-       /* Parameter Offset */
-       smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
-       /* Parameter Displacement */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Data Count */
-       smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
-       /* Data Offset */
-       smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
-       /* Data Displacement */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       smb_SetSMBParmByte(outp, parmSlot, 0);  /* Setup Count */
-       smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
-
-       outData = smb_GetSMBData(outp, NULL);
-       outData++;                      /* round to get to parmOffset */
-       *((ULONG *)outData) = 36; outData += 4; /* length */
-
-       if (maxData >= 36) {
-               memcpy(outData, nullSecurityDesc, 36);
-               outData += 36;
-               return 0;
-       } else
-               return CM_ERROR_BUFFERTOOSMALL;
+    int parmOffset, parmCount, dataOffset, dataCount;
+    int parmSlot;
+    int maxData;
+    char *outData;
+    char *parmp;
+    USHORT *sparmp;
+    ULONG *lparmp;
+    USHORT fid;
+    ULONG securityInformation;
+
+    parmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
+        | (smb_GetSMBOffsetParm(inp, 12, 1) << 16);
+    parmp = inp->data + parmOffset;
+    sparmp = (USHORT *) parmp;
+    lparmp = (ULONG *) parmp;
+
+    fid = sparmp[0];
+    securityInformation = lparmp[1];
+
+    maxData = smb_GetSMBOffsetParm(inp, 7, 1)
+        | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+
+    if (maxData < 36)
+        dataCount = 0;
+    else
+        dataCount = 36;
+
+    /* out parms */
+    parmOffset = 8*4 + 39;
+    parmOffset += 1;   /* pad to 4 */
+    parmCount = 4;
+    dataOffset = parmOffset + parmCount;
+
+    parmSlot = 1;
+    outp->oddByte = 1;
+    /* Total Parameter Count */
+    smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
+    /* Total Data Count */
+    smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
+    /* Parameter Count */
+    smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
+    /* Parameter Offset */
+    smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+    /* Parameter Displacement */
+    smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+    /* Data Count */
+    smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
+    /* Data Offset */
+    smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+    /* Data Displacement */
+    smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+    smb_SetSMBParmByte(outp, parmSlot, 0);     /* Setup Count */
+    smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
+
+    outData = smb_GetSMBData(outp, NULL);
+    outData++;                 /* round to get to parmOffset */
+    *((ULONG *)outData) = 36; outData += 4;    /* length */
+
+    if (maxData >= 36) {
+        memcpy(outData, nullSecurityDesc, 36);
+        outData += 36;
+        return 0;
+    } else
+        return CM_ERROR_BUFFERTOOSMALL;
 }
 
 long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -6062,7 +6816,7 @@ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     /* We can handle long names */
     if (vcp->flags & SMB_VCFLAG_USENT)
-        ((smb_t *)outp)->flg2 |= 0x40; /* IS_LONG_NAME */
+        ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
         
     switch (function) {
     case 6: 
@@ -6163,7 +6917,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         lock_ReleaseMutex(&dscp->mx);
 
         /* Convert to response packet */
-        ((smb_t *) watch)->reb = 0x80;
+        ((smb_t *) watch)->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
         ((smb_t *) watch)->wct = 0;
 
         /* out parms */
@@ -6208,6 +6962,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         smb_SetSMBDataLength(watch, parmCount + 1);
 
         if (parmCount != 0) {
+            char * p;
             outData = smb_GetSMBData(watch, NULL);
             outData++; /* round to get to parmOffset */
             oldOutData = outData;
@@ -6217,7 +6972,11 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
             /* Action */
             *((DWORD *)outData) = nameLen*2; outData += 4;
             /* File Name Length */
-            mbstowcs((WCHAR *)outData, filename, nameLen);
+            p = strdup(filename);
+            if (smb_StoreAnsiFilenames)
+                CharToOem(p,p);
+            mbstowcs((WCHAR *)outData, p, nameLen);
+            free(p);
             /* File Name */
             if (twoEntries) {
                 outData = oldOutData + oldParmCount;
@@ -6227,8 +6986,11 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                 /* Action */
                 *((DWORD *)outData) = otherNameLen*2;
                 outData += 4;  /* File Name Length */
-                mbstowcs((WCHAR *)outData, otherFilename,
-                          otherNameLen);       /* File Name */
+                p = strdup(otherFilename);
+                if (smb_StoreAnsiFilenames)
+                    CharToOem(p,p);
+                mbstowcs((WCHAR *)outData, p, otherNameLen);   /* File Name */
+                free(p);
             }       
         }       
 
@@ -6245,11 +7007,10 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
             ((smb_t *) watch)->errLow = 0;
             ((smb_t *) watch)->errHigh = 0;
             /* Set NT Status codes flag */
-            ((smb_t *) watch)->flg2 |= 0x4000;
+            ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
         }
 
         smb_SendPacket(vcp, watch);
-        smb_ReleaseVC(vcp);
         smb_FreePacket(watch);
         watch = nextWatch;
     }
@@ -6314,10 +7075,8 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             ((smb_t *)watch)->reh = 0x1;
             ((smb_t *)watch)->errLow = 0;
             ((smb_t *)watch)->errHigh = 0xC0;
-            ((smb_t *)watch)->flg2 |= 0x4000;
+            ((smb_t *)watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
             smb_SendPacket(vcp, watch);
-            if (watch->vcp)
-                smb_ReleaseVC(watch->vcp);
             smb_FreePacket(watch);
             return 0;
         }
@@ -6340,9 +7099,8 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *oldname, *newname;
+    char *oldPathp, *newPathp;
     long code = 0;
-    cm_user_t *userp;
     char * tp;
     int attrs;
     int rename_type;
@@ -6356,18 +7114,22 @@ long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 
     tp = smb_GetSMBData(inp, NULL);
-    oldname = smb_ParseASCIIBlock(tp, &tp);
-    newname = smb_ParseASCIIBlock(tp, &tp);
+    oldPathp = smb_ParseASCIIBlock(tp, &tp);
+    if (smb_StoreAnsiFilenames)
+        OemToChar(oldPathp,oldPathp);
+    newPathp = smb_ParseASCIIBlock(tp, &tp);
+    if (smb_StoreAnsiFilenames)
+        OemToChar(newPathp,newPathp);
 
     osi_Log3(smb_logp, "NTRename for [%s]->[%s] type [%s]",
-             osi_LogSaveString(smb_logp, oldname),
-             osi_LogSaveString(smb_logp, newname),
+             osi_LogSaveString(smb_logp, oldPathp),
+             osi_LogSaveString(smb_logp, newPathp),
              ((rename_type==RENAME_FLAG_RENAME)?"rename":"hardlink"));
 
     if (rename_type == RENAME_FLAG_RENAME) {
-        code = smb_Rename(vcp,inp,oldname,newname,attrs);
+        code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
     } else { /* RENAME_FLAG_HARD_LINK */
-        code = smb_Link(vcp,inp,oldname,newname);
+        code = smb_Link(vcp,inp,oldPathp,newPathp);
     }
     return code;
 }
@@ -6387,7 +7149,7 @@ cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine)
         lock_ObtainMutex(&unp->mx);
         unp->userp = cm_NewUser();
         lock_ReleaseMutex(&unp->mx);
-               osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
+        osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
         osi_LogEvent("AFS smb_FindCMUserByName : New User",NULL,"name[%s] machine[%s]",usern,machine);
     }  else    {
         osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));