cifs-rap-20040721
[openafs.git] / src / WINNT / afsd / smb3.c
index ec4b853..54b578f 100644 (file)
@@ -12,6 +12,9 @@
 
 #ifndef DJGPP
 #include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <lmaccess.h>
 #endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
@@ -25,8 +28,6 @@
 
 #include "smb.h"
 
-extern smb_vc_t *dead_vcp;
-
 extern osi_hyper_t hzero;
 
 smb_packet_t *smb_Directory_Watches = NULL;
@@ -34,6 +35,8 @@ osi_mutex_t smb_Dir_Watch_Lock;
 
 smb_tran2Dispatch_t smb_tran2DispatchTable[SMB_TRAN2_NOPCODES];
 
+smb_tran2Dispatch_t smb_rapDispatchTable[SMB_RAP_NOPCODES];
+
 /* protected by the smb_globalLock */
 smb_tran2Packet_t *smb_tran2AssemblyQueuep;
 
@@ -42,21 +45,21 @@ smb_tran2Packet_t *smb_tran2AssemblyQueuep;
 cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
 {
        smb_user_t *uidp;
-        cm_user_t *up = NULL;
+    cm_user_t *up = NULL;
         
-        uidp = smb_FindUID(vcp, inp->uid, 0);
-        if (!uidp) return NULL;
+    uidp = smb_FindUID(vcp, inp->uid, 0);
+    if (!uidp) return NULL;
         
        lock_ObtainMutex(&uidp->mx);
-        if (uidp->unp) {
-          up = uidp->unp->userp;
-          cm_HoldUser(up);
-        }
+    if (uidp->unp) {
+        up = uidp->unp->userp;
+        cm_HoldUser(up);
+    }
        lock_ReleaseMutex(&uidp->mx);
 
-        smb_ReleaseUID(uidp);
-        
-        return up;
+    smb_ReleaseUID(uidp);
+
+    return up;
 }
 
 /*
@@ -91,51 +94,691 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
 
 int smb_V3IsStarMask(char *maskp)
 {
-        char tc;
+    char tc;
 
        while (tc = *maskp++)
-         if (tc == '?' || tc == '*') return 1;
+        if (tc == '?' || tc == '*') 
+            return 1;
        return 0;
 }
 
 unsigned char *smb_ParseString(unsigned char *inp, char **chainpp)
 {
-        if (chainpp) {
+    if (chainpp) {
                /* 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;
+    char * buffer;
+
+    va_start( args, format );
+    len = _vscprintf( format, args ) // _vscprintf doesn't count
+                               + 3; // terminating '\0' + '\n'
+    buffer = malloc( len * sizeof(char) );
+    vsprintf( buffer, format, args );
+    strcat(buffer, "\n");
+    OutputDebugString(buffer);
+    free( buffer );
+}
+
+void OutputDebugHexDump(unsigned char * buffer, int len) {
+    int i,j,k;
+    char buf[256];
+    static char tr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+    OutputDebugF("Hexdump length [%d]",len);
+
+    for(i=0;i<len;i++) {
+        if(!(i%16)) {
+            if(i)
+                OutputDebugString(buf);
+            sprintf(buf,"%5x",i);
+            memset(buf+5,' ',80);
+            buf[85] = 0;
+            strcat(buf,"\n");
+        }
+
+        j = (i%16);
+        j = j*3 + 7 + ((j>7)?1:0);
+        k = buffer[i];
+
+        buf[j] = tr[k / 16]; buf[j+1] = tr[k % 16];
+
+        j = (i%16);
+        j = j + 56 + ((j>7)?1:0);
+
+        buf[j] = (k>32 && k<127)?k:'.';
+    }    
+    if(i)
+        OutputDebugString(buf);
+}   
+/**/
+
+#define SMB_EXT_SEC_PACKAGE_NAME "Negotiate"
+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;
+
+       *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;
+       }
+
+       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_E_OK )
+            OutputDebugF("AcceptSecurityContext status != CONTINUE  %lX", status);
+    }
+
+    /* Discard partial security context */
+    DeleteSecurityContext(&ctx);
+
+       if (secTok.pvBuffer) FreeContextBuffer( secTok.pvBuffer );
+
+       /* Discard credentials handle.  We'll reacquire one when we get the session setup X */
+       FreeCredentialsHandle(&creds);
+
+  nes_0:
+       return;
+}
+
+struct smb_ext_context {
+       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);
+       }
+
+    if (secBlobIn) {
+        OutputDebugF("Received incoming token:");
+        OutputDebugHexDump(secBlobIn,secBlobInLength);
+    }
+    
+    if (secCtx) {
+        OutputDebugF("Continuing with existing context.");             
+        creds = secCtx->creds;
+        ctx = secCtx->ctx;
+
+               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;
+       }
+
+    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;
+       }
+
+       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");
+
+               newSecCtx = malloc(sizeof(*newSecCtx));
+
+               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 );
+
+               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");
+
+               *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");
+
+               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;
+
+               lock_ObtainMutex( &vcp->mx );
+               vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
+               vcp->secCtx = newSecCtx;
+               lock_ReleaseMutex( &vcp->mx );
+
+               code = CM_ERROR_GSSCONTINUE;
+       }
+
+       if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
+               /* woo hoo! */
+               SecPkgContext_Names names;
+
+               OutputDebugF("Authentication completed");
+        OutputDebugF("Returned flags : [%lX]", flags);
+
+               if (!QueryContextAttributes(&ctx, SECPKG_ATTR_NAMES, &names)) {
+            OutputDebugF("Received name [%s]", names.sUserName);
+            strcpy(usern, names.sUserName);
+            strlwr(usern); /* in tandem with smb_GetNormalizedUsername */
+            FreeContextBuffer(names.sUserName);
+        } else {
+            /* Force the user to retry if the context is invalid */
+            OutputDebugF("QueryContextAttributes Names failed [%x]", GetLastError());
+            code = CM_ERROR_BADPASSWORD; 
+        }
+       } else if (!code) {
+        switch ( status ) {
+        case SEC_E_INVALID_TOKEN:
+            OutputDebugF("Returning bad password :: INVALID_TOKEN");
+            break;
+        case SEC_E_INVALID_HANDLE:
+            OutputDebugF("Returning bad password :: INVALID_HANDLE");
+            break;
+        case SEC_E_LOGON_DENIED:
+            OutputDebugF("Returning bad password :: LOGON_DENIED");
+            break;
+        case SEC_E_UNKNOWN_CREDENTIALS:
+            OutputDebugF("Returning bad password :: UNKNOWN_CREDENTIALS");
+            break;
+        case SEC_E_NO_CREDENTIALS:
+            OutputDebugF("Returning bad password :: NO_CREDENTIALS");
+            break;
+        case SEC_E_CONTEXT_EXPIRED:
+            OutputDebugF("Returning bad password :: CONTEXT_EXPIRED");
+            break;
+        case SEC_E_INCOMPLETE_CREDENTIALS:
+            OutputDebugF("Returning bad password :: INCOMPLETE_CREDENTIALS");
+            break;
+        case SEC_E_WRONG_PRINCIPAL:
+            OutputDebugF("Returning bad password :: WRONG_PRINCIPAL");
+            break;
+        case SEC_E_TIME_SKEW:
+            OutputDebugF("Returning bad password :: TIME_SKEW");
+            break;
+        default:
+            OutputDebugF("Returning bad password :: Status == %lX", status);
         }
-        return inp;
+               code = CM_ERROR_BADPASSWORD;
+       }
+
+       if (secCtx) {
+               if (secCtx->partialToken) free(secCtx->partialToken);
+               free(secCtx);
+       }
+
+       if (assembledBlob) {
+               free(assembledBlob);
+       }
+
+       if (secTokOut.pvBuffer)
+               FreeContextBuffer(secTokOut.pvBuffer);
+
+       if (code != CM_ERROR_GSSCONTINUE) {
+               DeleteSecurityContext(&ctx);
+               FreeCredentialsHandle(&creds);
+       }
+
+  aue_0:
+       return code;
 }
 
+#define P_LEN 256
+#define P_RESP_LEN 128
+
+/* 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;
+};
+
+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));
+
+       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.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);
+        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;
+       }
+}
+
+/* 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);
+       }
+
+       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.
+ */
 long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     char *tp;
-    char *usern, *pwd, *pwdx;
-    smb_user_t *uidp, *dead_uidp;
+    smb_user_t *uidp;
     unsigned short newUid;
-    unsigned long caps;
+    unsigned long caps = 0;
     cm_user_t *userp;
     smb_username_t *unp;
     char *s1 = " ";
+    long code = 0; 
+    char usern[SMB_MAX_USERNAME_LENGTH];
+    char *secBlobOut = NULL;
+    int  secBlobOutLength = 0;
 
     /* Check for bad conns */
     if (vcp->flags & SMB_VCFLAG_REMOTECONN)
         return CM_ERROR_REMOTECONN;
 
-    /* For NT LM 0.12 and up, get capabilities */
     if (vcp->flags & SMB_VCFLAG_USENT) {
-        caps = smb_GetSMBParm(inp, 11);
-        if (caps & 0x40)
+        if (smb_authType == SMB_AUTH_EXTENDED) {
+            /* extended authentication */
+            char *secBlobIn;
+            int secBlobInLength;
+        
+            if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
+                caps = smb_GetSMBParm(inp,10) | (((unsigned long) smb_GetSMBParm(inp,11)) << 16);
+            }
+
+            secBlobInLength = smb_GetSMBParm(inp, 7);
+            secBlobIn = smb_GetSMBData(inp, NULL);
+
+            code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength);
+
+            if (code == CM_ERROR_GSSCONTINUE) {
+                smb_SetSMBParm(outp, 2, 0);
+                smb_SetSMBParm(outp, 3, secBlobOutLength);
+                smb_SetSMBDataLength(outp, secBlobOutLength + smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength);
+                tp = smb_GetSMBData(outp, NULL);
+                if (secBlobOutLength) {
+                    memcpy(tp, secBlobOut, secBlobOutLength);
+                    free(secBlobOut);
+                    tp += secBlobOutLength;
+                }      
+                memcpy(tp,smb_ServerOS,smb_ServerOSLength);
+                tp += smb_ServerOSLength;
+                memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength);
+                tp += smb_ServerLanManagerLength;
+                memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength);
+                tp += smb_ServerDomainNameLength;
+            }
+
+            /* TODO: handle return code and continue auth. Also free secBlobOut if applicable. */
+        } else {
+            unsigned ciPwdLength, csPwdLength;
+            char *ciPwd, *csPwd;
+            char *accountName;
+            char *primaryDomain;
+            int  datalen;
+
+            /* 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 */
+
+            tp = smb_GetSMBData(inp, &datalen);
+
+            OutputDebugF("Session packet data size [%d]",datalen);
+
+            ciPwd = tp;
+            tp += ciPwdLength;
+            csPwd = tp;
+            tp += csPwdLength;
+
+            accountName = smb_ParseString(tp, &tp);
+            primaryDomain = smb_ParseString(tp, NULL);
+
+            if (smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
+                /* shouldn't happen */
+                code = CM_ERROR_BADSMB;
+                goto after_read_packet;
+            }
+
+            /* capabilities are only valid for first session packet */
+            if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
+                caps = smb_GetSMBParm(inp, 11) | (((unsigned long)smb_GetSMBParm(inp, 12)) << 16);
+            }
+
+            if (smb_authType == SMB_AUTH_NTLM) {
+                code = smb_AuthenticateUserLM(vcp, accountName, primaryDomain, ciPwd, ciPwdLength, csPwd, csPwdLength);
+            }
+        }
+    }  else { /* V3 */
+        unsigned ciPwdLength;
+        char *ciPwd;
+               char *accountName;
+               char *primaryDomain;
+
+               ciPwdLength = smb_GetSMBParm(inp, 7);
+        tp = smb_GetSMBData(inp, NULL);
+               ciPwd = tp;
+               tp += ciPwdLength;
+
+               accountName = smb_ParseString(tp, &tp);
+               primaryDomain = smb_ParseString(tp, NULL);
+
+               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);
+               }
+       }
+
+  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;
+        /* for the moment we can only deal with NTSTATUS */
+        if (caps & NTNEGOTIATE_CAPABILITY_NTSTATUS) {
             vcp->flags |= SMB_VCFLAG_STATUS32;
-        /* for now, ignore other capability bits */
-    }
+        }
+               lock_ReleaseMutex(&vcp->mx);
+       }
 
-    /* Parse the data */
-    tp = smb_GetSMBData(inp, NULL);
-    if (vcp->flags & SMB_VCFLAG_USENT)
-        pwdx = smb_ParseString(tp, &tp);
-    pwd = smb_ParseString(tp, &tp);
-    usern = smb_ParseString(tp, &tp);
+       /* 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;
+       }
+
+       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
@@ -152,7 +795,7 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         userp = unp->userp;
         newUid = (unsigned short)uidp->userID;  /* For some reason these are different types!*/
                osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,usern);
-               osi_Log3(afsd_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid);
+               osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid);
         smb_ReleaseUID(uidp);
     }
     else {
@@ -162,11 +805,12 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         /* Create a new UID and cm_user_t structure */
         userp = unp->userp;
         if (!userp)
-          userp = cm_NewUser();
+            userp = cm_NewUser();
         lock_ObtainMutex(&vcp->mx);
-               if(!vcp->uidCounter) vcp->uidCounter++; /* handle unlikely wraparounds */
-               newUid = (strlen(usern)==0)?0:vcp->uidCounter++;
-               lock_ReleaseMutex(&vcp->mx);
+        if (!vcp->uidCounter)
+            vcp->uidCounter++; /* handle unlikely wraparounds */
+        newUid = (strlen(usern)==0)?0:vcp->uidCounter++;
+        lock_ReleaseMutex(&vcp->mx);
 
         /* Create a new smb_user_t structure and connect them up */
         lock_ObtainMutex(&unp->mx);
@@ -176,8 +820,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         uidp = smb_FindUID(vcp, newUid, SMB_FLAG_CREATE);
         lock_ObtainMutex(&uidp->mx);
         uidp->unp = unp;
-               osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d],TicketKTCName[%s]",vcp,vcp->lana,vcp->lsn,newUid,usern);
-               osi_Log4(afsd_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid);
+               osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d],TicketKTCName[%s]",(int)vcp,vcp->lana,vcp->lsn,newUid,usern);
+               osi_Log4(smb_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid);
         lock_ReleaseMutex(&uidp->mx);
         smb_ReleaseUID(uidp);
     }
@@ -187,10 +831,45 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     /* Also to the next chained message */
     ((smb_t *)inp)->uid = newUid;
 
-    osi_Log3(afsd_logp, "SMB3 session setup name %s creating ID %d%s",
-             osi_LogSaveString(afsd_logp, usern), newUid, osi_LogSaveString(afsd_logp, s1));
+    osi_Log3(smb_logp, "SMB3 session setup name %s creating ID %d%s",
+             osi_LogSaveString(smb_logp, usern), newUid, osi_LogSaveString(smb_logp, s1));
+
     smb_SetSMBParm(outp, 2, 0);
-    smb_SetSMBDataLength(outp, 0);
+
+    if (vcp->flags & SMB_VCFLAG_USENT) {
+        if (smb_authType == SMB_AUTH_EXTENDED) {
+            smb_SetSMBParm(outp, 3, secBlobOutLength);
+            smb_SetSMBDataLength(outp, secBlobOutLength + smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength);
+            tp = smb_GetSMBData(outp, NULL);
+            if (secBlobOutLength) {
+                memcpy(tp, secBlobOut, secBlobOutLength);
+                free(secBlobOut);
+                tp += secBlobOutLength;
+            }  
+            memcpy(tp,smb_ServerOS,smb_ServerOSLength);
+            tp += smb_ServerOSLength;
+            memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength);
+            tp += smb_ServerLanManagerLength;
+            memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength);
+            tp += smb_ServerDomainNameLength;
+        } else {
+            smb_SetSMBDataLength(outp, 0);
+        }
+    } else {
+        if (smb_authType == SMB_AUTH_EXTENDED) {
+            smb_SetSMBDataLength(outp, smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength);
+            tp = smb_GetSMBData(outp, NULL);
+            memcpy(tp,smb_ServerOS,smb_ServerOSLength);
+            tp += smb_ServerOSLength;
+            memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength);
+            tp += smb_ServerLanManagerLength;
+            memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength);
+            tp += smb_ServerDomainNameLength;
+        } else {
+            smb_SetSMBDataLength(outp, 0);
+        }
+    }
+
     return 0;
 }
 
@@ -204,18 +883,16 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
 
        /* find the tree and free it */
-        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-               /* TODO: smb_ReleaseUID? */
-        if (uidp) {
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    /* TODO: smb_ReleaseUID() ? */
+    if (uidp) {
                char *s1 = NULL, *s2 = NULL;
 
                if (s2 == NULL) s2 = " ";
                if (s1 == NULL) {s1 = s2; s2 = " ";}
 
-               osi_Log4(afsd_logp, "SMB3 user logoffX uid %d name %s%s%s",
-                        uidp->userID,
-                        osi_LogSaveString(afsd_logp,
-                 (uidp->unp) ? uidp->unp->name: " "), s1, 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);
 
                lock_ObtainMutex(&uidp->mx);
                uidp->flags |= SMB_USERFLAG_DELETE;
@@ -223,119 +900,153 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 * it doesn't get deleted right away
                 * because the vcp points to it
                 */
-                lock_ReleaseMutex(&uidp->mx);
-        }
-       else
-               osi_Log0(afsd_logp, "SMB3 user logoffX");
+        lock_ReleaseMutex(&uidp->mx);
+    }
+       else    
+               osi_Log0(smb_logp, "SMB3 user logoffX");
 
-        smb_SetSMBDataLength(outp, 0);
-        return 0;
+    smb_SetSMBDataLength(outp, 0);
+    return 0;
 }
 
+#define SMB_SUPPORT_SEARCH_BITS        0x0001
+
 long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        smb_tid_t *tidp;
-        unsigned short newTid;
-        char shareName[256];
+    smb_tid_t *tidp;
+    smb_user_t *uidp;
+    unsigned short newTid;
+    char shareName[256];
        char *sharePath;
        int shareFound;
-        char *tp;
-        char *pathp;
-        char *passwordp;
+    char *tp;
+    char *pathp;
+    char *passwordp;
        char *servicep;
-        cm_user_t *userp;
+    cm_user_t *userp;
+       int ipc = 0;
         
-       osi_Log0(afsd_logp, "SMB3 receive tree connect");
+       osi_Log0(smb_logp, "SMB3 receive tree connect");
 
        /* parse input parameters */
        tp = smb_GetSMBData(inp, NULL);
-        passwordp = smb_ParseString(tp, &tp);
+    passwordp = smb_ParseString(tp, &tp);
        pathp = smb_ParseString(tp, &tp);
        servicep = smb_ParseString(tp, &tp);
 
        tp = strrchr(pathp, '\\');
-        if (!tp) {
-                return CM_ERROR_BADSMB;
-        }
-        strcpy(shareName, tp+1);
+    if (!tp) {
+        return CM_ERROR_BADSMB;
+    }
+    strcpy(shareName, tp+1);
 
-       if (strcmp(servicep, "IPC") == 0 || strcmp(shareName, "IPC$") == 0)
+       if (strcmp(servicep, "IPC") == 0 || strcmp(shareName, "IPC$") == 0) {
+#ifndef NO_IPC
+               osi_Log0(smb_logp, "TreeConnectX connecting to IPC$");
+               ipc = 1;
+#else
                return CM_ERROR_NOIPC;
+#endif
+       }
 
-        userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
 
        lock_ObtainMutex(&vcp->mx);
-        newTid = vcp->tidCounter++;
+    newTid = vcp->tidCounter++;
        lock_ReleaseMutex(&vcp->mx);
         
        tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
-       shareFound = smb_FindShare(vcp, inp, shareName, &sharePath);
+
+       if(!ipc) {
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+       shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
+    if (uidp)
+        smb_ReleaseUID(uidp);
        if (!shareFound) {
                smb_ReleaseTID(tidp);
                return CM_ERROR_BADSHARENAME;
        }
-        lock_ObtainMutex(&tidp->mx);
-        tidp->userp = userp;
-       tidp->pathname = sharePath;
-        lock_ReleaseMutex(&tidp->mx);
-        smb_ReleaseTID(tidp);
 
        if (vcp->flags & SMB_VCFLAG_USENT)
-               smb_SetSMBParm(outp, 2, 0);     /* OptionalSupport bits */
+    {
+        int policy = smb_FindShareCSCPolicy(shareName);
+        smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | (policy << 2));
+    }
+       } else {
+               smb_SetSMBParm(outp, 2, 0);
+               sharePath = NULL;
+       }
+
+    lock_ObtainMutex(&tidp->mx);
+    tidp->userp = userp;
+       tidp->pathname = sharePath;
+       if(ipc) tidp->flags |= SMB_TIDFLAG_IPC;
+    lock_ReleaseMutex(&tidp->mx);
+    smb_ReleaseTID(tidp);
 
        ((smb_t *)outp)->tid = newTid;
        ((smb_t *)inp)->tid = newTid;
        tp = smb_GetSMBData(outp, NULL);
-        *tp++ = 'A';
-        *tp++ = ':';
-        *tp++ = 0;
-        smb_SetSMBDataLength(outp, 3);
-        
-        osi_Log1(afsd_logp, "SMB3 tree connect created ID %d", newTid);
-        return 0;
+       if(!ipc) {
+    *tp++ = 'A';
+    *tp++ = ':';
+    *tp++ = 0;
+    smb_SetSMBDataLength(outp, 3);
+       } else {
+               strcpy(tp, "IPC");
+               smb_SetSMBDataLength(outp, 4);
+       }
+
+    osi_Log1(smb_logp, "SMB3 tree connect created ID %d", newTid);
+    return 0;
 }
 
 /* must be called with global tran lock held */
 smb_tran2Packet_t *smb_FindTran2Packet(smb_vc_t *vcp, smb_packet_t *inp)
 {
        smb_tran2Packet_t *tp;
-        smb_t *smbp;
+    smb_t *smbp;
         
-        smbp = (smb_t *) inp->data;
+    smbp = (smb_t *) inp->data;
        for(tp = smb_tran2AssemblyQueuep; tp; tp = (smb_tran2Packet_t *) osi_QNext(&tp->q)) {
                if (tp->vcp == vcp && tp->mid == smbp->mid && tp->tid == smbp->tid)
-                       return tp;
-        }
-        return NULL;
+            return tp;
+    }
+    return NULL;
 }
 
 smb_tran2Packet_t *smb_NewTran2Packet(smb_vc_t *vcp, smb_packet_t *inp,
        int totalParms, int totalData)
 {
        smb_tran2Packet_t *tp;
-        smb_t *smbp;
+    smb_t *smbp;
         
-        smbp = (smb_t *) inp->data;
+    smbp = (smb_t *) inp->data;
        tp = malloc(sizeof(*tp));
-        memset(tp, 0, sizeof(*tp));
-        tp->vcp = vcp;
-        smb_HoldVC(vcp);
-        tp->curData = tp->curParms = 0;
-        tp->totalData = totalData;
-        tp->totalParms = totalParms;
-        tp->tid = smbp->tid;
-        tp->mid = smbp->mid;
-        tp->uid = smbp->uid;
-        tp->pid = smbp->pid;
+    memset(tp, 0, sizeof(*tp));
+    tp->vcp = vcp;
+    smb_HoldVC(vcp);
+    tp->curData = tp->curParms = 0;
+    tp->totalData = totalData;
+    tp->totalParms = totalParms;
+    tp->tid = smbp->tid;
+    tp->mid = smbp->mid;
+    tp->uid = smbp->uid;
+    tp->pid = smbp->pid;
        tp->res[0] = smbp->res[0];
        osi_QAdd((osi_queue_t **)&smb_tran2AssemblyQueuep, &tp->q);
-        tp->opcode = smb_GetSMBParm(inp, 14);
        if (totalParms != 0)
-               tp->parmsp = malloc(totalParms);
+        tp->parmsp = malloc(totalParms);
        if (totalData != 0)
-               tp->datap = malloc(totalData);
+        tp->datap = malloc(totalData);
+       if (smbp->com == 0x25 || smbp->com == 0x26)
+               tp->com = 0x25;
+       else {
+           tp->opcode = smb_GetSMBParm(inp, 14);
+               tp->com = 0x32;
+       }
        tp->flags |= SMB_TRAN2PFLAG_ALLOC;
-        return tp;
+    return tp;
 }
 
 smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
@@ -348,18 +1059,19 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
        unsigned short dataAlign;
         
        tp = malloc(sizeof(*tp));
-        memset(tp, 0, sizeof(*tp));
-        tp->vcp = NULL;
-        tp->curData = tp->curParms = 0;
-        tp->totalData = totalData;
-        tp->totalParms = totalParms;
+    memset(tp, 0, sizeof(*tp));
+    tp->vcp = NULL;
+    tp->curData = tp->curParms = 0;
+    tp->totalData = totalData;
+    tp->totalParms = totalParms;
        tp->oldTotalParms = totalParms;
-        tp->tid = inp->tid;
-        tp->mid = inp->mid;
-        tp->uid = inp->uid;
-        tp->pid = inp->pid;
+    tp->tid = inp->tid;
+    tp->mid = inp->mid;
+    tp->uid = inp->uid;
+    tp->pid = inp->pid;
        tp->res[0] = inp->res[0];
-        tp->opcode = inp->opcode;
+    tp->opcode = inp->opcode;
+       tp->com = inp->com;
 
        /*
         * We calculate where the parameters and data will start.
@@ -376,20 +1088,20 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
        dataOffset += dataAlign;
        tp->datap = outp->data + dataOffset;
 
-        return tp;
+    return tp;
 }
 
 /* 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->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);
+    free(t2p);
 }
 
 /* called with a VC, an input packet to respond to, and an error code.
@@ -398,29 +1110,29 @@ void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
 void smb_SendTran2Error(smb_vc_t *vcp, smb_tran2Packet_t *t2p,
        smb_packet_t *tp, long code)
 {
-        smb_t *smbp;
-        unsigned short errCode;
-        unsigned char errClass;
+    smb_t *smbp;
+    unsigned short errCode;
+    unsigned char errClass;
        unsigned long NTStatus;
 
-        if (vcp->flags & SMB_VCFLAG_STATUS32)
+    if (vcp->flags & SMB_VCFLAG_STATUS32)
                smb_MapNTError(code, &NTStatus);
        else
                smb_MapCoreError(code, vcp, &errCode, &errClass);
 
-        smb_FormatResponsePacket(vcp, NULL, tp);
-        smbp = (smb_t *) tp;
-        
+    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 */
         
-        /* now copy important fields from the tran 2 packet */
-        smbp->com = 0x32;              /* tran 2 response */
-        smbp->tid = t2p->tid;
-        smbp->mid = t2p->mid;
-        smbp->pid = t2p->pid;
-        smbp->uid = t2p->uid;
+    /* now copy important fields from the tran 2 packet */
+    smbp->com = t2p->com;
+    smbp->tid = t2p->tid;
+    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);
@@ -430,83 +1142,84 @@ void smb_SendTran2Error(smb_vc_t *vcp, smb_tran2Packet_t *t2p,
                smbp->flg2 |= 0x4000;
        }
        else {
-               smbp->rcls = errClass;
+        smbp->rcls = errClass;
                smbp->errLow = (unsigned char) (errCode & 0xff);
                smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
        }
         
-        /* send packet */
-        smb_SendPacket(vcp, tp);
+    /* send packet */
+    smb_SendPacket(vcp, tp);
 }        
 
 void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp)
 {
-        smb_t *smbp;
-        unsigned short parmOffset;
+    smb_t *smbp;
+    unsigned short parmOffset;
        unsigned short dataOffset;
        unsigned short totalLength;
        unsigned short dataAlign;
-        char *datap;
+    char *datap;
         
-        smb_FormatResponsePacket(vcp, NULL, tp);
-        smbp = (smb_t *) tp;
+    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 */
-        
-        /* now copy important fields from the tran 2 packet */
-        smbp->com = 0x32;              /* tran 2 response */
-        smbp->tid = t2p->tid;
-        smbp->mid = t2p->mid;
-        smbp->pid = t2p->pid;
-        smbp->uid = t2p->uid;
+
+    /* now copy important fields from the tran 2 packet */
+    smbp->com = t2p->com;
+    smbp->tid = t2p->tid;
+    smbp->mid = t2p->mid;
+    smbp->pid = t2p->pid;
+    smbp->uid = t2p->uid;
        smbp->res[0] = t2p->res[0];
 
-        totalLength = 1 + t2p->totalData + t2p->totalParms;
+    totalLength = 1 + t2p->totalData + t2p->totalParms;
 
-        /* now add the core parameters (tran2 info) to the packet */
-        smb_SetSMBParm(tp, 0, t2p->totalParms);        /* parm bytes */
-        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 */
+    /* now add the core parameters (tran2 info) to the packet */
+    smb_SetSMBParm(tp, 0, t2p->totalParms);    /* parm bytes */
+    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 */
-        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 */
+    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;
-        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 */
-        
-        datap = smb_GetSMBData(tp, NULL);
+    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 */
+
+    datap = smb_GetSMBData(tp, NULL);
        *datap++ = 0;                           /* we rounded to even */
 
        totalLength += dataAlign;
-        smb_SetSMBDataLength(tp, totalLength);
+    smb_SetSMBDataLength(tp, totalLength);
         
-        /* next, send the datagram */
-        smb_SendPacket(vcp, tp);
-}
+    /* next, send the datagram */
+    smb_SendPacket(vcp, tp);
+}   
 
-long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       smb_tran2Packet_t *asp;
-       int totalParms;
-       int totalData;
-       int parmDisp;
-       int dataDisp;
-       int parmOffset;
-       int dataOffset;
-       int parmCount;
-       int dataCount;
-       int firstPacket;
-       long code;
+    smb_tran2Packet_t *asp;
+    int totalParms;
+    int totalData;
+    int parmDisp;
+    int dataDisp;
+    int parmOffset;
+    int dataOffset;
+    int parmCount;
+    int dataCount;
+    int firstPacket;
+       int rapOp;
+    long code = 0;
 
        /* We sometimes see 0 word count.  What to do? */
        if (*inp->wctp == 0) {
@@ -514,218 +1227,771 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                HANDLE h;
                char *ptbuf[1];
 
-               osi_Log0(afsd_logp, "TRANSACTION2 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);
+                           1, inp->ncb_length, ptbuf, inp);
                DeregisterEventSource(h);
 #else /* DJGPP */
-               osi_Log0(afsd_logp, "TRANSACTION2 word count = 0"); 
+               osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
 #endif /* !DJGPP */
 
-               smb_SetSMBDataLength(outp, 0);
-               smb_SendPacket(vcp, outp);
+        smb_SetSMBDataLength(outp, 0);
+        smb_SendPacket(vcp, outp);
                return 0;
        }
 
-       totalParms = smb_GetSMBParm(inp, 0);
-       totalData = smb_GetSMBParm(inp, 1);
-
-       firstPacket = (inp->inCom == 0x32);
-
+    totalParms = smb_GetSMBParm(inp, 0);
+    totalData = smb_GetSMBParm(inp, 1);
+        
+    firstPacket = (inp->inCom == 0x25);
+        
        /* find the packet we're reassembling */
        lock_ObtainWrite(&smb_globalLock);
-       asp = smb_FindTran2Packet(vcp, inp);
-       if (!asp) {
-               asp = smb_NewTran2Packet(vcp, inp, totalParms, totalData);
+    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 */
+    lock_ReleaseWrite(&smb_globalLock);
+        
+    /* now merge in this latest packet; start by looking up offsets */
        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);
+        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->maxReturnData = smb_GetSMBParm(inp, 3);
-
-               osi_Log3(afsd_logp, "SMB3 received T2 init packet total data %d, cur data %d, max return data %d",
-                       totalData, dataCount, asp->maxReturnData);
-       }
-       else {
-               parmDisp = smb_GetSMBParm(inp, 4);
-               parmOffset = smb_GetSMBParm(inp, 3);
-               dataDisp = smb_GetSMBParm(inp, 7);
-               dataOffset = smb_GetSMBParm(inp, 6);
-               parmCount = smb_GetSMBParm(inp, 2);
-               dataCount = smb_GetSMBParm(inp, 5);
-
-               osi_Log2(afsd_logp, "SMB3 received T2 aux packet parms %d, data %d",
-                       parmCount, dataCount);
-       }
+        asp->maxReturnData = smb_GetSMBParm(inp, 3);
 
-       /* now copy the parms and data */
-       if( parmCount != 0 )
-       {
-               memcpy(((char *)asp->parmsp) + parmDisp, inp->data + parmOffset, parmCount);
-       }
-       if( dataCount != 0 )
-       {
-               memcpy(asp->datap + dataDisp, inp->data + dataOffset, dataCount);
-       }
+               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);
+        parmOffset = smb_GetSMBParm(inp, 3);
+        dataDisp = smb_GetSMBParm(inp, 7);
+        dataOffset = smb_GetSMBParm(inp, 6);
+        parmCount = smb_GetSMBParm(inp, 2);
+        dataCount = smb_GetSMBParm(inp, 5);
+
+        osi_Log2(smb_logp, "SMB3 received Trans aux packet parms %d, data %d",
+                 parmCount, dataCount);
+    }   
+
+    /* now copy the parms and data */
+    if ( parmCount != 0 )
+    {
+        memcpy(((char *)asp->parmsp) + parmDisp, inp->data + parmOffset, parmCount);
+    }
+    if ( dataCount != 0 ) {
+        memcpy(asp->datap + dataDisp, inp->data + dataOffset, dataCount);
+    }
 
-       /* account for new bytes */
-       asp->curData += dataCount;
-       asp->curParms += parmCount;
+    /* account for new bytes */
+    asp->curData += dataCount;
+    asp->curParms += parmCount;
 
-       /* finally, if we're done, remove the packet from the queue and dispatch it */
-       if (asp->totalData <= asp->curData && asp->totalParms <= asp->curParms) {
+    /* finally, if we're done, remove the packet from the queue and dispatch it */
+    if (asp->totalData <= asp->curData && asp->totalParms <= asp->curParms) {
                /* we've received it all */
-               lock_ObtainWrite(&smb_globalLock);
+        lock_ObtainWrite(&smb_globalLock);
                osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
-               lock_ReleaseWrite(&smb_globalLock);
+        lock_ReleaseWrite(&smb_globalLock);
 
-               /* now dispatch it */
-               if(asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
-                       osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",vcp,vcp->lana,vcp->lsn);
-                       osi_Log4(afsd_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
-                       code = (*smb_tran2DispatchTable[asp->opcode].procp)(vcp, asp, outp);
-               }
-               else {
-                       osi_LogEvent("AFS-Dispatch-2 [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
-                       osi_Log4(afsd_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
-                       code = CM_ERROR_BADOP;
-               }
+        /* now dispatch it */
+               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);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%x] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
+            code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
+        }
+        else {
+            osi_LogEvent("AFS-Dispatch-RAP [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
+            code = CM_ERROR_BADOP;
+        }
 
                /* 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.
-               */
-               if (code != 0) {
-                       smb_SendTran2Error(vcp, asp, outp, code);
-               }
+         * otherwise the dispatched function already did the data sending.
+         * We give dispatched proc the responsibility since it knows how much
+         * space to allocate.
+         */
+        if (code != 0) {
+            smb_SendTran2Error(vcp, asp, outp, code);
+        }
 
                /* free the input tran 2 packet */
                lock_ObtainWrite(&smb_globalLock);
-               smb_FreeTran2Packet(asp);
+        smb_FreeTran2Packet(asp);
                lock_ReleaseWrite(&smb_globalLock);
-       }
-       else if (firstPacket) {
+    }
+    else if (firstPacket) {
                /* 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);
-       }
+         * ack to get more data.
+         */
+        smb_SetSMBDataLength(outp, 0);
+        smb_SendPacket(vcp, outp);
+    }
 
        return 0;
 }
 
-long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
-{
-       char *pathp;
-       smb_tran2Packet_t *outp;
-       long code;
-       cm_space_t *spacep;
-       int excl;
-       cm_user_t *userp;
-       cm_scache_t *dscp;              /* dir we're dealing with */
-       cm_scache_t *scp;               /* file we're creating */
-       cm_attr_t setAttr;
-       int initialModeBits;
-       smb_fid_t *fidp;
-       int attributes;
-       char *lastNamep;
-       long dosTime;
-       int openFun;
-       int trunc;
-       int openMode;
-       int extraInfo;
-       int openAction;
-       int parmSlot;                   /* which parm we're dealing with */
-       long returnEALength;
-       char *tidPathp;
-       cm_req_t req;
+/* ANSI versions.  The unicode versions support arbitrary length
+   share names, but we don't support unicode yet. */
 
-       cm_InitReq(&req);
+typedef struct smb_rap_share_info_0 {
+       char                    shi0_netname[13];
+} smb_rap_share_info_0_t;
 
-       scp = NULL;
+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 */
+} smb_rap_share_info_1_t;
 
-       extraInfo = (p->parmsp[0] & 1); /* return extra info */
-       returnEALength = (p->parmsp[0] & 8);    /* return extended attr length */
+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;
+} smb_rap_share_info_2_t;
 
-       openFun = p->parmsp[6];         /* open function */
-       excl = ((openFun & 3) == 0);
-       trunc = ((openFun & 3) == 2);   /* truncate it */
-       openMode = (p->parmsp[1] & 0x7);
-       openAction = 0;                 /* tracks what we did */
+#define SMB_RAP_MAX_SHARES 512
 
-       attributes = p->parmsp[3];
-       dosTime = p->parmsp[4] | (p->parmsp[5] << 16);
+typedef struct smb_rap_share_list {
+       int cShare;
+       int maxShares;
+       smb_rap_share_info_0_t * shares;
+} smb_rap_share_list_t;
 
-       /* compute initial mode bits based on read-only flag in attributes */
-       initialModeBits = 0666;
-       if (attributes & 1) initialModeBits &= ~0222;
+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;
 
-       pathp = (char *) (&p->parmsp[14]);
+       name = dep->name;
 
-       outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
+       if(name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
+               return 0; /* skip over '.' and '..' */
 
-       spacep = cm_GetSpace();
-       smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+       sp = (smb_rap_share_list_t *) vrockp;
 
-       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).
-               */
-               fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-               smb_SetupIoctlFid(fidp, spacep);
+       strncpy(sp->shares[sp->cShare].shi0_netname, name, 12);
+       sp->shares[sp->cShare].shi0_netname[12] = 0;
 
-               /* copy out remainder of the parms */
-               parmSlot = 0;
-               outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
-               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 */
-               }
-               /* and the final "always present" stuff */
-               outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
-               /* next write out the "unique" ID */
-               outp->parmsp[parmSlot] = 0x1234; parmSlot++;
-               outp->parmsp[parmSlot] = 0x5678; parmSlot++;
-               outp->parmsp[parmSlot] = 0; parmSlot++;
-               if (returnEALength) {
-                       outp->parmsp[parmSlot] = 0; parmSlot++;
-                       outp->parmsp[parmSlot] = 0; parmSlot++;
-               }
+       sp->cShare++;
 
-               outp->totalData = 0;
-               outp->totalParms = parmSlot * 2;
+       if(sp->cShare >= sp->maxShares)
+               return CM_ERROR_STOPNOW;
+       else
+               return 0;
+}
 
-               smb_SendTran2Packet(vcp, outp, op);
+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;
 
-               smb_FreeTran2Packet(outp);
+       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];
 
-               /* and clean up fid reference */
-               smb_ReleaseFID(fidp);
-               return 0;
+       if(infoLevel != 1) {
+               return CM_ERROR_INVAL;
        }
 
-#ifdef DEBUG_VERBOSE
-       {
-               char *hexp, *asciip;
-               asciip = (lastNamep ? lastNamep : pathp);
+       /* first figure out how many shares there are */
+    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);
+       }
+
+       rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\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;
+       }
+
+       /* 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);
+
+       userp = smb_GetTran2User(vcp,p);
+
+       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_ReleaseUser(userp);
+
+       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;
+       }
+    
+       outp = smb_GetTran2ResponsePacket(vcp, p, op, outParmsTotal, outDataTotal);
+
+       /* now for the submounts */
+    shares = (smb_rap_share_info_1_t *) outp->datap;
+       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);
+
+       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);
+            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);
+       }
+
+       nonrootShares = cshare;
+
+       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;
+               
+               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->totalData = cstrp - outp->datap;
+       outp->totalParms = outParmsTotal;
+
+       smb_SendTran2Packet(vcp, outp, op);
+       smb_FreeTran2Packet(outp);
+
+       free(rootShares.shares);
+
+       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);
+    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) {
+            rv = RegQueryValueEx(hkSubmount, shareName, NULL, NULL, NULL, NULL);
+                       if(rv == ERROR_SUCCESS) {
+                               shareFound = TRUE;
+                       }
+                       RegCloseKey(hkSubmount);
+               }
+       }
+
+       if(!shareFound) {
+               smb_FreeTran2Packet(outp);
+               return CM_ERROR_BADSHARENAME;
+       }
+
+       memset(outp->datap, 0, 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;
+        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->shi2_permissions = ACCESS_ALL;
+               info->shi2_max_uses = (unsigned short) -1;
+        info->shi2_path = 1 + (((unsigned char *) (info + 1)) - outp->datap);
+       }
+
+       outp->totalData = totalData;
+       outp->totalParms = totalParam;
+
+       smb_SendTran2Packet(vcp, outp, op);
+       smb_FreeTran2Packet(outp);
+
+       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;*/
+} 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;
+    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;
+       }
+
+       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)*/
+
+       outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, 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;
+
+       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;
+
+       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 */
+
+       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);
+
+       return code;
+}
+
+long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+       return CM_ERROR_BADOP;
+}
+
+long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+    smb_tran2Packet_t *asp;
+    int totalParms;
+    int totalData;
+    int parmDisp;
+    int dataDisp;
+    int parmOffset;
+    int dataOffset;
+    int parmCount;
+    int dataCount;
+    int firstPacket;
+    long code = 0;
+
+       /* We sometimes see 0 word count.  What to do? */
+       if (*inp->wctp == 0) {
+#ifndef DJGPP
+               HANDLE h;
+               char *ptbuf[1];
+
+               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);
+#else /* DJGPP */
+               osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
+#endif /* !DJGPP */
+
+        smb_SetSMBDataLength(outp, 0);
+        smb_SendPacket(vcp, outp);
+               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);
+    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;
+        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->maxReturnData = smb_GetSMBParm(inp, 3);
+
+               osi_Log3(smb_logp, "SMB3 received T2 init packet total data %d, cur data %d, max return data %d",
+                 totalData, dataCount, asp->maxReturnData);
+    }
+    else {
+        parmDisp = smb_GetSMBParm(inp, 4);
+        parmOffset = smb_GetSMBParm(inp, 3);
+        dataDisp = smb_GetSMBParm(inp, 7);
+        dataOffset = smb_GetSMBParm(inp, 6);
+        parmCount = smb_GetSMBParm(inp, 2);
+        dataCount = smb_GetSMBParm(inp, 5);
+
+        osi_Log2(smb_logp, "SMB3 received T2 aux packet parms %d, data %d",
+                 parmCount, dataCount);
+    }   
+
+    /* now copy the parms and data */
+    if ( parmCount != 0 )
+    {
+        memcpy(((char *)asp->parmsp) + parmDisp, inp->data + parmOffset, parmCount);
+    }
+    if ( dataCount != 0 ) {
+        memcpy(asp->datap + dataDisp, inp->data + dataOffset, dataCount);
+    }
+
+    /* account for new bytes */
+    asp->curData += dataCount;
+    asp->curParms += parmCount;
+
+    /* finally, if we're done, remove the packet from the queue and dispatch it */
+    if (asp->totalData <= asp->curData && asp->totalParms <= asp->curParms) {
+               /* we've received it all */
+        lock_ObtainWrite(&smb_globalLock);
+               osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
+        lock_ReleaseWrite(&smb_globalLock);
+
+        /* now dispatch it */
+        if ( asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
+            osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
+            code = (*smb_tran2DispatchTable[asp->opcode].procp)(vcp, asp, outp);
+        }
+        else {
+            osi_LogEvent("AFS-Dispatch-2 [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+            code = CM_ERROR_BADOP;
+        }
+
+               /* 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.
+         */
+        if (code != 0) {
+            smb_SendTran2Error(vcp, asp, outp, code);
+        }
+
+               /* free the input tran 2 packet */
+               lock_ObtainWrite(&smb_globalLock);
+        smb_FreeTran2Packet(asp);
+               lock_ReleaseWrite(&smb_globalLock);
+    }
+    else if (firstPacket) {
+               /* 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;
+}
+
+long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+       char *pathp;
+    smb_tran2Packet_t *outp;
+    long code = 0;
+       cm_space_t *spacep;
+    int excl;
+    cm_user_t *userp;
+    cm_scache_t *dscp;         /* dir we're dealing with */
+    cm_scache_t *scp;          /* file we're creating */
+    cm_attr_t setAttr;
+    int initialModeBits;
+    smb_fid_t *fidp;
+    int attributes;
+    char *lastNamep;
+    long dosTime;
+    int openFun;
+    int trunc;
+    int openMode;
+    int extraInfo;
+    int openAction;
+    int parmSlot;                      /* which parm we're dealing with */
+    long returnEALength;
+       char *tidPathp;
+       cm_req_t req;
+
+       cm_InitReq(&req);
+
+    scp = NULL;
+        
+       extraInfo = (p->parmsp[0] & 1); /* return extra info */
+    returnEALength = (p->parmsp[0] & 8);       /* return extended attr length */
+
+       openFun = p->parmsp[6];         /* open function */
+    excl = ((openFun & 3) == 0);
+    trunc = ((openFun & 3) == 2);      /* truncate it */
+       openMode = (p->parmsp[1] & 0x7);
+    openAction = 0;                    /* tracks what we did */
+
+    attributes = p->parmsp[3];
+    dosTime = p->parmsp[4] | (p->parmsp[5] << 16);
+        
+       /* compute initial mode bits based on read-only flag in attributes */
+    initialModeBits = 0666;
+    if (attributes & 1) initialModeBits &= ~0222;
+        
+    pathp = (char *) (&p->parmsp[14]);
+        
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
+
+       spacep = cm_GetSpace();
+    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+
+       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).
+         */
+        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+        smb_SetupIoctlFid(fidp, spacep);
+
+        /* copy out remainder of the parms */
+               parmSlot = 0;
+               outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+               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 */
+               }   
+               /* and the final "always present" stuff */
+        outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
+               /* next write out the "unique" ID */
+               outp->parmsp[parmSlot] = 0x1234; parmSlot++;
+               outp->parmsp[parmSlot] = 0x5678; parmSlot++;
+        outp->parmsp[parmSlot] = 0; parmSlot++;
+               if (returnEALength) {
+                       outp->parmsp[parmSlot] = 0; parmSlot++;
+                       outp->parmsp[parmSlot] = 0; parmSlot++;
+        }
+                
+        outp->totalData = 0;
+        outp->totalParms = parmSlot * 2;
+                
+        smb_SendTran2Packet(vcp, outp, op);
+                
+        smb_FreeTran2Packet(outp);
+
+               /* and clean up fid reference */
+        smb_ReleaseFID(fidp);
+        return 0;
+    }
+
+#ifdef DEBUG_VERBOSE
+       {
+               char *hexp, *asciip;
+               asciip = (lastNamep ? lastNamep : pathp);
                hexp = osi_HexifyString( asciip );
                DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip);
                free(hexp);
@@ -733,132 +1999,132 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 #endif
 
        userp = smb_GetTran2User(vcp, p);
-       /* In the off chance that userp is NULL, we log and abandon */
-       if(!userp) {
-               osi_Log1(afsd_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid);
-               smb_FreeTran2Packet(outp);
-               return CM_ERROR_BADSMB;
-       }
+    /* In the off chance that userp is NULL, we log and abandon */
+    if (!userp) {
+        osi_Log1(smb_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
 
        tidPathp = smb_GetTIDPath(vcp, p->tid);
 
        dscp = NULL;
        code = cm_NameI(cm_rootSCachep, pathp,
-               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-               userp, tidPathp, &req, &scp);
+                    CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                    userp, tidPathp, &req, &scp);
        if (code != 0) {
                code = cm_NameI(cm_rootSCachep, spacep->data,
-                       CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                       userp, tidPathp, &req, &dscp);
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &dscp);
                cm_FreeSpace(spacep);
 
-               if (code) {
-                       cm_ReleaseUser(userp);
+        if (code) {
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                       return code;
-               }
-
-               /* 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++;
-               code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
-                       &req, &scp);
-               if (code && code != CM_ERROR_NOSUCHFILE) {
+            return code;
+        }
+        
+        /* 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++;
+        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
+                         &req, &scp);
+        if (code && code != CM_ERROR_NOSUCHFILE) {
                        cm_ReleaseSCache(dscp);
-                       cm_ReleaseUser(userp);
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                       return code;
-               }
+            return code;
+        }
        }
-       else {
-               cm_FreeSpace(spacep);
+    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.
-       */
+        
+    /* 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);
-                       cm_ReleaseSCache(scp);
-                       cm_ReleaseUser(userp);
+        code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
+        if (code) {
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                       return code;
-               }
+            return code;
+        }
 
                if (excl) {
                        /* oops, file shouldn't be there */
-                       if (dscp) cm_ReleaseSCache(dscp);
-                       cm_ReleaseSCache(scp);
-                       cm_ReleaseUser(userp);
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                       return CM_ERROR_EXISTS;
-               }
+            return CM_ERROR_EXISTS;
+        }
 
                if (trunc) {
                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                       setAttr.length.LowPart = 0;
-                       setAttr.length.HighPart = 0;
+            setAttr.length.LowPart = 0;
+            setAttr.length.HighPart = 0;
                        code = cm_SetAttr(scp, &setAttr, userp, &req);
-                       openAction = 3; /* truncated existing file */
-               }
-               else openAction = 1;    /* found existing file */
-       }
+            openAction = 3;    /* truncated existing file */
+               }   
+        else openAction = 1;   /* found existing file */
+    }
        else if (!(openFun & SMB_ATTR_DIRECTORY)) {
                /* don't create if not found */
-               if (dscp) cm_ReleaseSCache(dscp);
-               osi_assert(scp == NULL);
-               cm_ReleaseUser(userp);
+        if (dscp) cm_ReleaseSCache(dscp);
+        osi_assert(scp == NULL);
+        cm_ReleaseUser(userp);
                smb_FreeTran2Packet(outp);
-               return CM_ERROR_NOSUCHFILE;
-       }
-       else {
+        return CM_ERROR_NOSUCHFILE;
+    }
+    else {
                osi_assert(dscp != NULL && scp == NULL);
                openAction = 2; /* created file */
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
-               code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
-                       &req);
+        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 (!excl && code == CM_ERROR_EXISTS) {
+                             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.
-                       */
-                       code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                               userp, &req, &scp);
-                       if (code == 0) {
-                               if (trunc) {
+                        * 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.length.LowPart = 0;
-                                       setAttr.length.HighPart = 0;
-                                       code = cm_SetAttr(scp, &setAttr, userp,
-                                               &req);
-                               }
+                    setAttr.length.LowPart = 0;
+                    setAttr.length.HighPart = 0;
+                    code = cm_SetAttr(scp, &setAttr, userp,
+                                      &req);
+                }   
                        }       /* lookup succeeded */
-               }
-       }
-
+        }
+    }
+        
        /* we don't need this any longer */
        if (dscp) cm_ReleaseSCache(dscp);
 
-       if (code) {
+    if (code) {
                /* something went wrong creating or truncating the file */
-               if (scp) cm_ReleaseSCache(scp);
-               cm_ReleaseUser(userp);
+        if (scp) cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
                smb_FreeTran2Packet(outp);
-               return code;
-       }
-
+        return code;
+    }
+        
        /* make sure we're about to open a file */
        if (scp->fileType != CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
@@ -867,81 +2133,81 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
                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);
-
+    /* 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 */
-       fidp->scp = scp;
-
+    fidp->scp = scp;
+        
        /* compute open mode */
-       if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
-       if (openMode == 1 || openMode == 2)
-               fidp->flags |= SMB_FID_OPENWRITE;
+    if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+    if (openMode == 1 || openMode == 2)
+        fidp->flags |= SMB_FID_OPENWRITE;
 
        smb_ReleaseFID(fidp);
-
+        
        cm_Open(scp, 0, userp);
 
-       /* copy out remainder of the parms */
+    /* copy out remainder of the parms */
        parmSlot = 0;
        outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
        lock_ObtainMutex(&scp->mx);
        if (extraInfo) {
-               outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
+        outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
                smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-               outp->parmsp[parmSlot] =  dosTime & 0xffff; parmSlot++;
-               outp->parmsp[parmSlot] = (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); 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 */
+       }   
        /* and the final "always present" stuff */
-       outp->parmsp[parmSlot] = openAction; parmSlot++;
+    outp->parmsp[parmSlot] = openAction; parmSlot++;
        /* 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++;
-       if (returnEALength) {
+    outp->parmsp[parmSlot] = 0; parmSlot++;
+    if (returnEALength) {
                outp->parmsp[parmSlot] = 0; parmSlot++;
                outp->parmsp[parmSlot] = 0; parmSlot++;
-       }
+    }
        lock_ReleaseMutex(&scp->mx);
        outp->totalData = 0;            /* total # of data bytes */
-       outp->totalParms = parmSlot * 2;        /* shorts are two bytes */
+    outp->totalParms = parmSlot * 2;   /* shorts are two bytes */
 
        smb_SendTran2Packet(vcp, outp, op);
+        
+    smb_FreeTran2Packet(outp);
 
-       smb_FreeTran2Packet(outp);
-
-       cm_ReleaseUser(userp);
-       /* leave scp held since we put it in fidp->scp */
-       return 0;
-}
+    cm_ReleaseUser(userp);
+    /* leave scp held since we put it in fidp->scp */
+    return 0;
+}   
 
 long smb_ReceiveTran2FindFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2FindNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
        smb_tran2Packet_t *outp;
-        smb_tran2QFSInfo_t qi;
+    smb_tran2QFSInfo_t qi;
        int responseSize;
        osi_hyper_t temp;
        static char FSname[6] = {'A', 0, 'F', 0, 'S', 0};
         
-       osi_Log1(afsd_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]);
+       osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]);
 
        switch (p->parmsp[0]) {
        case 1: responseSize = sizeof(qi.u.allocInfo); break;
@@ -953,24 +2219,24 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
        default: return CM_ERROR_INVAL;
        }
 
-        outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize);
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize);
        switch (p->parmsp[0]) {
        case 1:
                /* alloc info */
-                qi.u.allocInfo.FSID = 0;
-                qi.u.allocInfo.sectorsPerAllocUnit = 1;
-                qi.u.allocInfo.totalAllocUnits = 0x7fffffff;
-                qi.u.allocInfo.availAllocUnits = 0x3fffffff;
-                qi.u.allocInfo.bytesPerSector = 1024;
+        qi.u.allocInfo.FSID = 0;
+        qi.u.allocInfo.sectorsPerAllocUnit = 1;
+        qi.u.allocInfo.totalAllocUnits = 0x7fffffff;
+        qi.u.allocInfo.availAllocUnits = 0x3fffffff;
+        qi.u.allocInfo.bytesPerSector = 1024;
                break;
 
-        case 2:
+    case 2:
                /* volume info */
-                qi.u.volumeInfo.vsn = 1234;
-                qi.u.volumeInfo.vnCount = 4;
+        qi.u.volumeInfo.vsn = 1234;
+        qi.u.volumeInfo.vnCount = 4;
                /* we're supposed to pad it out with zeroes to the end */
                memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
-                memcpy(qi.u.volumeInfo.label, "AFS", 4);
+        memcpy(qi.u.volumeInfo.label, "AFS", 4);
                break;
 
        case 0x102:
@@ -1013,23 +2279,23 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
                qi.u.FSattributeInfo.FSnameLength = 6;
                memcpy(qi.u.FSattributeInfo.FSname, FSname, 6);
                break;
-        }
+    }
         
        /* copy out return data, and set corresponding sizes */
        outp->totalParms = 0;
-       outp->totalData = responseSize;
-       memcpy(outp->datap, &qi, responseSize);
+    outp->totalData = responseSize;
+    memcpy(outp->datap, &qi, responseSize);
 
        /* send and free the packets */
        smb_SendTran2Packet(vcp, outp, op);
-        smb_FreeTran2Packet(outp);
+    smb_FreeTran2Packet(outp);
 
-        return 0;
+    return 0;
 }
 
 long smb_ReceiveTran2SetFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 struct smb_ShortNameRock {
@@ -1049,7 +2315,7 @@ int cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
        /* compare both names and vnodes, though probably just comparing vnodes
         * would be safe enough.
         */
-       if (stricmp(dep->name, rockp->maskp) != 0)
+       if (cm_stricmp(dep->name, rockp->maskp) != 0)
                return 0;
        if (ntohl(dep->fid.vnode) != rockp->vnode)
                return 0;
@@ -1067,14 +2333,14 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp,
        cm_space_t *spacep;
        cm_scache_t *dscp;
        int caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
-       long code;
+       long code = 0;
        osi_hyper_t thyper;
 
        spacep = cm_GetSpace();
        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
-                       reqp, &dscp);
+                     reqp, &dscp);
        cm_FreeSpace(spacep);
        if (code) return code;
 
@@ -1086,7 +2352,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp,
        rock.vnode = vnode;
        rock.maskp = lastNamep;
        code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp,
-                          reqp, NULL);
+                        reqp, NULL);
 
        cm_ReleaseSCache(dscp);
 
@@ -1102,19 +2368,19 @@ 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;
-        unsigned long dosTime;
+    unsigned long dosTime;
        FILETIME ft;
-        unsigned short infoLevel;
-        int nbytesRequired;
-        unsigned short attributes;
+    unsigned short infoLevel;
+    int nbytesRequired;
+    unsigned short attributes;
        unsigned long extAttributes;
        char shortName[13];
        unsigned int len;
-        cm_user_t *userp;
+    cm_user_t *userp;
        cm_space_t *spacep;
-        cm_scache_t *scp, *dscp;
-        long code;
-        char *op;
+    cm_scache_t *scp, *dscp;
+    long code = 0;
+    char *op;
        char *tidPathp;
        char *lastComp;
        cm_req_t req;
@@ -1122,23 +2388,23 @@ 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;
+    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;
-        else {
-               osi_Log2(afsd_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
-                        p->opcode, infoLevel);
+    else {
+               osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+                  p->opcode, infoLevel);
                smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL);
-                return 0;
-        }
-       osi_Log2(afsd_logp, "T2 QPathInfo type 0x%x path %s", infoLevel,
-                osi_LogSaveString(afsd_logp, (char *)(&p->parmsp[3])));
+        return 0;
+    }
+       osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %s", infoLevel,
+             osi_LogSaveString(smb_logp, (char *)(&p->parmsp[3])));
 
-        outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, nbytesRequired);
+    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, nbytesRequired);
 
        if (infoLevel > 0x100)
                outp->totalParms = 2;
@@ -1146,22 +2412,22 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                outp->totalParms = 0;
         outp->totalData = nbytesRequired;
         
-        /* now, if we're at infoLevel 6, we're only being asked to check
-         * 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.
-         */
+    /* now, if we're at infoLevel 6, we're only being asked to check
+     * 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) {
                smb_SendTran2Packet(vcp, outp, opx);
-                smb_FreeTran2Packet(outp);
+        smb_FreeTran2Packet(outp);
                return 0;
-        }
+    }
         
-        userp = smb_GetTran2User(vcp, p);
-               if(!userp) {
-                       osi_Log1(afsd_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid);
-                       smb_FreeTran2Packet(outp);
-                       return CM_ERROR_BADSMB;
-               }
+    userp = smb_GetTran2User(vcp, p);
+    if (!userp) {
+        osi_Log1(smb_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
 
        tidPathp = smb_GetTIDPath(vcp, p->tid);
 
@@ -1183,63 +2449,64 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                spacep = cm_GetSpace();
                smb_StripLastComponent(spacep->data, &lastComp,
                                        (char *)(&p->parmsp[3]));
-               if(lastComp) {
-                       if (strcmp(lastComp, "\\desktop.ini") == 0) {
-                               code = cm_NameI(cm_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)
-                                               code = CM_ERROR_NOSUCHFILE;
-                                       else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
-                                               cm_buf_t *bp = buf_Find(dscp, &hzero);
-                                               if (bp)
-                                                       buf_Release(bp);
-                                               else
-                                                       code = CM_ERROR_NOSUCHFILE;
-                                       }
-                                       cm_ReleaseSCache(dscp);
-                                       if (code) {
-                                               cm_FreeSpace(spacep);
-                                               cm_ReleaseUser(userp);
-                                               smb_SendTran2Error(vcp, p, opx, code);
-                                               smb_FreeTran2Packet(outp);
-                                               return 0;
-                                       }
-                               }
-                       }
-               }
+               /* Make sure that lastComp is not NULL */
+               if (lastComp) {
+                   if (strcmp(lastComp, "\\desktop.ini") == 0) {
+                code = cm_NameI(cm_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)
+                        code = CM_ERROR_NOSUCHFILE;
+                    else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
+                        cm_buf_t *bp = buf_Find(dscp, &hzero);
+                        if (bp)
+                            buf_Release(bp);
+                        else
+                            code = CM_ERROR_NOSUCHFILE;
+                    }
+                    cm_ReleaseSCache(dscp);
+                    if (code) {
+                        cm_FreeSpace(spacep);
+                        cm_ReleaseUser(userp);
+                        smb_SendTran2Error(vcp, p, opx, code);
+                        smb_FreeTran2Packet(outp);
+                        return 0;
+                    }
+                }
+            }
+        }
                cm_FreeSpace(spacep);
        }
 
        /* now do namei and stat, and copy out the info */
-        code = cm_NameI(cm_rootSCachep, (char *)(&p->parmsp[3]),
-               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+    code = cm_NameI(cm_rootSCachep, (char *)(&p->parmsp[3]),
+                    CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
 
        if (code) {
                cm_ReleaseUser(userp);
-                smb_SendTran2Error(vcp, p, opx, code);
-                smb_FreeTran2Packet(outp);
-                return 0;
-        }
+        smb_SendTran2Error(vcp, p, opx, code);
+        smb_FreeTran2Packet(outp);
+        return 0;
+    }
 
-        lock_ObtainMutex(&scp->mx);
+    lock_ObtainMutex(&scp->mx);
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
        if (code) goto done;
         
-        /* now we have the status in the cache entry, and everything is locked.
+    /* now we have the status in the cache entry, and everything is locked.
         * Marshall the output data.
-         */
+     */
        op = outp->datap;
        /* for info level 108, figure out short name */
        if (infoLevel == 0x108) {
                code = cm_GetShortName((char *)(&p->parmsp[3]), userp, &req,
-                                       tidPathp, scp->fid.vnode, shortName,
-                                       (size_t *) &len);
+                                tidPathp, scp->fid.vnode, shortName,
+                                (size_t *) &len);
                if (code) {
                        goto done;
                }
@@ -1253,11 +2520,11 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        }
        if (infoLevel == 1 || infoLevel == 2) {
                smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-               *((u_long *)op) = dosTime; op += 4;     /* creation time */
-               *((u_long *)op) = dosTime; op += 4;     /* access time */
-               *((u_long *)op) = dosTime; op += 4;     /* write time */
-               *((u_long *)op) = scp->length.LowPart; op += 4; /* length */
-               *((u_long *)op) = scp->length.LowPart; op += 4; /* alloc size */
+        *((u_long *)op) = dosTime; op += 4;    /* creation time */
+        *((u_long *)op) = dosTime; op += 4;    /* access time */
+        *((u_long *)op) = dosTime; op += 4;    /* write time */
+        *((u_long *)op) = scp->length.LowPart; op += 4;        /* length */
+        *((u_long *)op) = scp->length.LowPart; op += 4;        /* alloc size */
                attributes = smb_Attributes(scp);
                *((u_short *)op) = attributes; op += 2; /* attributes */
        }
@@ -1291,20 +2558,22 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         
 
        /* send and free the packets */
-done:
+  done:
        lock_ReleaseMutex(&scp->mx);
-        cm_ReleaseSCache(scp);
-        cm_ReleaseUser(userp);
-       if (code == 0) smb_SendTran2Packet(vcp, outp, opx);
-        else smb_SendTran2Error(vcp, p, opx, code);
-        smb_FreeTran2Packet(outp);
+    cm_ReleaseSCache(scp);
+    cm_ReleaseUser(userp);
+       if (code == 0) 
+        smb_SendTran2Packet(vcp, outp, opx);
+    else 
+        smb_SendTran2Error(vcp, p, opx, code);
+    smb_FreeTran2Packet(outp);
 
-        return 0;
+    return 0;
 }
 
 long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
@@ -1316,16 +2585,16 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        int nbytesRequired;
        unsigned short fid;
        cm_user_t *userp;
-        smb_fid_t *fidp;
+    smb_fid_t *fidp;
        cm_scache_t *scp;
        char *op;
-       long code;
+       long code = 0;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        fid = p->parmsp[0];
-        fidp = smb_FindFID(vcp, fid, 0);
+    fid = p->parmsp[0];
+    fidp = smb_FindFID(vcp, fid, 0);
 
        if (fidp == NULL) {
                smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
@@ -1338,13 +2607,13 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        else if (infoLevel == 0x103) nbytesRequired = 4;
        else if (infoLevel == 0x104) nbytesRequired = 6;
        else {
-               osi_Log2(afsd_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
-                        p->opcode, infoLevel);
+               osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+                 p->opcode, infoLevel);
                smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL);
         smb_ReleaseFID(fidp);
                return 0;
        }
-       osi_Log2(afsd_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
+       osi_Log2(smb_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
 
        outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, nbytesRequired);
 
@@ -1355,16 +2624,16 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        outp->totalData = nbytesRequired;
 
        userp = smb_GetTran2User(vcp, p);
-       if(!userp) {
-               osi_Log1(afsd_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid);
-               code = CM_ERROR_BADSMB;
-               goto done;
-       }
+    if (!userp) {
+       osi_Log1(smb_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }
 
        scp = fidp->scp;
        lock_ObtainMutex(&scp->mx);
        code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                        CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
        if (code) goto done;
 
        /* now we have the status in the cache entry, and everything is locked.
@@ -1408,7 +2677,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        }
 
        /* send and free the packets */
-done:
+  done:
        lock_ReleaseMutex(&scp->mx);
        cm_ReleaseUser(userp);
        smb_ReleaseFID(fidp);
@@ -1421,7 +2690,7 @@ done:
 
 long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
-       long code;
+       long code = 0;
        unsigned short fid;
        smb_fid_t *fidp;
        unsigned short infoLevel;
@@ -1432,7 +2701,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
        cm_InitReq(&req);
 
-        fid = p->parmsp[0];
+    fid = p->parmsp[0];
        fidp = smb_FindFID(vcp, fid, 0);
 
        if (fidp == NULL) {
@@ -1442,7 +2711,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
        infoLevel = p->parmsp[1];
        if (infoLevel > 0x104 || infoLevel < 0x101) {
-               osi_Log2(afsd_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+               osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                         p->opcode, infoLevel);
                smb_SendTran2Error(vcp, p, op, CM_ERROR_INVAL);
         smb_ReleaseFID(fidp);
@@ -1461,7 +2730,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                return 0;
        }
 
-       osi_Log1(afsd_logp, "T2 SFileInfo type 0x%x", infoLevel);
+       osi_Log1(smb_logp, "T2 SFileInfo type 0x%x", infoLevel);
 
        outp = smb_GetTran2ResponsePacket(vcp, p, op, 2, 0);
 
@@ -1469,11 +2738,11 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        outp->totalData = 0;
 
        userp = smb_GetTran2User(vcp, p);
-       if(!userp) {
-               osi_Log1(afsd_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid);
-               code = CM_ERROR_BADSMB;
-               goto done;
-       }
+    if (!userp) {
+       osi_Log1(smb_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }
 
        scp = fidp->scp;
 
@@ -1487,8 +2756,8 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                 */
                lock_ObtainMutex(&scp->mx);
                code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                                CM_SCACHESYNC_GETSTATUS
-                                | CM_SCACHESYNC_NEEDCALLBACK);
+                         CM_SCACHESYNC_GETSTATUS
+                         | CM_SCACHESYNC_NEEDCALLBACK);
                if (code) {
                        lock_ReleaseMutex(&scp->mx);
                        goto done;
@@ -1496,22 +2765,20 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
                /* prepare for setattr call */
                attr.mask = 0;
+               
                lastMod = *((FILETIME *)(p->datap + 16));
-                /* when called as result of move a b, lastMod is (-1, -1). If the check for -1 
-                  is not present, timestamp
-                   of the resulting file will be 1969 (-1)
-                 */
-
-                if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && 
-                                               lastMod.dwLowDateTime != -1 && 
-                                               lastMod.dwHighDateTime != -1) 
-                {
-                        attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
-                        smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
-                                                        &lastMod);
-                        fidp->flags |= SMB_FID_MTIMESETDONE;
+               /* when called as result of move a b, lastMod is (-1, -1). 
+         * If the check for -1 is not present, timestamp
+                * of the resulting file will be 1969 (-1)
+                */
+               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && 
+            lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
+                       attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
+                       smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
+                                                       &lastMod);
+                       fidp->flags |= SMB_FID_MTIMESETDONE;
                }
-
+               
                attribute = *((u_long *)(p->datap + 32));
                if (attribute != 0) {
                        if ((scp->unixModeBits & 0222)
@@ -1556,7 +2823,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                        fidp->flags &= ~SMB_FID_DELONCLOSE;
                }
        }
-done:
+  done:
        cm_ReleaseUser(userp);
        smb_ReleaseFID(fidp);
        if (code == 0) smb_SendTran2Packet(vcp, outp, op);
@@ -1568,75 +2835,74 @@ done:
 
 long smb_ReceiveTran2FSCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2IOCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2FindNotifyFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2FindNotifyNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ReceiveTran2MKDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
-        return CM_ERROR_BADOP;
+    return CM_ERROR_BADOP;
 }
 
 long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
        smb_dirListPatch_t **dirPatchespp, int infoLevel, cm_user_t *userp,
        cm_req_t *reqp)
 {
-       long code;
-        cm_scache_t *scp;
-        cm_scache_t *targetScp;                        /* target if scp is a symlink */
-        char *dptr;
-        long dosTime;
+       long code = 0;
+    cm_scache_t *scp;
+    cm_scache_t *targetScp;                    /* target if scp is a symlink */
+    char *dptr;
+    long dosTime;
        FILETIME ft;
-        int shortTemp;
-        unsigned short attr;
+    int shortTemp;
+    unsigned short attr;
        unsigned long lattr;
-        smb_dirListPatch_t *patchp;
-        smb_dirListPatch_t *npatchp;
+    smb_dirListPatch_t *patchp;
+    smb_dirListPatch_t *npatchp;
         
-        for(patchp = *dirPatchespp; patchp; patchp =
-               (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+    for(patchp = *dirPatchespp; patchp; patchp =
+         (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
                code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
-                if (code) continue;
-                lock_ObtainMutex(&scp->mx);
-                code = cm_SyncOp(scp, NULL, userp, reqp, 0,
-                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-               if (code) {
+        if (code) continue;
+        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);
                        continue;
-                }
+        }
                 
-                /* now watch for a symlink */
-                if (scp->fileType == CM_SCACHETYPE_SYMLINK) {
+        /* now watch for a symlink */
+        if (scp->fileType == CM_SCACHETYPE_SYMLINK) {
                        lock_ReleaseMutex(&scp->mx);
-                        code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp,
-                                                 reqp);
-                        if (code == 0) {
+            code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, reqp);
+            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(afsd_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;
-                        }
-                        lock_ObtainMutex(&scp->mx);
-                }
+                scp = targetScp;
+            }
+            lock_ObtainMutex(&scp->mx);
+        }
 
                dptr = patchp->dptr;
 
@@ -1668,10 +2934,9 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
                        /* Copy attributes */
                        lattr = smb_ExtAttributes(scp);
-                       /* merge in hidden (dot file) attribute */
-                       if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
-                               lattr |= SMB_ATTR_HIDDEN;
-
+            /* merge in hidden (dot file) attribute */
+                       if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                               lattr |= SMB_ATTR_HIDDEN;
                        *((u_long *)dptr) = lattr;
                        dptr += 4;
                }
@@ -1719,43 +2984,120 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
                        /* 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;
-
+            /* merge in hidden (dot file) attribute */
+            if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                attr |= SMB_ATTR_HIDDEN;
                        *dptr++ = attr & 0xff;
                        *dptr++ = (attr >> 8) & 0xff;
                }
 
-                lock_ReleaseMutex(&scp->mx);
-                cm_ReleaseSCache(scp);
+        lock_ReleaseMutex(&scp->mx);
+        cm_ReleaseSCache(scp);
        }
         
-        /* now free the patches */
-        for(patchp = *dirPatchespp; patchp; patchp = npatchp) {
+    /* now free the patches */
+    for(patchp = *dirPatchespp; patchp; patchp = npatchp) {
                npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
-                free(patchp);
+        free(patchp);
        }
         
-        /* and mark the list as empty */
-        *dirPatchespp = NULL;
+    /* and mark the list as empty */
+    *dirPatchespp = NULL;
 
-        return code;
+    return code;
+}
+
+#ifndef USE_OLD_MATCHING
+// char table for case insensitive comparison
+char mapCaseTable[256];
+
+VOID initUpperCaseTable(VOID) 
+{
+    int i;
+    for (i = 0; i < 256; ++i) 
+       mapCaseTable[i] = toupper(i);
+    // make '"' match '.' 
+    mapCaseTable[(int)'"'] = toupper('.');
+    // make '<' match '*' 
+    mapCaseTable[(int)'<'] = toupper('*');
+    // make '>' match '?' 
+    mapCaseTable[(int)'>'] = toupper('?');    
+}
+
+// Compare 'pattern' (containing metacharacters '*' and '?') with the file
+// name 'name'.
+// Note : this procedure works recursively calling itself.
+// Parameters
+// PSZ pattern    : string containing metacharacters.
+// PSZ name       : file name to be compared with 'pattern'.
+// Return value
+// BOOL : TRUE/FALSE (match/mistmatch)
+
+BOOL szWildCardMatchFileName(PSZ pattern, PSZ name) {
+   PSZ pename;         // points to the last 'name' character
+   PSZ p;
+   pename = name + strlen(name) - 1;
+   while (*name) {
+      switch (*pattern) {
+         case '?':
+         case '>':
+            if (*(++pattern) != '<' || *(++pattern) != '*') {
+               if (*name == '.') 
+                   return FALSE;
+               ++name;
+               break;
+            } /* endif */
+         case '<':
+         case '*':
+            while ((*pattern == '<') || (*pattern == '*') || (*pattern == '?') || (*pattern == '>')) 
+                ++pattern;
+            if (!*pattern) 
+                return TRUE;
+            for (p = pename; p >= name; --p) {
+               if ((mapCaseTable[*p] == mapCaseTable[*pattern]) &&
+                   szWildCardMatchFileName(pattern + 1, p + 1))
+                  return TRUE;
+            } /* endfor */
+            return FALSE;
+         default:
+            if (mapCaseTable[*name] != mapCaseTable[*pattern]) 
+                return FALSE;
+            ++pattern, ++name;
+            break;
+      } /* endswitch */
+   } /* endwhile */ 
+   return !*pattern;
+}
+
+/* do a case-folding search of the star name mask with the name in namep.
+ * Return 1 if we match, otherwise 0.
+ */
+int smb_V3MatchMask(char *namep, char *maskp, int flags) 
+{
+       /* make sure we only match 8.3 names, if requested */
+       if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep)) 
+        return 0;
+       
+       return szWildCardMatchFileName(maskp, namep) ? 1:0;
 }
 
+#else /* USE_OLD_MATCHING */
 /* do a case-folding search of the star name mask with the name in namep.
  * Return 1 if we match, otherwise 0.
  */
 int smb_V3MatchMask(char *namep, char *maskp, int flags)
 {
        unsigned char tcp1, tcp2;       /* Pattern characters */
-        unsigned char tcn1;            /* Name characters */
-       int sawDot = 0, sawStar = 0;
+    unsigned char tcn1;                /* Name characters */
+       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 */
-       if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep)) return 0;
+    req8dot3 = (flags & CM_FLAG_8DOT3);
+       if (req8dot3 && !cm_Is8Dot3(namep)) 
+        return 0;
 
        /* loop */
        while (1) {
@@ -1812,8 +3154,8 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
                        tcp2 = *maskp++;
                        if (tcp2 == 0)
                                return 1;
-                       else if (tcp2 == '.' || tcp2 == '"') {
-                               while (tcn1 != '.' && tcn1 != 0)
+                       else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
+                               while (req8dot3 && tcn1 != '.' && tcn1 != 0)
                                        tcn1 = *++namep;
                                if (tcn1 == 0) {
                                        if (sawDot)
@@ -1839,12 +3181,13 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
                                        tcp2 = *maskp++;
 
                                /* skip over characters that don't match tcp2 */
-                               while (tcn1 != '.' && tcn1 != 0
-                                       && cm_foldUpper[tcn1] != cm_foldUpper[tcp2])
+                               while (req8dot3 && tcn1 != '.' && tcn1 != 0 && 
+                       ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) || 
+                         (!casefold && tcn1 != tcp2)))
                                        tcn1 = *++namep;
 
                                /* No match */
-                               if (tcn1 == '.' || tcn1 == 0)
+                               if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
                                        return 0;
 
                                /* Remember where we are */
@@ -1858,7 +3201,8 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
                }
                else {
                        /* tcp1 is not a wildcard */
-                       if (cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) {
+            if ((casefold && cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) || 
+                (!casefold && tcn1 == tcp1)) {
                                /* they match */
                                namep++;
                                continue;
@@ -1875,831 +3219,853 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
                }
        }
 }
+#endif /* USE_OLD_MATCHING */
 
 long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
 {
        int attribute;
-       long nextCookie;
-       char *tp;
-       long code;
-       char *pathp;
-       cm_dirEntry_t *dep;
-       int maxCount;
-       smb_dirListPatch_t *dirListPatchesp;
-       smb_dirListPatch_t *curPatchp;
-       cm_buf_t *bufferp;
-       long temp;
-       long orbytes;                   /* # of bytes in this output record */
-       long ohbytes;                   /* # of bytes, except file name */
-       long onbytes;                   /* # of bytes in name, incl. term. null */
-       osi_hyper_t dirLength;
-       osi_hyper_t bufferOffset;
-       osi_hyper_t curOffset;
-       osi_hyper_t thyper;
-       smb_dirSearch_t *dsp;
-       cm_scache_t *scp;
-       long entryInDir;
-       long entryInBuffer;
+    long nextCookie;
+    char *tp;
+    long code = 0;
+    char *pathp;
+    cm_dirEntry_t *dep;
+    int maxCount;
+    smb_dirListPatch_t *dirListPatchesp;
+    smb_dirListPatch_t *curPatchp;
+    cm_buf_t *bufferp;
+    long temp;
+    long orbytes;                      /* # of bytes in this output record */
+    long ohbytes;                      /* # of bytes, except file name */
+    long onbytes;                      /* # of bytes in name, incl. term. null */
+    osi_hyper_t dirLength;
+    osi_hyper_t bufferOffset;
+    osi_hyper_t curOffset;
+    osi_hyper_t thyper;
+    smb_dirSearch_t *dsp;
+    cm_scache_t *scp;
+    long entryInDir;
+    long entryInBuffer;
        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 */
+    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 */
-       cm_space_t *spacep;             /* for pathname buffer */
-       long maxReturnData;             /* max # of return data */
-       long maxReturnParms;            /* max # of return parms */
-       long bytesInBuffer;             /* # data bytes in the output buffer */
-       int starPattern;
-       char *maskp;                    /* mask part of path */
-       int infoLevel;
-       int searchFlags;
-       int eos;
-       smb_tran2Packet_t *outp;        /* response packet */
+    cm_space_t *spacep;                /* for pathname buffer */
+    long maxReturnData;                /* max # of return data */
+    long maxReturnParms;               /* max # of return parms */
+    long bytesInBuffer;                /* # data bytes in the output buffer */
+    int starPattern;
+    char *maskp;                       /* mask part of path */
+    int infoLevel;
+    int searchFlags;
+    int eos;
+    smb_tran2Packet_t *outp;   /* response packet */
        char *tidPathp;
        int align;
        char shortName[13];             /* 8.3 name if needed */
        int NeedShortName;
+    int foundInexact;
        char *shortNameEnd;
-       int fileType;
-       cm_fid_t fid;
+    int fileType;
+    cm_fid_t fid;
 
-       cm_req_t req;
+    cm_req_t req;
 
        cm_InitReq(&req);
 
        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];
-               searchFlags = p->parmsp[2];
-               dsp = smb_NewDirSearch(1);
-               dsp->attribute = attribute;
-               pathp = ((char *) p->parmsp) + 12;      /* points to path */
-               nextCookie = 0;
-               maskp = strrchr(pathp, '\\');
-               if (maskp == NULL) maskp = pathp;
+        attribute = p->parmsp[0];
+        maxCount = p->parmsp[1];
+        infoLevel = p->parmsp[3];
+        searchFlags = p->parmsp[2];
+        dsp = smb_NewDirSearch(1);
+        dsp->attribute = attribute;
+        pathp = ((char *) p->parmsp) + 12;     /* points to path */
+        nextCookie = 0;
+        maskp = strrchr(pathp, '\\');
+        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 */
-               starPattern = smb_V3IsStarMask(maskp);
-       }
-       else {
+        strcpy(dsp->mask, maskp);      /* and save mask */
+               /* track if this is likely to match a lot of entries */
+        starPattern = smb_V3IsStarMask(maskp);
+        }
+    else {
                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];
-               searchFlags = p->parmsp[5];
-               pathp = NULL;
-               nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
-               maskp = dsp->mask;
+        /* 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];
+        searchFlags = p->parmsp[5];
+        pathp = NULL;
+        nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
+        maskp = dsp->mask;
                starPattern = 1;        /* assume, since required a Find Next */
-       }
+    }
 
-       osi_Log4(afsd_logp,
-               "T2 search dir attr 0x%x, info level %d, max count %d, flags 0x%x",
-               attribute, infoLevel, maxCount, searchFlags);
+       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(afsd_logp, "...T2 search op %d, nextCookie 0x%x",
-               p->opcode, nextCookie);
+       osi_Log2(smb_logp, "...T2 search op %d, nextCookie 0x%x",
+              p->opcode, nextCookie);
 
        if (infoLevel >= 0x101)
                searchFlags &= ~4;      /* no resume keys */
 
-       dirListPatchesp = NULL;
+    dirListPatchesp = NULL;
 
        maxReturnData = p->maxReturnData;
-       if (p->opcode == 1)     /* find first */
-               maxReturnParms = 10;    /* bytes */
-       else
-               maxReturnParms = 8;     /* bytes */
+    if (p->opcode == 1)        /* find first */
+        maxReturnParms = 10;   /* bytes */
+       else    
+        maxReturnParms = 8;    /* bytes */
 
 #ifndef CM_CONFIG_MULTITRAN2RESPONSES
-       if (maxReturnData > 6000) maxReturnData = 6000;
+    if (maxReturnData > 6000) 
+        maxReturnData = 6000;
 #endif /* CM_CONFIG_MULTITRAN2RESPONSES */
 
        outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
-               maxReturnData);
-
-       osi_Log1(afsd_logp, "T2 receive search dir %s",
-               osi_LogSaveString(afsd_logp, pathp));
-
-       /* bail out if request looks bad */
-       if (p->opcode == 1 && !pathp) {
-               smb_ReleaseDirSearch(dsp);
-               smb_FreeTran2Packet(outp);
-               return CM_ERROR_BADSMB;
-       }
+                                      maxReturnData);
 
-       osi_Log2(afsd_logp, "T2 dir search cookie 0x%x, connection %d",
-               nextCookie, dsp->cookie);
-
-       userp = smb_GetTran2User(vcp, p);
-       if(!userp) {
-               osi_Log1(afsd_logp, "T2 dir search unable to resolve user [%d]", p->uid);
-               smb_ReleaseDirSearch(dsp);
-               smb_FreeTran2Packet(outp);
-               return CM_ERROR_BADSMB;
-       }
+    osi_Log1(smb_logp, "T2 receive search dir %s",
+             osi_LogSaveString(smb_logp, pathp));
+        
+    /* bail out if request looks bad */
+    if (p->opcode == 1 && !pathp) {
+        smb_ReleaseDirSearch(dsp);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
+        
+       osi_Log2(smb_logp, "T2 dir search cookie 0x%x, connection %d",
+             nextCookie, dsp->cookie);
+
+       userp = smb_GetTran2User(vcp, p);
+    if (!userp) {
+       osi_Log1(smb_logp, "T2 dir search 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;
-               cm_HoldSCache(scp);
-               code = 0;
-       }
-       else {
+        cm_HoldSCache(scp);
+        code = 0;
+    }
+    else {
                spacep = cm_GetSpace();
-               smb_StripLastComponent(spacep->data, NULL, pathp);
-               lock_ReleaseMutex(&dsp->mx);
+        smb_StripLastComponent(spacep->data, NULL, pathp);
+        lock_ReleaseMutex(&dsp->mx);
 
                tidPathp = smb_GetTIDPath(vcp, p->tid);
-               code = cm_NameI(cm_rootSCachep, spacep->data,
-                       CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                       userp, tidPathp, &req, &scp);
-               cm_FreeSpace(spacep);
+        code = cm_NameI(cm_rootSCachep, spacep->data,
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &scp);
+        cm_FreeSpace(spacep);
 
-               lock_ObtainMutex(&dsp->mx);
+        lock_ObtainMutex(&dsp->mx);
                if (code == 0) {
-                       if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
+            if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
                        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.
-                       */
-                       cm_HoldSCache(scp);
-                       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);
-               }
-       }
+             * 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.
+             */
+            cm_HoldSCache(scp);
+                       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);
+        }
+    }
        lock_ReleaseMutex(&dsp->mx);
-       if (code) {
+    if (code) {
                cm_ReleaseUser(userp);
-               smb_FreeTran2Packet(outp);
+        smb_FreeTran2Packet(outp);
                smb_DeleteDirSearch(dsp);
                smb_ReleaseDirSearch(dsp);
-               return code;
-       }
+        return code;
+        }
 
-       /* get the directory size */
+    /* get the directory size */
        lock_ObtainMutex(&scp->mx);
-       code = cm_SyncOp(scp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
        if (code) {
                lock_ReleaseMutex(&scp->mx);
-               cm_ReleaseSCache(scp);
-               cm_ReleaseUser(userp);
-               smb_FreeTran2Packet(outp);
+        cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        smb_FreeTran2Packet(outp);
                smb_DeleteDirSearch(dsp);
                smb_ReleaseDirSearch(dsp);
-               return code;
-       }
+        return code;
+    }
 
-       dirLength = scp->length;
-       bufferp = NULL;
-       bufferOffset.LowPart = bufferOffset.HighPart = 0;
-       curOffset.HighPart = 0;
-       curOffset.LowPart = nextCookie;
+  startsearch:
+    dirLength = scp->length;
+    bufferp = NULL;
+    bufferOffset.LowPart = bufferOffset.HighPart = 0;
+    curOffset.HighPart = 0;
+    curOffset.LowPart = nextCookie;
        origOp = outp->datap;
 
-       code = 0;
-       returnedNames = 0;
-       bytesInBuffer = 0;
-       while (1) {
+    foundInexact = 0;
+    code = 0;
+    returnedNames = 0;
+    bytesInBuffer = 0;
+    while (1) {
                op = origOp;
                if (searchFlags & 4)
                        /* skip over resume key */
                        op += 4;
 
                /* 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.
-               */
+         * 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);
-               if (curOffset.HighPart == 0 && curOffset.LowPart < 2048) {
+        if (curOffset.HighPart == 0 && curOffset.LowPart < 2048) {
                        /* we're in the first page */
-                       if (temp < 13*32) temp = 13*32;
+            if (temp < 13*32) temp = 13*32;
                }
                else {
                        /* we're in a later dir page */
-                       if (temp < 32) temp = 32;
-               }
-
-               /* make sure the low order 5 bits are zero */
-               temp &= ~(32-1);
-
-               /* now put temp bits back ito curOffset.LowPart */
-               curOffset.LowPart &= ~(2048-1);
-               curOffset.LowPart |= temp;
-
-               /* check if we've passed the dir's EOF */
-               if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
-                       eos = 1;
-                       break;
-               }
+            if (temp < 32) temp = 32;
+        }
+               
+        /* make sure the low order 5 bits are zero */
+        temp &= ~(32-1);
+                
+        /* now put temp bits back ito curOffset.LowPart */
+        curOffset.LowPart &= ~(2048-1);
+        curOffset.LowPart |= temp;
+
+        /* check if we've passed the dir's EOF */
+        if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+            eos = 1;
+            break;
+        }
 
-               /* check if we've returned all the names that will fit in the
-               * response packet; we check return count as well as the number
-               * of bytes requested.  We check the # of bytes after we find
-               * the dir entry, since we'll need to check its size.
-               */
-               if (returnedNames >= maxCount) {
-                       break;
-               }
+        /* check if we've returned all the names that will fit in the
+         * response packet; we check return count as well as the number
+         * of bytes requested.  We check the # of bytes after we find
+         * the dir entry, since we'll need to check its size.
+         */
+        if (returnedNames >= maxCount) {
+            break;
+        }
 
-               /* see if we can use the bufferp we have now; compute in which
-               * page the current offset would be, and check whether that's
-               * the offset of the buffer we have.  If not, get the buffer.
-               */
-               thyper.HighPart = curOffset.HighPart;
-               thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
-               if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+        /* see if we can use the bufferp we have now; compute in which
+         * page the current offset would be, and check whether that's
+         * the offset of the buffer we have.  If not, get the buffer.
+         */
+        thyper.HighPart = curOffset.HighPart;
+        thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+        if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
                        /* wrong buffer */
-                       if (bufferp) {
-                               buf_Release(bufferp);
-                               bufferp = NULL;
-                       }
+            if (bufferp) {
+                buf_Release(bufferp);
+                bufferp = NULL;
+                       }       
                        lock_ReleaseMutex(&scp->mx);
                        lock_ObtainRead(&scp->bufCreateLock);
-                       code = buf_Get(scp, &thyper, &bufferp);
+            code = buf_Get(scp, &thyper, &bufferp);
                        lock_ReleaseRead(&scp->bufCreateLock);
 
                        /* now, if we're doing a star match, do bulk fetching
-                       * of all of the status info for files in the dir.
-                       */
-                       if (starPattern) {
+                        * 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
-                                                       cm_TryBulkStat(scp, &thyper,
-                                                       userp, &req);
-                                       }
+                                          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
+                        cm_TryBulkStat(scp, &thyper, userp, &req);
+                               }
                        }
 
-                       lock_ObtainMutex(&scp->mx);
-                       if (code) break;
-                       bufferOffset = thyper;
+            lock_ObtainMutex(&scp->mx);
+            if (code) break;
+            bufferOffset = thyper;
 
-                       /* now get the data in the cache */
-                       while (1) {
+            /* now get the data in the cache */
+            while (1) {
                                code = cm_SyncOp(scp, bufferp, userp, &req,
-                                       PRSFS_LOOKUP,
-                                       CM_SCACHESYNC_NEEDCALLBACK
-                                       | CM_SCACHESYNC_READ);
-                               if (code) break;
-
-                               if (cm_HaveBuffer(scp, bufferp, 0)) break;
-
-                               /* otherwise, load the buffer and try again */
-                               code = cm_GetBuffer(scp, bufferp, NULL, userp,
-                                       &req);
+                                 PRSFS_LOOKUP,
+                                 CM_SCACHESYNC_NEEDCALLBACK
+                                 | CM_SCACHESYNC_READ);
                                if (code) break;
-                       }
-                       if (code) {
+                                
+                if (cm_HaveBuffer(scp, bufferp, 0)) break;
+
+                /* otherwise, load the buffer and try again */
+                code = cm_GetBuffer(scp, bufferp, NULL, userp,
+                                    &req);
+                if (code) break;
+            }
+            if (code) {
                                buf_Release(bufferp);
-                               bufferp = NULL;
-                               break;
+                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.
-               */
+        }      /* 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);
+        entryInBuffer = curOffset.LowPart & (buf_bufferSize - 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.
-               */
+                * 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);
-               temp &= ~(2048 - 1);    /* turn off intra-page bits */
+        temp &= ~(2048 - 1);   /* turn off intra-page bits */
                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.
-               */
-               slotInPage = (entryInDir & 0x7e0) >> 5;
-               if (!(pageHeaderp->freeBitmap[slotInPage>>3]
-               & (1 << (slotInPage & 0x7)))) {
+                * 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 */
-                       numDirChunks = 1;       /* only skip this guy */
-                       goto nextEntry;
-               }
+            numDirChunks = 1;  /* only skip this guy */
+            goto nextEntry;
+        }
 
                tp = bufferp->datap + entryInBuffer;
-               dep = (cm_dirEntry_t *) tp;     /* now points to AFS3 dir entry */
+        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.
-               *
-               * XXXX Probably should do more sanity checking.
-               */
+        /* 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.
+         *
+         * XXXX Probably should do more sanity checking.
+         */
                numDirChunks = cm_NameEntries(dep->name, &onbytes);
-
-               /* compute offset of cookie representing next entry */
-               nextEntryCookie = curOffset.LowPart
-                       + (CM_DIR_CHUNKSIZE * numDirChunks);
+               
+        /* 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;
-                       }
-
-                       if (dep->fid.vnode != 0
-                               && (smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)
-                               || (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))
-                                               goto nextEntry; /* no hidden files */
-
-                                       if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
-                                       {
-                                               /* We have already done the cm_TryBulkStat above */
-                                               fid.cell = scp->fid.cell;
-                                               fid.volume = scp->fid.volume;
-                                               fid.vnode = ntohl(dep->fid.vnode);
-                                               fid.unique = ntohl(dep->fid.unique);
-                                               fileType = cm_FindFileType(&fid);
-                                               /*osi_Log2(afsd_logp, "smb_ReceiveTran2SearchDir: file %s "
-                                               "has filetype %d", dep->name,
-                                               fileType);*/
-                                               if (fileType == CM_SCACHETYPE_DIRECTORY)
-                                                       goto nextEntry;
-                                       }
-
-                                       /* 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 */
-
-                                       if (infoLevel == 0x104)
-                                               ohbytes += 26;  /* Short name & length */
-
-                                       if (searchFlags & 4) {
-                                               ohbytes += 4;   /* if resume key required */
-                                       }
-
-                                       if (infoLevel != 1
-                                               && infoLevel != 0x101
-                                               && infoLevel != 0x103)
-                                               ohbytes += 4;   /* EASIZE */
+                   && dep->fid.vnode != 0
+                   && !cm_Is8Dot3(dep->name)) {
+                       cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
+                       NeedShortName = 1;
+               }
 
-                                       /* add header to name & term. null */
-                                       orbytes = onbytes + ohbytes + 1;
+        /* 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)))) {
+
+            /* Eliminate entries that don't match requested attributes */
+            if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && 
+                 smb_IsDotFile(dep->name))
+                goto nextEntry; /* no hidden files */
+                    
+            if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
+            {
+                /* We have already done the cm_TryBulkStat above */
+                fid.cell = scp->fid.cell;
+                fid.volume = scp->fid.volume;
+                fid.vnode = ntohl(dep->fid.vnode);
+                fid.unique = ntohl(dep->fid.unique);
+                fileType = cm_FindFileType(&fid);
+                /*osi_Log2(smb_logp, "smb_ReceiveTran2SearchDir: file %s "
+                 "has filetype %d", dep->name,
+                 fileType);*/
+                if (fileType == CM_SCACHETYPE_DIRECTORY)
+                    goto nextEntry;
+            }
+
+                       /* 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 */
+
+                       if (infoLevel == 0x104)
+                               ohbytes += 26;  /* Short name & length */
+
+            if (searchFlags & 4) {
+                ohbytes += 4;  /* if resume key required */
+                       }   
+
+            if (infoLevel != 1
+                 && infoLevel != 0x101
+                 && infoLevel != 0x103)
+                               ohbytes += 4;   /* EASIZE */
+
+                       /* 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.
+             */
+                       if (infoLevel >= 0x101)
+                               align = (4 - (orbytes & 3)) & 3;
+                       else
+                               align = 0;
+                       if (orbytes + bytesInBuffer + align > 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.
+             */
+                       /* First zero everything else */
+                       memset(origOp, 0, ohbytes);
+
+                       if (infoLevel <= 0x101)
+                *(origOp + ohbytes - 1) = (unsigned char) onbytes;
+                       else if (infoLevel == 0x103)
+                               *((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;
+                               }
+                       }
 
-                                       /* 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)
-                                               break;
+            /* now, adjust the # of entries copied */
+            returnedNames++;
 
-                                       /* 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);
+                       /* NextEntryOffset and FileIndex */
+                       if (infoLevel >= 101) {
+                               int entryOffset = orbytes + align;
+                               *((u_long *)op) = entryOffset;
+                               *((u_long *)(op+4)) = nextEntryCookie;
+                       }
 
-                                       if (infoLevel <= 0x101)
-                                               *(origOp + ohbytes - 1) = (unsigned char) onbytes;
-                                       else if (infoLevel == 0x103)
-                                               *((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;
-                                               }
-                                       }
-
-                                       /* 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;
-                                       }
-
-                                       /* 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
-                                       * 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.
-                                       */
-                                       if (infoLevel != 0x103) {
-                                               curPatchp = malloc(sizeof(*curPatchp));
-                                               osi_QAdd((osi_queue_t **) &dirListPatchesp,
-                                                       &curPatchp->q);
-                                               curPatchp->dptr = op;
-                                               if (infoLevel >= 0x101)
-                                                       curPatchp->dptr += 8;
-                                               
-                                               if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
-                                                       curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
-                                               }
-                                               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);
-
-                                               /* temp */
-                                               curPatchp->dep = dep;
-                                       }
-
-                                       if (searchFlags & 4)
-                                               /* put out resume key */
-                                               *((u_long *)origOp) = nextEntryCookie;
-
-                                       /* Adjust byte ptr and count */
-                                       origOp += orbytes;      /* skip entire record */
-                                       bytesInBuffer += orbytes;
-
-                                       /* and pad the record out */
-                                       while (--align >= 0) {
-                                               *origOp++ = 0;
-                                               bytesInBuffer++;
-                                       }
-
-                               }       /* if we're including this name */
-
-nextEntry:
-                               /* and adjust curOffset to be where the new cookie is */
-                               thyper.HighPart = 0;
-                               thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
-                               curOffset = LargeIntegerAdd(thyper, curOffset);
-       }               /* while copying data for dir listing */
+            /* 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
+             * 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.
+             */
+                       if (infoLevel != 0x103) {
+                               curPatchp = malloc(sizeof(*curPatchp));
+                osi_QAdd((osi_queue_t **) &dirListPatchesp,
+                          &curPatchp->q);
+                               curPatchp->dptr = op;
+                               if (infoLevel >= 0x101)
+                                       curPatchp->dptr += 8;
+
+                if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
+                    curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
+                }
+                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);
+
+                /* temp */
+                curPatchp->dep = dep;
+                       }   
+
+                       if (searchFlags & 4)
+                               /* put out resume key */
+                               *((u_long *)origOp) = nextEntryCookie;
+
+                       /* Adjust byte ptr and count */
+                       origOp += orbytes;      /* skip entire record */
+            bytesInBuffer += orbytes;
+
+                       /* and pad the record out */
+            while (--align >= 0) {
+                               *origOp++ = 0;
+                bytesInBuffer++;
+            }
+
+               }       /* if we're including this name */
+        else if (!NeedShortName &&
+                 !starPattern &&
+                 !foundInexact &&
+                                                       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;
+        }
+                
+      nextEntry:
+        /* and adjust curOffset to be where the new cookie is */
+               thyper.HighPart = 0;
+        thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
+        curOffset = LargeIntegerAdd(thyper, curOffset);
+    }          /* 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
+     * marking the query as a star pattern (matches all case permutations), and
+     * re-running the query. 
+     */
+    if (returnedNames == 0 && !starPattern && foundInexact) {
+        osi_Log0(afsd_logp,"T2 Search: No exact matches. Re-running for inexact matches");
+        starPattern = 1;
+        goto startsearch;
+    }
 
        /* release the mutex */
        lock_ReleaseMutex(&scp->mx);
-       if (bufferp) buf_Release(bufferp);
+    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.
-       */
-       smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
-               &req);
-
-       /* now put out the final parameters */
+        * will be empty, but better safe (and freeing everything) than sorry.
+     */
+    smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
+                              &req);
+        
+    /* now put out the final parameters */
        if (returnedNames == 0) eos = 1;
-       if (p->opcode == 1) {
+    if (p->opcode == 1) {
                /* find first */
-               outp->parmsp[0] = (unsigned short) dsp->cookie;
-               outp->parmsp[1] = returnedNames;
-               outp->parmsp[2] = eos;
-               outp->parmsp[3] = 0;            /* nothing wrong with EAS */
-               outp->parmsp[4] = 0;    /* don't need last name to continue
-                                                               * search, cookie is enough.  Normally,
-                                                               * this is the offset of the file name
-                                                               * of the last entry returned.
-                                                               */
-               outp->totalParms = 10;  /* in bytes */
-       }
-       else {
-               /* find next */
-               outp->parmsp[0] = returnedNames;
-               outp->parmsp[1] = eos;
-               outp->parmsp[2] = 0;    /* EAS error */
-               outp->parmsp[3] = 0;    /* last name, as above */
-               outp->totalParms = 8;   /* in bytes */
-       }
+        outp->parmsp[0] = (unsigned short) dsp->cookie;
+        outp->parmsp[1] = returnedNames;
+        outp->parmsp[2] = eos;
+        outp->parmsp[3] = 0;           /* nothing wrong with EAS */
+        outp->parmsp[4] = 0;   
+        /* don't need last name to continue
+         * search, cookie is enough.  Normally,
+         * this is the offset of the file name
+         * of the last entry returned.
+         */
+        outp->totalParms = 10; /* in bytes */
+    }
+    else {
+        /* find next */
+        outp->parmsp[0] = returnedNames;
+        outp->parmsp[1] = eos;
+        outp->parmsp[2] = 0;   /* EAS error */
+        outp->parmsp[3] = 0;   /* last name, as above */
+        outp->totalParms = 8;  /* in bytes */
+    }   
 
        /* return # of bytes in the buffer */
-       outp->totalData = bytesInBuffer;
+    outp->totalData = bytesInBuffer;
 
-       osi_Log2(afsd_logp, "T2 search dir done, %d names, code %d",
-               returnedNames, code);
+       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;
 
        /* 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) */
-       /* pbh - added patch submitted to openafs-dev from James Petterson on 26 Feb, 2003 */
-       if ((searchFlags & 1) || (returnedNames == 0) || ((searchFlags & 2) && eos)
-               || code != 0) 
-               smb_DeleteDirSearch(dsp);
+     * 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) || 
+         ((searchFlags & 2) && eos) || code != 0)
+           smb_DeleteDirSearch(dsp);
        if (code)
-               smb_SendTran2Error(vcp, p, opx, code);
+        smb_SendTran2Error(vcp, p, opx, code);
        else {
-               smb_SendTran2Packet(vcp, outp, opx);
+        smb_SendTran2Packet(vcp, outp, opx);
        }
        smb_FreeTran2Packet(outp);
-       smb_ReleaseDirSearch(dsp);
-       cm_ReleaseSCache(scp);
-       cm_ReleaseUser(userp);
-       return 0;
+    smb_ReleaseDirSearch(dsp);
+    cm_ReleaseSCache(scp);
+    cm_ReleaseUser(userp);
+    return 0;
 }
 
 long smb_ReceiveV3FindClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        int dirHandle;
-        smb_dirSearch_t *dsp;
+    int dirHandle;
+    smb_dirSearch_t *dsp;
 
-        dirHandle = smb_GetSMBParm(inp, 0);
+    dirHandle = smb_GetSMBParm(inp, 0);
        
-        osi_Log1(afsd_logp, "SMB3 find close handle %d", dirHandle);
+    osi_Log1(smb_logp, "SMB3 find close handle %d", dirHandle);
 
-        dsp = smb_FindDirSearch(dirHandle);
+    dsp = smb_FindDirSearch(dirHandle);
         
-        if (!dsp)
+    if (!dsp)
                return CM_ERROR_BADFD;
        
-        /* otherwise, we have an FD to destroy */
-        smb_DeleteDirSearch(dsp);
-        smb_ReleaseDirSearch(dsp);
+    /* otherwise, we have an FD to destroy */
+    smb_DeleteDirSearch(dsp);
+    smb_ReleaseDirSearch(dsp);
         
        /* and return results */
        smb_SetSMBDataLength(outp, 0);
 
-        return 0;
+    return 0;
 }
 
 long smb_ReceiveV3FindNotifyClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        smb_SetSMBDataLength(outp, 0);
-        return 0;
+    return 0;
 }
 
 long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
+    long code = 0;
        cm_space_t *spacep;
-        int excl;
-        cm_user_t *userp;
-        cm_scache_t *dscp;             /* dir we're dealing with */
-        cm_scache_t *scp;              /* file we're creating */
-        cm_attr_t setAttr;
-        int initialModeBits;
-        smb_fid_t *fidp;
-        int attributes;
-        char *lastNamep;
-        long dosTime;
-        int openFun;
-        int trunc;
-        int openMode;
-        int extraInfo;
-        int openAction;
-        int parmSlot;                  /* which parm we're dealing with */
+    int excl;
+    cm_user_t *userp;
+    cm_scache_t *dscp;         /* dir we're dealing with */
+    cm_scache_t *scp;          /* file we're creating */
+    cm_attr_t setAttr;
+    int initialModeBits;
+    smb_fid_t *fidp;
+    int attributes;
+    char *lastNamep;
+    long 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;
 
        cm_InitReq(&req);
 
-        scp = NULL;
+    scp = NULL;
         
        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 */
+    excl = ((openFun & 3) == 0);
+    trunc = ((openFun & 3) == 2);              /* truncate it */
        openMode = (smb_GetSMBParm(inp, 3) & 0x7);
-        openAction = 0;                        /* tracks what we did */
+    openAction = 0;                    /* tracks what we did */
+
+    attributes = smb_GetSMBParm(inp, 5);
+    dosTime = smb_GetSMBParm(inp, 6) | (smb_GetSMBParm(inp, 7) << 16);
 
-        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 */
-        initialModeBits = 0666;
-        if (attributes & 1) initialModeBits &= ~0222;
+    initialModeBits = 0666;
+    if (attributes & 1) initialModeBits &= ~0222;
         
-        pathp = smb_GetSMBData(inp, NULL);
+    pathp = smb_GetSMBData(inp, NULL);
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        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).
-                 */
+         * (since IOCTL calls themselves aren't getting through).
+         */
 #ifdef NOTSERVICE
-                       osi_Log0(afsd_logp, "IOCTL Open");
+        osi_Log0(smb_logp, "IOCTL Open");
 #endif
-               fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-                smb_SetupIoctlFid(fidp, spacep);
+
+        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 */
-               inp->fid = fidp->fid;
+        inp->fid = fidp->fid;
         
-               /* copy out remainder of the parms */
+        /* copy out remainder of the parms */
                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++;
-                       smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;  /* len */
-                       smb_SetSMBParm(outp, parmSlot, 0x7fff); parmSlot++;
-                       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 */
-               }
+            smb_SetSMBParm(outp, parmSlot, /* attrs */ 0); parmSlot++;
+            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* mod time */
+            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
+            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* len */
+            smb_SetSMBParm(outp, parmSlot, 0x7fff); parmSlot++;
+            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 */
-               smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
+        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++;
-               smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
-               smb_SetSMBDataLength(outp, 0);
+        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
+        smb_SetSMBDataLength(outp, 0);
 
                /* and clean up fid reference */
-                smb_ReleaseFID(fidp);
-                return 0;
-        }
+        smb_ReleaseFID(fidp);
+        return 0;
+    }
 
 #ifdef DEBUG_VERBOSE
-       {
-               char *hexp, *asciip;
-               asciip = (lastNamep ? lastNamep : pathp );
-               hexp = osi_HexifyString(asciip);
-               DEBUG_EVENT2("AFS", "V3Open H[%s] A[%s]", hexp, asciip );
-               free(hexp);
-       }
+    {
+       char *hexp, *asciip;
+       asciip = (lastNamep ? lastNamep : pathp );
+       hexp = osi_HexifyString(asciip);
+       DEBUG_EVENT2("AFS", "V3Open H[%s] A[%s]", hexp, asciip );
+       free(hexp);
+    }
 #endif
-
-       userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
 
        dscp = NULL;
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        code = cm_NameI(cm_rootSCachep, pathp,
-               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-               userp, tidPathp, &req, &scp);
+                    CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                    userp, tidPathp, &req, &scp);
        if (code != 0) {
                code = cm_NameI(cm_rootSCachep, spacep->data,
-                               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                               userp, tidPathp, &req, &dscp);
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &dscp);
 
-               if (code) {
-                       cm_ReleaseUser(userp);
-                       return code;
-               }
+        if (code) {
+            cm_ReleaseUser(userp);
+            return code;
+        }
         
-               /* 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++;
-               code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
-                                &req, &scp);
-               if (code && code != CM_ERROR_NOSUCHFILE) {
+        /* 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++;
+        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
+                          &req, &scp);
+        if (code && code != CM_ERROR_NOSUCHFILE) {
                        cm_ReleaseSCache(dscp);
-                       cm_ReleaseUser(userp);
-                       return code;
-               }
+            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 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) {
-               code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
-                if (code) {
-                        if (dscp) cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
-                        return code;
-                }
+        code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
+        if (code) {
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            return code;
+        }
 
                if (excl) {
                        /* oops, file shouldn't be there */
-                        if (dscp) cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
-                        return CM_ERROR_EXISTS;
-                }
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            return CM_ERROR_EXISTS;
+        }
 
                if (trunc) {
                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                       setAttr.length.LowPart = 0;
-                       setAttr.length.HighPart = 0;
+            setAttr.length.LowPart = 0;
+            setAttr.length.HighPart = 0;
                        code = cm_SetAttr(scp, &setAttr, userp, &req);
-                        openAction = 3;        /* truncated existing file */
+            openAction = 3;    /* truncated existing file */
                }
-                else openAction = 1;   /* found existing file */
-        }
+        else openAction = 1;   /* found existing file */
+    }
        else if (!(openFun & 0x10)) {
                /* don't create if not found */
-                if (dscp) cm_ReleaseSCache(dscp);
-                cm_ReleaseUser(userp);
-                return CM_ERROR_NOSUCHFILE;
-        }
-        else {
+        if (dscp) cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+    else {
                osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp, "smb_ReceiveV3OpenX creating file %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+               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);
-                code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
-                                &req);
+        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 (!excl && code == CM_ERROR_EXISTS) {
+                             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.
-                         */
-                        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
-                        if (code == 0) {
-                               if (trunc) {
+             */
+            code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
+                             userp, &req, &scp);
+            if (code == 0) {
+                if (trunc) {
                                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                                       setAttr.length.LowPart = 0;
-                                       setAttr.length.HighPart = 0;
-                                       code = cm_SetAttr(scp, &setAttr, userp,
-                                                         &req);
-                               }
+                    setAttr.length.LowPart = 0;
+                    setAttr.length.HighPart = 0;
+                    code = cm_SetAttr(scp, &setAttr, userp, &req);
+                }   
                        }       /* lookup succeeded */
-                }
         }
+    }
         
        /* we don't need this any longer */
        if (dscp) cm_ReleaseSCache(dscp);
 
-        if (code) {
+    if (code) {
                /* something went wrong creating or truncating the file */
-                if (scp) cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+        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) {
@@ -2708,55 +4074,55 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                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);
+    /* 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 */
-        fidp->scp = scp;
+    fidp->scp = scp;
         
        /* compute open mode */
-        if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
-        if (openMode == 1 || openMode == 2)
-               fidp->flags |= SMB_FID_OPENWRITE;
+    if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+    if (openMode == 1 || openMode == 2)
+        fidp->flags |= SMB_FID_OPENWRITE;
 
        smb_ReleaseFID(fidp);
         
        cm_Open(scp, 0, userp);
 
        /* set inp->fid so that later read calls in same msg can find fid */
-        inp->fid = fidp->fid;
+    inp->fid = fidp->fid;
         
-        /* copy out remainder of the parms */
+    /* copy out remainder of the parms */
        parmSlot = 2;
        smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
        lock_ObtainMutex(&scp->mx);
        if (extraInfo) {
-               smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
                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++;
-                smb_SetSMBParm(outp, parmSlot, (scp->length.LowPart >> 16) & 0xffff); parmSlot++;
-                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 */
+        smb_SetSMBParm(outp, parmSlot, dosTime & 0xffff); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, (dosTime>>16) & 0xffff); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, scp->length.LowPart & 0xffff); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, (scp->length.LowPart >> 16) & 0xffff); parmSlot++;
+        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 */
-        smb_SetSMBParm(outp, parmSlot, openAction); parmSlot++;
+    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++;
-        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
+    smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
        lock_ReleaseMutex(&scp->mx);
-        smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBDataLength(outp, 0);
 
-       osi_Log1(afsd_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;
-}
+    cm_ReleaseUser(userp);
+    /* leave scp held since we put it in fidp->scp */
+    return 0;
+}   
 
 long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
@@ -2772,7 +4138,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        LARGE_INTEGER LOffset, LLength;
        smb_waitingLock_t *waitingLock;
        void *lockp;
-       long code;
+       long code = 0;
        int i;
 
        cm_InitReq(&req);
@@ -2785,7 +4151,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                return CM_ERROR_BADFD;
        }
        /* set inp->fid so that later read calls in same msg can find fid */
-        inp->fid = fid;
+    inp->fid = fid;
 
        userp = smb_GetUser(vcp, inp);
 
@@ -2891,59 +4257,59 @@ doneSync:
 long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned short fid;
-        smb_fid_t *fidp;
-        cm_scache_t *scp;
-        long code;
-        long searchTime;
-        cm_user_t *userp;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
+    long code = 0;
+    long searchTime;
+    cm_user_t *userp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        fid = smb_GetSMBParm(inp, 0);
-        fid = smb_ChainFID(fid, inp);
+    fid = smb_GetSMBParm(inp, 0);
+    fid = smb_ChainFID(fid, inp);
         
-        fidp = smb_FindFID(vcp, fid, 0);
-        if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
                return CM_ERROR_BADFD;
-        }
+    }
         
-        userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
         
-        scp = fidp->scp;
+    scp = fidp->scp;
         
-        /* otherwise, stat the file */
+    /* otherwise, stat the file */
        lock_ObtainMutex(&scp->mx);
-        code = cm_SyncOp(scp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
        if (code) goto done;
 
        /* 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.
-         */
+     * 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_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff);  /* ctime */
-        smb_SetSMBParm(outp, 1, searchTime & 0xffff);
-        smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff);  /* atime */
-        smb_SetSMBParm(outp, 3, searchTime & 0xffff);
-        smb_SetSMBParm(outp, 4, (searchTime >> 16) & 0xffff);  /* mtime */
-        smb_SetSMBParm(outp, 5, searchTime & 0xffff);
-        
-        /* now handle file size and allocation size */
-        smb_SetSMBParm(outp, 6, scp->length.LowPart & 0xffff);         /* file size */
-        smb_SetSMBParm(outp, 7, (scp->length.LowPart >> 16) & 0xffff);
-        smb_SetSMBParm(outp, 8, scp->length.LowPart & 0xffff);         /* alloc size */
-        smb_SetSMBParm(outp, 9, (scp->length.LowPart >> 16) & 0xffff);
-        
+    smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff);      /* ctime */
+    smb_SetSMBParm(outp, 1, searchTime & 0xffff);
+    smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff);      /* atime */
+    smb_SetSMBParm(outp, 3, searchTime & 0xffff);
+    smb_SetSMBParm(outp, 4, (searchTime >> 16) & 0xffff);      /* mtime */
+    smb_SetSMBParm(outp, 5, searchTime & 0xffff);
+
+    /* now handle file size and allocation size */
+    smb_SetSMBParm(outp, 6, scp->length.LowPart & 0xffff);             /* file size */
+    smb_SetSMBParm(outp, 7, (scp->length.LowPart >> 16) & 0xffff);
+    smb_SetSMBParm(outp, 8, scp->length.LowPart & 0xffff);             /* alloc size */
+    smb_SetSMBParm(outp, 9, (scp->length.LowPart >> 16) & 0xffff);
+
        /* file attribute */
-        smb_SetSMBParm(outp, 10, smb_Attributes(scp));
+    smb_SetSMBParm(outp, 10, smb_Attributes(scp));
         
-        /* and finalize stuff */
-        smb_SetSMBDataLength(outp, 0);
-        code = 0;
+    /* and finalize stuff */
+    smb_SetSMBDataLength(outp, 0);
+    code = 0;
 
-done:
+  done:
        lock_ReleaseMutex(&scp->mx);
        cm_ReleaseUser(userp);
        smb_ReleaseFID(fidp);
@@ -2953,51 +4319,49 @@ done:
 long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned short fid;
-        smb_fid_t *fidp;
-        cm_scache_t *scp;
-        long code;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
+    long code = 0;
        long searchTime;
-        long unixTime;
-        cm_user_t *userp;
-        cm_attr_t attrs;
+    long unixTime;
+    cm_user_t *userp;
+    cm_attr_t attrs;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        fid = smb_GetSMBParm(inp, 0);
-        fid = smb_ChainFID(fid, inp);
+    fid = smb_GetSMBParm(inp, 0);
+    fid = smb_ChainFID(fid, inp);
         
-        fidp = smb_FindFID(vcp, fid, 0);
-        if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
                return CM_ERROR_BADFD;
-        }
+    }
         
-        userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
         
-        scp = fidp->scp;
+    scp = fidp->scp;
         
        /* 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.
-         */
+     * 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);
         
-        if (searchTime != 0) {
+    if (searchTime != 0) {
                smb_UnixTimeFromSearchTime(&unixTime, searchTime);
 
-                       if (unixTime != -1) {
-                attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
-                attrs.clientModTime = unixTime;
-                code = cm_SetAttr(scp, &attrs, userp, &req);
+        if ( unixTime != -1 ) {
+            attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
+            attrs.clientModTime = unixTime;
+            code = cm_SetAttr(scp, &attrs, userp, &req);
 
-                               osi_Log1(afsd_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
-                       }
-                       else {
-                               osi_Log1(afsd_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
-                       }
-        
-               }
-        else code = 0;
+            osi_Log1(smb_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
+        } else {
+            osi_Log1(smb_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
+        }
+    }
+    else code = 0;
 
        cm_ReleaseUser(userp);
        smb_ReleaseFID(fidp);
@@ -3008,59 +4372,59 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        osi_hyper_t offset;
-        long count, finalCount;
-        unsigned short fd;
-        smb_fid_t *fidp;
-        long code;
-        cm_user_t *userp;
-        char *op;
-        
-        fd = smb_GetSMBParm(inp, 2);
-        count = smb_GetSMBParm(inp, 5);
-        offset.HighPart = 0;   /* too bad */
-        offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+    long count, finalCount;
+    unsigned short fd;
+    smb_fid_t *fidp;
+    long code = 0;
+    cm_user_t *userp;
+    char *op;
         
-        osi_Log3(afsd_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
-               fd, offset.LowPart, count);
+    fd = smb_GetSMBParm(inp, 2);
+    count = smb_GetSMBParm(inp, 5);
+    offset.HighPart = 0;       /* too bad */
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+    osi_Log3(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
+             fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
-        fidp = smb_FindFID(vcp, fd, 0);
-        if (!fidp) {
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp) {
                return CM_ERROR_BADFD;
-        }
+    }
        /* set inp->fid so that later read calls in same msg can find fid */
-        inp->fid = fd;
+    inp->fid = fd;
 
-        if (fidp->flags & SMB_FID_IOCTL) {
+    if (fidp->flags & SMB_FID_IOCTL) {
                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,
-         * 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 */
+     * 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 */
-        /* 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 */
+    /* 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 */
 
        /* get op ptr after putting in the parms, since otherwise we don't
-         * know where the data really is.
-         */
-        op = smb_GetSMBData(outp, NULL);
+     * know where the data really is.
+     */
+    op = smb_GetSMBData(outp, NULL);
         
-        /* now fill in offset from start of SMB header to first data byte (to op) */
-        smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
+    /* 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 */
-        smb_SetSMBDataLength(outp, count);
+    smb_SetSMBDataLength(outp, count);
 
 #ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
@@ -3072,11 +4436,11 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        smb_SetSMBParm(outp, 5, finalCount);
        smb_SetSMBDataLength(outp, finalCount);
 
-        smb_ReleaseFID(fidp);
+    smb_ReleaseFID(fidp);
 
-        cm_ReleaseUser(userp);
-        return code;
-}
+    cm_ReleaseUser(userp);
+    return code;
+}   
         
 /*
  * Values for createDisp, copied from NTDDK.H
@@ -3092,20 +4456,20 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp, *realPathp;
-       long code;
+       long code = 0;
        cm_space_t *spacep;
        cm_user_t *userp;
        cm_scache_t *dscp;              /* parent dir */
        cm_scache_t *scp;               /* file to create or open */
        cm_attr_t setAttr;
        char *lastNamep;
-       char *treeStartp;
+    char *treeStartp;
        unsigned short nameLength;
        unsigned int flags;
        unsigned int requestOpLock;
        unsigned int requestBatchOpLock;
        unsigned int mustBeDir;
-       unsigned int treeCreate;
+    unsigned int treeCreate;
        int realDirFlag;
        unsigned int desiredAccess;
        unsigned int extAttributes;
@@ -3127,36 +4491,36 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        cm_InitReq(&req);
 
-       treeCreate = FALSE;
+    treeCreate = FALSE;
        foundscp = FALSE;
        scp = NULL;
 
        nameLength = smb_GetSMBOffsetParm(inp, 2, 1);
        flags = smb_GetSMBOffsetParm(inp, 3, 1)
-               | (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
+                 | (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
        requestOpLock = flags & 0x02;
        requestBatchOpLock = flags & 0x04;
        mustBeDir = flags & 0x08;
 
        /*
-       * Why all of a sudden 32-bit FID?
-       * We will reject all bits higher than 16.
-       */
+        * Why all of a sudden 32-bit FID?
+        * We will reject all bits higher than 16.
+        */
        if (smb_GetSMBOffsetParm(inp, 6, 1) != 0)
                return CM_ERROR_INVAL;
        baseFid = smb_GetSMBOffsetParm(inp, 5, 1);
        desiredAccess = smb_GetSMBOffsetParm(inp, 7, 1)
-               | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+                         | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
        extAttributes = smb_GetSMBOffsetParm(inp, 13, 1)
-               | (smb_GetSMBOffsetParm(inp, 14, 1) << 16);
+                         | (smb_GetSMBOffsetParm(inp, 14, 1) << 16);
        createDisp = smb_GetSMBOffsetParm(inp, 17, 1)
-               | (smb_GetSMBOffsetParm(inp, 18, 1) << 16);
+                       | (smb_GetSMBOffsetParm(inp, 18, 1) << 16);
        createOptions = smb_GetSMBOffsetParm(inp, 19, 1)
-               | (smb_GetSMBOffsetParm(inp, 20, 1) << 16);
+                         | (smb_GetSMBOffsetParm(inp, 20, 1) << 16);
 
        /* mustBeDir is never set; createOptions directory bit seems to be
-       * more important
-       */
+     * more important
+        */
        if (createOptions & 1)
                realDirFlag = 1;
        else if (createOptions & 0x40)
@@ -3165,9 +4529,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                realDirFlag = -1;
 
        /*
-       * compute initial mode bits based on read-only flag in
-       * extended attributes
-       */
+        * compute initial mode bits based on read-only flag in
+        * extended attributes
+        */
        initialModeBits = 0666;
        if (extAttributes & 1) initialModeBits &= ~0222;
 
@@ -3180,15 +4544,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
 
-       osi_Log1(afsd_logp,"NTCreateX for [%s]",osi_LogSaveString(afsd_logp,realPathp));
-       osi_Log4(afsd_logp,"NTCreateX da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
+    osi_Log1(smb_logp,"NTCreateX for [%s]",osi_LogSaveString(smb_logp,realPathp));
+    osi_Log4(smb_logp,"NTCreateX da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
+    osi_Log1(smb_logp,"NTCreateX lastNamep=[%s]",osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
 
        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).
-               */
+                * (since IOCTL calls themselves aren't getting through).
+                */
                fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
                smb_SetupIoctlFid(fidp, spacep);
+               osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid);
 
                /* set inp->fid so that later read calls in same msg can find fid */
                inp->fid = fidp->fid;
@@ -3220,42 +4586,40 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        }
 
 #ifdef DEBUG_VERBOSE
-       {
-               char *hexp, *asciip;
-               asciip = (lastNamep? lastNamep : realPathp);
-               hexp = osi_HexifyString( asciip );
-               DEBUG_EVENT2("AFS", "NTCreateX H[%s] A[%s]", hexp, asciip);
-               free(hexp);
-       }
+    {
+       char *hexp, *asciip;
+       asciip = (lastNamep? lastNamep : realPathp);
+       hexp = osi_HexifyString( asciip );
+       DEBUG_EVENT2("AFS", "NTCreateX H[%s] A[%s]", hexp, asciip);
+       free(hexp);
+    }
 #endif
-
-       userp = smb_GetUser(vcp, inp);
-
-       if(!userp) {
-               osi_Log1(afsd_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
-               free(realPathp);
-               return CM_ERROR_INVAL;
-       }
+    userp = smb_GetUser(vcp, inp);
+    if (!userp) {
+       osi_Log1(smb_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
+       free(realPathp);
+       return CM_ERROR_INVAL;
+    }
 
        if (baseFid == 0) {
                baseDirp = cm_rootSCachep;
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        }
        else {
-               baseFidp = smb_FindFID(vcp, baseFid, 0);
-               if(!baseFidp) {
-                       osi_Log1(afsd_logp, "NTCreateX Invalid base fid [%d]", baseFid);
-                       free(realPathp);
-                       cm_ReleaseUser(userp);
-                       return CM_ERROR_INVAL;
-               }
+        baseFidp = smb_FindFID(vcp, baseFid, 0);
+        if (!baseFidp) {
+               osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+               free(realPathp);
+               cm_ReleaseUser(userp);
+               return CM_ERROR_INVAL;
+        }
                baseDirp = baseFidp->scp;
                tidPathp = NULL;
        }
 
-       osi_Log1(afsd_logp, "NTCreateX tidPathp=[%s]", (tidPathp==NULL)?"null": osi_LogSaveString(afsd_logp,tidPathp));
-
-       /* compute open mode */
+    osi_Log1(smb_logp, "NTCreateX tidPathp=[%s]", (tidPathp==NULL)?"null": osi_LogSaveString(smb_logp,tidPathp));
+       
+    /* compute open mode */
        fidflags = 0;
        if (desiredAccess & DELETE)
                fidflags |= SMB_FID_OPENDELETE;
@@ -3266,94 +4630,129 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        dscp = NULL;
        code = 0;
-       code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-               userp, tidPathp, &req, &scp);
-       if (code == 0) foundscp = TRUE;
-       if (code != 0
-               || (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*
-                       the immediate parent.  We have to work our way up realPathp until we hit something that we
-                       recognize.
-                       */
-
-                       while(1) {
-                               char *tp;
-
-                               code = cm_NameI(baseDirp, spacep->data,
-                                       CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                                       userp, tidPathp, &req, &dscp);
-
-                               if(code && 
-                                       (tp = strrchr(spacep->data,'\\')) &&
-                                       (createDisp == 2) &&
-                                       (realDirFlag == 1)) {
-                                               *tp++ = 0;
-                                               treeCreate = TRUE;
-                                               treeStartp = realPathp + (tp - spacep->data);
-
-                                               if(*tp && !smb_IsLegalFilename(tp)) {
-                                                       if(baseFid != 0) smb_ReleaseFID(baseFidp);
-                                                       cm_ReleaseUser(userp);
-                                                       free(realPathp);
-                                                       return CM_ERROR_BADNTFILENAME;
-                                               }
-                                       }
-                               else
-                                       break;
-                       }
+    /* For an exclusive create, we want to do a case sensitive match for the last component. */
+    if (createDisp == 2 || createDisp == 4 || createDisp == 5) {
+        code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &dscp);
+        if (code == 0) {
+            code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
+                             userp, &req, &scp);
+            if (code == CM_ERROR_NOSUCHFILE) {
+                code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, 
+                                 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp);
+                if (code == 0 && realDirFlag == 1) {
+                                       cm_ReleaseSCache(scp);
+                    cm_ReleaseSCache(dscp);
+                    cm_ReleaseUser(userp);
+                    free(realPathp);
+                    return CM_ERROR_EXISTS;
+                }
+            }
+        } else
+            dscp = NULL;
+    } else {
+        code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &scp);
+    }
+    if (code == 0) 
+               foundscp = TRUE;
 
-                       if (baseFid != 0) smb_ReleaseFID(baseFidp);
+       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*
+         * the immediate parent.  We have to work our way up realPathp until we hit something that we
+         * recognize.
+         */
 
-                       if (code) {
-                               osi_Log0(afsd_logp,"NTCreateX parent not found");
-                               cm_ReleaseUser(userp);
-                               free(realPathp);
-                               return code;
-                       }
+        if ( !dscp ) {
+            while (1) {
+                char *tp;
+
+                code = cm_NameI(baseDirp, spacep->data,
+                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                             userp, tidPathp, &req, &dscp);
+
+                if (code && 
+                     (tp = strrchr(spacep->data,'\\')) &&
+                     (createDisp == 2) &&
+                     (realDirFlag == 1)) {
+                    *tp++ = 0;
+                    treeCreate = TRUE;
+                    treeStartp = realPathp + (tp - spacep->data);
+
+                    if (*tp && !smb_IsLegalFilename(tp)) {
+                        if (baseFid != 0) 
+                            smb_ReleaseFID(baseFidp);
+                        cm_ReleaseUser(userp);
+                        free(realPathp);
+                        return CM_ERROR_BADNTFILENAME;
+                    }
+                }
+                else
+                    break;
+            }
+        } else
+            code = 0;
 
-                       if(treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
-                /* A file exists where we want a directory. */
-                               cm_ReleaseSCache(dscp);
-                               cm_ReleaseUser(userp);
-                               free(realPathp);
-                               return CM_ERROR_EXISTS;
-                       }
+        if (baseFid != 0) 
+                       smb_ReleaseFID(baseFidp);
+
+        if (code) {
+            osi_Log0(smb_logp,"NTCreateX parent not found");
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return code;
+        }
+
+        if (treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
+            /* A file exists where we want a directory. */
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_EXISTS;
+        }
 
-                       if (!lastNamep) lastNamep = realPathp;
-                       else lastNamep++;
+        if (!lastNamep) 
+            lastNamep = realPathp;
+        else 
+            lastNamep++;
 
-                       if (!smb_IsLegalFilename(lastNamep)) {
+        if (!smb_IsLegalFilename(lastNamep)) {
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_BADNTFILENAME;
+        }
+
+        if (!foundscp && !treeCreate) {
+            if (createDisp == 2 || createDisp == 4)
+                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);
+                       if (code && code != CM_ERROR_NOSUCHFILE) {
                                cm_ReleaseSCache(dscp);
                                cm_ReleaseUser(userp);
                                free(realPathp);
-                               return CM_ERROR_BADNTFILENAME;
-                       }
-
-                       if (!foundscp && !treeCreate) {
-                               code = cm_Lookup(dscp, lastNamep,
-                                       CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                                       userp, &req, &scp);
-                               if (code && code != CM_ERROR_NOSUCHFILE) {
-                                       cm_ReleaseSCache(dscp);
-                                       cm_ReleaseUser(userp);
-                                       free(realPathp);
-                                       return code;
-                               }
+                               return code;
                        }
                }
+       }
        else {
-               if (baseFid != 0) smb_ReleaseFID(baseFidp);
+               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.
-       */
+        * 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) {
                code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
-                       &req);
+                                     &req);
                if (code) {
                        if (dscp) cm_ReleaseSCache(dscp);
                        cm_ReleaseSCache(scp);
@@ -3372,13 +4771,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                }
 
                if (createDisp == 4
-                       || createDisp == 5) {
-                               setAttr.mask = CM_ATTRMASK_LENGTH;
-                               setAttr.length.LowPart = 0;
-                               setAttr.length.HighPart = 0;
-                               code = cm_SetAttr(scp, &setAttr, userp, &req);
-                               openAction = 3; /* truncated existing file */
-                       }
+                   || createDisp == 5) {
+                       setAttr.mask = CM_ATTRMASK_LENGTH;
+                       setAttr.length.LowPart = 0;
+                       setAttr.length.HighPart = 0;
+                       code = cm_SetAttr(scp, &setAttr, userp, &req);
+                       openAction = 3; /* truncated existing file */
+               }
                else openAction = 1;    /* found existing file */
        }
        else if (createDisp == 1 || createDisp == 4) {
@@ -3390,62 +4789,63 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        }
        else if (realDirFlag == 0 || realDirFlag == -1) {
                osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating file %s",
-                       osi_LogSaveString(afsd_logp, lastNamep));
+               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);
+                                &req);
                if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                        smb_NotifyChange(FILE_ACTION_ADDED,
-                       FILE_NOTIFY_CHANGE_FILE_NAME,
-                       dscp, lastNamep, NULL, TRUE);
+                                        FILE_NOTIFY_CHANGE_FILE_NAME,
+                                        dscp, lastNamep, NULL, TRUE);
                if (code == CM_ERROR_EXISTS && createDisp != 2) {
                        /* 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.
-                       */
+                        * 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);
+                                        userp, &req, &scp);
                        if (code == 0) {
                                if (createDisp == 5) {
                                        setAttr.mask = CM_ATTRMASK_LENGTH;
                                        setAttr.length.LowPart = 0;
                                        setAttr.length.HighPart = 0;
                                        code = cm_SetAttr(scp, &setAttr, userp,
-                                               &req);
+                                                         &req);
                                }
                        }       /* lookup succeeded */
                }
        }
        else {
-               char *tp, *pp;
-               char *cp; /* This component */
-               int clen; /* length of component */
-               cm_scache_t *tscp;
-               int isLast = 0;
-
-               /* create directory */
-               if(!treeCreate) treeStartp = lastNamep;
-               osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory [%s]",
-                       osi_LogSaveString(afsd_logp, treeStartp));
+        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) {
+               while (pp && *pp) {
                        tp = strchr(pp, '\\');
-                       if(!tp) {
+                       if (!tp) {
                                strcpy(cp,pp);
+                clen = strlen(cp);
                                isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
                        }
                        else {
@@ -3456,7 +4856,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        }
                        pp = tp;
 
-                       if(clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */
+                       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);
@@ -3475,9 +4875,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                                        code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
                                                userp, &req, &scp);
                                }
-                       if(code) break;
+                       if (code) break;
 
-                       if(!isLast) { /* for anything other than dscp, release it unless it's the last one */
+                       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 */
                        }
@@ -3493,7 +4893,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (code) {
                /* something went wrong creating or truncating the file */
                if (scp) cm_ReleaseSCache(scp);
-               if (dscp) cm_ReleaseSCache(dscp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return code;
@@ -3502,15 +4902,15 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        /* make sure we have file vs. dir right (only applies for single component case) */
        if (realDirFlag == 0 && 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_ISDIR;
        }
-       /* (only applies for single component case) */
+    /* (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;
@@ -3552,7 +4952,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
        smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
-       parmSlot += 2;
+                                               parmSlot += 2;
        smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
        smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;  /* filetype */
@@ -3562,14 +4962,14 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        lock_ReleaseMutex(&scp->mx);
        smb_SetSMBDataLength(outp, 0);
 
-       osi_Log2(afsd_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid,
-               osi_LogSaveString(afsd_logp, realPathp));
+       osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid,
+                osi_LogSaveString(smb_logp, realPathp));
 
        smb_ReleaseFID(fidp);
 
        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;
@@ -3582,7 +4982,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp, *realPathp;
-       long code;
+       long code = 0;
        cm_space_t *spacep;
        cm_user_t *userp;
        cm_scache_t *dscp;              /* parent dir */
@@ -3594,14 +4994,18 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        unsigned int requestOpLock;
        unsigned int requestBatchOpLock;
        unsigned int mustBeDir;
-       unsigned int extendedRespRequired;
+    unsigned int extendedRespRequired;
        int realDirFlag;
        unsigned int desiredAccess;
-       /*unsigned int allocSize;*/
-       /*unsigned int shareAccess;*/
+#ifdef DEBUG_VERBOSE    
+    unsigned int allocSize;
+    unsigned int shareAccess;
+#endif
        unsigned int extAttributes;
        unsigned int createDisp;
-       /*unsigned int sdLen;*/
+#ifdef DEBUG_VERBOSE
+    unsigned int sdLen;
+#endif
        unsigned int createOptions;
        int initialModeBits;
        unsigned short baseFid;
@@ -3634,7 +5038,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        requestOpLock = flags & 0x02;
        requestBatchOpLock = flags & 0x04;
        mustBeDir = flags & 0x08;
-       extendedRespRequired = flags & 0x10;
+    extendedRespRequired = flags & 0x10;
 
        /*
         * Why all of a sudden 32-bit FID?
@@ -3644,19 +5048,25 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                return CM_ERROR_INVAL;
        baseFid = (unsigned short)lparmp[1];
        desiredAccess = lparmp[2];
-       /*allocSize = lparmp[3];*/
+#ifdef DEBUG_VERBOSE
+    allocSize = lparmp[3];
+#endif /* DEBUG_VERSOSE */
        extAttributes = lparmp[5];
-       /*shareAccess = lparmp[6];*/
+#ifdef DEBUG_VEROSE
+    shareAccess = lparmp[6];
+#endif
        createDisp = lparmp[7];
        createOptions = lparmp[8];
-       /*sdLen = lparmp[9];*/
+#ifdef DEBUG_VERBOSE
+    sdLen = lparmp[9];
+#endif
        nameLength = lparmp[11];
 
-       /*
-       osi_Log4(afsd_logp,"NTTransCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
-       osi_Log2(afsd_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
-       osi_Log1(afsd_logp,"... flags[%x]",flags);
-       */
+#ifdef DEBUG_VERBOSE
+       osi_Log4(smb_logp,"NTTransCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+       osi_Log2(smb_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
+       osi_Log1(smb_logp,"... flags[%x]",flags);
+#endif
 
        /* mustBeDir is never set; createOptions directory bit seems to be
          * more important
@@ -3688,6 +5098,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         * Nothing here to handle SMB_IOCTL_FILENAME.
         * Will add it if necessary.
         */
+
 #ifdef DEBUG_VERBOSE
        {
                char *hexp, *asciip;
@@ -3699,49 +5110,75 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 #endif
 
        userp = smb_GetUser(vcp, inp);
-       if(!userp) {
-               osi_Log1(afsd_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid);
-               free(realPathp);
-               return CM_ERROR_INVAL;
-       }
+    if (!userp) {
+       osi_Log1(smb_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid);
+       free(realPathp);
+       return CM_ERROR_INVAL;
+    }
 
        if (baseFid == 0) {
                baseDirp = cm_rootSCachep;
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        }
        else {
-               baseFidp = smb_FindFID(vcp, baseFid, 0);
-                       if(!baseFidp) {
-                               osi_Log1(afsd_logp, "NTTranCreate Invalid fid [%d]", baseFid);
-                               free(realPathp);
-                               cm_ReleaseUser(userp);
-                               return CM_ERROR_INVAL;
-                       }
+        baseFidp = smb_FindFID(vcp, baseFid, 0);
+        if (!baseFidp) {
+               osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+               free(realPathp);
+               cm_ReleaseUser(userp);
+               return CM_ERROR_INVAL;
+        }
                baseDirp = baseFidp->scp;
                tidPathp = NULL;
        }
 
-        /* compute open mode */
-        fidflags = 0;
-        if (desiredAccess & DELETE)
-                fidflags |= SMB_FID_OPENDELETE;
-        if (desiredAccess & AFS_ACCESS_READ)
-                fidflags |= SMB_FID_OPENREAD;
-        if (desiredAccess & AFS_ACCESS_WRITE)
-                fidflags |= SMB_FID_OPENWRITE;
+    /* compute open mode */
+    fidflags = 0;
+    if (desiredAccess & DELETE)
+        fidflags |= SMB_FID_OPENDELETE;
+    if (desiredAccess & AFS_ACCESS_READ)
+        fidflags |= SMB_FID_OPENREAD;
+    if (desiredAccess & AFS_ACCESS_WRITE)
+        fidflags |= SMB_FID_OPENWRITE;
 
        dscp = NULL;
        code = 0;
-       code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                       userp, tidPathp, &req, &scp);
+    if (createDisp == 2 || createDisp == 4 || createDisp == 5) {
+        code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &dscp);
+        if (code == 0) {
+            code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
+                             userp, &req, &scp);
+            if (code == CM_ERROR_NOSUCHFILE) {
+                code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, 
+                                 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp);
+                if (code == 0 && realDirFlag == 1) {
+                                       cm_ReleaseSCache(scp);
+                    cm_ReleaseSCache(dscp);
+                    cm_ReleaseUser(userp);
+                    free(realPathp);
+                    return CM_ERROR_EXISTS;
+                }
+            }
+        } else 
+            dscp = NULL;
+    } else {
+        code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &scp);
+    }
+
        if (code == 0) foundscp = TRUE;
        if (code != 0
            || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
                /* look up parent directory */
-               code = cm_NameI(baseDirp, spacep->data,
-                               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                               userp, tidPathp, &req, &dscp);
-               cm_FreeSpace(spacep);
+        if ( !dscp ) {
+            code = cm_NameI(baseDirp, spacep->data,
+                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                             userp, tidPathp, &req, &dscp);
+        } else
+            code = 0;
+        
+        cm_FreeSpace(spacep);
 
                if (baseFid != 0) {
            smb_ReleaseFID(baseFidp);
@@ -3757,13 +5194,17 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                if (!lastNamep) lastNamep = realPathp;
                else lastNamep++;
 
-                if (!smb_IsLegalFilename(lastNamep))
-                        return CM_ERROR_BADNTFILENAME;
+        if (!smb_IsLegalFilename(lastNamep))
+            return CM_ERROR_BADNTFILENAME;
 
                if (!foundscp) {
-                       code = cm_Lookup(dscp, lastNamep,
-                                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
+            if (createDisp == 2 || createDisp == 4)
+                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);
                        if (code && code != CM_ERROR_NOSUCHFILE) {
                                cm_ReleaseSCache(dscp);
                                cm_ReleaseUser(userp);
@@ -3824,8 +5265,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        }
        else if (realDirFlag == 0 || realDirFlag == -1) {
                osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp, "smb_ReceiveNTTranCreate creating file %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+               osi_Log1(smb_logp, "smb_ReceiveNTTranCreate creating file %s",
+                 osi_LogSaveString(smb_logp, lastNamep));
                openAction = 2;         /* created file */
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                setAttr.clientModTime = time(NULL);
@@ -3858,9 +5299,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        else {
                /* create directory */
                osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp,
+               osi_Log1(smb_logp,
                                "smb_ReceiveNTTranCreate creating directory %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+                               osi_LogSaveString(smb_logp, lastNamep));
                openAction = 2;         /* created directory */
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                setAttr.clientModTime = time(NULL);
@@ -3913,13 +5354,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
        fidp->flags = fidflags;
 
-        /* save parent dir and pathname for deletion or change notification */
-        if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
-                fidp->flags |= SMB_FID_NTOPEN;
-                fidp->NTopen_dscp = dscp;
-                cm_HoldSCache(dscp);
-                fidp->NTopen_pathp = strdup(lastNamep);
-        }
+    /* save parent dir and pathname for deletion or change notification */
+    if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
+        fidp->flags |= SMB_FID_NTOPEN;
+        fidp->NTopen_dscp = dscp;
+        cm_HoldSCache(dscp);
+        fidp->NTopen_pathp = strdup(lastNamep);
+    }
        fidp->NTopen_wholepathp = realPathp;
 
        /* we don't need this any longer */
@@ -3930,118 +5371,115 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        /* set inp->fid so that later read calls in same msg can find fid */
        inp->fid = fidp->fid;
 
-       /* check whether we are required to send and extended response */
-       if(!extendedRespRequired) {
-               /* out parms */
-               parmOffset = 8*4 + 39;
-               parmOffset += 1;        /* pad to 4 */
-               dataOffset = parmOffset + 70;
-
-               parmSlot = 1;
-               outp->oddByte = 1;
-               /* Total Parameter Count */
-               smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
-               /* Total Data Count */
-               smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-               /* Parameter Count */
-               smb_SetSMBParmLong(outp, parmSlot, 70); 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, 0); 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, 70);
-
-               lock_ObtainMutex(&scp->mx);
-               outData = smb_GetSMBData(outp, NULL);
-               outData++;                      /* round to get to parmOffset */
-               *outData = 0; outData++;        /* oplock */
-               *outData = 0; outData++;        /* reserved */
-               *((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
-               *((ULONG *)outData) = openAction; outData += 4;
-               *((ULONG *)outData) = 0; outData += 4;  /* EA error offset */
-               smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
-               *((FILETIME *)outData) = ft; outData += 8;      /* creation time */
-               *((FILETIME *)outData) = ft; outData += 8;      /* last access time */
-               *((FILETIME *)outData) = ft; outData += 8;      /* last write time */
-               *((FILETIME *)outData) = ft; outData += 8;      /* change time */
-               *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
-               *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
-               *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
-               *((USHORT *)outData) = 0; outData += 2; /* filetype */
-               *((USHORT *)outData) = 0; outData += 2; /* dev state */
-               *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
-               outData += 2;   /* is a dir? */
-               lock_ReleaseMutex(&scp->mx);
-
-       } else { /* extended response required */
-
-               /* out parms */
-               parmOffset = 8*4 + 39;
-               parmOffset += 1;        /* pad to 4 */
-               dataOffset = parmOffset + 104;
-
-               parmSlot = 1;
-               outp->oddByte = 1;
-               /* Total Parameter Count */
-               smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
-               /* Total Data Count */
-               smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-               /* Parameter Count */
-               smb_SetSMBParmLong(outp, parmSlot, 101); 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, 0); 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, 105);
+    /* check whether we are required to send an extended response */
+    if (!extendedRespRequired) {
+        /* out parms */
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;       /* pad to 4 */
+        dataOffset = parmOffset + 70;
+
+        parmSlot = 1;
+        outp->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 70); 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, 0); 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, 70);
 
-               lock_ObtainMutex(&scp->mx);
-               outData = smb_GetSMBData(outp, NULL);
-               outData++;                      /* round to get to parmOffset */
-               *outData = 0; outData++;        /* oplock */
-               *outData = 1; outData++;        /* response type */
-               *((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
-               *((ULONG *)outData) = openAction; outData += 4;
-               *((ULONG *)outData) = 0; outData += 4;  /* EA error offset */
-               smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
-               *((FILETIME *)outData) = ft; outData += 8;      /* creation time */
-               *((FILETIME *)outData) = ft; outData += 8;      /* last access time */
-               *((FILETIME *)outData) = ft; outData += 8;      /* last write time */
-               *((FILETIME *)outData) = ft; outData += 8;      /* change time */
-               *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
-               *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
-               *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
-               *((USHORT *)outData) = 0; outData += 2; /* filetype */
-               *((USHORT *)outData) = 0; outData += 2; /* dev state */
-               *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
-               outData += 1;   /* is a dir? */
-               memset(outData,0,24); outData += 24; /* Volume ID and file ID */
-               *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
-               *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
-               lock_ReleaseMutex(&scp->mx);
-       }
+        lock_ObtainMutex(&scp->mx);
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to parmOffset */
+        *outData = 0; outData++;       /* oplock */
+        *outData = 0; outData++;       /* reserved */
+        *((USHORT *)outData) = fidp->fid; outData += 2;        /* fid */
+        *((ULONG *)outData) = openAction; outData += 4;
+        *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
+        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* change time */
+        *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
+        *((USHORT *)outData) = 0; outData += 2;        /* filetype */
+        *((USHORT *)outData) = 0; outData += 2;        /* dev state */
+        *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+        outData += 2;  /* is a dir? */
+        lock_ReleaseMutex(&scp->mx);
+    } else {
+        /* out parms */
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;       /* pad to 4 */
+        dataOffset = parmOffset + 104;
+        
+        parmSlot = 1;
+        outp->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 101); 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, 0); 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, 105);
+        
+        lock_ObtainMutex(&scp->mx);
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to parmOffset */
+        *outData = 0; outData++;       /* oplock */
+        *outData = 1; outData++;       /* response type */
+        *((USHORT *)outData) = fidp->fid; outData += 2;        /* fid */
+        *((ULONG *)outData) = openAction; outData += 4;
+        *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
+        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* change time */
+        *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
+        *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
+        *((USHORT *)outData) = 0; outData += 2;        /* filetype */
+        *((USHORT *)outData) = 0; outData += 2;        /* dev state */
+        *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+        outData += 1;  /* is a dir? */
+        memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+        *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
+        *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
+        lock_ReleaseMutex(&scp->mx);
+    }
 
-       osi_Log1(afsd_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
+       osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
 
        smb_ReleaseFID(fidp);
 
        cm_ReleaseUser(userp);
 
-       /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */
-
+       /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */
        /* leave scp held since we put it in fidp->scp */
        return 0;
 }
@@ -4053,40 +5491,39 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
        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 ? */
-
-       fidp = smb_FindFID(vcp, fid, 0);
+       watchtree = smb_GetSMBParm(inp, 22) && 0xffff;  /* TODO: should this be 0xff ? */
 
-       if(!fidp) {
-               osi_Log1(afsd_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
-               return CM_ERROR_BADFD;
-       }
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp) {
+        osi_Log1(smb_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+        return CM_ERROR_BADFD;
+    }
 
        savedPacketp = smb_CopyPacket(inp);
-       savedPacketp->vcp = vcp; /* TODO: refcount vcp? */
+    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);
 
-       osi_Log4(afsd_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
-                filter, fid, watchtree, osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
+    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));
 
-       scp = fidp->scp;
-       lock_ObtainMutex(&scp->mx);
-       if (watchtree)
-               scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
-       else
-               scp->flags |= CM_SCACHEFLAG_WATCHED;
-       lock_ReleaseMutex(&scp->mx);
-       smb_ReleaseFID(fidp);
+    scp = fidp->scp;
+    lock_ObtainMutex(&scp->mx);
+    if (watchtree)
+        scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
+    else
+        scp->flags |= CM_SCACHEFLAG_WATCHED;
+    lock_ReleaseMutex(&scp->mx);
+    smb_ReleaseFID(fidp);
 
        outp->flags |= SMB_PACKETFLAG_NOSEND;
-
        return 0;
 }
 
@@ -4179,7 +5616,7 @@ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        function = smb_GetSMBParm(inp, 18);
 
-       osi_Log1(afsd_logp, "SMB NT Transact function %d", function);
+       osi_Log1(smb_logp, "SMB NT Transact function %d", function);
 
        /* We can handle long names */
        if (vcp->flags & SMB_VCFLAG_USENT)
@@ -4226,13 +5663,16 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                otherAction = FILE_ACTION_RENAMED_NEW_NAME;
        }
 
+    osi_Log2(smb_logp,"in smb_NotifyChange for file [%s] dscp [%x]",
+              osi_LogSaveString(smb_logp,filename),dscp);
+
        lock_ObtainMutex(&smb_Dir_Watch_Lock);
        watch = smb_Directory_Watches;
        while (watch) {
                filter = smb_GetSMBParm(watch, 19)
                                | (smb_GetSMBParm(watch, 20) << 16);
                fid = smb_GetSMBParm(watch, 21);
-               wtree = smb_GetSMBParm(watch, 22) & 0xffff; /* TODO: should this be 0xff ? */
+               wtree = smb_GetSMBParm(watch, 22) & 0xffff;  /* TODO: should this be 0xff ? */
                maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
                                | (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
                vcp = watch->vcp;
@@ -4245,24 +5685,26 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                        filter = 0x17;
 
                fidp = smb_FindFID(vcp, fid, 0);
-               if(!fidp) {
-                       lastWatch = watch;
-                       watch = watch->nextp;
-                       continue;
-               }
+        if (!fidp) {
+            osi_Log1(smb_logp," no fidp for fid[%d]",fid);
+               lastWatch = watch;
+               watch = watch->nextp;
+               continue;
+        }
                if (fidp->scp != dscp
                    || (filter & notifyFilter) == 0
                    || (!isDirectParent && !wtree)) {
-                       smb_ReleaseFID(fidp);
+            osi_Log1(smb_logp," passing fidp->scp[%x]", fidp->scp);
+            smb_ReleaseFID(fidp);
                        lastWatch = watch;
                        watch = watch->nextp;
                        continue;
                }
                smb_ReleaseFID(fidp);
 
-               osi_Log4(afsd_logp,
+               osi_Log4(smb_logp,
                         "Sending Change Notification for fid %d filter 0x%x wtree %d file %s",
-                        fid, filter, wtree, osi_LogSaveString(afsd_logp, filename));
+                        fid, filter, wtree, osi_LogSaveString(smb_logp, filename));
 
                nextWatch = watch->nextp;
                if (watch == smb_Directory_Watches)
@@ -4365,6 +5807,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                }
 
                smb_SendPacket(vcp, watch);
+        smb_ReleaseVC(vcp);
                smb_FreePacket(watch);
                watch = nextWatch;
        }
@@ -4379,7 +5822,7 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        smb_fid_t *fidp;
        cm_scache_t *scp;
 
-       osi_Log0(afsd_logp, "SMB3 receive NT cancel");
+       osi_Log0(smb_logp, "SMB3 receive NT cancel");
 
        lock_ObtainMutex(&smb_Dir_Watch_Lock);
        watch = smb_Directory_Watches;
@@ -4398,23 +5841,27 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        fid = smb_GetSMBParm(watch, 21);
                        watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
 
+            if (vcp != watch->vcp)
+                osi_Log2(smb_logp, "smb_ReceiveNTCancel: vcp %x not equal to watch vcp %x", 
+                         vcp, watch->vcp);
+
                        fidp = smb_FindFID(vcp, fid, 0);
-                       if(fidp) {
-                               osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s", 
-                                       fid, watchtree,
-                                       osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
-
-                               scp = fidp->scp;
-                               lock_ObtainMutex(&scp->mx);
-                               if (watchtree)
-                                       scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
-                               else
-                                       scp->flags &= ~CM_SCACHEFLAG_WATCHED;
-                               lock_ReleaseMutex(&scp->mx);
-                               smb_ReleaseFID(fidp);
-                       } else {
-                               osi_Log2(afsd_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
-                       }
+            if (fidp) {
+                osi_Log3(smb_logp, "Cancelling change notification for fid %d wtree %d file %s", 
+                         fid, watchtree,
+                         osi_LogSaveString(smb_logp, (fidp)?fidp->NTopen_wholepathp:""));
+
+                scp = fidp->scp;
+                lock_ObtainMutex(&scp->mx);
+                if (watchtree)
+                    scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+                else
+                    scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+                lock_ReleaseMutex(&scp->mx);
+                smb_ReleaseFID(fidp);
+            } else {
+                osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
+            }
 
                        /* assume STATUS32; return 0xC0000120 (CANCELED) */
                        replyWctp = watch->wctp;
@@ -4427,6 +5874,8 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        ((smb_t *)watch)->errHigh = 0xC0;
                        ((smb_t *)watch)->flg2 |= 0x4000;
                        smb_SendPacket(vcp, watch);
+            if (watch->vcp)
+                smb_ReleaseVC(watch->vcp);
                        smb_FreePacket(watch);
                        return 0;
                }
@@ -4445,7 +5894,6 @@ void smb3_Init()
 
 cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine)
 {
-    cm_user_t *userp;
     /*int newUid;*/
     smb_username_t *unp;
 
@@ -4454,9 +5902,11 @@ 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_LogEvent("AFS smb_FindCMUserByName New User",NULL,"name[%s] machine[%s]",usern,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_LogEvent("AFS smb_FindCMUserByName Found",NULL,"name[%s] machine[%s]",usern,machine);
+        osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
+        osi_LogEvent("AFS smb_FindCMUserByName : Found",NULL,"name[%s] machine[%s]",usern,machine);
        }
     return unp->userp;
 }